Kubernetes AWS Cloudwatch 适配器未获取 EKS HPA 自动缩放的自定义指标值

Kubernetes AWS Cloudwatch adapter not fetching custom metric value for EKS HPA autoscaling

我正在尝试通过 Kubernetes Cloudwatch 适配器根据自定义 Cloudwatch 指标启用 AWS EKS 自动缩放。我已将自定义指标推送到 AWS Cloudwatch,并验证它们出现在 Cloudwatch 控制台中,并且可以使用 boto3 客户端 get_metric_data 检索。这是我用来将自定义指标发布到 Cloudwatch 的代码:

import boto3
from datetime import datetime

client = boto3.client('cloudwatch')

cloudwatch_response = client.put_metric_data(
    Namespace='TestMetricNS',
    MetricData=[
        {
            'MetricName': 'TotalUnprocessed',
            'Timestamp': datetime.now(),
            'Value': 40,
            'Unit': 'Megabytes',
        }
    ]
)

我有以下 yaml 文件用于在 kubernetes 中建立外部指标和 hpa 自动缩放器:

extMetricCustom.yaml:

apiVersion: metrics.aws/v1alpha1
kind: ExternalMetric
metadata:
  name: test-custom-metric
spec:
  name: test-custom-metric
  resource:
    resource: "deployment"
  queries:
    - id: sqs_test
      metricStat:
        metric:
          namespace: "TestMetricNS"
          metricName: "TotalUnprocessed"
        period: 60
        stat: Average
        unit: Megabytes
      returnData: true

hpaCustomMetric.yaml

kind: HorizontalPodAutoscaler
apiVersion: autoscaling/v2beta1
metadata:
  name: test-scaler
spec:
  scaleTargetRef:
    apiVersion: apps/v1beta1
    kind: Deployment
    name: sqs-consumer
  minReplicas: 1
  maxReplicas: 4
  metrics:
  - type: External
    external:
      metricName: test-custom-metric
      targetAverageValue: 2

当我评估 Kubernetes Cloudwatch 适配器是否正确获取我的自定义指标 (kubectl get hpa) 时,它始终显示该指标为 0:

NAME          REFERENCE                 TARGETS     MINPODS   MAXPODS   REPLICAS   AGE
test-scaler   Deployment/sqs-consumer   0/2 (avg)   1         4         1          161m

如何根据我的 Cloudwatch 自定义指标正确自动缩放?

在这个 out-of-band 上与 OP 合作,并且在当天晚些时候仍然打开这个问题的选项卡,因此将结果发布在这里以供后代使用,以供偶然发现它的任何人使用。

问题的根本原因是时区冲突。指标监视器基于“当前”指标,但指标生成器脚本中的以下行生成了未指定时区的时间戳,并且也在本地时区中。

            'Timestamp': datetime.now(),

由于当前时区“没有数据”(由于 -X UTC 偏移,只有过去 X 小时的数据),系统没有启动缩放,因为值为“0”/nil/null 有效。相反,可以指定 UTC 时间字符串以确保生成的指标是及时的:

            'Timestamp': datetime.utcnow(),

次要考虑因素是 Kubernetes 节点需要访问权限以从 CloudWatch 轮询指标。这是通过将 this policy 附加到节点的 IAM 角色来完成的:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "cloudwatch:GetMetricData"
            ],
            "Resource": "*"
        }
    ]
}