ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

深入解析 Kubernetes VPA 高级特性:推荐取整、原地更新(In-Place)与 CPU 启动加速

2026/9/16 12:25:32 拓冰建站 浏览量
深入解析 Kubernetes VPA 高级特性:推荐取整、原地更新(In-Place)与 CPU 启动加速 深入解析 Kubernetes VPA 高级特性推荐取整、原地更新In-Place与 CPU 启动加速【免费下载链接】autoscalerAutoscaling components for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/au/autoscaler导读本文以 Kubernetes 官方 autoscaler 仓库中vertical-pod-autoscaler/docs/features.md为骨架系统讲解 VPAVertical Pod Autoscaler垂直 Pod 自动扩缩容提供的六大核心特性资源限制控制Limits Control、内存推荐值人性化显示、CPU/内存推荐值向上取整以及基于 KubernetesInPlacePodVerticalScaling能力的原地更新模式InPlaceOrRecreate与零驱逐的InPlace最后覆盖面向 Java 等冷启动敏感应用的 CPU 启动加速CPU Startup Boost。阅读本文后你将掌握每个特性的启用方式、配置参数、行为边界、回退策略与监控指标并能在真实集群中正确选型与排障。本文涉及的所有功能均以当前仓库源码为据关键实现可在 recommender 配置与模型、updater 原地更新逻辑、原地更新限制器、VPA API 类型定义 与 特性门控定义 中找到对应实现。0. 前置知识VPA 组件与更新模式速览在深入各特性之前先建立两个基础概念后续所有特性都围绕它们展开VPA 三大组件Recommender基于历史用量生成资源推荐值、Updater决定何时把推荐值落实到 Pod 上、Admission Controller在新 Pod 创建时注入推荐值。本文大部分特性开关分散在这三个组件的启动参数中。更新模式updateModeVPA 通过spec.updatePolicy.updateMode决定如何应用推荐值合法的取值在 types.go 中以 CEL 校验枚举定义包括Off、Initial、Recreate、InPlaceOrRecreate、InPlace以及已废弃的Auto。其中InPlaceOrRecreate与InPlace是本文的核心Recreate则是传统的驱逐重建模式。1. 资源限制控制Limits Control1.1 机制说明当 VPA 设置容器 Limits 时会遵循 resource policy 的约束为所有容器保持 Limits 与 Requests 的固定比例关系。这意味着只要你在containerPolicies中显式声明了controlledResources与maxAllowed/minAllowedVPA 生成的推荐值target、lowerBound、upperBound都会在同一比例模型下计算。同时VPA 会尝试将推荐值截断在 LimitRange 的 min/max 范围内。但需要注意冲突优先级当LimitRange 与 VPA resource policy 冲突时VPA 遵循自身 policy允许产生超出 LimitRange 范围的值。换句话说VPA 的显式策略优先于命名空间的默认约束。1.2 排除单个容器mode: Off若要针对某个容器关闭 VPA 推荐只需在containerPolicies中将该容器的mode设置为Off。该行为在源码层面有明确印证在 update_priority_calculator.go 中Updater 计算更新优先级时会调用GetContainerResourcePolicy若发现容器的Mode为ContainerScalingModeOff则直接跳过该容器的快速 OOM判定与更新评估其含义是VPA 不为该容器生成推荐也不因该容器触发任何更新动作。2. 内存推荐值人性化显示Memory Value Humanization[!WARNING]已废弃该特性自 VPA v1.5.0 起被标记为 DEPRECATED将在未来版本移除。官方建议改用--round-memory-bytes完成内存推荐值的格式化。该特性最初在 v1.3.0 加入。2.1 功能与用法--humanize-memory是 Recommender 组件的布尔开关开启后会把内存推荐值从原始字节raw bytes转换为人类可读的二进制单位KiB、MiB、GiB、TiB。转换规则为自动选择最合适的二进制单位KiB/MiB/GiB/TiB最多保留 2 位小数同时作用于 target、lower bound、upper bound 三个推荐值。启用方式Recommender 启动参数--humanize-memorytrue效果示例原本显示为262144000字节的内存推荐开启后显示为250.00Mi。2.2 精度注意点由于采用了二进制单位换算和十进制小数舍入人性化后的值可能比原始字节推荐值略高。例如1537字节会被显示为1.50Ki即 1536 字节。进行精细容量规划时需考虑这一微小差异。2.3 源码实现印证该功能的底层实现位于 recommender/model/types.go 的ResourcesAsResourceList函数当humanizeMemory为 true 且数值非零时调用HumanizeMemoryQuantity见 types.go#L169-L190完成转换。该函数按 TiB→GiB→MiB→KiB 的优先级逐级判断使用%.2f格式输出两位小数小于 1KiB 的值保持原字节整数显示。同时日志中会打印DEPRECATED: Converting raw value to humanized value. Use --round-memory-bytes instead.提示。对应标志的定义与默认值默认false位于 config.go 与 config.go#L136。3. CPU 推荐值向上取整CPU Recommendation Rounding3.1 功能与用法--round-cpu-millicores是 Recommender 组件的整数参数用于把 CPU 推荐值向上取整到指定毫核millicore的整数倍让资源数值更规整、便于理解和配置向上取整到指定 millicore 值的最近倍数同时作用于 target、lower bound、upper bound 三个推荐值。启用示例--round-cpu-millicores50效果示例CPU 推荐79m会被取整为100m34m会被取整为50m。3.2 源码实现印证取整逻辑实现在 types.go 的RoundUpToScale函数中roundedValue : int64(math.Ceil(float64(value)/float64(scale64))) * scale64即除法 → 向上取整 → 乘以倍数保证结果严格不小于原始值。ResourcesAsResourceList中当roundCPUMillicores ! 1且数值非零时执行取整取整失败例如 scale 非法时会记录日志并保持原值不动。标志定义见 config.go#L210默认值为 1即不取整见 config.go#L137。4. 内存推荐值向上取整Memory Recommendation Rounding4.1 功能与用法--round-memory-bytes是 Recommender 组件的整数参数把内存推荐值向上取整到指定字节数的整数倍同样作用于 target、lower bound、upper bound 三个推荐值。启用示例--round-memory-bytes134217728效果示例以134217728字节即 128Mi为步长时内存推荐200Mi会被取整为256Mi80Mi会被取整为128Mi。4.2 源码实现印证内存取整与 CPU 取整共用同一RoundUpToScale实现见 types.go#L192-L200在 ResourcesAsResourceList 的内存分支中当roundMemoryBytes ! 1且数值非零时执行。标志定义见 config.go#L211默认值为 1不取整见 config.go#L138。[!TIP]--round-memory-bytes正是官方推荐的替代--humanize-memory的格式化方案前者向上取整到规整的二进制倍数如 128Mi既保持了可读性又不会破坏字节量只增不减的语义。5. 原地更新InPlaceOrRecreate[!NOTE] 功能状态Feature StateVPA v1.4.0 [alpha]VPA v1.5.0 [beta]VPA v1.6.0 [ga]VPA 支持**原地更新In-Place Updates**来降低应用推荐值时的扰动它利用 Kubernetes 的 Pod 原地扩容能力该能力在 Kubernetes 1.33 中处于 beta 状态直接修改容器资源而无需重建 Pod。设计文档详见 AEP-4016Support for in place updates in VPA。5.1 用法将 VPA 的updateMode设置为InPlaceOrRecreateapiVersion: autoscaling.k8s.io/v1 kind: VerticalPodAutoscaler metadata: name: my-vpa spec: updatePolicy: updateMode: InPlaceOrRecreate5.2 行为在该模式下VPA 会优先尝试原地更新如果原地更新失败则回退为 Pod 重建。更新尝试的触发条件为容器 Requests 超出推荐值上下界OutsideRecommendedRange发生快速 OOM容器在启动后很短时间内被OOMKilled对长时间运行的 Pod存活超过 12 小时推荐值与当前配置差异显著变化超过 10%。上述阈值与源码一致Updater 的默认配置中PodLifetimeUpdateThreshold: time.Hour * 12、EvictAfterOOMThreshold: 10 * time.Minute见 updater/config/config.go#L78-L79且通过--in-recommendation-bounds-eviction-lifetime-threshold与--evict-after-oom-threshold两个标志可调见 config.go#L104-L105。快速 OOM 的检测逻辑在 update_priority_calculator.go 中当容器LastTerminationState的退出原因为OOMKilled且存活时长小于阈值时判定为 quick OOM。完整更新判定条件请求超出推荐范围 / 存活超阈值且资源差异达到最小变更优先级 / 快速 OOM见 update_priority_calculator.go#L129-L147。重要说明扰动可能性原地更新旨在最小化扰动但无法保证零扰动——实际的 resize 操作由容器运行时负责执行。内存限制缩减在 beta 版本中对设置了resizePolicy: PreferNoRestart的 Pod 不支持内存限制缩减此时 VPA 会回退为 Pod 重建。5.3 对非扰动更新的跳过中断预算Skipping Disruption Budget默认情况下即使原地更新VPA 依然遵守中断预算驱逐容忍度、最小副本数等。但当原地更新不需要重启容器时它实际上是零扰动的这些检查可能过于保守。--in-place-skip-disruption-budget标志默认false允许 VPA 在满足以下条件时跳过原地更新的中断预算检查Pod 中所有容器对 CPU 和内存的 resize policy 均为NotRequired或未定义任何 resize policy。该判断在源码中对应 updater/utils/pod.go#L36-L48 的IsNonDisruptiveResize函数只要任一容器的任一资源的RestartPolicy RestartContainer即返回 false。限制器在 pods_inplace_restriction.go#L178-L184 中依据此函数放行或回退到常规中断预算判断singleGroupStats.isPodDisruptable()。标志定义见 updater/config/config.go#L97。中断预算仍然生效的场景即使开启该标志以下情况中断预算依然被强制执行任一容器对任一资源设置了RestartContainerresize policy更新将导致 Pod 被驱逐/重建回退场景。5.4 要求RequirementsKubernetes 1.33且启用InPlacePodVerticalScaling特性门控VPA 版本要求v1.4.0 需要启用InPlaceOrRecreate特性门控自 v1.5.0 起该门控默认开启v1.7.0 起该门控被移除不再需要显式配置。5.5 限制LimitationsPod 内所有容器一起更新不支持部分更新内存缩减需谨慎评估防止因缩减过快导致 OOM更新仍遵循 VPA 标准的更新条件与时间限制若更新会导致 Pod 的 QoS 类别发生变化则原地更新会失败。5.6 回退行为Fallback BehaviorVPA 在以下场景回退到 Pod 重建原地更新不可行infeasible如节点资源不足等对应 kubelet 上报的 Resize 状态更新被**推迟deferred**超过 5 分钟更新**进行中in progress**超过 1 小时更新会导致 Pod 的 QoS 类别改变需要配合PreferNoRestart策略进行内存限制缩减。上述 5 分钟与 1 小时的超时阈值定义于 pods_inplace_restriction.go#L44-L52DeferredResizeUpdateTimeout 5 * time.Minute、InProgressResizeUpdateTimeout 1 * time.Hour回退驱逐的判定入口为CanEvictInPlacingPod见 pods_inplace_restriction.go#L290。5.7 监控MonitoringVPA 提供以下指标跟踪原地更新操作指标命名空间为vpa_updater见 updater.go#L30指标定义见 updater.go#L95-L133指标名类型说明vpa_updater_in_place_updatable_pods_totalGauge符合原地更新条件的 Pod 数量vpa_updater_in_place_updated_pods_totalCounter成功原地更新的 Pod 数量vpa_updater_vpas_with_in_place_updatable_pods_totalGauge拥有可原地更新 Pod 的 VPA 对象数量vpa_updater_vpas_with_in_place_updated_pods_totalGauge拥有已原地更新 Pod 的 VPA 对象数量vpa_updater_failed_in_place_update_attempts_totalCounter原地更新失败尝试次数含 reason 标签此外源码中还额外定义了vpa_updater_in_place_infeasible_skip_pods_total因缓存到不可行而跳过的 Pod 数量见 updater.go#L135-L139可用于观测 infeasible 缓存命中情况。6. 零驱逐原地更新InPlace[!WARNING] 功能状态VPA v1.7.0 [alpha]InPlace模式专为任何扰动都不可接受的工作负载设计。与InPlaceOrRecreate不同该模式永不驱逐 Pod——只尝试原地更新并在集群条件变化后自动重试。设计文档详见 AEP-8818Eviction-Free In-Place Updates in VPA。6.1 用法先启用InPlace特性门控对应源码 features.go#L61-L63默认关闭、Alpha 级见 versioned_features.go#L33-L35再将updateMode设置为InPlace--feature-gatesInPlacetrueapiVersion: autoscaling.k8s.io/v1 kind: VerticalPodAutoscaler metadata: name: my-vpa spec: updatePolicy: updateMode: InPlace6.2 行为在InPlace模式下VPA 尝试就地应用资源更新从不回退到 Pod 驱逐。若更新无法应用VPA 会推迟defer并在后续的协调循环中重试。Updater 通过CanInPlaceUpdate函数评估每个 Pod接口定义见 pods_inplace_restriction.go#L54-L74返回以下决策之一决策含义InPlaceApprovedPod 可以原地更新InPlaceDeferred当前无法更新下一轮循环重试InPlaceInfeasible更新不可行记录该次尝试以便跟踪InPlaceInfeasibleCached此前已缓存不可行状态跳过不重复检查当 Pod 正处于 resize 过程中时VPA 会检查 kubelet 上报的 resize 状态处理逻辑见 pods_inplace_restriction.go#L142-L166Resize 状态动作ResizeDeferred等待 kubelet 继续处理ResizeInProgress等待完成ResizeInfeasible记录为不可行跳过该 PodResizeError瞬时 kubelet 错误推迟并在下一轮重试ResizeNone无待处理的 resize继续更新评估同时updater.go#L341-L359 表明当updateMode InPlace但特性门控未开启时Updater 会打印告警并不做任何操作——这是该模式与InPlaceOrRecreate的显著差异点后者在 v1.7.0 后无需门控。6.3 不可行尝试追踪Infeasible Attempt Tracking为防止无限重试循环VPA 会记录不可行的 resize 尝试当更新被判定为不可行无论是 kubelet 上报ResizeInfeasible还是 API Server 拒绝 patch时VPA 将本次尝试的资源值存入内存映射infeasibleAttempts[pod.UID]见 pods_inplace_restriction.go#L126-L133只有当新推荐值中至少有一个资源值低于上次不可行尝试存储的值时通过RecommendationHasLowerResource判断该 Pod 才会被重试命中缓存时返回InPlaceInfeasibleCached直接跳过并上报vpa_updater_in_place_infeasible_skip_pods_total指标。6.4 要求RequirementsKubernetes 1.33且启用InPlacePodVerticalScaling特性门控VPA v1.7.0且启用InPlace特性门控。6.5 限制LimitationsResize 从不保证成功节点容量约束可能使原地 resize 无限期无法完成内存限制缩减存在 OOMKill 风险若当前用量超过新限制值即可能被杀这是原地更新的固有特性并非 VPA 特有缺陷不可行尝试映射存储在内存中Updater 重启后之前不可行的尝试会被重试一次。6.6 监控MonitoringInPlace模式复用InPlaceOrRecreate的全部指标见上文 5.7 节表格另可关注源码中额外的vpa_updater_in_place_infeasible_skip_pods_total指标以观测 infeasible 缓存命中率。7. CPU 启动加速CPU Startup Boost[!WARNING] 功能状态VPA v1.7.0 [alpha]CPU Startup Boost 允许 VPA 在 Pod 启动期间临时提高容器的 CPU 请求与限制。这对启动阶段有高 CPU 需求的工作负载如 Java 应用特别有帮助可显著缩短启动时间。当 Pod 变为Ready且经过可选时长后VPA 通过原地 resize 将 CPU 资源回落到正常水平。设计文档详见 AEP-7862CPU Startup Boost。7.1 用法CPU Startup Boost 通过VerticalPodAutoscalerSpec中的startupBoost字段配置也支持在 per-container 的containerPolicies中配置从而实现全局与单容器两种粒度的叠加配置。对应 API 类型定义见 types.go#L114-L164。以下示例为目标 Deployment 的所有容器启用启动加速Pod Ready 后 10 秒内 CPU 乘以 3 倍apiVersion: autoscaling.k8s.io/v1 kind: VerticalPodAutoscaler metadata: name: example-vpa spec: targetRef: apiVersion: apps/v1 kind: Deployment name: example updatePolicy: updateMode: Recreate startupBoost: cpu: type: Factor factor: 3 durationSeconds: 107.2 行为当 VPA 管理的 Pod 被创建时VPA Admission Controller应用 CPU boostVPA Updater监控该 Pod一旦 Pod 条件变为Ready且经过startupBoost.cpu.durationSeconds就通过原地 resize将 CPU 资源回落回落目标为VPA 推荐值若该容器启用了 VPA或Pod spec 中定义的原始 CPU 资源。底层实现细节可在源码中印证Admission Controller 在应用 boost 时会把容器的原始资源规格以注解形式保存注解前缀为vpaCpuStartupBoost/见 utils/annotations/vpa_cpu_boost.go#L26-L35以便后续精确回落Updater 在计算原地更新 patch 时会先检查启动 boost 注解是否已过期若过期则调用getContainerResourcesForUnboost生成回落 patch——回落目标优先取 VPA 推荐值推荐为空时回落到注解中保存的原始资源见 updater/inplace/resource_updates.go#L54-L88 与 L123-L134处于 boost 中的 Pod 会被排除在常规驱逐/原地更新处理之外由独立的 boost worker 队列负责到期回落从而避免不必要的驱逐见 updater/logic/updater.go#L321-L329。7.3 要求RequirementsKubernetes 1.33且启用InPlacePodVerticalScaling特性门控回落动作依赖原地 resize 能力VPA v1.7.0且启用CPUStartupBoost特性门控。7.4 配置Configuration在 VPA 的admission-controller 与 updater两个组件上启用特性门控--feature-gatesCPUStartupBoosttrue对应源码定义见 features.go#L46-L47 与 versioned_features.go#L30-L32默认关闭、Alpha 级。startupBoost字段包含cpu子字段其参数如下字段校验规则见 types.go#L128-L155通过 CEL 交叉校验保证Factor/Quantity类型与对应字段严格配套字段必填类型说明type是Factor/Quantity加速类型Factor表示乘以倍数Quantity表示加一个具体 CPU 值factor当typeFactor时必填int32倍数例如2表示 2 倍 CPUquantity当typeQuantity时必填Quantity追加的 CPU 值例如500mdurationSeconds否int32Pod 变为Ready后保持 boost 的时长默认0[!NOTE] 若type使用Quantityboost 期间容器 CPU 请求与限制将直接设置为该绝对数值而非在原有基础上累加使用Factor则是在原请求/限制基础上按倍数放大。8. 特性选型速查表特性组件开关/字段功能状态适用场景Limits Control—containerPolicies/resourcePolicyGA保持 limit/request 比例、按容器精细化控制推荐Memory HumanizationRecommender--humanize-memory已废弃v1.5.0用--round-memory-bytes替代CPU RoundingRecommender--round-cpu-millicoresGA规整 CPU 推荐值默认 1关闭Memory RoundingRecommender--round-memory-bytesGA规整内存推荐值默认 1关闭In-Place UpdatesUpdaterupdateMode: InPlaceOrRecreateGAv1.6.0优先原地、失败回退重建Eviction-Free In-PlaceUpdater--feature-gatesInPlacetrueupdateMode: InPlacealphav1.7.0完全不可驱逐的工作负载CPU Startup BoostAdmission Controller Updater--feature-gatesCPUStartupBoosttruestartupBoostalphav1.7.0Java 等冷启动高 CPU 需求应用9. 延伸阅读完整特性文档vertical-pod-autoscaler/docs/features.md全部命令行标志参考vertical-pod-autoscaler/docs/flags.md原地更新设计文档AEP-4016、零驱逐原地更新 AEP-8818、CPU 启动加速 AEP-7862核心源码recommender 配置 config.go、推荐值模型与取整实现 types.go、updater 主逻辑 updater.go、原地更新限制器 pods_inplace_restriction.go、VPA API 类型 types.go、特性门控 features.go【免费下载链接】autoscalerAutoscaling components for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/au/autoscaler创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考