← 返回博客
2026-10-28 08:00:01

K8s集群管理实战:从部署到自动伸缩

K8s集群管理实战:从部署到自动伸缩

一个典型的翻车现场:电商大促前,运维把 Deployment 的 replicas 从 4 手改成 20,Pod 起来了,流量也进来了,结果 HPA 同时也在扩,两边打架,节点资源被挤爆,一批 Pod 卡在 Pending。问题不在 HPA,在于没人给扩容定过规则。这篇从一次部署开始,把资源请求、HPA、节点扩容串成一条线。

一、先把 Deployment 写对

自动伸缩的前提是 Pod 有明确的资源请求。没有 requests,HPA 算出来的利用率是空的,调度器也不知道该把 Pod 放哪。先看一个能用的 Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-server
spec:
  replicas: 3
  selector:
    matchLabels: { app: api-server }
  template:
    metadata:
      labels: { app: api-server }
    spec:
      containers:
      - name: api
        image: registry.example.com/api-server:1.8.2
        ports: [{ containerPort: 8080 }]
        resources:
          requests: { cpu: 250m, memory: 256Mi }
          limits:   { cpu: 500m, memory: 512Mi }
        readinessProbe:
          httpGet: { path: /healthz, port: 8080 }
          initialDelaySeconds: 5
          periodSeconds: 10

关键点在 requests 和 limits 的比例。CPU 设成 1:2 是常见做法,留出突发空间;内存别这么干,内存超 limit 直接被 OOMKill,比例设 1:1 或 1:1.2 更稳。readinessProbe 必须配,否则新 Pod 还没准备好就被塞流量,扩容反而制造 502。

另一个坑:image 用了固定 tag 而不是 latest,这是故意的。滚动更新时 tag 不变,K8s 不会重新拉镜像,你会以为发布成功了其实跑的还是旧代码。

二、HPA 别只看 CPU

Deployment 跑起来之后,流量一涨,手动改副本数就跟不上了。上 HPA:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: api-server-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: api-server
  minReplicas: 3
  maxReplicas: 30
  metrics:
  - type: Resource
    resource:
      name: cpu
      target: { type: Utilization, averageUtilization: 60 }
  - type: Pods
    pods:
      metric: { name: http_requests_per_second }
      target: { type: AverageValue, averageValue: "200" }
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 30
      policies:
      - type: Percent
        value: 100
        periodSeconds: 60
    scaleDown:
      stabilizationWindowSeconds: 300

这里的重点是 behavior。默认 HPA 缩容窗口是 5 分钟,扩容没有限制,流量尖峰时可能一口气翻几倍。scaleUp 设成 60 秒内最多翻倍,避免把节点打爆;scaleDown 留 300 秒稳定窗口,防止指标抖动导致副本数上上下下。自定义指标 http_requests_per_second 需要 Prometheus Adapter 把指标喂给 HPA,CPU 指标只是兜底。

踩坑提醒:averageUtilization: 60 是相对 requests 算的。requests 写 250m,60% 就是 150m 触发扩容。如果 requests 填得太小(比如 50m),HPA 会疯狂扩容,因为随便一点流量就超过阈值。

三、Pod 扩了,节点装不下怎么办

HPA 把副本从 3 拉到 30,节点只剩 2 个,多出来的 Pod 全 Pending。这时候需要节点层面的弹性,Cluster Autoscaler 或 Karpenter 二选一。

维度Cluster AutoscalerKarpenter
触发方式监听 Pending Pod监听 Pending Pod + 直接调度
节点选择按 NodeGroup 预设规格按 Pod 需求实时挑实例类型
缩容有空节点才缩主动合并、驱逐
配置复杂度低,云厂商托管常见略高,需自建 CRD

小集群用 Cluster Autoscaler 够用,配好 NodeGroup 的 min/max 就行。Karpenter 适合实例类型多、成本敏感的团队,它能在几十秒内起一台刚好装下 Pod 的机器,不用等 NodeGroup 预设。选型看一点:你的节点规格是不是长期固定?固定就 CA,不固定就 Karpenter。

四、把这条链接起来验证

部署完别急着庆祝,跑一遍压测看链路是否通:

kubectl get hpa api-server-hpa -w
kubectl get pods -l app=api-server -w
kubectl get nodes -w

三个窗口一起看。正常表现是:HPA 的 TARGETS 先涨,Pod 数跟着涨,节点数最后涨。如果 Pod 一直 Pending 而节点没动静,八成是 Cluster Autoscaler 的 NodeGroup 到了 max 上限,或者 Pod 的 requests 超过了任何可用实例规格——后者最隐蔽,Pod 永远调度不上去。

再补一条:给 HPA 加 minReplicas 不低于 3,单可用区挂掉时还有余量。大促前把 maxReplicas 提前调高,别等流量来了再改,HPA 读的是当前 spec,改完要几十秒才生效。


核心收获就一句:自动伸缩不是打开 HPA 就完事,requests 定基准、HPA 定节奏、节点扩容兜底,三者缺一个就会在流量高峰翻车。下一步动作很具体——先给现有 Deployment 补上 requests 和 readinessProbe,再开 HPA 观察一周指标,最后决定要不要接节点自动扩容。

本文关键词:Kubernetes、HPA、Cluster Autoscaler、Karpenter、Deployment