【问题标题】:kubernetes Autoscaler - Cannot obtain loadbalancing.googleapis.com|https|request_countkubernetes Autoscaler - 无法获取 loadbalancing.googleapis.com|https|request_count
【发布时间】:2020-02-18 01:09:18
【问题描述】:

我正在尝试为两个 Kubernetes 服务定义一个 Horizo​​ntal Pod Autoscaler。

Autoscaler 策略依赖于 3 个指标:

  1. CPU
  2. pubsub.googleapis.com|subscription|num_undelivered_messages
  3. 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/&LabelSelector{MatchLabels:map[string]string{resource.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 指标?

【问题讨论】:

    标签: kubernetes autoscaling


    【解决方案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--*
      

      我尝试了几种方法,都没有成功:

      1. 使用注释强制forwarding_rule_name
      2. 使用不同的 machLabel,作为 backend_target_name
      3. 使用命令获取 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
      

      有什么方法可以让我选择我需要的资源,以获取请求计数指标?

      【讨论】:

      【解决方案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。此外,为了便于理解,我宁愿将附加信息添加为对问题的编辑,而不是作为答案。
      猜你喜欢
      • 2019-06-04
      • 2022-09-29
      • 1970-01-01
      • 2023-04-10
      • 2018-09-21
      • 2020-09-30
      • 1970-01-01
      • 2019-05-01
      • 2021-10-26
      相关资源
      最近更新 更多