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 服务定义一个 Horizo​​ntal Pod Autoscaler。

Autoscaler 策略依赖于 3 个指标:

    CPU pubsub.googleapis.com|subscription|num_undelivered_messages loadbalancing.googleapis.com|https|request_count

CPUnum_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

并查看根据您的指标名称和特定指标选择器返回的内容。

这些正是 Horizo​​ntal Pod Autoscaler 在运行时发出的请求。通过手动复制它们,您应该能够查明问题的根源。


关于附加信息的评论:

1) 83m 是 Kubernetes 的写法 0.083(读作 83“毫单位”)。

2) 在 Horizo​​ntalPodAutoscaler 定义中,您使用 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 Horizo​​ntal 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

Kubernetes Pod Horizo​​ntal Autoscaler pod 和对象选择器字段是字符串吗?

16-Kubernetes-Pod控制器详解-Horizontal Pod Autoscaler(HPA)