编程 In-Place Pod Resize:v1.33 默认开启后,如何不重建 Pod 调整 CPU/内存

2026-10-08 00:03:55

In-Place Pod Resize:v1.33 默认开启后,如何不重建 Pod 调整 CPU/内存

In-Place Pod Resize(KEP-1287,In-Place Update of Pod Resources,也叫 In-Place Pod Vertical Scaling / InPlacePodVerticalScaling)的目标很直接:不重建 Pod,直接改 Pod/容器 的 CPU 与内存 requests/limits,尽量避免重启容器带来的中断。

  • KEP-1287:
  • 容器级 resize 文档:
  • Pod 级 resize 文档:

演进阶段

  • v1.27:alpha,需要显式打开 InPlacePodVerticalScaling feature gate。
  • v1.33:进入 Beta 并默认启用。
  • KEP-1287 计划在 Kubernetes v1.35 GA。

触发方式:/resize 子资源

resize 只能通过新的 /resize 子资源触发。/resize 接受 Update 与 Patch 动词,请求和响应都是整个 Pod 对象,但只允许修改特定字段(容器 resources 的 cpu/memory 请求与限制)。

kubectl 需要 v1.32+ 才支持 --subresource resize,旧版本会报 invalid subresource。

kubectl patch pod resize-demo -n qos-example --subresource resize --patch \
'{"spec":{"containers":[{"name":"pause", "resources":{"requests":{"cpu":"800m"}, "limits":{"cpu":"800m"}}}]}}'

字段语义:期望值 vs 实际值

spec.containers[*].resources 现在代表期望值,且对 cpu/memory 可变,不能再当作容器实际生效资源的依据。

实际生效值要看 status.containerStatuses[*].resources(kubelet 通过 CRI 查询 runtime 得到)。新增的 status.containerStatuses[*].allocatedResources 表示调度给该 Pod 的节点资源。status.containerStatuses[].restartCount 可用来确认是否真的发生了重启。

resizePolicy

spec.containers[*].resizePolicy 是 []v1.ContainerResizePolicy,按资源名(cpu/memory)声明是否允许不重启:

  • NotRequired(默认;v1.33 起语义细化,KEP 中改名为 PreferNoRestart):尽量不重启、就地应用。
  • RestartContainer:应用新资源值需要重启容器(比如 Java 进程要改 -Xmx)。

如果同时改 CPU 和 memory,而 memory 的策略是 RestartContainer,容器就会重启。

状态与条件

v1.27 曾有 status.resize 字段,取值 Proposed / InProgress / Deferred / Infeasible。v1.33 起改用两个 Pod condition 跟踪:

  • PodResizePending:带 reason/message。Infeasible 表示节点永远无法满足;Deferred 表示暂时放不下,会重试。
  • PodResizeInProgress:kubelet 已接受并分配资源,正在应用。

Kubelet 处理逻辑与 CRI 语义

kubelet 先检查期望资源能否放进节点可分配资源:计算节点上除被 resize Pod 外所有 Pod 已分配资源之和,再加上被 resize Pod 的新期望 requests。

  • 放得下:接受请求,更新 allocatedResources,加上 PodResizeInProgress,调用 CRI UpdateContainerResources 更新容器限制;全部成功后把 status 的 Resources 更新为新值并移除该 condition。
  • 放不下:标记 Deferred(持续重试)或 Infeasible(永远无法满足)。

CRI 自 v1.20 起就提供 UpdateContainerResources,containerd 与 CRI-O 均已实现,且该调用必须幂等。v1.33 起 CRI 合约更新:runtime 不应为了调整资源而故意重启容器;若必须重启才能 resize,runtime 应返回错误(best-effort,无强制约束)。

v1.33 的变化

  • 用 Pod condition 替换 status.resize。
  • 禁止内存 limit 下调(memory limit downsizing 在后台被禁止)。
  • ResizeRestartPolicy 的 NotRequired 改名 PreferNoRestart,并更新 CRI UpdateContainerResources 合约。
  • 新增 Pod 级 AllocatedResources。
  • resize 执行改为边缘触发(edge-triggered)。
  • ResizePolicy 变为不可变(immutable)。

Pod 级资源 resize

Pod 的 spec.resources 定义该 Pod 全部容器的聚合资源上界,可以直接修改运行中 Pod 的这个聚合并就地生效。它不需要 Pod 级重启策略:Pod 级资源只是 Pod cgroup 的总约束,不直接管理容器内运行时。是否重启单个容器,仍由容器级 resizePolicy 决定。

校验规则:

  • 只有 Pod 级 requests >= 所有容器对应 requests 之和时,才允许 resize。
  • 容器 limit <= Pod 级 limit 才允许。
  • 容器 limit 之和可以超过 Pod 级 limit(允许 Pod 内容器共享资源)。
apiVersion: v1
kind: Pod
metadata:
name: pod-level-resize-demo
spec:
containers:
- name: pause
image: registry.k8s.io/pause:3.9
resizePolicy:
- resourceName: cpu
restartPolicy: NotRequired
- resourceName: memory
restartPolicy: RestartContainer
resources:
requests:
cpu: 100m
memory: 100Mi
- name: nginx-server
image: registry.k8s.io/nginx:latest
resizePolicy:
- resourceName: cpu
restartPolicy: RestartContainer
- resourceName: memory
restartPolicy: RestartContainer
resources:
requests:
cpu: 200m
memory: 200Mi
limits:
cpu: 200m
memory: 200Mi

把 Pod 级 CPU 调大到 300m:

kubectl patch pod pod-level-resize-demo --subresource resize --patch \
'{"spec":{"resources":{"requests":{"cpu":"300m"}, "limits":{"cpu":"300m"}}}}'

memory-backed emptyDir 的 sizeLimit

打开 InPlacePodVerticalScalingMemoryBackedVolumes feature gate 后,可以通过 Pod 的 /resize 子资源更新 medium: Memory 的 emptyDir 卷 sizeLimit,不需要重启容器或重建 Pod。前提是节点运行 cgroup v2;cgroup v1 节点会被判为 infeasible 并拒绝。磁盘型 emptyDir 与持久卷不能通过该子资源调整。

已知限制

  • 只有 CPU 和内存可以 resize。
  • Static CPU management policy 与本特性不兼容。
  • containerd 低于 v1.6.9 缺少完整 CRI 支持,resize 会卡在 InProgress 且 status 不更新。
  • Windows Pod 不支持就地 resize。
  • resize 与其它 Pod 更新可能竞态,导致延迟。
  • status 反映新资源可能有延迟。

VPA 集成

resize 失败的多种 failure mode 会冒泡给 VPA(如 InPlaceOrRestart 等);VPA 对无法就地完成的 resize 会按策略重建 Pod。

排障对照

现象含义处理方向
PodResizePending + Deferred节点当前可分配资源放不下新期望值等待重试,或腾出节点资源
PodResizePending + Infeasible节点永远无法满足(如 cgroup v1 上调整 memory-backed emptyDir sizeLimit)换节点/换特性路径,别继续等
PodResizeInProgress 长期不退kubelet 已接受,但 container runtime 未完成检查 containerd 版本(< v1.6.9 会卡住)
status 资源未更新status 更新有延迟,或 resize 未真正落地对比 status.containerStatuses[*].resources 与 allocatedResources
restartCount 增加该容器按 resizePolicy 走了 RestartContainer属预期行为,非故障

取舍上:CPU 通常能用 NotRequired/PreferNoRestart 平滑调整;内存若受运行时参数约束(如 JVM 堆),只能接受 RestartContainer;内存 limit 下调在 v1.33 起被禁止,需要降内存上限时只能走重建路径。

推荐文章

程序员茄子在线接单