k8s Vertical Pod Autoscaler

395 阅读8分钟

调整分配给容器的 CPU 和内存资源的大小

功能状态:Kubernetes v1.33 [beta] (默认启用:true)

本页介绍如何在不重新创建 Pod 的情况下更改分配给容器的 CPU 和内存资源请求和限制。

传统上,更改 Pod 的资源需求需要删除现有的 Pod 并创建一个替代 Pod,通常由工作负载控制器管理。

就地 Pod 大小调整允许更改正在运行的 Pod 中容器的 CPU/内存分配,同时可能避免应用程序中断。

Key Concepts:  关键概念:

  • 所需资源:  容器的 spec.containers[*].resources 表示容器所需的资源,并且对于 CPU 和内存是可变的。
  • 实际资源:  该 status.containerStatuses[*].resources 字段反映当前为正在运行的容器配置的资源。对于尚未启动或已重启的容器,它反映了下次启动时分配的资源。
  • 触发调整大小:  您可以通过更新所需的请求来请求调整大小 和 Pod 规范中的限制。这通常使用 kubectl patch、kubectl apply 或 kubectl edit 来完成 以 Pod 的 resize 子资源为目标。当所需的资源与分配的资源不匹配时,Kubelet 将尝试调整容器的大小。
  • 分配的资源(高级):  该 status.containerStatuses[*].allocatedResources 字段跟踪 Kubelet 确认的资源值,主要用于内部调度逻辑。对于大多数监视和验证目的,请重点关注 status.containerStatuses[*].resources 。

如果节点的 Pod 具有待处理或未完成的调整大小(请参阅下面的 Pod 调整大小状态 ),则调度器在做出调度决策时使用状态中容器的所需请求数、已分配请求数和实际请求数中的最大值 。

Before you begin  准备工作

您的 Kubernetes 服务器必须为 1.33 或更高版本。

要检查版本,请输入 kubectl version。

InPlacePodVerticalScaling 特性门控 必须启用 对于您的控制平面和集群中的所有节点。

The kubectl client version must be at least v1.32 to use the --subresource=resize flag.
kubectl 客户端版本必须至少为 v1.32 才能使用 --subresource=resize 标志。

Pod resize status  Pod 大小调整状态

The Kubelet updates the Pod's status conditions to indicate the state of a resize request:
Kubelet 更新 Pod 的状态条件以指示调整大小请求的状态:

  • type: PodResizePending: Kubelet 无法立即授予请求。message 字段提供了原因的说明。

    • reason: Infeasible: 原因:不可行 :请求的大小调整在当前节点上是不可能的(例如,请求的资源超过节点拥有的资源)。
    • reason: Deferred: 原因:延迟 :请求的调整大小目前是不可能的,但以后可能会变得可行(例如,如果删除了另一个 pod)。Kubelet 将重试调整大小。
  • type: PodResizeInProgress: Kubelet 已接受调整大小并分配资源,但更改仍在应用中。这通常很简短,但可能需要更长的时间,具体取决于资源类型和运行时行为。启动期间的任何错误都会在 message 字段中报告(以及原因:Error)。

Container resize policies 容器大小调整策略

您可以通过在容器规范中设置 resizePolicy 来控制在调整大小时是否应重新启动容器。这允许根据资源类型 (CPU 或内存) 进行精细控制。

    resizePolicy:
    - resourceName: cpu
      restartPolicy: NotRequired
    - resourceName: memory
      restartPolicy: RestartContainer
  • NotRequired:(默认)将资源更改应用于正在运行的容器,而无需重新启动它。
  • RestartContainer:重启容器以应用新的资源值。这对于内存更改通常是必需的,因为许多应用程序和运行时无法动态调整其内存分配。

如果未为资源指定 resizePolicy[*].restartPolicy,则默认为 NotRequired。

注意:

如果 Pod 的整体 restartPolicy 为 Never,则所有资源的任何容器 resizePolicy 都必须为 NotRequired。你不能在此类 Pod 中配置需要重启的 resize 策略。

示例场景:

考虑一个为 CPU 和 restartPolicy: RestartContainer 内存配置了 restartPolicy: NotRequired 的容器。

  • 如果仅更改 CPU 资源,则会就地调整容器的大小。
  • 如果仅更改内存资源,则重新启动容器。
  • 如果 CPU 和内存资源同时更改,则容器将重新启动(由于内存策略)。

## 局限性

对于 Kubernetes 1.33,就地调整 Pod 资源的大小具有以下限制:

  • Resource Types: 资源类型:  只能调整 CPU 和内存资源的大小。

  • Memory Decrease: 内存减少:  除非内存的 resizePolicy 为 RestartContainer, 否则无法降低内存限制。通常可以减少内存请求。

  • QoS Class:   QoS 等级: Pod 的原始服务质量 (QoS) 类 (Guaranteed、Burstable 或 BestEffort)在创建时确定, 不能通过调整大小来更改。调整大小的资源值仍必须遵循原始 QoS 类的规则:

    • Guaranteed: 保证 :调整大小后,请求必须继续等于 CPU 和内存的限制。
    • Burstable: 可突增 :CPU 和内存的请求和限制不能同时相等(因为这会将其更改为 Guaranteed)。
    • BestEffort:无法添加资源要求 ( 请求或限制 ) (因为这会将其更改为 Burstable 或 Guaranteed) 。
  • Container Types:   集装箱类型:  不可重启的 init 容器和 临时容器无法调整大小。 可以调整 sidecar 容器的大小。

  • Resource Removal: 资源移除:  资源请求和限制一旦设置就无法完全删除;它们只能更改为不同的值。

  • Operating System:  操作系统: Windows Pod 不支持就地调整大小。

  • Node Policies:   节点策略:  由静态 CPU 或内存管理器策略管理的 Pod 无法就地调整大小。

  • Swap:  交换:  除非内存的 resizePolicy 是 RestartContainer,否则使用交换内存的 Pod 无法调整内存请求的大小。

这些限制可能会在未来的 Kubernetes 版本中放宽。

Example 1: Resizing CPU without restart 示例 1:在不重新启动的情况下调整 CPU 大小

First, create a Pod designed for in-place CPU resize and restart-required memory resize.
首先,创建一个专为就地调整 CPU 大小和需要重启的内存大小而设计的 Pod。

pods/resource/pod-resize.yaml

apiVersion: v1
kind: Pod
metadata:
  name: resize-demo
spec:
  containers:
  - name: pause
    image: registry.k8s.io/pause:3.8
    resizePolicy:
    - resourceName: cpu
      restartPolicy: NotRequired # Default, but explicit here
    - resourceName: memory
      restartPolicy: RestartContainer
    resources:
      limits:
        memory: "200Mi"
        cpu: "700m"
      requests:
        memory: "200Mi"
        cpu: "700m"

Create the pod:  创建 Pod:

kubectl create -f pod-resize.yaml

此 Pod 从 Guaranteed QoS 类开始。验证其初始状态:

# Wait a moment for the pod to be running
kubectl get pod resize-demo --output=yaml

观察 spec.containers[0].resources 和 status.containerStatuses[0].resources .它们应与清单匹配(700M CPU,200Mi 内存)。请注意 status.containerStatuses[0].restartCount (应为 0)。

现在,将 CPU 请求和限制增加到 800m。您可以使用带有 --subresource resize 命令行参数的 kubectl patch。

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

# Alternative methods:
# kubectl -n qos-example edit pod resize-demo --subresource resize
# kubectl -n qos-example apply -f <updated-manifest> --subresource resize
 注意:

--subresource resize 命令行参数需要 kubectl 客户端版本 v1.32.0 或更高版本。旧版本将报告 invalid subresource 错误。

patching 后再次检查 Pod 状态:

kubectl get pod resize-demo --output=yaml --namespace=qos-example

You should see:  您应该会看到:

  • spec.containers[0].resources 现在显示 cpu: 800m。
  • status.containerStatuses[0].resources 还显示 CPU: 800M,表示节点上的调整大小成功。
  • status.containerStatuses[0].restartCount 保持 0,因为 CPU resizePolicy 为 NotRequired。

Example 2: Resizing memory with restart 示例 2:通过重启调整内存大小

现在,通过将同一 Pod 的内存增加到 300Mi 来调整其大小。由于内存 resizePolicy 是 RestartContainer,因此容器应重新启动。

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

patching 后不久检查 Pod 状态:

kubectl get pod resize-demo --output=yaml

您现在应该观察到:

  • spec.containers[0].resources 显示内存:300Mi。
  • status.containerStatuses[0].resources 还显示内存:300Mi。
  • status.containerStatuses[0].restartCount 已增加到 1(如果之前发生过重启,则为更多),表示容器已重启以应用内存更改。

Troubleshooting: Infeasible resize request 疑难解答:不可行的大小调整请求

接下来,尝试请求不合理的 CPU 数量,例如 1000 个完整内核(对于毫核,则写为 “1000” 而不是 “1000m”),这可能会超出节点容量。

# Attempt to patch with an excessively large CPU request
kubectl patch pod resize-demo --subresource resize --patch \
  '{"spec":{"containers":[{"name":"pause", "resources":{"requests":{"cpu":"1000"}, "limits":{"cpu":"1000"}}}]}}'

查询 Pod 的详细信息:

kubectl get pod resize-demo --output=yaml

您将看到指示问题的更改:

  • spec.containers[0].resources 反映了所需的状态 (cpu: “1000”)。
  • 已将类型为 PodResizePending 且原因为 Infeasible 的条件添加到 Pod 中。
  • 条件的消息将解释原因 ( Node didn't have enough capacity: cpu, requested: 800000, capacity: ... )
  • 至关重要的是, status.containerStatuses[0].resources 它仍然会显示以前的值 (cpu:800m,memory``:300Mi),因为 Kubelet 没有应用不可行的调整大小。
  • restartCount 不会因为这次失败的尝试而改变。

要解决此问题,您需要使用可行的资源值再次修补 Pod。

Clean up

Delete the pod:  删除 Pod:

kubectl delete pod resize-demo