kubernetes Autoscaler - 无法获取 loadbalancing.googleapis.com|https|request_count
Posted
技术标签:
【中文标题】kubernetes Autoscaler - 无法获取 loadbalancing.googleapis.com|https|request_count【英文标题】:kubernetes Autoscaler - Cannot obtain loadbalancing.googleapis.com|https|request_count 【发布时间】:2020-02-18 01:09:18 【问题描述】:我正在尝试为两个 Kubernetes 服务定义一个 Horizontal Pod Autoscaler。
Autoscaler 策略依赖于 3 个指标:
-
CPU
pubsub.googleapis.com|subscription|num_undelivered_messages
loadbalancing.googleapis.com|https|request_count
CPU 和 num_undelivered_messages 正确获取,但无论我做什么,我都无法获取 request_count 指标。
第一个服务是后端服务(服务 A),另一个(服务 B)是一个 API,它使用 Ingress 来管理对服务的外部访问。
自动缩放策略基于 Google 文档:Autoscaling Deployments with External Metrics。
对于服务 A,以下定义了用于自动缩放的指标:
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
name: ServiceA
spec:
scaleTargetRef:
apiVersion: extensions/v1beta1
kind: Deployment
name: ServiceA
minReplicas: 1
maxReplicas: 3
metrics:
- type: Resource
resource:
name: cpu
targetAverageUtilization: 80
- external:
metricName: pubsub.googleapis.com|subscription|num_undelivered_messages
metricSelector:
matchLabels:
resource.labels.subscription_id: subscription_id
targetAverageValue: 100
type: External
对于服务 B,以下定义了用于自动缩放的指标:
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
name: ServiceB
spec:
scaleTargetRef:
apiVersion: extensions/v1beta1
kind: Deployment
name: ServiceB
minReplicas: 1
maxReplicas: 3
metrics:
- type: Resource
resource:
name: cpu
targetAverageUtilization: 80
- external:
metricName: loadbalancing.googleapis.com|https|request_count
metricSelector:
matchLabels:
resource.labels.forwarding_rule_name: k8s-fws-default-serviceb--3a908157de956ba7
targetAverageValue: 100
type: External
如上篇文章中定义的那样,metrics server 正在运行,metrics server 适配器已经部署:
$ kubectl get apiservices |egrep metrics
v1beta1.custom.metrics.k8s.io custom-metrics/custom-metrics-stackdriver-adapter True 2h
v1beta1.external.metrics.k8s.io custom-metrics/custom-metrics-stackdriver-adapter True 2h
v1beta1.metrics.k8s.io kube-system/metrics-server True 2h
v1beta2.custom.metrics.k8s.io custom-metrics/custom-metrics-stackdriver-adapter True 2h
对于服务 A,所有指标 CPU 和 num_undelivered_messages 都正确获取:
$ kubectl get hpa ServiceA
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
ServiceA Deployment/ServiceA 0/100 (avg), 1%/80% 1 3 1 127m
对于服务 B,HPA 无法获取 Request Count:
$ kubectl get hpa ServiceB
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
ServiceB Deployment/ServiceB <unknown>/100 (avg), <unknown>/80% 1 3 1 129m
访问 Ingress 时,我收到以下警告:
无法获取外部指标 default/loadbalancing.googleapis.com|https|request_count/&LabelSelectorMatchLabels:map[string]stringresource.labels.forwarding_rule_name: k8s-fws-default-serviceb--3a908157de956ba7,,MatchExpressions :[],: 没有从外部指标 API 返回指标
转发规则的 metricSelector 是正确的,在描述入口时已确认(仅显示相关信息):
$ kubectl describe ingress serviceb
Annotations:
ingress.kubernetes.io/https-forwarding-rule: k8s-fws-default-serviceb--3a908157de956ba7
我尝试使用不同的指标选择器,例如,使用 url_map_name,但无济于事,我遇到了类似的错误。
我已遵循 Google 文档中的确切指南,并查看了一些参考完全相同过程的在线教程,但我无法理解我缺少什么。 我可能缺少一些配置或一些具体细节,但我在任何地方都找不到它的文档。
我缺少什么,这解释了为什么我无法获得 loadbalancing.googleapis.com|https|request_count 指标?
【问题讨论】:
【参考方案1】:您定义的指标似乎在External Metrics API 中不可用。要了解发生了什么,您可以直接检查 External Metrics API:
kubectl get --raw="/apis/external.metrics.k8s.io/v1beta1" | jq
输出中是否报告了 loadbalancing.googleapis.com|https|request_count 指标?
然后您可以通过发出请求of the following form 来深入挖掘:
kubectl get --raw="/apis/external.metrics.k8s.io/v1beta1/namespaces/<namespace_name>/<metric_name>?labelSelector=<selector>" | jq
并查看根据您的指标名称和特定指标选择器返回的内容。
这些正是 Horizontal Pod Autoscaler 在运行时发出的请求。通过手动复制它们,您应该能够查明问题的根源。
关于附加信息的评论:
1) 83m 是 Kubernetes 的写法 0.083(读作 83“毫单位”)。
2) 在 HorizontalPodAutoscaler 定义中,您使用 targetAverageValue
。因此,如果存在具有此指标的多个目标,HPA 会计算它们的平均值。因此,83m 可能是多个目标的平均值。为确保您仅使用单个目标的指标,您可以使用targetValue
字段(请参阅API reference)。
3) 不知道为什么 API 响应中的 items: []
数组为空。文档中提到采样后,数据在 210 秒内不可见......您可以尝试在 HPA 未运行时发出 API 请求。
【讨论】:
【参考方案2】:非常感谢您的详细回复。
当使用metricSelector选择特定的forwarding_rule_name时,我们需要使用入口定义的准确forwarding_rule_name:
metricSelector:
matchLabels:
resource.labels.forwarding_rule_name: k8s-fws-default-serviceb--3a908157de956ba7
$ kubectl describe ingress
Name: serviceb
...
Annotations:
ingress.kubernetes.io/https-forwarding-rule: k8s-fws-default-serviceb--9bfb478c0886702d
...
kubernetes.io/ingress.allow-http: false
kubernetes.io/ingress.global-static-ip-name: static-ip
问题在于,forwarding_rule_name (3a908157de956ba7) 的后缀会随每次部署而变化,并在 Ingress 创建时动态创建:
k8s-fws-default-serviceb--3a908157de956ba7我们使用 Helm 进行了全自动部署,因此,在创建 HPA 时,我们不知道 forwarding_rule_name 将是什么。
而且,似乎 matchLabels 不接受正则表达式,否则我们将简单地执行以下操作:
metricSelector:
matchLabels:
resource.labels.forwarding_rule_name: k8s-fws-default-serviceb--*
我尝试了几种方法,都没有成功:
-
使用注释强制forwarding_rule_name
使用不同的 machLabel,作为 backend_target_name
使用命令获取 forwarding_rule_name,以便稍后将其插入到 yaml 文件中。
使用注释强制forwarding_rule_name:
在创建入口时,我可以使用特定的注释来更改默认行为,或者定义特定的值,例如在 Ingress.yaml 上:
annotations:
kubernetes.io/ingress.global-static-ip-name: static-ip
我尝试使用 https-forwarding-rule 注释来强制使用特定的“静态”名称,但这不起作用:
annotations:
ingress.kubernetes.io/https-forwarding-rule: some_name
annotations:
kubernetes.io/https-forwarding-rule: some_name
使用不同的 machLabel,作为 backend_target_name
metricSelector:
matchLabels:
resource.labels.backend_target_name: serviceb
也失败了。
使用命令获取forwarding_rule_name
执行以下命令时,我得到了转发规则列表,但针对所有集群。而根据documentation,是不可能按集群过滤的:
gcloud compute forwarding-rules list
NAME P_ADDRESS IP_PROTOCOL TARGET
k8s-fws-default-serviceb--4e1c268b39df8462 xx TCP k8s-tps-default-serviceb--4e1c268b39df8462
k8s-fws-default-serviceb--9bfb478c0886702d xx TCP k8s-tps-default-serviceb--9bfb478c0886702d
有什么方法可以让我选择我需要的资源,以获取请求计数指标?
【讨论】:
我在 GoogleCloudPlatform/k8s-stackdriver GitHub 上创建了一个问题:github.com/GoogleCloudPlatform/k8s-stackdriver/issues/296,但很遗憾,它尚未分配给任何人。【参考方案3】:我的代码似乎一切正常,但是在 request_count 指标可用之前存在时间延迟(大约 10m)。在这段时间之后,该指标现在已计算并可用:
$ kubectl get hpa ServiceB
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
ServiceB Deployment/ServiceB 83m/100 (avg), 1%/80% 1 3 1 18m
现在,关于 loadbalancing.googleapis.com|https|request_count 指标,我不明白它是如何呈现的。 83m 是什么意思?
根据Load balancing metrics 的 Google 文档:
https/request_bytes_count 请求字节数
DELTA,INT64,按
GA
HTTP/S 负载平衡器处理的请求数。每 60 次采样 秒。采样后,最长 210 秒内数据不可见。
根据Metric Details:
在 DELTA 指标中,每个数据点代表一个值的变化 在时间间隔内。例如,服务请求的数量 自上次测量以来收到的将是一个增量指标。
我已经向服务发出了一个请求,所以我期望值为 1,但我无法理解 83m 的含义。 p>
另一种可能性,可能是我没有使用正确的指标。 我选择了 loadbalancing.googleapis.com|https|request_count 指标,假设它将提供服务通过负载均衡器执行的请求数。
loadbalancing.googleapis.com|https|request_count 指标提供的信息不正是这些信息吗?
关于上述注释,执行时:
kubectl get --raw="/apis/external.metrics.k8s.io/v1beta1/namespaces/default/pubsub.googleapis.com|subscription|num_undelivered_messages" | jq
我得到了正确的数据:
... "metricName": "pubsub.googleapis.com|subscription|num_undelivered_messages", “公制标签”: “resource.labels.project_id”:“项目 ID”, “resource.labels.subscription_id”:“subscription_id”, “resource.type”:“pubsub_subscription” , "时间戳": "2019-10-22T15:39:58Z", “价值”:“4” ...
但是,执行时:
kubectl get --raw="/apis/external.metrics.k8s.io/v1beta1/namespaces/default/loadbalancing.googleapis.com|https|request_count" | jq
我一无所获:
"kind": "ExternalMetricValueList", "apiVersion": “external.metrics.k8s.io/v1beta1”,“元数据”: "selfLink": >"/apis/external.metrics.k8s.io/v1beta1/namespaces/default/loadbalancing.googleapis.com%7Chttps%7Crequest_count" , "项目": []
【讨论】:
请参阅上一个答案中的 cmets。此外,为了便于理解,我宁愿将附加信息添加为对问题的编辑,而不是作为答案。以上是关于kubernetes Autoscaler - 无法获取 loadbalancing.googleapis.com|https|request_count的主要内容,如果未能解决你的问题,请参考以下文章
Pod 副本缩减在 Kubernetes Horizontal Pod Autoscaler 中是如何工作的?
Docker&Kubernetes ❀ Kubernetes集群Pod控制器 - Horizontal Pod Autoscaler(HPA)
Docker&Kubernetes ❀ Kubernetes集群Pod控制器 - Horizontal Pod Autoscaler(HPA)
kubernetes Autoscaler - 无法获取 loadbalancing.googleapis.com|https|request_count