仅当使用Kubernetes中的Horizo​​ntalPodAutoscaler处理消息(吊舱完成其任务)时,才可以缩小吊舱的尺寸吗?

时间:2019-06-11 21:56:16

标签: kubernetes rabbitmq autoscaling

我使用prometheus适配器https://github.com/DirectXMan12/k8s-prometheus-adapter使用自定义指标设置了Kubernetes Horizo​​ntal Pod Autoscaler。普罗米修斯(Prometheus)正在监控Rab​​bitmq,而我正在监视 rabbitmq_queue_messages 指标。队列中的消息由Pod提取,然后进行一些处理,该过程可能持续数小时。

根据队列中消息的数量进行放大和缩小。

问题: 当广告连播完成处理并确认消息后,该数字将降低。队列中的消息数,这将触发自动缩放器终止容器。如果我有multipe pod执行处理,并且其中一个完成了,如果Im没记错,Kubernetes可以终止仍在处理自己消息的Pod。这是不希望的,因为吊舱正在执行的所有处理都将丢失。

有没有办法解决这个问题,或者有另一种方法可以解决这个问题?

这是Autoscaler配置:

kind: HorizontalPodAutoscaler
apiVersion: autoscaling/v2beta1
metadata:
  name: sample-app-rabbitmq
  namespace: monitoring
spec:
  scaleTargetRef:
    # you created above
    apiVersion: apps/v1
    kind: Deployment
    name: sample-app
  minReplicas: 1
  maxReplicas: 10
  metrics:
  - type: Object
    object:
      target:
        kind: Service
        name: rabbitmq-cluster
      metricName: rabbitmq_queue_messages_ready
      targetValue: 5

2 个答案:

答案 0 :(得分:0)

您可以考虑使用 preStop挂钩

根据文档Container StatesDefine postStart and preStop handlers

  

在容器进入Terminated之前,执行preStop挂钩(如果有)。

因此您可以在部署中使用:

lifecycle:
      preStop:
        exec:
          command: ["your script"]

### 更新

  1. 由于一些研究,我想提供更多信息: 有一个有趣的project

      

    KEDA允许事件驱动的Kubernetes工作负载进行细粒度的自动缩放(包括从零到零)。 KEDA充当Kubernetes Metrics服务器,允许用户使用专用的Kubernetes自定义资源定义来定义自动缩放规则。   KEDA可以在云和边缘上运行,可以与Kubernetes组件(例如Horizo​​ntal Pod Autoscaler)进行本地集成,并且没有外部依赖性。

  2. 对于主要问题“ Kubernetes可以终止仍在处理其自身消息的Pod”。

    根据文档:

      

    “部署是一个高级概念,可管理副本集,并提供Pod的声明式更新以及许多其他有用的功能”

部署由Replicaset支持。按照此控制器代码,存在功能“ getPodsToDelete”。结合使用“ filteredPods ”可得出结果:“ 这可确保我们尽可能早地删除豆荚。

因此,作为概念证明:

您可以使用初始化容器创建部署。初始化容器应检查队列中是否有消息,并在出现至少一条消息时退出。这将允许主容器启动,接收和处理该消息。在这种情况下,我们将有两种豆荚-那些处理消息并消耗CPU的豆荚,以及那些处于启动状态的豆荚并等待下一条消息。在这种情况下,当HPA决定减少部署中的副本数时,起始容器将首先被删除

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    app: complete
  name: complete
spec:
  replicas: 5
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: complete
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: complete
    spec:
      hostname: c1
      containers:
      - name: complete
        command: 
        - "bash"
        args:
        - "-c"
        - "wa=$(shuf -i 15-30 -n 1)&& echo $wa && sleep $wa"
        image: ubuntu
        imagePullPolicy: IfNotPresent
        resources: {}
      initContainers:
      - name: wait-for
        image: ubuntu
        command: ['bash', '-c', 'sleep 30']


  dnsPolicy: ClusterFirst
  restartPolicy: Always
  terminationGracePeriodSeconds: 30

希望获得帮助。

答案 1 :(得分:0)

Horizo​​ntal Pod Autoscaler不适用于长时间运行的任务,因此不太适合。如果您需要为每条消息产生一个长期运行的处理任务,则可以采用以下两种方法之一:

  • 使用任务队列,例如Celery。它旨在解决您的确切问题:拥有需要分配给工作人员的任务队列,并确保任务能够完成。 Kubernetes甚至提供了此设置的official example
  • 如果您不想引入其他组件(例如Celery),则可以自己为每个传入消息生成Kubernetes job。 Kubernetes将确保该作业至少完成一次-如果该Pod死了,则重新安排该pod的时间,等等。在这种情况下,您将需要编写一个脚本来读取RabbitMQ消息并自己为它们创建作业。

在两种情况下,请确保还启用了Cluster Autoscaler,以便在当前节点不足以处理负载时自动配置新节点。