编程 K8s 1.35 原地扩缩容 GA:改 requests/limits 不用重建 Pod,但内存缩容仍可能要重启

2026-11-14 21:05:25

K8s 1.35 原地扩缩容 GA:改 requests/limits 不用重建 Pod,但内存缩容仍可能要重启

Kubernetes v1.35 于 2025-12-17 发布,共 60 项增强:17 项 stable、19 项 beta、22 项 alpha。其中与日常运维关系最直接的一项是 In-place update of Pod resources 达到 GA(KEP #1287,SIG Node)。

改 resources 不再触发 Pod 重建

GA 之后,直接修改运行中 Pod 的 resources.requests 与 resources.limits 即可调整 CPU 和内存,不需要删除重建 Pod,也不需要重启容器。此前的原地更新只覆盖基础设施层面的 requests/limits 记录,现在真正落到容器的 cgroup 限制上,可以做无中断的垂直扩缩。

apiVersion: v1
kind: Pod
metadata:
  name: resize-demo
spec:
  containers:
  - name: app
    image: nginx
    resources:
      requests:
        cpu: 500m
        memory: 256Mi
      limits:
        cpu: "1"
        memory: 512Mi
    resizePolicy:
    - resourceName: cpu
      restartPolicy: NotRequired
    - resourceName: memory
      restartPolicy: RestartContainer

resizePolicy 按资源维度声明:NotRequired 表示原地调整,RestartContainer 表示需要重启容器才能生效。CPU 通常可以设为 NotRequired,因为调整 CPU 份额可以即时生效;内存则更复杂。

内存缩容的边界:resizePolicy 与容器当前用量

缩容内存受两个条件约束:

  • resizePolicy 中该资源的 restartPolicy;
  • 容器当前的实际内存用量。

调低内存 limit 时,如果新 limit 低于容器当前已用量,内核无法把已经分配出去的页收回,这个 resize 请求就无法原地完成。此时容器必须重启,才能让新 limit 生效。也就是说,扩内存基本是安全的,缩内存则可能触发重启,取决于当时负载的实际用量。这一点决定了不能把原地缩容当成完全无感的操作来用。

用 generation 确认 kubelet 真的处理了

metadata.generation 在 v1.33 作为 alpha 引入,v1.35 稳定:每次 Pod spec 更新都会递增。与之配套的 status.observedGeneration 表示 kubelet 已经看到并处理到了哪个 generation,Pod 的各个 condition 上也各自带有 observedGeneration。

kubectl get pod resize-demo \
  -o jsonpath='{.metadata.generation} {.status.observedGeneration}'

两个值相等,说明 kubelet 已经处理完这次 spec 变更;不相等说明还在处理,或者被卡住了。判断原地扩缩容是否真正完成,直接比较这两个值即可,此外还要检查 condition 上的 observedGeneration,避免只看到 API 对象已更新就误以为 cgroup 已经改好。

用 patch 改运行中的 Pod

kubectl patch pod resize-demo --subresource resize --type=merge -p '
{"spec":{"containers":[
  {"name":"app","resources":{
    "requests":{"cpu":"800m","memory":"256Mi"},
    "limits":{"cpu":"2","memory":"512Mi"}}}
]}}'

注意这里改的是 Pod 本身,而不是工作负载模板。Deployment 的 spec.template 里改 resources 仍然走滚动更新,Pod 照样重建,原地扩缩容不会改变这条路径。

还没 GA 的部分

Pod 级 resources(KEP #5419)仍是 alpha,不能当作可用能力依赖。它和容器级 resources 是两个不同的字段层级,本文的结论只对容器级生效。

与 HPA、VPA、ResourceQuota 的关系

  • HPA 调整的是副本数,不涉及单个 Pod 的 resources,原地扩缩容对它没有影响。v1.35 里 HPA 另有一项 beta:可按资源设置 tolerance(默认开启)。
  • VPA 会修改 Pod 的 resources,原地扩缩容正是它避免重建 Pod 的路径,但内存缩容同样受上面两个条件约束。
  • ResourceQuota 按 requests/limits 记账。原地扩容后,Pod 的 requests 合计不能超过命名空间配额,超出的更新会被 apiserver 直接拒绝,不会进入 resize 流程。

其它与本次发布相关的变更

  • Pod certificates(KEP #4317)Beta:kubelet 生成密钥、通过 PodCertificateRequest 申请证书并写入 Pod 文件系统,apiserver 在 admission 时强制节点限制。
  • Node declared features(KEP #5328)Alpha:Node 通过 .status.declaredFeatures 上报支持的特性,供 scheduler/admission 使用。
  • PreferSameNode trafficDistribution 新增;原 PreferClose 改名 PreferSameZone,保留兼容。
  • Job API 新增 managedBy(stable),用于 MultiKueue 等外部控制器同步 Job 状态。
  • Downward API 暴露节点拓扑标签(beta):topology.kubernetes.io/zone、topology.kubernetes.io/region 可注入为环境变量或 projected volume,升级后每个 Pod 会多出若干标签。
  • 存储版本迁移原生支持(beta 默认开启)。
  • KYAML beta 默认开启,可用 KUBECTL_KYAML=false 关闭。
  • Pod user namespaces 支持。
  • image volume 类型默认启用,需要 containerd 2.1+。
  • Kubelet 对已缓存镜像做凭据校验(beta 默认开启,KubeletEnsureSecretPulledImages 可关,imagePullCredentialsVerificationPolicy 配置严格程度)。
  • 容器级 restartPolicy / restartPolicyRules(beta 默认开启)。
  • Gang scheduling:Workload API 与 PodGroup(alpha)。
  • 受限 impersonation(alpha,ConstrainedImpersonation)。
  • /flagz 与 /statusz 支持 JSON 输出。
  • cgroups v1 支持默认禁用。
复制全文 生成海报 Kubernetes 运维 容器

推荐文章

程序员茄子在线接单