在 Kubernetes 的资源管理模型中,长期存在一个看似"合理"、但在生产环境中代价极高的设计:
Pod 的 CPU / 内存一旦修改,就必须重建 Pod。
这意味着:
- 连接中断
- 状态丢失
- 冷启动
- 调度不确定性
而这些,恰恰是在线服务最不能承受的代价。
在 Kubernetes 1.35 中,这一历史限制终于被正式解除:
In-Place Pod Resize(Pod 原地扩容)进入 GA(General Availability)阶段。
这是一次真正改变运维方式的能力升级。
镜像拉取解决方案: https://zhiliaole.top/archives/1763544164789
一、什么是 Pod 原地扩容?
官方能力的工程化定义:
在不重启 Pod、不重启容器、不重新调度的前提下,在线修改 Pod 的 CPU / 内存 requests 与 limits。
一眼看懂的变化对比
| 维度 | K8s 1.35 之前 | K8s 1.35 之后 |
|---|---|---|
| 修改 CPU / 内存 | Pod 必须重建 | Pod 不变 |
| IP / 长连接 | 中断 | 保持不变 |
| 运行状态 | 丢失 | 完整保留 |
| 调度行为 | 重新调度 | 不调度 |
二、支持与不支持的修改范围(非常关键)
✅ 支持原地修改的资源
| 资源项 | 是否支持 | 说明 |
|---|---|---|
cpu.requests |
✅ | 即时更新 cgroup |
cpu.limits |
✅ | 立刻生效 |
memory.requests |
✅ | 影响 QoS / 调度 |
memory.limits |
✅ | 扩容立即生效 |
❌ 不支持的修改项
| 项目 | 原因 |
|---|---|
| Pod QoS Class 变更 | 会破坏调度与回收语义 |
| GPU / HugePages | 节点级硬资源绑定 |
| 容器数量 / 镜像 | Pod 结构性变更 |
| 节点资源不足时扩容 | 保证失败是安全的 |
核心原则:
👉 原地扩容只解决「资源弹性」,不解决「Pod 形态变化」。
三、CPU 与内存的行为差异(生产必读)
很多事故,来自于不了解 CPU 和内存 resize 行为差异。
行为对比表
| 维度 | CPU | 内存 |
|---|---|---|
| 扩容生效 | 立即 | 立即 |
| 缩容策略 | 立即 | 渐进式回收 |
| OOM 风险 | 极低 | 显著降低 |
| 实现机制 | cgroup quota | cgroup memory |
Kubernetes 对内存缩容采用了保守策略 :
宁可慢一点,也不制造 OOM 事故。
四、与传统资源调整方式的对比
不同方案能力对比
| 方案 | 是否重启 | 是否断连 | 是否重调度 | 典型适用场景 |
|---|---|---|---|---|
| Deployment 滚动更新 | ✅ | 可能 | ✅ | 应用升级 |
| 旧版 VPA | ✅ | 是 | ✅ | 离线任务 |
| 手工删 Pod | ✅ | 是 | ✅ | 紧急处理 |
| 原地扩容(1.35) | ❌ | ❌ | ❌ | 在线服务 |
五、使用示例:如何真正用起来?
下面给出 可直接在 1.35 集群中使用的示例。
示例 1:直接对运行中的 Pod 进行原地扩容
原始 Pod 配置
yaml
apiVersion: v1
kind: Pod
metadata:
name: demo-app
spec:
containers:
- name: app
image: nginx
resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
cpu: "1"
memory: "1Gi"
原地扩容 CPU 和内存
vbnet
kubectl patch pod demo-app -p '
spec:
containers:
- name: app
resources:
requests:
cpu: "2"
memory: "2Gi"
limits:
cpu: "4"
memory: "4Gi"
'
👉 结果:
- Pod 不会重建
- 容器 不会重启
- 连接 不会中断
示例 2:查看扩容状态
sql
kubectl describe pod demo-app
你会看到类似状态:
ContainerResizeInProgressContainerResizeCompleted- 或
ResizeFailed
示例 3:节点资源不足时的行为
| 场景 | 行为 |
|---|---|
| 节点剩余资源不足 | 扩容失败 |
| Pod 是否被杀 | ❌ 不会 |
| 原资源配置 | 保持不变 |
| 可观测性 | 状态明确可见 |
这保证了失败是安全的、可回滚的。
六、与 VPA 结合:这才是"完全体"
原地扩容并不是替代 VPA,而是让 VPA 真正进入生产可用状态。
VPA 行为对比
| 维度 | 1.35 之前 | 1.35 之后 |
|---|---|---|
| 资源推荐 | 支持 | 支持 |
| 执行方式 | 删 Pod | 在线 resize |
| 业务影响 | 明显 | 几乎无感 |
| 适用场景 | 谨慎 | 推荐 |
这对以下服务是质变:
- JVM / Spring 服务
- 长连接网关
- 在线推理 / AI 服务
- 有状态中间件
七、对平台与运维团队的长期影响
运维方式变化
| 过去 | 现在 |
|---|---|
| 改资源 = 变更窗口 | 改资源 = 日常操作 |
| 高峰期不敢动 | 高峰期可调 |
| 靠经验估算 | 动态修正 |
成本与容量管理
| 维度 | 改变 |
|---|---|
| 初始资源 | 可更保守 |
| Over-Provision | 明显降低 |
| 集群利用率 | 明显提升 |
八、是否可以直接用于生产?
推荐条件
| 条件 | 是否必须 |
|---|---|
| Kubernetes ≥ 1.35 | ✅ |
| containerd 新版本 | ✅ |
| 节点有资源冗余 | ✅ |
| 依赖 GPU / HugePages | ❌ |
该特性已 GA,意味着:
- API 稳定
- 行为可预期
- 支持长期维护
九、总结
Pod 原地扩容是 Kubernetes 资源管理能力的一次"质变"。
它让 Kubernetes:
- 从"只能靠重启解决问题"
- 走向"真正的在线资源调度系统"
如果说 Kubernetes 早期解决的是
"如何把应用跑起来" ,
那么 1.35 的原地扩容解决的是
"如何让应用长期、稳定、优雅地跑下去" 。