大数跨境

详解K8s 1.33原地扩缩容功能:原理、实践、局限与发展

详解K8s 1.33原地扩缩容功能:原理、实践、局限与发展 云妙算
2025-05-27
1

点击上方卡片,关注「CloudPilot AI」

回复关键词【案例】

查看奥迪、Grafana等名企的云端降本实践


原文链接:

https://itnext.io/kubernetes-1-33-resizing-pods-without-the-drama-finally-88e4791be8d1

编译:CloudPilot AI


你是否有过这样的经历?


精心配置了 Kubernetes 的 Pod,设置了“刚刚好”的 CPU 和内存(至少你当时是这么想的),结果应用不是资源紧张喘不过气,就是像“双十一”抢购一样疯狂抢占资源。


过去,唯一的解决办法就是重启整个 Pod ——这种破坏性的做法就像用黄油刀做开胸手术,而 SRE 团队正透过手术室的窗户盯着看,紧张但无能为力。


不过,近期发布的 Kubernetes 1.33 版本带来了我们梦寐以求的功能:原地 Pod 垂直伸缩(In-place Pod Vertical Scaling)


在 Kubernetes 1.33 中该功能已升级为 Beta 版,并且默认启用。


你不再需要手动启用特性,这使得它在生产环境中更加易用。


可查阅 Kubernetes 官方文档:

https://kubernetes.io/docs/tasks/configure-pod-container/resize-container-resources/


这意味着你可以调整正在运行的 Pod 的 CPU 和内存配置,而无需重启


如果你一直在琢磨垂直自动伸缩(VPA)的细节,那么这次更新会令人格外兴奋——虽然 VPA 的“重新创建”(recreate)模式在理论上很美好,但实操过程中常常状况百出。


原地 Pod 垂直伸缩提供了一种更加优雅的资源调整方式,或许能让 VPA 的体验更加顺滑。


01/

为什么这项更新如此重要?


对 Kubernetes 用户来说,这是一项革新式的重要更新。


假设当应用突然遇到流量激增的高峰期时,过去的做法是要么预留大量资源,但成本很高;要么触发 VPA 更新,导致 Pod 重启。


而现在,通过这项更新可以直接实时增加 CPU 和内存配置不会造成应用卡顿,用户侧几乎无感。


尤其对于那些有状态应用、数据库,或要求持续可用性的服务而言,原地扩缩容能大幅降低宕机时间提供更加无缝的弹性伸缩体验


为什么这项特性能实现这一效果?我们来简单分析一下:


1. 告别 Pod 重启

过去每次调整资源,服务是否宕机全看运气。VPA 会像一个过于热情的保安一样把 Pod 赶下线。现在呢?扩容丝滑得像咖啡师拉花。


2. 成本优化魔法

不再需要为了“以防万一”的情况,而过度配置资源。


正如 Sysdig 团队指出的,这实现了真正的按需付费云经济。


3. 拯救有状态工作负载

数据库不再需要在“性能”与“可用性”之间做选择了。这就像在行驶的汽车上换轮胎 ——虽然有风险,但现在已经可行!


02/

实际应用场景


以下是一些具体的应用场景,从中可以窥见这一功能的实用性:


  • 数据库工作负载

当你的 PostgreSQL 实例突然需要更多 RAM 来处理营销部门的数据分析的请求时,你可以在不中断正在进行的交易或清空连接池的情况下扩展资源。用户再也不会看到“请稍后再试”的消息了!


  • Node.js API 服务

Node.js 应用可以在无需重启的情况下动态使用新增的 CPU 和内存。因此非常适合使用原地扩缩容来应对流量激增。


  • 机器学习推理服务

TensorFlow Serving 等服务在处理更大批量或更复杂模型时,可以实时扩容,无需中断正在进行的推理请求。


  • 服务网格 Sidecar

在 Istio 之类的服务网格中, Envoy 代理现在可以根据流量模式动态调整资源,而不会干扰主应用容器的运行。


关于 Java 应用的提醒:

对于基于 JVM 的应用,仅仅调整 Pod 的内存配置并不会自动改变 JVM 的堆(heap)大小,后者通常是在启动时通过-Xmx等参数设置的。虽然原地 Pod 调整可以优化非堆内存和 CPU 资源的使用,但如果想要充分利用扩容后的内存限制,Java应用通常需要调整配置并重启。因此,对于不希望重启的场景来说,Java 应用并不适合进行内存扩容。


03/

技术揭秘:

Kubernetes 如何灵活调整资源


接下来,让我们深入探讨技术细节,下图展示了 K8s 资源调整的工作流程:



实际发生了什么

1. 可变资源字段已支持动态更新

得益于这个 issue(链接见下方),Pod 规范中的resources.requestsresources.limits字段现在支持动态修改,无需再为 Spec 是否不可变而争论了。


https://github.com/kubernetes/enhancements/issues/1287


2. Kubelet 的评估机制

当你提交 patch 时,kubelet 会评估:

(节点可用资源总量) - (当前所有容器资源分配总和) ≥ (新请求资源)?

满足条件就允许变更,否则返回PodResizePending 


3. CRI 协议握手

kubelet 会通过容器运行时接口 (CRI) 与 containerd 或 CRI-O 通信:“给这个容器加点资源”。运行时随后会调整对应的 cgroup,无需重启,轻松搞定。这是异步、非阻塞的流程,Kubelet 可以在处理资源调整的同时继续执行其他重要任务。


4. 状态更新提示

在执行 kubectl describe pod 时,你会看到两个新状态:

  • PodResizePending —— “节点当前资源不足,稍后再试。”

  • PodResizeInProgress —— “正在处理,资源调整中。”


容器运行时兼容性

这一功能在不同的容器运行时中均可使用,但支持程度有差异,情况如下:

  • containerd(v1.6+):完全支持,可以平滑调整 CPU 和内存的 cgroup

  • CRI-O(v1.24+):完全支持原地扩缩容

  • Docker:支持有限,因为它正在逐步退出 Kubernetes


注意:cgroup v2 在内存回收方面比 cgroup v1 更强大,特别是对于内存限制减少的情况下。


04/

上手实践:安全地搞点事情 


让我们通过一个简单的演示来展示原地 Pod 调整的实际效果,你可以从 Kubernetes API 和 Pod 内部同时查看资源变更。


整个演示运行在 GKE 的 Kubernetes 1.33 上。


1. 创建一个资源监控 Pod

首先创建一个持续监控自身资源分配的Pod:

kubectl apply -f - <<EOFapiVersion: v1kind: Podmetadata:  name: resize-demospec:  containers:  - name: resource-watcher    image: ubuntu:22.04    command:    - "/bin/bash"    - "-c"    - |      apt-get update && apt-get install -y procps bc      echo "=== Pod Started: $(date) ==="
      # Functions to read container resource limits      get_cpu_limit() {        if [ -f /sys/fs/cgroup/cpu.max ]; then          # cgroup v2          local cpu_data=$(cat /sys/fs/cgroup/cpu.max)          local quota=$(echo $cpu_data | awk '{print $1}')          local period=$(echo $cpu_data | awk '{print $2}')
          if [ "$quota" = "max" ]; then            echo "unlimited"          else            echo "$(echo "scale=3$quota / $period" | bc) cores"          fi        else          # cgroup v1          local quota=$(cat /sys/fs/cgroup/cpu/cpu.cfs_quota_us)          local period=$(cat /sys/fs/cgroup/cpu/cpu.cfs_period_us)
          if [ "$quota" = "-1" ]; then            echo "unlimited"          else            echo "$(echo "scale=3$quota / $period" | bc) cores"          fi        fi      }
      get_memory_limit() {        if [ -f /sys/fs/cgroup/memory.max ]; then          # cgroup v2          local mem=$(cat /sys/fs/cgroup/memory.max)          if [ "$mem" = "max" ]; then            echo "unlimited"          else            echo "$((mem / 1048576)) MiB"          fi        else          # cgroup v1          local mem=$(cat /sys/fs/cgroup/memory/memory.limit_in_bytes)          echo "$((mem / 1048576)) MiB"        fi      }
      # Print resource info every 5 seconds      while true; do        echo "---------- Resource Check: $(date) ----------"        echo "CPU limit: $(get_cpu_limit)"        echo "Memory limit: $(get_memory_limit)"        echo "Available memory: $(free -h | grep Mem | awk '{print $7}')"        sleep 5      done    resizePolicy:    - resourceName: cpu      restartPolicy: NotRequired    - resourceName: memory      restartPolicy: NotRequired    resources:      requests:        memory: "128Mi"        cpu: "100m"      limits:        memory: "128Mi"        cpu: "100m"EOF


2. 查看 Pod 的初始状态

从 Kubernetes API 的角度查看 Pod 的资源:

kubectl describe pod resize-demo | grep -A8 Limits:


你会看到类似以下输出:

Limits:      cpu:     100m      memory:  128Mi    Requests:      cpu:     100m      memory:  128Mi


现在,看看 Pod 自身如何看待它的资源:

kubectl logs resize-demo --tail=8


输出中会包含容器视角的 CPU 和内存限制。


3. 无缝调整 CPU

让我们在不重启的情况下将 CPU 加倍:

kubectl patch pod resize-demo --subresource resize --patch \  '{"spec":{"containers":[{"name":"resource-watcher""resources":{"requests":{"cpu":"200m"}, "limits":{"cpu":"200m"}}}]}}'


检查调整状态:

kubectl get pod resize-demo -o jsonpath='{.status.conditions[?(@.type=="PodResizeInProgress")]}'


💡注意:

在 GKE 的 Kubernetes 1.33 上,你可能看不到PodResizeInProgress状态,即使调整操作已经成功。如果 kubectl get pod resize-demo -o jsonpath='{.status.conditions}' 没有显示调整信息,请直接检查实际资源。


调整完成后,从 Kubernetes API 查看更新后的资源:

kubectl describe pod resize-demo | grep -A8 Limits:


并验证 Pod 现在看到的 CPU 限制:

kubectl logs resize-demo --tail=8


你会注意到 CPU 限制从 100m 翻倍到 200m ,而 Pod 没有重启!Pod 的日志会显示 cgroup 的 CPU 限制从大约 10000/100000 变为 20000/100000 (表示从 100m 到 200m 的 CPU)。


4. 无痛调整内存

现在,让我们将内存分配加倍:

kubectl patch pod resize-demo --subresource resize --patch \  '{"spec":{"containers":[{"name":"resource-watcher""resources":{"requests":{"memory":"256Mi"}, "limits":{"memory":"256Mi"}}}]}}'


稍等片刻后,从 API 验证:

kubectl describe pod resize-demo | grep -A8 Limits:


从 Pod 内部查看:

kubectl logs resize-demo --tail=8


你会看到内存限制从 128Mi 变为 256Mi,而容器没有重启!


5. 验证是否重启

确认在调整过程中容器从未重启:

kubectl get pod resize-demo -o jsonpath='{.status.containerStatuses[0].restartCount}'


输出应该是 0——证明我们实现了无需服务中断就能调整资源需求。


6. 清理资源

检验完成后:

kubectl delete pod resize-demo


搞定!你已经成功地在不重启 Pod 的情况下原地调整了 CPU 和内存资源


这种模式适用于任何容器化应用,除了设置适当的 resizePolicy 外,不需要任何特殊配置。


05/

云厂商支持情况


在进行生产环境的尝试之前,先看看各大 Kubernetes 服务商的支持情况:

  • Google Kubernetes Engine (GKE):在 GKE 的 Rapid 渠道中提供支持

  • Amazon EKS:Kubernetes 1.33 版本预计将于 2025 年 5 月发布

  • Azure AKS:Kubernetes 1.33 版本现已提供预览

  • 自建集群:只要运行 Kubernetes 1.33+ 并使用 containerd 或 CRI-O 运行时,完全支持


06/

局限性:

功能虽然强大,但也有边界


尽管这个功能很酷,但请记住以下几点:


平台和运行时限制

  • Windows 用户暂不支持:目前仅限Linux

  • 某些节点级 Pod 不支持如果节点启用了静态 CPU 或内存管理器(如 CPU 静态管理器策略),则该节点上的 Pod 将不支持原地扩缩容

  • 容器运行时要求需要 containerd v1.6+ 或 CRI-O v1.24+ 才能提供完整支持


资源管理限制

1. QoS 类别不可更改:

Pod 的原始服务质量等级(Guaranteed/Burstable/BestEffort)保持不变。无法通过调整将 BestEffort 升级为 Guaranteed


2. 目前只支持 CPU 和内存:

想动态调整 GPU 或临时存储?暂时还做不到。目前仅支持 CPU 和内存的原地调整。


3. 内存缩容需谨慎:

不重启容器的情况下降低内存限制,就像炸弹——理论上可行,实际上极危险。建议你设置 restartPolicy: RestartContainer 以免场面失控。这在使用 cgroup v1 的系统中尤其关键。


4. Swap 使用限制:

如果 Pod 开启了 Swap 功能,那你就无法动态调整内存,除非将内存的 resizePolicy 设置为 RestartContainer


5. 资源无法移除:

一旦设置了资源 request 或 limit,就不能通过原地调整将其删除,只能修改数值。


配置和集成限制

1. 并非所有容器都适用


  • 初始化容器和临时容器不支持,这些一次性启动的容器无法使用此功能,因为他们本身就无法重启。

  • 支持 Sidecar 容器:如果你喜欢用 Sidecar 模式,Sidecar 容器和主容器一样,支持原地进行资源调整,互不打扰。


2. resizePolicy不可更改:

一旦 Pod 创建,就无法更改其 resizePolicy 。所以请慎重选择,这是资源配置关系里的“从一而终”。


3. 特定应用限制:

如前所述,基于 JVM 的应用在不进行配置修改的情况下,无法自动使用扩容后的内存,通常还需要重启。这类限制适用于所有自行管理内存池的应用


4. 缩容的风险:

如果你尝试把内存限制调低到低于当前使用量(即使设置了 restartPolicy)也可能导致内存溢出(OOM)。


性能注意事项

1. 节点预留资源很关键:

节点需要有足够的可用容量才能成功调度资源。在资源紧张的集群中,Pod 可能会长时间处于 PodResizePending 状态,迟迟不能完成调整。


2. 资源调整并非实时完成:

kubelet 是异步处理调整请求的。复杂的 cgroup 更新可能需要几秒钟才能完全生效。


3. 调度器不感知扩缩容状态:

Kubernetes 调度器在进行 Pod 调度时不会感知有 Pod 正在调整资源,这可能导致资源压力误判,甚至调度冲突。


记住这些注意事项,你就能避免最糟糕的情况。


07/

VPA:很努力但还差点意思


正如我最近在 LinkedIn 上感叹的,垂直 Pod 自动扩缩容(VPA)就像弹性伸缩家族聚会里那个总被忽视的尴尬亲戚。


但好消息是,它的“逆袭”正在进行中。


当前状态(截至 Kubernetes 1.33):


  • VPA 尚不支持原地调整——它在调整资源时仍然会直接删除然后再重建 Pod,这在很多场景下显得非常粗暴

  • Kubernetes文档明确指出这一限制:“截至Kubernetes 1.33,VPA 不支持原地调整 Pod,但相关集成正在开发中。


在 kubernetes/autoscaler PR #7673 中,社区已着手将 VPA 与原地扩缩容机制集成。(链接见下方)


https://github.com/kubernetes/autoscaler/pull/7673


这意味着未来我们有望看到 VPA 真正实现资源动态调整,而无需重启应用



这种混合方案有望让 VPA 真正能具备在生产环境中支持有状态工作负载的能力。在此之前,我们只能继续手动和 Pod 玩资源叠叠乐,谨慎地调整资源。


当前结合 VPA 和手动调整的方法

虽然 VPA 尚未原生支持原地扩缩容,但你仍然可以同时受益于两者:

1. 使用 VPA 的“Off”模式:只生成资源推荐,不自动调整

2. 基于推荐手动执行扩缩容:根据 VPA 的建议手动进行原地调整

3编写脚本自动化操作流程:通过脚本自动化手动步骤,避免 Pod 重建


# Example of a simple script to apply VPA recommendations via in-place resize#!/bin/bashPOD_NAME="my-important-db"CPU_REC=$(kubectl get vpa db-vpa -o jsonpath='{.status.recommendation.containerRecommendations[0].target.cpu}')MEM_REC=$(kubectl get vpa db-vpa -o jsonpath='{.status.recommendation.containerRecommendations[0].target.memory}')


kubectl patch pod $POD_NAME --subresource resize --patch \  "{\"spec\":{\"containers\":[{\"name\":\"database\",\"resources\":{\"requests\":{\"cpu\":\"$CPU_REC\",\"memory\":\"$MEM_REC\"}}}]}}"


08/

与其他解决方案的对比



09/

展望未来


Kubernetes 1.33 引入的原地 Pod 调整是让垂直扩缩容走向“无感知”的重要一步,但这只是开始。接下来还有更多令人期待的进展:


  • VPA 深度集成(开发中)

    首先尝试原地调整,仅在绝对必要时才重建 Pod,不再有突发的 Pod 驱逐。

  • 支持更多资源类型

    不止 CPU 和内存,未来可能连 GPU、临时存储都能动态调整。

  • 调度器智能感知

    目前调整操作不会通知调度器,Pod 仍可能因节点资源不足被驱逐。后续可能让其具备感知能力,优先保障资源,避免被意外重新调度。

  • 和 Cluster Autoscaler / Karpenter 的联动

    实现更智能的资源决策,仅在无法原地调整时扩展节点。

  • 基于应用指标的自动调整

    资源不再只盯着 CPU 和内存,未来可能支持基于“请求延迟”、“队列深度”等应用级指标进行资源动态调整。


这些逐步完善的功能功能共同描绘出一个未来愿景:Kubernetes 正在迈向一个真正智能、高效、不中断的垂直扩缩容时代


对于开发者和平台团队而言,原地扩缩容(in-place pod resize)功能已经具备实验性使用的条件,非常适合在非生产环境中进行测试和评估。


需要注意的是,尽管该特性功能强大,引入生产环境前仍需充分验证与测试,以规避潜在的不确定性和兼容性风险。期待这个功能可以帮助你持续提升集群资源管理效率,也欢迎扫描文末二维码加入 K8s 资源管理技术交流群。


推荐阅读

别让 Spot 中断影响你下班!7 个策略教你优雅化解

年薪百万,每周只干5小时,硅谷工程师开始“摆烂”了?

“海外滴滴”Uber的Arm迁移实录:重构大规模基础设施

公司介绍

CloudPilot AI 是一家全球领先的 Karpenter 托管云服务提供商,致力于通过智能化、自动化的云资源调度和编排技术,帮助企业最大化云资源利用率。我们秉持“让客户在云中花费的每一分钱都物超所值”的使命,为客户提升10倍的资源效率,同时将云成本降低50%以上。


目前,开源K8s弹性伸缩器 Karpenter 已为全球超500家知名企业在生产环境中提供服务,包括阿迪达斯、Anthropic、Slack、Figma等。CloudPilot AI 已为数十家全球顶尖科技公司提供服务,累计为客户节省超过30万美金,平均节省67%。 选择CloudPilot AI,让每一笔支出都更智慧。


免费试用,2步5分钟,降低50%云成本:

cloudpilot.ai

【声明】内容源于网络
0
0
云妙算
让您在云中花费的每一分钱都物超所值
内容 0
粉丝 0
云妙算 让您在云中花费的每一分钱都物超所值
总阅读0
粉丝0
内容0