k8s Vertical Pod Autoscaler

266 阅读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 patchkubectl 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