遇到 HPA 不扩缩,很多人第一反应是改配置,或者调整资源阈值。我的建议是先别急,先把 HPA 当前的状态和它依赖的指标链路看一遍。因为 Pod 数量不增加,往往不是 HPA 本身算不出来,而是它根本拿不到指标,或者指标一直没达到目标值。
先确认 HPA 自己有没有在正常工作
先看 HPA 的全局描述,用 kubectl get hpa 看每列输出。重点看 TARGETS 列:如果显示 unknown 或者没有数字,说明指标还没采集到;如果显示了百分比但一直低于目标,说明 HPA 在正常工作,只是还没达到扩容条件。再用 kubectl describe hpa YOUR_HPA 看 Events 和 Conditions,通常能看到类似 ScalingActive、AbleToScale 这些状态。如果 ScalingActive 是 False,往往是因为指标解析失败;如果 AbleToScale 是 False,可能是副本数限制或资源配额问题。
这里有一个关键点:HPA 不会因为 Pod 数量不增加就报错,它只会把条件标成 False。所以先看条件,能少走很多弯路。
检查 metrics-server 是否真的活着
HPA 默认从 metrics-server 拿指标。先看 metrics-server 的 pod 是否正常,再看它的日志——不过先看 pod 状态更稳妥。执行 kubectl get pods -n kube-system | grep metrics-server,确认不是 CrashLoopBackOff 或 Pending。如果 pod 正常,再用 kubectl top nodes 和 kubectl top pods 验证指标采集是否正常。如果 top 命令能返回数据,说明 metrics-server 基本没问题;如果它报 error 或者没有输出,那问题就出在采集链路上。
很多情况下,top 命令返回不了数据的原因是证书问题。metrics-server 访问 kubelet 时需要验证证书,如果你用的集群在安装时没配置好 CA,通常会在日志里出现 x509 或 tls 错误。
从 metrics-server 日志里找线索
如果 top 命令无数据,直接看 metrics-server 日志。先获取 pod 名字,然后 kubectl logs -n kube-system metrics-server-XXXX。常见错误有两类:一类是 HTTPS TLS 握手失败,另一类是权限不足。TLS 错误多半和 kubelet 端口有关,老版本的 kubelet 默认监听 10255,但新版本默认监听 10250,而且需要证书。metrics-server 必须带 --kubelet-preferred-address-types=InternalDNS,InternalIP 和 --kubelet-insecure-tls(或者在受信任环境下使用),否则会连不上。不过不建议直接给 metrics-server 加 --kubelet-insecure-tls,除非是内部测试环境,生产环境应该正确配置 CA。
如果日志里出现 forbidden,那要看 metrics-server 的 RBAC 是否完整。通常需要 ClusterRole 绑定,允许它访问 nodes/metrics 和 pods/metrics。这些配置在部署文件里能看到。
确认 HPA 定义的指标和资源名称是否匹配
指标采集正常不代表 HPA 就能用。如果 HPA 里写的是 cpu,但容器没有声明 requests.cpu,HPA 是无法计算的。Kubernetes 的 HPA 必须先有资源请求,否则 metrics-server 拿不到百分比基数。同样,如果你用自定义指标,要确认指标名称是否和 metrics-server 或外面聚合的 API 一致。用 kubectl describe hpa 看 Current Metrics 部分,如果出现 unknown,大概率是资源名称对不上。
还要注意一个容易被忽略的地方:HPA 默认查询 metrics.k8s.io API,这个 API 通常由 metrics-server 提供。用 kubectl get apiservice v1beta1.metrics.k8s.io 检查是否可用。如果 unavailable,HPA 会一直拿不到指标。
看 HPA 的事件和副本限制
如果以上都正常,但 Pod 还是不增加,再看 HPA 的行为策略。默认 HPA 有缩放冷却时间,可能你想它扩容,但它还在等待观察期。这不是故障,只是策略。另外确认一下 Deployment 的 replicas 上限,如果 HPA 的 maxReplicas 设得比当前数量还小,自然没法增加。HPA 的事件里也会写清楚,比如 FailedRescale 是因为达到 max limit。
最后再提醒一个容易踩的坑:如果你的 Deployment 有多个容器,HPA 计算 CPU 目标时用的是所有容器 CPU 请求的总和,而不是某个容器的。如果资源请求设得太低或太高,都会影响扩容触发。所以配置 HPA 前,先想清楚目标值到底代表什么。
排查到这里,问题基本就定位了。如果还有异常,再检查一下集群聚合层是否正常,或者直接重装 metrics-server。重装前最好把原来的配置备份好,避免引入新的变量。