工作负载伸缩FAQ

本文介绍使用工作负载伸缩功能(包括HPA、CronHPA等)时可能遇到的常见问题及解决方案。

索引

HPA的监控数据current字段为何显示为unknown

当HPA的监控数据的current字段显示为unknown时,表示kube-controller-manager无法访问监控数据源获取对应的监控数据,HPA扩缩容时会失败。

Name:                                                  kubernetes-tutorial-deployment
Namespace:                                             default
Labels:                                                <none>
Annotations:                                           <none>
CreationTimestamp:                                     Mon, 10 Jun 2019 11:46:48  0530
Reference:                                             Deployment/kubernetes-tutorial-deployment
Metrics:                                               ( current / target )
  resource cpu on pods  (as a percentage of request):  <unknown> / 2%
Min replicas:                                          1
Max replicas:                                          4
Deployment pods:                                       1 current / 0 desired
Conditions:
  Type           Status  Reason                   Message
  ----           ------  ------                   -------
  AbleToScale    True    SucceededGetScale        the HPA controller was able to get the target's current scale
  ScalingActive  False   FailedGetResourceMetric  the HPA was unable to compute the replica count: unable to get metrics for resource cpu: unable to fetch metrics from resource metrics API: the server is currently unable to handle the request (get pods.metrics.k8s.io)
Events:
  Type     Reason                   Age                      From                       Message
  ----     ------                   ----                     ----                       -------
  Warning  FailedGetResourceMetric  3m3s (x1009 over 4h18m)  horizontal-pod-autoscaler  unable to get metrics for resource cpu: unable to fetch metrics from resource metrics API: the server is currently unable to handle the request (get pods.metrics.k8s.io)

原因一:Resource Metrics数据源无法使用

请先执行命令kubectl top pod检查是否返回数据。如果所有的Pod都无数据,请执行kubectl get apiservice检查当前提供Resource Metrics的数据源的情况。返回的示例数据如下。

展开查看返回的示例数据

NAME                                   SERVICE                      AVAILABLE   AGE
v1.                                    Local                        True        29h
v1.admissionregistration.k8s.io        Local                        True        29h
v1.apiextensions.k8s.io                Local                        True        29h
v1.apps                                Local                        True        29h
v1.authentication.k8s.io               Local                        True        29h
v1.authorization.k8s.io                Local                        True        29h
v1.autoscaling                         Local                        True        29h
v1.batch                               Local                        True        29h
v1.coordination.k8s.io                 Local                        True        29h
v1.monitoring.coreos.com               Local                        True        29h
v1.networking.k8s.io                   Local                        True        29h
v1.rbac.authorization.k8s.io           Local                        True        29h
v1.scheduling.k8s.io                   Local                        True        29h
v1.storage.k8s.io                      Local                        True        29h
v1alpha1.argoproj.io                   Local                        True        29h
v1alpha1.fedlearner.k8s.io             Local                        True        5h11m
v1beta1.admissionregistration.k8s.io   Local                        True        29h
v1beta1.alicloud.com                   Local                        True        29h
v1beta1.apiextensions.k8s.io           Local                        True        29h
v1beta1.apps                           Local                        True        29h
v1beta1.authentication.k8s.io          Local                        True        29h
v1beta1.authorization.k8s.io           Local                        True        29h
v1beta1.batch                          Local                        True        29h
v1beta1.certificates.k8s.io            Local                        True        29h
v1beta1.coordination.k8s.io            Local                        True        29h
v1beta1.events.k8s.io                  Local                        True        29h
v1beta1.extensions                     Local                        True        29h
...
[v1beta1.metrics.k8s.io                 kube-system/metrics-server   True        29h]
...
v1beta1.networking.k8s.io              Local                        True        29h
v1beta1.node.k8s.io                    Local                        True        29h
v1beta1.policy                         Local                        True        29h
v1beta1.rbac.authorization.k8s.io      Local                        True        29h
v1beta1.scheduling.k8s.io              Local                        True        29h
v1beta1.storage.k8s.io                 Local                        True        29h
v1beta2.apps                           Local                        True        29h
v2beta1.autoscaling                    Local                        True        29h
v2beta2.autoscaling                    Local                        True        29h

如果v1beta1.metrics.k8s.io所对应的API Service不是kube-system/metrics-server,检查是否由于安装Prometheus Operator覆盖导致。如果是覆盖导致的问题,可以通过部署以下的YAML模板进行恢复。

apiVersion: apiregistration.k8s.io/v1beta1
kind: APIService
metadata:
  name: v1beta1.metrics.k8s.io
spec:
  service:
    name: metrics-server
    namespace: kube-system
  group: metrics.k8s.io
  version: v1beta1
  insecureSkipTLSVerify: true
  groupPriorityMinimum: 100
  versionPriority: 100

如果非上述问题,请确认已在集群的运维管理>组件管理页面安装了metrics-server组件。更多信息,请参见metrics-server

原因二:滚动发布或扩容时无法获取数据

默认metrics-server的采集周期是1 min。刚扩容或更新完成后,metrics-server会有一段时间无法获取监控数据。请于扩容或更新后2 min左右进行查看。

原因三:未配置request字段

HPA默认是通过实际的利用率/request作为利用率的数值,因此可以检查Pod的resource字段中是否包含request字段。

原因四:指标名填写错误

请检查指标名(包括大小写)是否正确。例如,如果将HPA支持的cpu指标误写为CPU,监控数据current字段会显示为unknown

HPA扩缩容失败,指标获取异常怎么办?

HPA扩缩容失败可能是因为指标获取异常,HPA的监控数据current字段将显示为unknown。此时,HPA将无法获取用于决策扩缩容的指标,也就无法调整Pod数量。请参见节点自动伸缩FAQ排查问题原因,并采取对应的解决措施。

为何HPA在滚动时扩容出了多余的Pod?

社区Controller Manager在滚动发布时,对于没有监控数据的Pod,进行监控数据的补零操作,从而有一定的概率出现扩容出多余的Pod现象(多弹现象)。您可以通过以下配置防止多弹。

集群维度配置

您可以通过升级ACK提供的最新版metrics-server,并在metrics-server的启动参数上开启开关以防止多弹。

这是全局开关,设置后对集群内所有相关负载生效。

# 在metrics-server的启动参数中加入以下选项。
--enable-hpa-rolling-update-skipped=true  

工作负载维度配置

如果只想对指定的工作负载开启防止多弹,您可以使用以下两种方法防止多弹。

  • 方法一:通过在指定工作负载的模板中添加以下Annotation,可以在滚动发布时临时暂停HPA的判断生效。

    #工作负载的spec.template.metadata.annotations加入Annotation,滚动发布时临时暂停HPA的判断生效。
    HPARollingUpdateSkipped: "true"

    展开查看示例代码详情

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-deployment-basic
      labels:
        app: nginx
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: nginx
        template:
            metadata:
              labels:
                app: nginx
              annotations:
                HPARollingUpdateSkipped: "true"  # 跳过滚动发布时的HPA的效果。
            spec:
              containers:
              - name: nginx
                image: nginx:1.7.9
                ports:
                - containerPort: 80
  • 方法二:通过在指定工作负载的模板中添加以下Annotation,可以在应用发布开始阶段跳过设定的预热时间段。

    #工作负载的spec.template.metadata.annotations加入Annotation,在应用发布开始阶段跳过设定的预热的时间段。
    HPAScaleUpDelay: 3m # 3m仅为示例,具体时间段请按需设置

    展开查看示例代码详情

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-deployment-basic
      labels:
        app: nginx
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: nginx
        template:
            metadata:
              labels:
                app: nginx
              annotations:
                HPAScaleUpDelay: 3m  # m代表分钟,表示HPA在Pod创建3分钟后开始生效,可选单位为[s(秒),m(分)]。
            spec:
              containers:
              - name: nginx
                image: nginx:1.7.9
                ports:
                - containerPort: 80

HPA到达阈值为何不进行扩缩容?

HPA的扩缩容的触发条件不仅是CPU使用率或内存使用率超过阈值与低于阈值,需要额外考虑的是如果扩容或者缩容后,是否会再次触发缩容或者扩容,减少震荡的场景。

例如当您的扩容阈值设置为80%,如果有两个Pod的CPU目前使用率都是70%,这种情况下就不会缩容。因为缩容后可能单个Pod的CPU使用率高于80%,就会触发扩容,这样就会来回扩缩容出现震荡。

HPA采集周期如何配置?

对版本号大于v0.2.1-b46d98c-aliyun的metric-server,在metric-server的启动参数中设置--metric-resolution,例如--metric-resolution=15s即可。

CronHPA是否兼容HPA?如何兼容HPA?

CronHPA可以兼容HPA。阿里云容器服务ACK将CronHPA中的scaleTargetRef设置为HPA对象,然后通过HPA对象来寻找真实的scaleTargetRef,从而让CronHPA感知HPA的当前状态。CronHPA不会直接调整Deployment的副本数目,而是通过HPA来操作Deployment,这样可以避免HPA和CronHPA的冲突问题。关于CronHPA兼容HPA的更多信息,请参见实现CronHPA与HPA的协同

如何解决HPA启动时CPU或内存飙高造成扩容出多余Pod的多弹现象?

对于Java等需要预热的语言与框架而言,在容器刚启动的时候,有可能会出现分钟级别的CPU、内存飙高,可能会造成HPA的误触发。您可以通过将ACK提供的metrics-server组件升级至0.3.9.6版本以上,并在Pod的Annotation上增加开关防止误触发,解决此问题。关于如何升级metrics-server组件,请参见升级集群至v1.12版本前升级metrics-server组件

增加开关防止误触发部署示例YAML如下。

展开查看示例YAML详情

## 以Deployment为例
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment-basic
  labels:
    app: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
      annotations:
        HPAScaleUpDelay: 3m # m代表分钟,表示HPA在Pod创建3分钟后开始生效,可选单位为[s(秒),m(分)]。
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9 # Replace it with your exactly <image_name:tags>.
        ports:
        - containerPort: 80 

为什么HPA审计日志数值未达阈值但扩缩了?

问题原因

Pod水平自动扩缩控制器根据当前指标和期望指标来计算扩缩比例,期望副本数 = ceil(当前副本数 × (当前指标 / 期望指标))

从这个公式可以看出,期望副本数的准确度是由当前副本数、当前指标和期望指标的准确度来保证的。以HPA中应用广泛的资源指标为例,HPA获取当前副本数时,是先获取scaleTargetRef所定义的对象的scale子资源(subResources),然后将scalestatusSelector的值转化为labelselector,以此作为条件去匹配获取Pod。如果某个时刻,用这个条件获取到的Pod并不完全属于scaleTargetRef中定义的对象,那以此计算出的期望副本数就很可能不符合预期(比如实时指标低于阈值却扩容了)。

常见可能导致匹配Pod数目不准确的原因:

  • 滚动发布。

  • 给其他不属于scaleTargetRef中对象的Pod打标了相同Label。执行如下命令,可判断是否有其他Pod。

    kubectl get pods -n {命名空间名字} -l {scale子资源的status.Selector的值}

解决方案

  • 针对滚动发布,解决方案请参见节点自动伸缩FAQ

  • 针对给其他不属于scaleTargetRef中对象的Pod打上了相同Label。定位出这类Pod,如果还需要使用则更换为不同Label,如果不再需要,删除即可。

HPA缩容时,能够决定Pod缩容的顺序吗?

不能。HPA可以根据定义的指标自动增加或减少Pod的数量,但并不能决定哪些Pod应该首先被终止。Pod终止的顺序、优雅退出时间等特性均由管理Pod的Controller决定。

HPA使用率指标单位的含义是什么?

使用率指标通常为无单位的整数值或以m为单位的整数值,换算比例为1000m=1。例如,当tcp_connection_counts为70000m时,等同于70。

如果执行kubectl get hpa后发现target一栏为unknown怎么办?

请按照以下操作解决。

  1. 执行kubectl describe hpa <hpa_name>,确认HPA失效的原因。

    • 如果Conditions字段提示AbleToScaleFalse,请确认Deployment是否正常部署。

    • 如果Conditions字段提示ScalingActiveFalse,请继续执行下一步。

  2. 执行kubectl get --raw "/apis/external.metrics.k8s.io/v1beta1/"。如果返回为Error from server (NotFound): the server could not find the requested resource,请确认alibaba-cloud-metrics-adapter的启动状态。

    如alibaba-cloud-metrics-adapter状态正常,请确认HPA指标是否是Ingress相关指标。如果是Ingress相关指标,您需要提前部署日志服务组件。更多信息,请参见Nginx Ingress访问日志分析与监控

  3. 确认HPA指标填写正确。sls.ingress.route的值格式为<namespace>-<svc>-<port>

    • namespace:Ingress所在的命名空间。

    • svc:Ingress对应的Service名称。

    • port:Ingress对应Service的端口名称。

如何查找HPA支持的指标名称?

请参见阿里云HPA指标,以下列举为常用指标。

指标名称

描述

附加参数

sls_ingress_qps

指定的IngressRoute每秒查询率

sls.ingress.route

sls_alb_ingress_qps

ALB数据的IngressRoute每秒查询率

sls.ingress.route

sls_ingress_latency_avg

所有请求的延迟

sls.ingress.route

sls_ingress_latency_p50

50%请求的延迟

sls.ingress.route

sls_ingress_latency_p95

95%请求的延迟

sls.ingress.route

sls_ingress_latency_p99

99%请求的延迟

sls.ingress.route

sls_ingress_latency_p9999

99.99%请求的延迟

sls.ingress.route

sls_ingress_inflow

Ingress的流入带宽

sls.ingress.route

自定义了Nginx Ingress日志格式后如何进行适配操作?

您可以参见基于阿里云组件指标的容器水平伸缩了解如何使用SLS Ingress指标进行容器水平伸缩,需要您开启并正确配置集群中Nginx Ingress日志接入阿里云日志服务。

  • 创建集群时,日志服务默认开启。当您保持默认值不变,集群创建成功后,您可以在日志服务控制台查看Nginx Ingress的访问日志分析报表和监控Nginx Ingress实时状态。

  • 在创建集群时,若您手动关闭了日志服务,集群创建完成后,如果想要使用SLS Ingress指标进行容器水平伸缩,请重新开启或配置日志服务。详细信息,请参见Nginx Ingress访问日志分析与监控

  • 当您需要自定义Nginx Ingress日志格式时,由于集群中初次开启日志服务部署AliyunLogConfig的CRD只针对ACK默认Ingress Controller中的日志格式生效,若您修改过Ingress Controller的访问日志格式,请修改CRD配置中的正则表达式提取processor_regex部分。具体操作,请参见通过DaemonSet-CRD方式采集容器日志