You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何获取SQS的消息总数?以及如何解决基于SQS指标实现Kubernetes HPA合理扩缩容的问题?

解决Kubernetes HPA结合SQS消息数扩缩容的痛点

你遇到的这个问题确实很典型——单独依赖ApproximateNumberOfMessagesVisible会导致Pod刚取到消息就被缩容(因为消息变为不可见),而只用ApproximateNumberOfMessagesNotVisible又没法触发扩容。除了自定义求和指标之外,这里有几个可行的解决方案:

1. 使用SQS自带的总消息数指标

AWS SQS其实在CloudWatch中提供了一个ApproximateNumberOfMessages指标,它正好是ApproximateNumberOfMessagesVisibleApproximateNumberOfMessagesNotVisible的总和。直接用这个指标作为HPA的外部指标,就能同时反映队列中待处理和正在处理的总消息量,完美解决你的问题。

修改后的外部指标模板可以这样写:

apiVersion: metrics.aws/v1alpha1
kind: ExternalMetric
metadata:
  name: sqs-total-messages
spec:
  name: sqs-total-messages
  queries:
    - id: total_messages
      metricStat:
        metric:
          namespace: "AWS/SQS"
          metricName: "ApproximateNumberOfMessages"
          dimensions:
            - name: QueueName
              value: "queue_name"
        period: 60
        stat: Average
        unit: Count
      returnData: true

对应的HPA配置只需要把metricName改成这个新指标即可。

2. 同时配置两个外部指标并设置合理权重

如果因为某些原因不能用总消息数指标,你可以在HPA中同时引入VisibleNotVisible两个指标,分别设置权重来平衡扩容和缩容逻辑:

kind: HorizontalPodAutoscaler
apiVersion: autoscaling/v2beta1
metadata:
  name: hpa-name
spec:
  scaleTargetRef:
    apiVersion: apps/v1beta1
    kind: Deployment
    name: deployment-name
  minReplicas: 1
  maxReplicas: 50
  metrics:
    - type: External
      external:
        metricName: sqs-visible-messages
        targetAverageValue: 2
    - type: External
      external:
        metricName: sqs-not-visible-messages
        targetAverageValue: 1

这里的思路是:用Visible消息数驱动扩容(当待处理消息增多时增加Pod),用NotVisible消息数来限制缩容(当还有大量正在处理的消息时,不会轻易减少Pod)。你可以根据实际业务调整targetAverageValue的数值,找到适合的平衡。

3. 调整可见性超时和HPA缩容冷却时间

另一种思路是通过调整SQS的消息可见性超时(Visibility Timeout)和HPA的缩容冷却时间(scaleDownStabilizationWindowSeconds)来避免过早缩容:

  • 调整可见性超时:把消息的可见性超时设置得比Pod处理单条消息的时间长一些,确保Pod在处理完消息并删除它之前,消息不会重新变为可见。这样ApproximateNumberOfMessagesVisible不会因为Pod取走消息就立即下降,给HPA足够的时间判断是否需要缩容。
  • 设置缩容冷却时间:在HPA配置中添加scaleDownStabilizationWindowSeconds,让HPA在缩容前等待一段时间,确保队列中的消息确实已经处理完毕,而不是刚被Pod取走:
kind: HorizontalPodAutoscaler
apiVersion: autoscaling/v2beta1
metadata:
  name: hpa-name
spec:
  scaleTargetRef:
    apiVersion: apps/v1beta1
    kind: Deployment
    name: deployment-name
  minReplicas: 1
  maxReplicas: 50
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300 # 等待5分钟再缩容
  metrics:
    - type: External
      external:
        metricName: sqs-visible-messages
        targetAverageValue: 1

这个方案适合那些不想修改指标配置,只想通过参数调优解决问题的场景。

4. 结合Pod的CPU/内存指标做混合扩缩容

你还可以把SQS的消息数指标和Pod的CPU、内存使用率结合起来,做混合模式的HPA扩缩容:

kind: HorizontalPodAutoscaler
apiVersion: autoscaling/v2beta1
metadata:
  name: hpa-name
spec:
  scaleTargetRef:
    apiVersion: apps/v1beta1
    kind: Deployment
    name: deployment-name
  minReplicas: 1
  maxReplicas: 50
  metrics:
    - type: Resource
      resource:
        name: cpu
        targetAverageUtilization: 70
    - type: External
      external:
        metricName: sqs-visible-messages
        targetAverageValue: 1

这样,HPA会同时参考CPU使用率和队列消息数:当队列消息增多时触发扩容,当CPU使用率下降且队列消息很少时再触发缩容,避免因为消息刚被取走就误缩容。

内容的提问来源于stack exchange,提问作者Chakradar Raju

火山引擎 最新活动