HorizontalPodAutoscaler:用于在 GKE 中部署自定义指标 Stackdriver 适配器的已发布文档是否完整且正确?
HorizontalPodAutoscaler: Is the published documentation for deploying the custom metrics stackdriver adapter in GKE complete and correct?
Google 发布了使用自定义指标驱动 HorizontalPodAutoscaler
here 的教程,本教程包含以下说明:
- 使用 Kubernetes 清单将自定义指标适配器部署到
custom-metrics
命名空间。
- 正在部署虚拟应用程序以生成指标。
- 配置 HPA 以使用自定义指标。
我们正在部署到没有任何特殊 VPC 规则的默认集群中,我们大致遵循了教程的指导,但有一些例外:
- 我们正在使用 Helm v2,而不是向 Tiller 授予集群管理员角色,我们已经授予所有必要的集群角色和角色绑定,以允许 custom-metrics-adapter-deploying Kubernetes 清单工作。我们认为那里没有问题;至少自定义指标适配器启动并运行。
- 我们定义了一些自定义指标,这些指标基于从 Stackdriver 日志中的 jsonPayload 中提取的数据。
- 我们已经部署了一个每分钟的 CronJob,它读取上述指标并发布一个派生指标,这是我们想要用来驱动自动缩放器的值。 CronJob 正在运行,我们可以在日志指标浏览器中以每个 Pod 为基础,在派生指标中看到指标:
我们正在将 HPA 配置为根据属于有状态集的所有 pods 的派生指标的平均值进行扩展(HPA 具有类型为 Pods 的指标条目) .但是,HPA 无法读取我们的派生指标。我们看到此错误消息:
failed to get object metric value: unable to get metric xxx_scaling_metric: no metrics returned from custom metrics API
更新
我们看到了 DNS 错误,但这些显然是误报,可能在集群启动时出现在日志中。
我们使用命令行选项 --v=5
重新启动了 Stackdriver 指标适配器,以进行更详细的调试。我们看到这样的日志条目:
I0123 20:23:08.069406 1 wrap.go:47] GET /apis/custom.metrics.k8s.io/v1beta1/namespaces/defaults/pods/%2A/xxx_scaling_metric: (56.16652ms) 200 [kubectl/v1.13.11 (darwin/amd64) kubernetes/2e298c7 10.44.1.1:36286]
I0123 20:23:12.997569 1 translator.go:570] Metric 'xxx_scaling_metric' not found for pod 'xxx-0'
I0123 20:23:12.997775 1 wrap.go:47] GET /apis/custom.metrics.k8s.io/v1beta2/namespaces/default/pods/%2A/xxx_scaling_metric?labelSelector=app%3Dxxx: (98.101205ms) 200 [kube-controller-manager/v1.13.11 (linux/amd64) kubernetes/56d8986/system:serviceaccount:kube-system:horizontal-pod-autoscaler 10.44.1.1:36286]
所以它 在我们看来 好像 HPA 正在对基于 pods 的自定义指标进行正确的查询。如果我们询问自定义指标 API 它有什么数据,并使用 jq
过滤我们感兴趣的指标,我们会看到:
{"kind":"MetricValueList",
"apiVersion":"custom.metrics.k8s.io/v1beta1",
"metadata: {"selfLink":"/apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pods/%2A/xxx_scaling_metric"},
"items":[]}
项目数组为空令人不安。同样,我们可以在指标资源管理器中看到数据,所以我们想知道发布我们的缩放指标的 CronJob 应用程序是否提供了正确的字段,以便将数据保存在 Stackdriver 中或通过指标适配器公开。
我们在 CronJob 中发布的时间序列的 resource.labels 地图的价值如下:
{'cluster_name': 'test-gke',
'zone': 'us-central1-f',
'project_id': 'my-project-1234',
'container_name': '',
'instance_id': '1234567890123456789',
'pod_id': 'xxx-0',
'namespace_id': 'default'}
我们终于解决了这个问题。我们的 CronJob 发布了我们想要使用的派生指标,它从从 Stackdriver 日志中提取的另外两个指标获取原始数据,并计算一个新值并将其发布回 Stackdriver。
我们在发布派生指标时使用了从这些指标中看到的资源标签。我们正在阅读的 "input" Stackdriver 指标中的 POD_ID
资源标签值是 pod 的名称。但是,位于 gcr.io/google-containers/custom-metrics-stackdriver-adapter:v0.10.0
的 stackdriver 自定义指标适配器正在枚举命名空间中的 pods 并要求 stackdriver 提供与 pods 的 UID 关联的数据,而不是它们的名称。 (阅读适配器的源代码来解决这个问题...)
因此,我们的 CronJob 现在构建一个 pod 名称到 pod UID 的映射(这要求它具有 RBAC pod 列表并获取角色),并发布我们用于 HPA 的派生指标,其中 POD_ID
设置为pod 的 UID 而不是它的名称。
已发布的 HPA 自定义指标示例(如 this)起作用的原因是它们使用向下 API 获取 pod 的 UID,并将该值提供为 "POD_ID".回想起来,如果我们查看 "dummy" 指标导出器如何获得其 pod id 值,那应该是显而易见的,但肯定有一些示例(如 Stackdriver 日志指标)其中 POD_ID
最终成为名称而不是 UID。
Google 发布了使用自定义指标驱动 HorizontalPodAutoscaler
here 的教程,本教程包含以下说明:
- 使用 Kubernetes 清单将自定义指标适配器部署到
custom-metrics
命名空间。 - 正在部署虚拟应用程序以生成指标。
- 配置 HPA 以使用自定义指标。
我们正在部署到没有任何特殊 VPC 规则的默认集群中,我们大致遵循了教程的指导,但有一些例外:
- 我们正在使用 Helm v2,而不是向 Tiller 授予集群管理员角色,我们已经授予所有必要的集群角色和角色绑定,以允许 custom-metrics-adapter-deploying Kubernetes 清单工作。我们认为那里没有问题;至少自定义指标适配器启动并运行。
- 我们定义了一些自定义指标,这些指标基于从 Stackdriver 日志中的 jsonPayload 中提取的数据。
- 我们已经部署了一个每分钟的 CronJob,它读取上述指标并发布一个派生指标,这是我们想要用来驱动自动缩放器的值。 CronJob 正在运行,我们可以在日志指标浏览器中以每个 Pod 为基础,在派生指标中看到指标:
我们正在将 HPA 配置为根据属于有状态集的所有 pods 的派生指标的平均值进行扩展(HPA 具有类型为 Pods 的指标条目) .但是,HPA 无法读取我们的派生指标。我们看到此错误消息:
failed to get object metric value: unable to get metric xxx_scaling_metric: no metrics returned from custom metrics API
更新
我们看到了 DNS 错误,但这些显然是误报,可能在集群启动时出现在日志中。
我们使用命令行选项 --v=5
重新启动了 Stackdriver 指标适配器,以进行更详细的调试。我们看到这样的日志条目:
I0123 20:23:08.069406 1 wrap.go:47] GET /apis/custom.metrics.k8s.io/v1beta1/namespaces/defaults/pods/%2A/xxx_scaling_metric: (56.16652ms) 200 [kubectl/v1.13.11 (darwin/amd64) kubernetes/2e298c7 10.44.1.1:36286]
I0123 20:23:12.997569 1 translator.go:570] Metric 'xxx_scaling_metric' not found for pod 'xxx-0'
I0123 20:23:12.997775 1 wrap.go:47] GET /apis/custom.metrics.k8s.io/v1beta2/namespaces/default/pods/%2A/xxx_scaling_metric?labelSelector=app%3Dxxx: (98.101205ms) 200 [kube-controller-manager/v1.13.11 (linux/amd64) kubernetes/56d8986/system:serviceaccount:kube-system:horizontal-pod-autoscaler 10.44.1.1:36286]
所以它 在我们看来 好像 HPA 正在对基于 pods 的自定义指标进行正确的查询。如果我们询问自定义指标 API 它有什么数据,并使用 jq
过滤我们感兴趣的指标,我们会看到:
{"kind":"MetricValueList",
"apiVersion":"custom.metrics.k8s.io/v1beta1",
"metadata: {"selfLink":"/apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pods/%2A/xxx_scaling_metric"},
"items":[]}
项目数组为空令人不安。同样,我们可以在指标资源管理器中看到数据,所以我们想知道发布我们的缩放指标的 CronJob 应用程序是否提供了正确的字段,以便将数据保存在 Stackdriver 中或通过指标适配器公开。
我们在 CronJob 中发布的时间序列的 resource.labels 地图的价值如下:
{'cluster_name': 'test-gke',
'zone': 'us-central1-f',
'project_id': 'my-project-1234',
'container_name': '',
'instance_id': '1234567890123456789',
'pod_id': 'xxx-0',
'namespace_id': 'default'}
我们终于解决了这个问题。我们的 CronJob 发布了我们想要使用的派生指标,它从从 Stackdriver 日志中提取的另外两个指标获取原始数据,并计算一个新值并将其发布回 Stackdriver。
我们在发布派生指标时使用了从这些指标中看到的资源标签。我们正在阅读的 "input" Stackdriver 指标中的 POD_ID
资源标签值是 pod 的名称。但是,位于 gcr.io/google-containers/custom-metrics-stackdriver-adapter:v0.10.0
的 stackdriver 自定义指标适配器正在枚举命名空间中的 pods 并要求 stackdriver 提供与 pods 的 UID 关联的数据,而不是它们的名称。 (阅读适配器的源代码来解决这个问题...)
因此,我们的 CronJob 现在构建一个 pod 名称到 pod UID 的映射(这要求它具有 RBAC pod 列表并获取角色),并发布我们用于 HPA 的派生指标,其中 POD_ID
设置为pod 的 UID 而不是它的名称。
已发布的 HPA 自定义指标示例(如 this)起作用的原因是它们使用向下 API 获取 pod 的 UID,并将该值提供为 "POD_ID".回想起来,如果我们查看 "dummy" 指标导出器如何获得其 pod id 值,那应该是显而易见的,但肯定有一些示例(如 Stackdriver 日志指标)其中 POD_ID
最终成为名称而不是 UID。