本文发布已超过一年。较旧的文章可能包含过时内容。请检查页面信息自发布以来是否已失效。

Kubernetes 1.27:Kubernetes Pod 的原地资源调整 (alpha) | Kubernetes

如果您使用指定了 CPU 和/或内存资源的配置部署了 Kubernetes Pod,您可能已经注意到更改资源值需要重启 Pod。这对正在运行的工作负载来说是一个破坏性操作……直到现在。

在 Kubernetes v1.27 中,我们添加了一个新的 Alpha 特性,允许用户在不重启容器的情况下调整分配给 Pod 的 CPU/内存资源。为了实现这一点,Pod 容器中的 resources 字段现在允许对 cpumemory 资源进行修改。只需修补正在运行的 Pod spec 即可更改它们。

这也意味着 Pod spec 中的 resources 字段不能再作为 Pod 实际资源的指示器。监控工具和其他此类应用程序现在必须查看 Pod 状态中的新字段。Kubernetes 通过 CRI(容器运行时接口)API 调用运行时(例如负责运行容器的 containerd)来查询正在运行的容器上强制执行的实际 CPU 和内存请求和限制。容器运行时的响应反映在 Pod 的状态中。

此外,还为调整大小添加了一个新的 restartPolicy。它允许用户控制在资源调整大小时如何处理其容器。

v1.27 中有哪些新功能?

除了在 Pod spec 中添加调整大小策略外,Pod 状态中的 containerStatuses 还添加了一个名为 allocatedResources 的新字段。此字段反映分配给 Pod 容器的节点资源。

此外,容器状态中还添加了一个名为 resources 的新字段。此字段反映了容器运行时报告的,正在运行的容器上配置的实际资源请求和限制。

最后,Pod 状态中添加了一个名为 resize 的新字段,用于显示最后一次请求的调整大小的状态。Proposed 值表示对请求的调整大小的确认,并表明请求已通过验证并记录。InProgress 值表示节点已接受调整大小请求,并且正在将调整大小请求应用于 Pod 的容器。Deferred 值表示当前无法满足请求的调整大小,并且节点将继续重试。当其他 Pod 离开并释放节点资源时,可能会批准调整大小。Infeasible 值表示节点无法满足请求的调整大小。如果请求的调整大小超过节点可以为 Pod 分配的最大资源,则可能会发生这种情况。

何时使用此功能?

以下是一些此功能可能有用的场景示例:

  • Pod 正在节点上运行,但分配的资源过多或过少。
  • 由于资源过度分配的 Pod 正在运行,导致集群资源利用率低,但新 Pod 因缺乏足够的 CPU 或内存而无法调度。
  • 将需要更多资源的某些有状态 Pod 驱逐并在更大的节点上重新调度是一项昂贵或破坏性的操作,而此时可以缩小或移动节点上的其他低优先级 Pod。

如何使用此功能?

为了在 v1.27 中使用此功能,必须启用 InPlacePodVerticalScaling 功能门控。可以如下所示启动启用此功能的本地集群:

root@vbuild:~/go/src/k8s.io/kubernetes# FEATURE_GATES=InPlacePodVerticalScaling=true ./hack/local-up-cluster.sh
go version go1.20.2 linux/arm64
+++ [0320 13:52:02] Building go targets for linux/arm64
    k8s.io/kubernetes/cmd/kubectl (static)
    k8s.io/kubernetes/cmd/kube-apiserver (static)
    k8s.io/kubernetes/cmd/kube-controller-manager (static)
    k8s.io/kubernetes/cmd/cloud-controller-manager (non-static)
    k8s.io/kubernetes/cmd/kubelet (non-static)
...
...
Logs:
  /tmp/etcd.log
  /tmp/kube-apiserver.log
  /tmp/kube-controller-manager.log

  /tmp/kube-proxy.log
  /tmp/kube-scheduler.log
  /tmp/kubelet.log

To start using your cluster, you can open up another terminal/tab and run:

  export KUBECONFIG=/var/run/kubernetes/admin.kubeconfig
  cluster/kubectl.sh

Alternatively, you can write to the default kubeconfig:

  export KUBERNETES_PROVIDER=local

  cluster/kubectl.sh config set-cluster local --server=https://localhost:6443 --certificate-authority=/var/run/kubernetes/server-ca.crt
  cluster/kubectl.sh config set-credentials myself --client-key=/var/run/kubernetes/client-admin.key --client-certificate=/var/run/kubernetes/client-admin.crt
  cluster/kubectl.sh config set-context local --cluster=local --user=myself
  cluster/kubectl.sh config use-context local
  cluster/kubectl.sh

本地集群启动并运行后,Kubernetes 用户可以调度带有资源的 Pod,并通过 kubectl 调整 Pod 的大小。以下演示视频展示了如何使用此功能。

示例用例

基于云的开发环境

在此场景下,开发者或开发团队在本地编写代码,但在 Kubernetes Pod 中构建和测试他们的代码,Pod 配置与生产环境保持一致。当开发者编写代码时,此类 Pod 只需要少量资源;但在构建代码或运行一系列测试时,需要显著更多的 CPU 和内存。此用例可以利用 Pod 原地调整大小功能(辅以 eBPF 的一些帮助),快速调整 Pod 的资源,并避免内核 OOM(内存不足)杀手终止其进程。

这个KubeCon 北美 2022 会议演讲展示了此用例。

Java 进程初始化时的 CPU 需求

一些 Java 应用程序在初始化期间可能需要比正常进程运行时间显著更多的 CPU。如果此类应用程序指定的 CPU 请求和限制仅适用于正常操作,它们的启动时间可能会非常长。此类 Pod 可以在创建时请求更高的 CPU 值,并在应用程序初始化完成后,将其调整到正常的运行需求。

已知问题

此功能在 v1.27 中进入 Alpha 阶段。以下是用户可能遇到的一些已知问题:

  • 低于 v1.6.9 的 containerd 版本不具备此功能端到端完整操作所需的 CRI 支持。尝试调整 Pod 大小时会显示为卡在 InProgress 状态,并且 Pod 状态中的 resources 字段永远不会更新,尽管新的资源可能已经在运行的容器上生效。
  • Pod 调整大小可能与其他 Pod 更新发生竞态条件,导致 Pod 调整大小的延迟生效。
  • 在 Pod 状态中反映已调整大小的容器资源可能需要一段时间。
  • 此功能不支持静态 CPU 管理策略。

致谢

此功能是高度协作的 Kubernetes 社区共同努力的结果。在此向许多贡献了无数时间和精力促成此事的成员表示感谢,这仅是其中一部分:

  • @thockin 贡献了注重细节的 API 设计和严谨的代码评审。
  • @derekwaynecarr 贡献了简化设计和彻底的 API 及节点评审。
  • @dchen1107 带来了 Borg 系统的丰富知识,帮助我们避免陷阱。
  • @ruiwen-zhao 添加了 containerd 支持,使得完整的 E2E 实现成为可能。
  • @wangchen615 实现了全面的 E2E 测试并推动了调度器的修复。
  • @bobbypage 在 CI 准备就绪和快速调查问题方面提供了宝贵的帮助,并在我休假期间代劳。
  • @Random-Liu 进行了彻底的 kubelet 评审并识别了潜在的竞态条件问题。
  • @Huang-Wei, @ahg-g, @alculquicondor 帮助完成了调度器的变更。
  • @mikebrow @marosset 在短时间内进行了评审,帮助 CRI 的变更成功纳入 v1.25。
  • @endocrimes, @ehashman 帮助确保常常被忽视的测试处于良好状态。
  • @mrunalp 评审了 cgroupv2 的变更并确保 v1 与 v2 之间的清晰处理。
  • @liggitt, @gjkim42 在合并后追踪并定位了重要但被遗漏的问题。
  • @SergeyKanzhelev 在最后冲刺阶段支持并引导了各种问题。
  • @pdgetrf 使第一个原型成为现实。
  • @dashpole 帮助我快速掌握了“Kubernetes 方式”做事方法。
  • @bsalamat, @kgolab 在早期阶段提供了非常深刻的见解和建议。
  • @sftim, @tengqm 确保文档易于理解。
  • @dims 无处不在,并在关键时刻帮助完成合并。
  • 发布团队确保项目保持健康。

并特别感谢我的支持性管理层丁晓宁博士熊英博士的耐心和鼓励。

参考资料

面向应用开发者

面向集群管理员