本文介绍使用工作负载伸缩功能(包括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的数据源的情况。返回的示例数据如下。
如果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"
方法二:通过在指定工作负载的模板中添加以下Annotation,可以在应用发布开始阶段跳过设定的预热时间段。
#工作负载的spec.template.metadata.annotations加入Annotation,在应用发布开始阶段跳过设定的预热的时间段。 HPAScaleUpDelay: 3m # 3m仅为示例,具体时间段请按需设置
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如下。
为什么HPA审计日志数值未达阈值但扩缩了?
问题原因
Pod水平自动扩缩控制器根据当前指标和期望指标来计算扩缩比例,期望副本数 = ceil(当前副本数 × (当前指标 / 期望指标))
。
从这个公式可以看出,期望副本数的准确度是由当前副本数、当前指标和期望指标的准确度来保证的。以HPA中应用广泛的资源指标为例,HPA获取当前副本数时,是先获取scaleTargetRef
所定义的对象的scale
子资源(subResources
),然后将scale
的status
的Selector
的值转化为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
怎么办?
请按照以下操作解决。
执行
kubectl describe hpa <hpa_name>
,确认HPA失效的原因。如果
Conditions
字段提示AbleToScale
为False
,请确认Deployment是否正常部署。如果
Conditions
字段提示ScalingActive
为False
,请继续执行下一步。
执行
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访问日志分析与监控。
确认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方式采集容器日志。