ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Kubernetes VPA 已知限制与避坑指南:从 Pod 重建、OOM 到 HPA 共存的全面解析

Kubernetes VPA 已知限制与避坑指南:从 Pod 重建、OOM 到 HPA 共存的全面解析 Kubernetes VPA 已知限制与避坑指南从 Pod 重建、OOM 到 HPA 共存的全面解析【免费下载链接】autoscalerAutoscaling components for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/au/autoscalerVertical Pod AutoscalerVPA能够根据容器实际用量自动调整 Pod 的 CPU 与内存请求但它的每一项能力背后都伴随一系列必须提前了解的边界与约束。本文以官方文档 vertical-pod-autoscaler/docs/known-limitations.md 为主线结合本仓库内 recommender、updater、admission-controller 的源码实现逐条剖析 VPA 的已知限制及其规避手段。读完本文你将能够判断 VPA 是否适合你的工作负载、如何与 HPA / Cluster Autoscaler 正确搭配以及如何通过启动参数与配置规避Pod 无法调度等生产环境高频问题。限制一应用资源调整必然引发 Pod 重建VPA 更新 Pod 资源时Pod 会被重建所有正在运行的容器都会随之重建且新 Pod 可能被调度到不同的节点上。这是 VPA 更新机制的本质特征VPA 无法像部分原地升级方案那样直接修改运行中 Pod 的资源字段而是依赖删除旧 Pod → 以新 request 重建新 Pod的流程生效。从 admission-controller 的 patch 逻辑 可以看到只有当 VPA 的 updateMode 不是Off时webhook 才会在 Pod 创建时注入推荐资源。也就是说推荐值真正落地的时刻是 Pod 被创建的那一刻因此对运行中的 Pod 而言生效的唯一途径就是重建。更新模式UpdateMode决定了何时重建VPA 通过spec.updatePolicy.updateMode控制资源更新的时机完整取值定义见 types.goUpdateMode行为Off自动缩放器从不更改 Pod 资源仅提供建议人工决策Initial仅在 Pod 创建时分配资源之后不再调整Recreate在 Pod 创建时分配资源并可通过驱逐eviction重建 Pod 以应用更新Auto同上但该模式已标记为弃用deprecatedInPlace/InPlaceOrRecreate尝试通过 Kubernetes 的原地in-placePod 资源更新能力调整资源需要特别注意的是本仓库的 admission controller 在创建默认 VPA 时已明确将默认更新模式从Auto改为Recreate并在注释中说明这是Auto 模式弃用流程的一部分见 handler.go// Changed from UpdateModeAuto to UpdateModeRecreate as part of Auto mode deprecation defaultUpdateMode : vpa_types.UpdateModeRecreate因此如果你看到的文档仍以Auto为例实际部署时请以Recreate或支持原地更新的InPlace系列为准。重建对工作负载的直接影响由于重建是删旧建新以下场景需要格外评估会话状态如果应用将状态保存在 Pod 本地内存、本地磁盘重建后状态必然丢失请确保应用为无状态或使用外部存储。节点漂移新 Pod 可能调度到不同节点可能影响网络延迟、数据本地性data locality等。滚动中断对于副本数较少的工作负载重建会造成短暂不可用建议结合 PodDisruptionBudgetPDB与 VPA updater 的驱逐速率限制使用。限制二驱逐后不保证 Pod 能成功重建VPA 在Recreate及已弃用的Auto模式下会驱逐或删除 Pod 以应用推荐值但无法保证这些 Pod 一定能被成功重建。原因在于驱逐只负责释放Pod新 Pod 是否可调度取决于集群当时的容量。缓解该问题最直接的手段是将 VPA 与 Cluster Autoscaler 配合使用当驱逐后集群容量不足时Cluster Autoscaler 可以扩容节点来承接新 Pod。本仓库的 cluster-autoscaler 即为此而设计——它是一个独立的节点级自动缩放组件与 VPA 的 Pod 级缩放互补。但需注意这种组合只是部分缓解并不能绝对保证重建成功详见限制五。另外VPA updater 在驱逐时本身带有自我保护机制相关参数定义见 updater/config/config.go--eviction-rate-limit每秒可驱逐的 Pod 数设为0或-1可禁用限速默认-1即默认不禁用逻辑。--eviction-rate-burst允许的驱逐突发量默认1。--eviction-tolerance可被驱逐的副本比例默认0.5超过该比例时 updater 会暂停驱逐避免一次性重建过多副本。--min-replicas执行更新所需的最小副本数默认2副本过少时不做更新。--pod-update-threshold低于该优先级的更新将被忽略默认0.1。这些参数共同保证了即使要重建也要控制在可接受的破坏范围内但它们无法消除容量不足导致重建失败这一根本风险。限制三不被控制器管理的 Pod 不会更新VPA不会更新不在任何控制器Controller管理下的 Pod 资源。所谓控制器管理指 Deployment、StatefulSet、DaemonSet、ReplicaSet 等拥有 Pod 管理权的资源直接通过kubectl run创建、或手动创建的不受控 PodVPA 无法为其应用资源更新——因为 VPA 更新流程依赖驱逐后由控制器重建裸 Pod 被驱逐后没有控制器负责重建。这是 VPA 的基本使用前提请务必让目标工作负载处于某个控制器管理之下这也是官方 examples.md 中所有示例均基于 Deployment 的原因。限制四与 HPA 在同资源指标上冲突当前版本不应将 VPA 与 HPAHorizontal Pod Autoscaler用于同一资源指标CPU 或内存。理由很直观HPA 通过增减副本数来应对负载VPA 通过调整单副本的 request来应对负载如果两者都盯住 CPU 指标可能出现VPA 把 CPU request 调高 → HPA 认为负载降低而缩容 → VPA 又把 request 调低之类的互相干扰循环导致系统行为不可预测。可以安全搭配的场景VPA 与 HPA 的和平共处需要错开指标维度VPA 管内存、HPA 管 CPU不同资源指标例如 VPA 依据内存用量调 request、HPA 依据 CPU 使用率调副本数两者互不干扰。HPA 使用自定义指标custom metrics或外部指标external metrics当 HPA 不基于 CPU/内存这两种资源指标时与 VPA 没有直接冲突。一个 Pod 内多个容器分别由 VPA/HPA 管理只要不是同一资源指标理论上可以并存。此外VPA 与 HPA 的共存也受限于限制一的重建机制VPA 触发重建时副本数会短暂波动请确保 HPA 的minReplicas留有足够余量。限制五推荐值可能超出可用资源导致 Pod 进入 PendingVPA 的推荐值是依据历史用量与安全边际计算出来的它并不知道集群的实际容量。因此推荐值可能超出节点规格Node size集群可用容量available capacity命名空间配额ResourceQuota;一旦发生Pod 将无法调度进入 Pending 状态。这是生产环境中最常见的 VPA 事故场景之一。缓解手段有两种方案一与 Cluster Autoscaler 配合让集群在容量不足时自动扩容节点以承接请求更高的 Pod。其局限是如果推荐值超过了集群内最大节点的可分配量allocatable即使扩容也无法调度——没有哪台节点能装下这个 Pod。方案二为 recommender 设置全局推荐上限通过两个全局 flag 限制单容器推荐值的上限--container-recommendation-max-allowed-cpu--container-recommendation-max-allowed-memory这两个 flag 在 recommender/config/config.go 中定义语义为单个容器将被推荐的最大 CPU / 内存量。其局限是如果一个 Pod 内有多个容器同时被 VPA 缩放各容器推荐值之和仍可能超过最大节点的可分配量Pod 依然可能无法调度。关于这两个 flag 的取值建议官方 examples.md 给出了非常具体的计算方法推荐值应取集群中最大节点的可分配量Node 的.status.allocatable字段减去 DaemonSet Pod 的资源请求再减去一个安全边际safety margin。同时文档也指出一个实际的放宽条件通常情况下 Pod 中只有一个主容器需要自动缩放其余多为 sidecar 容器——它们要么不参与缩放要么资源请求不高因此多容器之和超限在实践中并不常见但理论上仍可能发生。优先级的细节VPA 对象级上限 全局 flag注意VPA 对象自身的spec.resourcePolicy.containerPolicies.maxAllowed对象级上限优先于全局 flag若 VPA 已定义 maxAllowed则全局 flag 不生效若 VPA 仅对 CPU 或内存之一定义了 maxAllowed则另一个维度使用全局 flag 的上限若 VPA 未定义任何 maxAllowed则使用全局 flag 的上限。限制六多个 VPA 匹配同一 Pod 的行为未定义如果集群中存在多个 VPA 资源同时匹配同一个 Pod它们的行为是未定义的——可能互相覆盖推荐值、可能都尝试更新也可能产生意料之外的组合结果。请务必保证一个 Pod 至多由一个 VPA 管理为 VPA 设置精确的spec.targetRef明确指向某个 Deployment / StatefulSet避免多个 VPA 的 selector 范围重叠命名空间划分也是一种隔离手段见 admission-controller 的--vpa-object-namespace与--ignored-vpa-object-namespaces参数。从 admission-controller 的 matcher 逻辑 可以看出匹配时 VPA 会检查 updateMode 是否为OffOff模式且无 CPU Startup Boost 时不会应用补丁但多 VPA 重叠匹配的场景下哪个 VPA 胜出并没有被明确保证。限制七VPA 对 OOM 的响应不完整VPA 能够响应大部分内存溢出OOM事件但并非所有场景。理解这一限制需要先了解 VPA 如何看到 OOM本仓库的 OOM 观察器observer位于 pkg/recommender/input/oom/observer.go它通过监听两类信号捕获 OOMEviction 事件parseEvictionEvent解析 Kubernetes 驱逐事件提取 offending container 生成OomInfoPod 容器状态变化在OnUpdate中检查容器终止状态是否为OOMKilled包括当前已终止和上次终止两种情况从而捕获未触发驱逐事件的 OOM。捕获到的OomInfo会进入观察者通道由 cluster_feeder.go 消费并记录到集群状态中最终影响内存推荐。触发机制与兜底参数OOM 发生后recommender 会按以下参数调高内存推荐相关定义见 recommender/config/config.go--oom-bump-up-ratioOOM 发生时的内存上调比例默认1.2即上调 20%--oom-min-bump-up-bytesOOM 发生时内存的最小上调量默认100 * 1024 * 1024即 100Mi。两者以取两者中较大的上调量的方式共同决定 OOM 后的新内存推荐。与此同时updater 还提供--evict-after-oom-threshold默认 10 分钟对启动后短时间内就 OOM的 Pod在阈值内会尽快驱逐以快速应用更高的内存请求避免反复崩溃。为什么仍有遗漏以下场景 OOM 可能不会被完整感知或正确处理节点级内存压力导致的系统级 OOM非容器OOMKilled状态OOM 事件发生在 VPA 未监听的时间窗口如组件重启间隙Pod 被删除后事件信息未及时保留导致 OomInfo 丢失——相关测试 cluster_feeder_test.go 专门覆盖了Pod 已删除后仍要处理 OOM 事件的边界情况说明这正是实现中被特别关注的薄弱环节。限制八大规模集群性能未充分验证VPA 的性能尚未在大规模集群中经过充分测试。这意味着在拥有数千节点、数万 Pod 的集群中recommender 的历史数据聚合、admission-controller 的 webhook 调用都可能出现延迟或资源占用偏高的问题。如果你运行的是超大规模集群建议关注 recommender 的--recommender-interval默认 1 分钟与--update-worker-count默认 10等参数合理调节聚合与更新并发关注--kube-api-qps默认 50与--kube-api-burst默认 100等 API 限流参数防止高负载下被 API Server 限流详见 flags.md先在中小规模集群或测试环境验证行为再逐步推广。限制九GKE 上启用 leader election 的 Lease 冲突在 GKE 集群中如果以--leader-electtrue运行 vpa-recommender会与 GKE 系统组件持有的名为vpa-recommender的 Lease产生争用contention。官方给出的规避方法是使用不同的 Lease 名--leader-electtrue --leader-elect-resource-namevpa-recommender-lease这一限制实际上已经在当前仓库的源码层面得到修复在 pkg/recommender/main.go 中默认的 leader election 资源名已被改为vpa-recommender-lease并附注说明// This was changed from vpa-recommender to avoid conflicts with managed VPA deployments. ResourceName: vpa-recommender-lease,也就是说使用当前仓库构建的 vpa-recommender即使不显式传参默认也不会与 GKE 托管的同名 Lease 冲突但如果你在 GKE 上使用旧版本或需要自定义命名仍应显式指定--leader-elect-resource-name。其他相关 leader election 参数见 flags.mdFlag默认值说明--leader-electfalse是否启用 leader election高可用多副本时开启--leader-elect-resource-namevpa-recommender-lease锁资源对象名称--leader-elect-resource-namespacekube-system锁资源所在命名空间--leader-elect-lease-duration15s租约有效期--leader-elect-renew-deadline10s续约截止时间必须小于租约时长--leader-elect-retry-period2s获取/续约租约的重试间隔限制十Admission Controller 之间的交互冲突VPA 的 admission controller 本质上是一个admission webhook。如果在集群中同时部署了其他 admission webhook如 Pod 安全策略、网络策略注入、Istio 注入等必须分析它们之间的交互方式确认是否会相互冲突。冲突的来源执行顺序admission controller 的执行顺序由 API Server 的--enable-admission-plugins与 webhook 配置admissionregistration.k8s.io/v1的MutatingWebhookConfiguration共同决定如果某个 webhook 先于 VPA 修改了 Pod 的资源请求VPA 的推荐值可能被覆盖或反之覆盖他人的修改。补丁冲突多个 mutating webhook 都在修改同一个 Pod 的同一字段时后执行的 webhook 可能把前一个的修改冲掉last-write-wins产生难以排查的资源请求最终不是预期值的问题。排查与规避建议明确各 webhook 的matchPolicy、namespaceSelector、objectSelector尽量缩小 VPA webhook 的匹配范围通过 webhook 的reinvocationPolicy如IfNeeded允许 API Server 在链式调用中对补丁进行再调用在 admission-controller-deployment.yaml 的部署中可关注--webhook-timeout-seconds默认 30 秒等参数避免 webhook 链超时导致 Pod 创建失败在变更 webhook 配置前务必在测试环境验证与其他 webhook 的叠加效果。总结VPA 生产化部署检查清单结合以上十条限制在生产环境启用 VPA 前建议逐项核对工作负载形态目标负载由 Deployment / StatefulSet 等控制器管理且无状态或可接受重建。更新模式选择默认使用Recreate若集群支持原地更新可评估InPlace/InPlaceOrRecreate以减少重建频率。与 HPA 的边界严禁 VPA 与 HPA 共用同一资源指标错开指标维度如 VPA 管内存、HPA 管 CPU或让 HPA 使用自定义/外部指标。容量保护为 recommender 配置--container-recommendation-max-allowed-cpu/--container-recommendation-max-allowed-memory取值参照最大节点 allocatable − DaemonSet 请求 − 安全边际必要时叠加 Cluster Autoscaler。对象唯一性确保每个 Pod 只被一个 VPA 匹配避免多个 VPA 重叠。OOM 兜底保留默认的--oom-bump-up-ratio1.2与--oom-min-bump-up-bytes100Mi并理解其并非覆盖所有 OOM 场景。Webhook 治理梳理集群内所有 mutating webhook 的执行顺序与补丁冲突风险。GKE 特判确认 recommender 版本自带vpa-recommender-lease默认值或显式指定--leader-elect-resource-name。以上所有限制的原文与完整参数表可在 known-limitations.md、flags.md 与 examples.md 中进一步查阅对应的实现细节可深入 pkg/recommender、pkg/updater 与 pkg/admission-controller 目录下的源码验证。【免费下载链接】autoscalerAutoscaling components for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/au/autoscaler创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表