<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>Jimmy Song – 调度与弹性</title><link>https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/</link><description>Recent content in 调度与弹性 on Jimmy Song</description><generator>Hugo -- gohugo.io</generator><language>zh</language><managingEditor>Jimmy Song</managingEditor><webMaster>Jimmy Song</webMaster><follow_challenge><feedId>51621818828612637</feedId><userId>59800919738273792</userId></follow_challenge><lastBuildDate>Sun, 01 Nov 2026 00:00:00 +0800</lastBuildDate><atom:link href="https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/index.xml" rel="self" type="application/rss+xml"/><item><title>调度与弹性概述</title><link>https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/overview/</link><pubDate>Mon, 13 Oct 2025 00:00:00 +0000</pubDate><author>Jimmy Song</author><guid>https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/overview/</guid><description>本章概览：梳理 Kubernetes 调度器工作原理、资源 requests/limits、调度约束、优先级抢占、节点压力驱逐、PDB、HPA/VPA 与节点弹性、装箱策略与多调度器，并给出各主题的深入阅读导引。</description><content:encoded>
&lt;blockquote&gt;
&lt;p&gt;灵活的调度与资源管理，是 Kubernetes 实现弹性、高可用和高效资源利用的核心竞争力。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Kubernetes 通过灵活的调度与资源管理机制，实现了高效的工作负载分布与资源利用。本文作为本章概览，系统梳理调度流程、资源分配、自动扩缩容、优先级抢占、节点压力驱逐等核心内容；每个主题在本章后续文章中都有专门的深入讨论。&lt;/p&gt;
&lt;h2 id="调度与资源管理概述"&gt;调度与资源管理概述&lt;/h2&gt;
&lt;p&gt;Kubernetes 需要复杂的系统来决定工作负载的运行位置及资源分配方式。这些系统确保：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pod 被调度到合适的节点&lt;/li&gt;
&lt;li&gt;资源分配高效且公平&lt;/li&gt;
&lt;li&gt;高优先级工作负载在资源紧张时能优先运行&lt;/li&gt;
&lt;li&gt;系统可根据资源需求动态调整&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;下图展示了调度与资源管理的主要组件关系：&lt;/p&gt;
&lt;figure class="mx-auto text-center"&gt;
&lt;img src="https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/overview/scheduling-core-components.svg" data-img="/zh/book/kubernetes-handbook/scheduling/overview/scheduling-core-components.svg"
alt="图 1: 调度与资源管理核心组件" data-caption="图 1: 调度与资源管理核心组件" loading="lazy" decoding="async"
width="2160"
height=" 1140"
onerror="handleImageError(this); this.classList.remove('image-loading');"
onload="this.classList.remove('image-loading'); this.classList.add('image-loaded');"
class="image-loading"
style="width: 100%; height: auto;"&gt;
&lt;figcaption&gt;图 1: 调度与资源管理核心组件&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="kubernetes-调度器原理"&gt;Kubernetes 调度器原理&lt;/h2&gt;
&lt;p&gt;Kubernetes 调度器（kube-scheduler）负责为新建 Pod 分配节点。它持续监听未分配节点的 Pod，并为每个 Pod 选择最优节点。&lt;/p&gt;
&lt;h3 id="调度流程"&gt;调度流程&lt;/h3&gt;
&lt;p&gt;调度分为两大阶段：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;过滤（Filtering）&lt;/strong&gt;：筛选出可运行 Pod 的节点集合&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;打分（Scoring）&lt;/strong&gt;：对候选节点评分，选出最优节点&lt;/li&gt;
&lt;/ol&gt;
&lt;figure class="mx-auto text-center"&gt;
&lt;img src="https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/overview/scheduling-cycle-and-binding.svg" data-img="/zh/book/kubernetes-handbook/scheduling/overview/scheduling-cycle-and-binding.svg"
alt="图 2: 调度流程：调度周期与绑定周期" data-caption="图 2: 调度流程：调度周期与绑定周期" loading="lazy" decoding="async"
width="2160"
height=" 1000"
onerror="handleImageError(this); this.classList.remove('image-loading');"
onload="this.classList.remove('image-loading'); this.classList.add('image-loaded');"
class="image-loading"
style="width: 100%; height: auto;"&gt;
&lt;figcaption&gt;图 2: 调度流程：调度周期与绑定周期&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id="调度框架与插件机制"&gt;调度框架与插件机制&lt;/h3&gt;
&lt;p&gt;调度器采用可插拔架构（Scheduling Framework），支持多种扩展点，便于自定义调度逻辑。&lt;/p&gt;
&lt;figure class="mx-auto text-center"&gt;
&lt;img src="https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/overview/scheduling-framework-extension-points.svg" data-img="/zh/book/kubernetes-handbook/scheduling/overview/scheduling-framework-extension-points.svg"
alt="图 3: 调度框架扩展点" data-caption="图 3: 调度框架扩展点" loading="lazy" decoding="async"
width="2080"
height=" 880"
onerror="handleImageError(this); this.classList.remove('image-loading');"
onload="this.classList.remove('image-loading'); this.classList.add('image-loaded');"
class="image-loading"
style="width: 100%; height: auto;"&gt;
&lt;figcaption&gt;图 3: 调度框架扩展点&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id="默认调度插件"&gt;默认调度插件&lt;/h3&gt;
&lt;p&gt;下表列举了常用内置调度插件及其作用：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;插件&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;扩展点&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;NodeResourcesFit&lt;/td&gt;
&lt;td&gt;检查节点资源是否充足&lt;/td&gt;
&lt;td&gt;preFilter, filter, score&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PodTopologySpread&lt;/td&gt;
&lt;td&gt;实现拓扑分布约束&lt;/td&gt;
&lt;td&gt;preFilter, filter, preScore, score&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NodeAffinity&lt;/td&gt;
&lt;td&gt;节点亲和性与选择器&lt;/td&gt;
&lt;td&gt;filter, score&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TaintToleration&lt;/td&gt;
&lt;td&gt;污点与容忍度&lt;/td&gt;
&lt;td&gt;filter, preScore, score&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NodeName&lt;/td&gt;
&lt;td&gt;节点名匹配&lt;/td&gt;
&lt;td&gt;filter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NodePorts&lt;/td&gt;
&lt;td&gt;检查端口可用性&lt;/td&gt;
&lt;td&gt;preFilter, filter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NodeUnschedulable&lt;/td&gt;
&lt;td&gt;过滤不可调度节点&lt;/td&gt;
&lt;td&gt;filter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;InterPodAffinity&lt;/td&gt;
&lt;td&gt;Pod 间亲和/反亲和&lt;/td&gt;
&lt;td&gt;preFilter, filter, preScore, score&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PrioritySort&lt;/td&gt;
&lt;td&gt;优先级排序&lt;/td&gt;
&lt;td&gt;queueSort&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DefaultBinder&lt;/td&gt;
&lt;td&gt;默认绑定机制&lt;/td&gt;
&lt;td&gt;bind&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DefaultPreemption&lt;/td&gt;
&lt;td&gt;抢占逻辑&lt;/td&gt;
&lt;td&gt;postFilter&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;figcaption class="text-center mb-3"&gt;
表 1: Kubernetes 默认调度插件及扩展点
&lt;/figcaption&gt;
&lt;h2 id="资源管理机制"&gt;资源管理机制&lt;/h2&gt;
&lt;p&gt;Kubernetes 支持为 Pod 中的容器指定资源请求（requests）与限制（limits），用于调度与资源分配。&lt;/p&gt;
&lt;h3 id="资源类型"&gt;资源类型&lt;/h3&gt;
&lt;p&gt;主要资源类型如下：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;资源类型&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;单位&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CPU&lt;/td&gt;
&lt;td&gt;计算资源&lt;/td&gt;
&lt;td&gt;核心数（1、0.5、100m 等）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Memory&lt;/td&gt;
&lt;td&gt;内存&lt;/td&gt;
&lt;td&gt;字节（Ki、Mi、Gi 等）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ephemeral Storage&lt;/td&gt;
&lt;td&gt;临时存储&lt;/td&gt;
&lt;td&gt;字节（Ki、Mi、Gi 等）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Huge Pages&lt;/td&gt;
&lt;td&gt;大页内存（Linux）&lt;/td&gt;
&lt;td&gt;指定大小（如 hugepages-2Mi）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Extended Resources&lt;/td&gt;
&lt;td&gt;自定义扩展资源&lt;/td&gt;
&lt;td&gt;整数单位&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;figcaption class="text-center mb-3"&gt;
表 2: Kubernetes 支持的资源类型
&lt;/figcaption&gt;
&lt;h3 id="requests-与-limits"&gt;Requests 与 Limits&lt;/h3&gt;
&lt;p&gt;每个容器可指定资源请求与限制。下图展示了 Pod 内多容器资源汇总关系：&lt;/p&gt;
&lt;figure class="mx-auto text-center"&gt;
&lt;img src="https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/overview/pod-requests-limits-rollup.svg" data-img="/zh/book/kubernetes-handbook/scheduling/overview/pod-requests-limits-rollup.svg"
alt="图 4: Pod 资源请求与限制示意" data-caption="图 4: Pod 资源请求与限制示意" loading="lazy" decoding="async"
width="1920"
height=" 880"
onerror="handleImageError(this); this.classList.remove('image-loading');"
onload="this.classList.remove('image-loading'); this.classList.add('image-loaded');"
class="image-loading"
style="width: 100%; height: auto;"&gt;
&lt;figcaption&gt;图 4: Pod 资源请求与限制示意&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Requests&lt;/strong&gt;：调度时保证的最小资源&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Limits&lt;/strong&gt;：运行时允许的最大资源&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;调度器依据 requests 进行节点选择，kubelet 依据 limits 强制资源上限。&lt;/p&gt;
&lt;h3 id="资源限制的强制机制"&gt;资源限制的强制机制&lt;/h3&gt;
&lt;p&gt;kubelet 与容器运行时协作，强制资源限制：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CPU 限制&lt;/strong&gt;：通过限流实现，超出部分被限制&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;内存限制&lt;/strong&gt;：超限时触发 OOM 杀手，容器被终止&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;若容器超出 requests 但未超 limits，且节点资源紧张，Pod 可能被驱逐。&lt;/p&gt;
&lt;h2 id="pod-调度策略"&gt;Pod 调度策略&lt;/h2&gt;
&lt;p&gt;Kubernetes 提供多种机制控制 Pod 在节点间的分布。&lt;/p&gt;
&lt;h3 id="拓扑分布约束topology-spread-constraints"&gt;拓扑分布约束（Topology Spread Constraints）&lt;/h3&gt;
&lt;p&gt;拓扑分布约束可控制 Pod 在不同故障域（如区域、可用区、节点）间的分布。&lt;/p&gt;
&lt;figure class="mx-auto text-center"&gt;
&lt;img src="https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/overview/topology-spread-constraints.svg" data-img="/zh/book/kubernetes-handbook/scheduling/overview/topology-spread-constraints.svg"
alt="图 5: 拓扑分布约束示意" data-caption="图 5: 拓扑分布约束示意" loading="lazy" decoding="async"
width="1920"
height=" 840"
onerror="handleImageError(this); this.classList.remove('image-loading');"
onload="this.classList.remove('image-loading'); this.classList.add('image-loaded');"
class="image-loading"
style="width: 100%; height: auto;"&gt;
&lt;figcaption&gt;图 5: 拓扑分布约束示意&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;常用字段包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;maxSkew&lt;/code&gt;：最大分布偏差&lt;/li&gt;
&lt;li&gt;&lt;code&gt;topologyKey&lt;/code&gt;：节点标签键&lt;/li&gt;
&lt;li&gt;&lt;code&gt;whenUnsatisfiable&lt;/code&gt;：无法满足约束时的处理方式&lt;/li&gt;
&lt;li&gt;&lt;code&gt;labelSelector&lt;/code&gt;：约束作用的 Pod 选择器&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="污点与容忍taints--tolerations"&gt;污点与容忍（Taints &amp;amp; Tolerations）&lt;/h3&gt;
&lt;p&gt;污点与容忍机制确保 Pod 不会被调度到不合适的节点。&lt;/p&gt;
&lt;figure class="mx-auto text-center"&gt;
&lt;img src="https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/overview/taints-and-tolerations.svg" data-img="/zh/book/kubernetes-handbook/scheduling/overview/taints-and-tolerations.svg"
alt="图 6: 污点与容忍调度示意" data-caption="图 6: 污点与容忍调度示意" loading="lazy" decoding="async"
width="2080"
height=" 840"
onerror="handleImageError(this); this.classList.remove('image-loading');"
onload="this.classList.remove('image-loading'); this.classList.add('image-loaded');"
class="image-loading"
style="width: 100%; height: auto;"&gt;
&lt;figcaption&gt;图 6: 污点与容忍调度示意&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;常见场景包括专用节点、特殊硬件节点、节点压力驱逐等。&lt;/p&gt;
&lt;h2 id="优先级与抢占"&gt;优先级与抢占&lt;/h2&gt;
&lt;p&gt;Kubernetes 支持通过优先级（Priority）指定 Pod 重要性。高优先级 Pod 无法调度时，调度器可抢占低优先级 Pod。&lt;/p&gt;
&lt;h3 id="pod-优先级"&gt;Pod 优先级&lt;/h3&gt;
&lt;p&gt;通过 PriorityClass 对象和 &lt;code&gt;priorityClassName&lt;/code&gt; 字段指定。优先级值越高，Pod 越重要。&lt;/p&gt;
&lt;figure class="mx-auto text-center"&gt;
&lt;img src="https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/overview/pod-priority-classes.svg" data-img="/zh/book/kubernetes-handbook/scheduling/overview/pod-priority-classes.svg"
alt="图 7: Pod 优先级示意" data-caption="图 7: Pod 优先级示意" loading="lazy" decoding="async"
width="1800"
height=" 920"
onerror="handleImageError(this); this.classList.remove('image-loading');"
onload="this.classList.remove('image-loading'); this.classList.add('image-loaded');"
class="image-loading"
style="width: 100%; height: auto;"&gt;
&lt;figcaption&gt;图 7: Pod 优先级示意&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;内置优先级类包括 &lt;code&gt;system-cluster-critical&lt;/code&gt; 和 &lt;code&gt;system-node-critical&lt;/code&gt;。&lt;/p&gt;
&lt;h3 id="抢占机制"&gt;抢占机制&lt;/h3&gt;
&lt;p&gt;抢占流程如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;高优先级 Pod 无法调度&lt;/li&gt;
&lt;li&gt;调度器查找可抢占节点&lt;/li&gt;
&lt;li&gt;选择低优先级 Pod 进行驱逐&lt;/li&gt;
&lt;li&gt;高优先级 Pod 获得调度机会&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="节点压力驱逐"&gt;节点压力驱逐&lt;/h2&gt;
&lt;p&gt;kubelet 监控节点资源压力，主动驱逐 Pod 以防节点故障。&lt;/p&gt;
&lt;h3 id="驱逐信号与阈值"&gt;驱逐信号与阈值&lt;/h3&gt;
&lt;p&gt;kubelet 依据多种信号判断资源压力：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;驱逐信号&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;memory.available&lt;/td&gt;
&lt;td&gt;节点可用内存&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;nodefs.available&lt;/td&gt;
&lt;td&gt;节点文件系统可用空间&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;nodefs.inodesFree&lt;/td&gt;
&lt;td&gt;节点文件系统可用 inode&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;imagefs.available&lt;/td&gt;
&lt;td&gt;镜像存储可用空间&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;pid.available&lt;/td&gt;
&lt;td&gt;可用进程数&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;figcaption class="text-center mb-3"&gt;
表 3: 节点驱逐信号说明
&lt;/figcaption&gt;
&lt;p&gt;阈值分为软阈值（有宽限期）和硬阈值（立即驱逐）。驱逐顺序依次考虑 QoS 类别、资源使用与优先级。&lt;/p&gt;
&lt;h2 id="pod-中断预算pdb"&gt;Pod 中断预算（PDB）&lt;/h2&gt;
&lt;p&gt;Pod Disruption Budget（PDB）用于限制自愿中断（如节点维护、升级）时可同时中断的 Pod 数量。&lt;/p&gt;
&lt;figure class="mx-auto text-center"&gt;
&lt;img src="https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/overview/pdb-protection.svg" data-img="/zh/book/kubernetes-handbook/scheduling/overview/pdb-protection.svg"
alt="图 8: PDB 保护机制示意" data-caption="图 8: PDB 保护机制示意" loading="lazy" decoding="async"
width="2000"
height=" 880"
onerror="handleImageError(this); this.classList.remove('image-loading');"
onload="this.classList.remove('image-loading'); this.classList.add('image-loaded');"
class="image-loading"
style="width: 100%; height: auto;"&gt;
&lt;figcaption&gt;图 8: PDB 保护机制示意&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;PDB 可指定 &lt;code&gt;minAvailable&lt;/code&gt; 或 &lt;code&gt;maxUnavailable&lt;/code&gt;，仅保护自愿中断，不防止节点故障或资源驱逐。&lt;/p&gt;
&lt;h2 id="自动扩缩容autoscaling"&gt;自动扩缩容（Autoscaling）&lt;/h2&gt;
&lt;p&gt;Kubernetes 支持基于指标的自动扩缩容，提升资源利用率。&lt;/p&gt;
&lt;h3 id="水平-pod-自动扩缩容hpa"&gt;水平 Pod 自动扩缩容（HPA）&lt;/h3&gt;
&lt;p&gt;HPA 控制器根据指标自动调整副本数。下图展示了 HPA 工作流程：&lt;/p&gt;
&lt;figure class="mx-auto text-center"&gt;
&lt;img src="https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/overview/hpa-workflow.svg" data-img="/zh/book/kubernetes-handbook/scheduling/overview/hpa-workflow.svg"
alt="图 9: HPA 工作流程" data-caption="图 9: HPA 工作流程" loading="lazy" decoding="async"
width="2360"
height=" 840"
onerror="handleImageError(this); this.classList.remove('image-loading');"
onload="this.classList.remove('image-loading'); this.classList.add('image-loaded');"
class="image-loading"
style="width: 100%; height: auto;"&gt;
&lt;figcaption&gt;图 9: HPA 工作流程&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;HPA 支持 CPU、内存、自定义与外部指标。核心算法如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;desiredReplicas = ceil[currentReplicas * (currentMetricValue / desiredMetricValue)]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="可配置扩缩容策略"&gt;可配置扩缩容策略&lt;/h3&gt;
&lt;p&gt;HPA 支持分别配置扩容与缩容策略：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;behavior&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;scaleDown&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;stabilizationWindowSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;300&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;policies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Percent&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;periodSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;60&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;scaleUp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;stabilizationWindowSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;policies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Percent&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;periodSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;15&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Pods&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;periodSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;15&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;selectPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Max&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;可控制扩缩容速度、窗口期与单次变更幅度。v1.37 起还可在 &lt;code&gt;behavior.scaleUp/scaleDown.tolerance&lt;/code&gt; 中为单个 HPA 设置容差（默认集群级 10%），并以 &lt;code&gt;minReplicas: 0&lt;/code&gt;（Beta，仅自定义/外部指标）实现缩容到零。&lt;/p&gt;
&lt;h3 id="垂直扩缩容与原地调整"&gt;垂直扩缩容与原地调整&lt;/h3&gt;
&lt;p&gt;垂直 Pod 自动扩缩容（VPA）根据历史用量推荐并调整容器的 &lt;code&gt;requests&lt;/code&gt;/&lt;code&gt;limits&lt;/code&gt;。v1.35 GA 的 Pod 原地资源调整让 VPA 的 &lt;code&gt;InPlaceOrRecreate&lt;/code&gt; 模式可以在不重建 Pod 的情况下生效，有状态服务的垂直弹性由此成为可能。同一工作负载不要让 HPA 与 VPA 同时基于 CPU/内存做决策。&lt;/p&gt;
&lt;h3 id="节点级弹性"&gt;节点级弹性&lt;/h3&gt;
&lt;p&gt;HPA 扩出的 Pod 若无节点可调度，由 Cluster Autoscaler（基于节点组）或 Karpenter（按 Pending Pod 需求实时创建合适规格节点）补充节点；两者均依赖 Pod 的 &lt;code&gt;requests&lt;/code&gt; 做容量计算，这也是&amp;quot;始终设置 requests&amp;quot;的又一理由。&lt;/p&gt;
&lt;h2 id="资源装箱bin-packing策略"&gt;资源装箱（Bin Packing）策略&lt;/h2&gt;
&lt;p&gt;Kubernetes 支持多种资源装箱策略，提升集群利用率。&lt;/p&gt;
&lt;h3 id="mostallocated-策略"&gt;MostAllocated 策略&lt;/h3&gt;
&lt;p&gt;MostAllocated 策略倾向于将 Pod 调度到资源利用率高的节点。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;kubescheduler.config.k8s.io/v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;KubeSchedulerConfiguration&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;profiles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="nt"&gt;pluginConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;scoringStrategy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;cpu&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;memory&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;MostAllocated&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;NodeResourcesFit&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="requestedtocapacityratio-策略"&gt;RequestedToCapacityRatio 策略&lt;/h3&gt;
&lt;p&gt;该策略可更细粒度控制资源分配比例，适用于复杂场景。&lt;/p&gt;
&lt;h2 id="多调度器支持"&gt;多调度器支持&lt;/h2&gt;
&lt;p&gt;Kubernetes 支持同时运行多个调度器，满足特殊调度需求。&lt;/p&gt;
&lt;figure class="mx-auto text-center"&gt;
&lt;img src="https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/overview/multi-scheduler.svg" data-img="/zh/book/kubernetes-handbook/scheduling/overview/multi-scheduler.svg"
alt="图 10: 多调度器调度示意" data-caption="图 10: 多调度器调度示意" loading="lazy" decoding="async"
width="1640"
height=" 1200"
onerror="handleImageError(this); this.classList.remove('image-loading');"
onload="this.classList.remove('image-loading'); this.classList.add('image-loaded');"
class="image-loading"
style="width: 100%; height: auto;"&gt;
&lt;figcaption&gt;图 10: 多调度器调度示意&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;通过 Pod 的 &lt;code&gt;schedulerName&lt;/code&gt; 字段指定调度器。&lt;/p&gt;
&lt;h2 id="集群规模与可扩展性"&gt;集群规模与可扩展性&lt;/h2&gt;
&lt;p&gt;Kubernetes 支持大规模集群，常见上限如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;节点数：5000&lt;/li&gt;
&lt;li&gt;总 Pod 数：150,000&lt;/li&gt;
&lt;li&gt;总容器数：300,000&lt;/li&gt;
&lt;li&gt;单节点最大 Pod 数：110&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;大集群需关注控制面容量、资源配额、云厂商限制、网络与存储性能等。&lt;/p&gt;
&lt;h2 id="本章导读"&gt;本章导读&lt;/h2&gt;
&lt;p&gt;本章其余文章按&amp;quot;调度 → 资源管理 → 弹性&amp;quot;的顺序展开：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;主题&lt;/th&gt;
&lt;th&gt;文章&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;调度器工作原理与调度框架&lt;/td&gt;
&lt;td&gt;&lt;a href="../kube-scheduler"&gt;kube-scheduler 资源调度&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;nodeSelector、亲和性、拓扑分布约束&lt;/td&gt;
&lt;td&gt;&lt;a href="../scheduling-constraints"&gt;调度约束&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PriorityClass、抢占与 PDB 的交互&lt;/td&gt;
&lt;td&gt;&lt;a href="../priority-and-preemption"&gt;优先级与抢占&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Guaranteed/Burstable/BestEffort 与驱逐顺序&lt;/td&gt;
&lt;td&gt;&lt;a href="../qos"&gt;服务质量等级&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;命名空间级配额与默认资源&lt;/td&gt;
&lt;td&gt;&lt;a href="../resource-quota-and-limitrange"&gt;ResourceQuota 与 LimitRange&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;资源预留、节点压力驱逐、CPU/内存/拓扑管理器&lt;/td&gt;
&lt;td&gt;&lt;a href="../kubelet-resource-management"&gt;kubelet 节点资源管理&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;基于指标的水平扩缩&lt;/td&gt;
&lt;td&gt;&lt;a href="../hpa"&gt;Horizontal Pod Autoscaling&lt;/a&gt;、&lt;a href="../custom-autoscaler"&gt;自定义 Pod 自动扩缩容器&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;纵向扩缩与事件驱动扩缩&lt;/td&gt;
&lt;td&gt;&lt;a href="../vpa-and-keda"&gt;VPA 与 KEDA&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;节点层弹性&lt;/td&gt;
&lt;td&gt;&lt;a href="../node-autoscaling"&gt;节点自动扩缩&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;批处理与 AI 的成组调度&lt;/td&gt;
&lt;td&gt;&lt;a href="../volcano"&gt;Volcano 批处理调度器&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;figcaption class="text-center mb-3"&gt;
表 4: 调度与弹性章节导读
&lt;/figcaption&gt;
&lt;h2 id="总结"&gt;总结&lt;/h2&gt;
&lt;p&gt;Kubernetes 通过灵活的调度与资源管理体系，实现了高效的工作负载分布、资源利用与弹性伸缩。合理配置调度策略、资源限制、优先级与自动扩缩容机制，可显著提升集群的性能、可靠性与可维护性。&lt;/p&gt;
&lt;h2 id="参考文献"&gt;参考文献&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/" target="_blank" rel="noopener"&gt;Pod Priority and Preemption - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/scheduling-eviction/scheduling-framework/" target="_blank" rel="noopener"&gt;Kubernetes Scheduling - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/" target="_blank" rel="noopener"&gt;Resource Management for Pods and Containers - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/" target="_blank" rel="noopener"&gt;Horizontal Pod Autoscaler - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/workloads/pods/disruptions/" target="_blank" rel="noopener"&gt;Pod Disruption Budgets - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</content:encoded></item><item><title>资源调度</title><link>https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/kube-scheduler/</link><pubDate>Sat, 21 May 2022 00:00:00 +0800</pubDate><author>Jimmy Song</author><guid>https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/kube-scheduler/</guid><description>深入探讨 Kubernetes 中的资源调度机制，包括 kube-scheduler 组件的工作原理、调度策略、高级调度功能以及相关的扩展工具。</description><content:encoded>
&lt;blockquote&gt;
&lt;p&gt;资源调度是 Kubernetes 实现弹性伸缩与高效资源利用的核心能力，合理配置调度策略可显著提升集群稳定性与业务连续性。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Kubernetes 作为现代容器编排调度平台，资源调度是其核心功能之一。本节将深入探讨 Kubernetes 中的资源调度机制，包括调度器的工作原理、调度策略以及高级调度场景。&lt;/p&gt;
&lt;h2 id="调度器组件"&gt;调度器组件&lt;/h2&gt;
&lt;p&gt;Kubernetes 的调度器（kube-scheduler）负责将新建的 Pod 分配到合适的节点上。理解其工作原理有助于优化资源分配和业务弹性。&lt;/p&gt;
&lt;h3 id="kube-scheduler-工作原理"&gt;kube-scheduler 工作原理&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;kube-scheduler&lt;/code&gt; 是 Kubernetes 集群中负责 Pod 调度的核心组件，其主要职责包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;监听 &lt;code&gt;kube-apiserver&lt;/code&gt; 中未调度的 Pod&lt;/li&gt;
&lt;li&gt;根据调度算法为 Pod 选择合适的节点&lt;/li&gt;
&lt;li&gt;通过预选和优选两个阶段完成调度决策&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="调度流程"&gt;调度流程&lt;/h3&gt;
&lt;p&gt;Kubernetes 调度流程分为以下三个阶段：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;预选阶段（Filtering）&lt;/strong&gt;：过滤掉不满足 Pod 运行条件的节点&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;优选阶段（Scoring）&lt;/strong&gt;：对候选节点进行评分，选择最优节点&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;绑定阶段（Binding）&lt;/strong&gt;：将 Pod 分配到选定的节点上&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="调度策略"&gt;调度策略&lt;/h2&gt;
&lt;p&gt;Kubernetes 支持多种调度策略，适配不同类型的工作负载和业务需求。下表总结了常见工作负载的调度特性。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;资源类型&lt;/th&gt;
&lt;th&gt;调度特性&lt;/th&gt;
&lt;th&gt;典型场景&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Deployment&lt;/td&gt;
&lt;td&gt;副本分散调度&lt;/td&gt;
&lt;td&gt;无状态服务&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DaemonSet&lt;/td&gt;
&lt;td&gt;每节点运行一个 Pod 副本&lt;/td&gt;
&lt;td&gt;节点级守护进程&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;StatefulSet&lt;/td&gt;
&lt;td&gt;有序调度，稳定标识&lt;/td&gt;
&lt;td&gt;有状态服务&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;figcaption class="text-center mb-3"&gt;
表 1: Kubernetes 工作负载调度策略对比
&lt;/figcaption&gt;
&lt;h3 id="高级调度功能"&gt;高级调度功能&lt;/h3&gt;
&lt;p&gt;通过为节点和 Pod 添加标签（Labels）和污点（Taints），可以实现更精细的调度控制。常见高级调度机制包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;节点选择器（NodeSelector）&lt;/strong&gt;：通过标签选择目标节点&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;节点亲和性（Node Affinity）&lt;/strong&gt;：表达更复杂的节点选择规则&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pod 亲和性和反亲和性（Pod Affinity/Anti-Affinity）&lt;/strong&gt;：控制 Pod 之间的调度关系&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;污点和容忍（Taints and Tolerations）&lt;/strong&gt;：实现节点隔离与专用资源分配&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;拓扑分布约束（Topology Spread Constraints）&lt;/strong&gt;：按可用区、节点等拓扑域均匀分布 Pod，是跨可用区高可用的首选手段&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;优先级与抢占（PriorityClass）&lt;/strong&gt;：高优先级 Pod 在资源不足时可抢占低优先级 Pod&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;调度门控（Scheduling Gates，v1.30 GA）&lt;/strong&gt;：Pod 创建时带有 &lt;code&gt;spec.schedulingGates&lt;/code&gt;，在外部控制器移除门控前调度器不会处理它，为配额、预算等外部准入提供挂钩&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;动态资源分配（DRA，v1.34 GA）&lt;/strong&gt;：调度器根据 &lt;code&gt;ResourceClaim&lt;/code&gt; 为 Pod 挑选同时满足 CPU/内存与 GPU 等设备约束的节点&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;成组调度（Gang Scheduling）&lt;/strong&gt;：&lt;code&gt;Workload&lt;/code&gt;/&lt;code&gt;PodGroup&lt;/code&gt; API（v1.35 Alpha，v1.37 Beta 但默认关闭）让一组 Pod 要么全部调度、要么全部等待，面向分布式训练等场景&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以下示例展示了拓扑分布约束与调度门控的用法：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Pod&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;web&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;web&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;schedulingGates&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;example.com/quota-check &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 由外部控制器在校验通过后移除&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;topologySpreadConstraints&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;maxSkew&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;topologyKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;topology.kubernetes.io/zone&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;whenUnsatisfiable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;DoNotSchedule&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;labelSelector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;matchLabels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;web&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;web&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;nginx:1.27&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="动态调度扩展"&gt;动态调度扩展&lt;/h2&gt;
&lt;p&gt;在实际生产环境中，调度需求常常随着业务变化而动态调整。Kubernetes 支持多种扩展方式以满足复杂场景。&lt;/p&gt;
&lt;h3 id="重调度场景"&gt;重调度场景&lt;/h3&gt;
&lt;p&gt;当需要对已调度的 Pod 进行重新分配时，常见场景包括集群负载均衡和数据本地性优化。&lt;/p&gt;
&lt;h4 id="集群负载均衡"&gt;集群负载均衡&lt;/h4&gt;
&lt;p&gt;当集群中新增节点时，可能需要重新平衡各节点的资源利用率。原生 kube-scheduler 不支持 Pod 的重调度，可借助如下工具：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://github.com/kubernetes-sigs/descheduler" target="_blank" rel="noopener"&gt;Descheduler&lt;/a&gt;&lt;/strong&gt;：用于驱逐过载节点上的 Pod，实现集群负载重平衡&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="数据本地性优化"&gt;数据本地性优化&lt;/h4&gt;
&lt;p&gt;对于大数据和批处理应用，Pod 的调度需要考虑数据分布：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://volcano.sh/" target="_blank" rel="noopener"&gt;Volcano&lt;/a&gt;&lt;/strong&gt;（原 kube-batch）：专为批处理和机器学习工作负载设计的调度器，支持队列管理、资源配额和任务调度&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://kueue.sigs.k8s.io/" target="_blank" rel="noopener"&gt;Kueue&lt;/a&gt;&lt;/strong&gt;：Kubernetes SIG 维护的作业排队系统，不替换调度器，而是通过调度门控控制 Job/JobSet 何时进入调度，实现配额与公平共享&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://karpenter.sh/" target="_blank" rel="noopener"&gt;Karpenter&lt;/a&gt;&lt;/strong&gt;：按待调度 Pod 的实际需求实时创建合适规格的节点，取代传统 Cluster Autoscaler 的节点组模型&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="扩展调度器"&gt;扩展调度器&lt;/h3&gt;
&lt;p&gt;Kubernetes 支持多调度器和调度器扩展，便于自定义调度逻辑和策略。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;多调度器&lt;/strong&gt;：同时运行多个调度器实例，Pod 通过 &lt;code&gt;spec.schedulerName&lt;/code&gt; 选择&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;调度器扩展&lt;/strong&gt;：通过 Scheduler Framework 插件机制在 PreFilter、Filter、Score、Bind 等扩展点自定义调度流程&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;调度器配置&lt;/strong&gt;：通过 &lt;code&gt;KubeSchedulerConfiguration&lt;/code&gt;（&lt;code&gt;kubescheduler.config.k8s.io/v1&lt;/code&gt;）启用/禁用插件、配置多个 profile&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;调度器框架与插件开发详见 &lt;a href="../../extend/scheduler-extension"&gt;调度架构与 Framework 扩展&lt;/a&gt;。&lt;/p&gt;
&lt;h2 id="最佳实践"&gt;最佳实践&lt;/h2&gt;
&lt;p&gt;为提升调度效率和集群稳定性，建议遵循以下实践：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;合理设置资源请求和限制，确保调度器能够做出正确的调度决策&lt;/li&gt;
&lt;li&gt;使用节点标签和选择器，实现精确的节点选择&lt;/li&gt;
&lt;li&gt;跨可用区部署优先使用拓扑分布约束，而不是只靠 Pod 反亲和性&lt;/li&gt;
&lt;li&gt;为关键系统组件设置 PriorityClass，保证资源紧张时优先运行&lt;/li&gt;
&lt;li&gt;监控 &lt;code&gt;scheduler_pending_pods&lt;/code&gt;、&lt;code&gt;scheduler_scheduling_attempt_duration_seconds&lt;/code&gt; 等指标，及时发现和解决调度瓶颈&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="总结"&gt;总结&lt;/h2&gt;
&lt;p&gt;Kubernetes 资源调度机制通过灵活的调度策略和可扩展的调度框架，实现了高效的资源分配与业务弹性。掌握调度原理与高级功能，有助于构建稳定、可扩展的云原生集群环境。&lt;/p&gt;
&lt;h2 id="参考文献"&gt;参考文献&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/scheduling-eviction/kube-scheduler/" target="_blank" rel="noopener"&gt;Kubernetes Scheduler - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/scheduling-eviction/pod-scheduling-readiness/" target="_blank" rel="noopener"&gt;Pod Scheduling Readiness - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/" target="_blank" rel="noopener"&gt;Pod Topology Spread Constraints - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>调度约束：节点选择、亲和性与拓扑分布</title><link>https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/scheduling-constraints/</link><pubDate>Sun, 01 Nov 2026 00:00:00 +0800</pubDate><author>Jimmy Song</author><guid>https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/scheduling-constraints/</guid><description>系统介绍 Kubernetes 中控制 Pod 落点的四类调度约束：nodeSelector、节点亲和性、Pod 亲和/反亲和、拓扑分布约束，解释硬/软约束语义、拓扑键、matchLabelKeys、minDomains、nodeAffinityPolicy 等字段，并给出跨可用区高可用部署的推荐组合。</description><content:encoded>
&lt;blockquote&gt;
&lt;p&gt;调度约束表达的是业务对&amp;quot;在哪里运行&amp;quot;的意图：高可用要分散、低延迟要聚合、特殊硬件要匹配——四种机制各管一段，组合起来才是完整答案。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;默认情况下 kube-scheduler 只保证 Pod 落到有足够资源的节点上，不关心 Pod 之间的相对位置。但真实的生产需求远不止于此：数据库副本必须分布在不同可用区，GPU 任务必须落到带特定型号显卡的节点，缓存应与访问它的服务同处一个机架，同一服务的副本要尽量均匀铺开而不是挤在一台机器上。Kubernetes 提供了四类调度约束来表达这些意图，本文逐一介绍并说明如何组合使用。&lt;/p&gt;
&lt;h2 id="四类约束概览"&gt;四类约束概览&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;机制&lt;/th&gt;
&lt;th&gt;字段&lt;/th&gt;
&lt;th&gt;决策依据&lt;/th&gt;
&lt;th&gt;支持软约束&lt;/th&gt;
&lt;th&gt;典型用途&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;节点选择器&lt;/td&gt;
&lt;td&gt;&lt;code&gt;spec.nodeSelector&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;节点标签精确匹配&lt;/td&gt;
&lt;td&gt;否&lt;/td&gt;
&lt;td&gt;简单的&amp;quot;只能跑在某类节点&amp;quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;节点亲和性&lt;/td&gt;
&lt;td&gt;&lt;code&gt;spec.affinity.nodeAffinity&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;节点标签表达式（In/NotIn/Exists/Gt/Lt）&lt;/td&gt;
&lt;td&gt;是&lt;/td&gt;
&lt;td&gt;复杂节点选择、偏好某类节点&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pod 亲和/反亲和&lt;/td&gt;
&lt;td&gt;&lt;code&gt;spec.affinity.podAffinity&lt;/code&gt; / &lt;code&gt;podAntiAffinity&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;拓扑域内是否已有匹配标签的 Pod&lt;/td&gt;
&lt;td&gt;是&lt;/td&gt;
&lt;td&gt;与某服务同置、副本互斥&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;拓扑分布约束&lt;/td&gt;
&lt;td&gt;&lt;code&gt;spec.topologySpreadConstraints&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;各拓扑域内匹配 Pod 的数量差&lt;/td&gt;
&lt;td&gt;是&lt;/td&gt;
&lt;td&gt;跨可用区/节点均匀分布&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;figcaption class="text-center mb-3"&gt;
表 1: Kubernetes 调度约束对比
&lt;/figcaption&gt;
&lt;p&gt;除这四类外，污点与容忍（见 &lt;a href="../../cluster/taint-and-toleration"&gt;Taint 和 Toleration&lt;/a&gt;）从节点侧&amp;quot;排斥&amp;quot;Pod，与亲和性从 Pod 侧&amp;quot;选择&amp;quot;节点互为补充；&lt;code&gt;spec.nodeName&lt;/code&gt; 则完全绕过调度器直接绑定节点，仅用于静态 Pod 等特殊场景。&lt;/p&gt;
&lt;h2 id="节点选择器"&gt;节点选择器&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;nodeSelector&lt;/code&gt; 是最简单的约束：Pod 只会被调度到拥有全部指定标签的节点。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Pod&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;gpu-job&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;nodeSelector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;nvidia.com/gpu.product&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;NVIDIA-H100-80GB-HBM3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;topology.kubernetes.io/zone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;cn-beijing-a&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;train&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;my-trainer:1.0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Kubernetes 为每个节点自动维护一组众所周知的标签，是编写约束时最常用的拓扑键：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;标签&lt;/th&gt;
&lt;th&gt;含义&lt;/th&gt;
&lt;th&gt;设置者&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;kubernetes.io/hostname&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;节点主机名&lt;/td&gt;
&lt;td&gt;kubelet&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;kubernetes.io/os&lt;/code&gt;、&lt;code&gt;kubernetes.io/arch&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;操作系统与 CPU 架构（linux/amd64、arm64 等）&lt;/td&gt;
&lt;td&gt;kubelet&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;topology.kubernetes.io/zone&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;可用区&lt;/td&gt;
&lt;td&gt;云控制器 / 管理员&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;topology.kubernetes.io/region&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;地域&lt;/td&gt;
&lt;td&gt;云控制器 / 管理员&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;node.kubernetes.io/instance-type&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;云实例规格&lt;/td&gt;
&lt;td&gt;云控制器&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;node-role.kubernetes.io/control-plane&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;控制面节点&lt;/td&gt;
&lt;td&gt;kubeadm&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;figcaption class="text-center mb-3"&gt;
表 2: 常用的内建节点标签
&lt;/figcaption&gt;
&lt;p&gt;GPU 型号、内核特性等硬件标签通常由 &lt;a href="https://kubernetes-sigs.github.io/node-feature-discovery/" target="_blank" rel="noopener"&gt;Node Feature Discovery&lt;/a&gt;（NFD）或 NVIDIA GPU Feature Discovery 自动打上。&lt;/p&gt;
&lt;h2 id="节点亲和性"&gt;节点亲和性&lt;/h2&gt;
&lt;p&gt;节点亲和性是 &lt;code&gt;nodeSelector&lt;/code&gt; 的超集，支持集合运算符、多组条件以及&amp;quot;尽量满足&amp;quot;的软约束：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;affinity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;nodeAffinity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;requiredDuringSchedulingIgnoredDuringExecution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 硬约束：不满足则不调度&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;nodeSelectorTerms&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;matchExpressions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;topology.kubernetes.io/zone&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;In&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="l"&gt;cn-beijing-a, cn-beijing-b]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;node.kubernetes.io/instance-type&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;NotIn&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="l"&gt;ecs.t6-c1m1.large]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;preferredDuringSchedulingIgnoredDuringExecution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 软约束：按权重加分&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;preference&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;matchExpressions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;karpenter.sh/capacity-type&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;In&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="l"&gt;spot]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;preference&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;matchExpressions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;node.kubernetes.io/instance-type&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;In&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="l"&gt;ecs.g8i.xlarge]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;语义要点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;nodeSelectorTerms&lt;/code&gt; 中的多个条目是&lt;strong&gt;或&lt;/strong&gt;关系，单个条目内的 &lt;code&gt;matchExpressions&lt;/code&gt; 是&lt;strong&gt;与&lt;/strong&gt;关系&lt;/li&gt;
&lt;li&gt;&lt;code&gt;IgnoredDuringExecution&lt;/code&gt; 表示约束只在调度时评估，Pod 运行后节点标签变化不会触发驱逐；&lt;code&gt;RequiredDuringExecution&lt;/code&gt; 变体至今未实现，需要该语义时可用污点的 &lt;code&gt;NoExecute&lt;/code&gt; 效果&lt;/li&gt;
&lt;li&gt;软约束的 &lt;code&gt;weight&lt;/code&gt; 取值 1 – 100，调度器把所有满足的偏好权重相加作为该节点的亲和性得分，再与其他打分插件的结果合并&lt;/li&gt;
&lt;li&gt;运算符 &lt;code&gt;Gt&lt;/code&gt;/&lt;code&gt;Lt&lt;/code&gt; 只对整数字符串有效，常用于按 CPU 核数、显存大小等数值标签筛选&lt;/li&gt;
&lt;li&gt;&lt;code&gt;matchFields&lt;/code&gt; 可按节点字段（目前仅 &lt;code&gt;metadata.name&lt;/code&gt;）匹配&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="pod-亲和性与反亲和性"&gt;Pod 亲和性与反亲和性&lt;/h2&gt;
&lt;p&gt;Pod 亲和性依据&lt;strong&gt;其他 Pod 的位置&lt;/strong&gt;做决策：在某个拓扑域（由 &lt;code&gt;topologyKey&lt;/code&gt; 指定的节点标签划分）内，若已存在匹配 &lt;code&gt;labelSelector&lt;/code&gt; 的 Pod，则该域对当前 Pod 具有亲和（吸引）或反亲和（排斥）效果。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;affinity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;podAffinity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;requiredDuringSchedulingIgnoredDuringExecution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;labelSelector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;matchLabels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;redis-cache&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;topologyKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;topology.kubernetes.io/zone &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 与缓存同可用区&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;podAntiAffinity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;requiredDuringSchedulingIgnoredDuringExecution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;labelSelector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;matchLabels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;web&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;topologyKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;kubernetes.io/hostname &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 同一节点不放两个 web 副本&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;preferredDuringSchedulingIgnoredDuringExecution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;podAffinityTerm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;labelSelector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;matchLabels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;web&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;topologyKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;topology.kubernetes.io/zone &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 尽量跨可用区&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;几个实践中容易踩坑的细节：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;labelSelector&lt;/code&gt; 默认只匹配&lt;strong&gt;同命名空间&lt;/strong&gt;的 Pod，跨命名空间需显式写 &lt;code&gt;namespaces&lt;/code&gt; 或 &lt;code&gt;namespaceSelector&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;硬反亲和 + &lt;code&gt;topologyKey: kubernetes.io/hostname&lt;/code&gt; 意味着副本数不能超过节点数，扩容时会出现 Pending；跨可用区分散更推荐用拓扑分布约束&lt;/li&gt;
&lt;li&gt;Pod 亲和性需要扫描所有节点上的 Pod，在数千节点集群中开销显著高于节点亲和性，应避免在大规模 DaemonSet 类工作负载上使用&lt;/li&gt;
&lt;li&gt;&lt;code&gt;matchLabelKeys&lt;/code&gt;（v1.33 GA）可把当前 Pod 自身的某些标签值自动合并进 &lt;code&gt;labelSelector&lt;/code&gt;，典型用法是加上 &lt;code&gt;pod-template-hash&lt;/code&gt;，让反亲和只在&lt;strong&gt;同一次 Deployment 版本&lt;/strong&gt;的副本间生效，避免滚动更新时新旧版本互相排斥导致卡住：&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;podAntiAffinity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;requiredDuringSchedulingIgnoredDuringExecution&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;labelSelector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;matchLabels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;web&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;matchLabelKeys&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="l"&gt;pod-template-hash]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;topologyKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;kubernetes.io/hostname&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;mismatchLabelKeys&lt;/code&gt; 则相反，用于&amp;quot;与标签值不同的 Pod 共置&amp;quot;，例如多租户场景中让不同 &lt;code&gt;tenant&lt;/code&gt; 的 Pod 分开。&lt;/p&gt;
&lt;h2 id="拓扑分布约束"&gt;拓扑分布约束&lt;/h2&gt;
&lt;p&gt;拓扑分布约束（Topology Spread Constraints）解决的是&amp;quot;均匀铺开&amp;quot;问题：以 &lt;code&gt;topologyKey&lt;/code&gt; 划分拓扑域，要求各域内匹配 Pod 的数量之差不超过 &lt;code&gt;maxSkew&lt;/code&gt;。相比反亲和性的&amp;quot;要么同域要么不同域&amp;quot;二元语义，它能表达&amp;quot;3 个可用区各放 2 个副本&amp;quot;这样的量化分布，且在域数少于副本数时仍可正常工作。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;apps/v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Deployment&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;web&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;replicas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;matchLabels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;web&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;web&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;topologySpreadConstraints&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;maxSkew&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;topologyKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;topology.kubernetes.io/zone&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;whenUnsatisfiable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;DoNotSchedule &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 硬约束&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;labelSelector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;matchLabels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;web&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;matchLabelKeys&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="l"&gt;pod-template-hash] &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 只在同一版本内计算倾斜&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;minDomains&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 至少铺开到 3 个可用区&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;maxSkew&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;topologyKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;kubernetes.io/hostname&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;whenUnsatisfiable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ScheduleAnyway &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 软约束：尽量按节点均匀&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;labelSelector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;matchLabels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;web&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;web&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;nginx:1.27&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;字段&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;状态&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;maxSkew&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;任意两个拓扑域内匹配 Pod 数量的最大允许差值，必须 ≥ 1&lt;/td&gt;
&lt;td&gt;GA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;topologyKey&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;划分拓扑域的节点标签键&lt;/td&gt;
&lt;td&gt;GA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;whenUnsatisfiable&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;DoNotSchedule&lt;/code&gt;（硬）或 &lt;code&gt;ScheduleAnyway&lt;/code&gt;（软，尽量减小倾斜）&lt;/td&gt;
&lt;td&gt;GA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;labelSelector&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;统计哪些 Pod&lt;/td&gt;
&lt;td&gt;GA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;matchLabelKeys&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;把当前 Pod 的指定标签值并入选择器，滚动更新时避免新旧版本混算&lt;/td&gt;
&lt;td&gt;v1.27 Beta，v1.34 起与 &lt;code&gt;labelSelector&lt;/code&gt; 合并语义 Beta&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;minDomains&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;拓扑域少于该值时视为倾斜，迫使调度器&amp;quot;撑开&amp;quot;域数；仅 &lt;code&gt;DoNotSchedule&lt;/code&gt; 时有效&lt;/td&gt;
&lt;td&gt;v1.30 GA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nodeAffinityPolicy&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;计算倾斜时是否只统计满足 Pod 节点亲和性的节点（默认 &lt;code&gt;Honor&lt;/code&gt;）&lt;/td&gt;
&lt;td&gt;v1.33 GA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nodeTaintsPolicy&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;计算倾斜时是否排除有不可容忍污点的节点（默认 &lt;code&gt;Ignore&lt;/code&gt;）&lt;/td&gt;
&lt;td&gt;v1.33 GA&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;figcaption class="text-center mb-3"&gt;
表 3: 拓扑分布约束字段说明
&lt;/figcaption&gt;
&lt;p&gt;两个经常被忽视的默认行为：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;拓扑域的集合由&lt;strong&gt;集群中存在的节点标签值&lt;/strong&gt;决定。若某可用区暂时没有节点（例如节点池缩容到零），该域不会被计入，&lt;code&gt;minDomains&lt;/code&gt; 正是为此而设&lt;/li&gt;
&lt;li&gt;默认 &lt;code&gt;nodeTaintsPolicy: Ignore&lt;/code&gt; 会把带污点的节点（如控制面节点）也算进拓扑域，可能导致&amp;quot;控制面所在可用区副本为 0&amp;quot;被判定为倾斜而无法调度，生产中通常应设为 &lt;code&gt;Honor&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="集群级默认约束"&gt;集群级默认约束&lt;/h3&gt;
&lt;p&gt;管理员可以在调度器配置中为所有未声明 &lt;code&gt;topologySpreadConstraints&lt;/code&gt; 的 Pod 设置默认约束。Kubernetes 自身的内建默认值是：按可用区 &lt;code&gt;maxSkew: 3&lt;/code&gt; 软约束、按主机名 &lt;code&gt;maxSkew: 5&lt;/code&gt; 软约束，均只统计同一 Service/ReplicaSet/StatefulSet 下的 Pod。可通过 &lt;code&gt;PodTopologySpread&lt;/code&gt; 插件参数覆盖：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;kubescheduler.config.k8s.io/v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;KubeSchedulerConfiguration&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;profiles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="nt"&gt;schedulerName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;default-scheduler&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;pluginConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;PodTopologySpread&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;defaultConstraints&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;maxSkew&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;topologyKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;topology.kubernetes.io/zone&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;whenUnsatisfiable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ScheduleAnyway&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;defaultingType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;List&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="推荐组合"&gt;推荐组合&lt;/h2&gt;
&lt;p&gt;不同目标对应的推荐写法如下：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;目标&lt;/th&gt;
&lt;th&gt;推荐做法&lt;/th&gt;
&lt;th&gt;不推荐&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;跨可用区高可用&lt;/td&gt;
&lt;td&gt;&lt;code&gt;topologySpreadConstraints&lt;/code&gt;（zone，&lt;code&gt;DoNotSchedule&lt;/code&gt;，&lt;code&gt;minDomains&lt;/code&gt;）+ 按节点的软分布&lt;/td&gt;
&lt;td&gt;硬 Pod 反亲和（域数不足即 Pending）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;同节点最多一个副本&lt;/td&gt;
&lt;td&gt;拓扑分布按 &lt;code&gt;hostname&lt;/code&gt;、&lt;code&gt;maxSkew: 1&lt;/code&gt;、&lt;code&gt;DoNotSchedule&lt;/code&gt;；或硬反亲和 + &lt;code&gt;matchLabelKeys&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;不带 &lt;code&gt;matchLabelKeys&lt;/code&gt; 的硬反亲和（滚动更新易卡住）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;必须使用特定硬件&lt;/td&gt;
&lt;td&gt;&lt;code&gt;nodeAffinity&lt;/code&gt; 硬约束 + 节点污点让其他 Pod 远离；GPU 场景优先用 DRA 按属性申请&lt;/td&gt;
&lt;td&gt;仅靠 &lt;code&gt;nodeSelector&lt;/code&gt; 而不加污点，普通 Pod 会挤占昂贵节点&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;与依赖服务就近&lt;/td&gt;
&lt;td&gt;软 Pod 亲和（zone），配合 Service &lt;code&gt;trafficDistribution: PreferSameZone&lt;/code&gt; 让流量也就近&lt;/td&gt;
&lt;td&gt;硬亲和（依赖服务不可用时自身也无法调度）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;偏好 Spot 节点但允许回退&lt;/td&gt;
&lt;td&gt;&lt;code&gt;preferredDuringScheduling&lt;/code&gt; 节点亲和 + 容忍 Spot 污点&lt;/td&gt;
&lt;td&gt;硬约束到 Spot（容量不足时 Pending）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;关键系统组件独占节点&lt;/td&gt;
&lt;td&gt;节点污点 &lt;code&gt;NoSchedule&lt;/code&gt; + 组件容忍 + &lt;code&gt;nodeAffinity&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;仅靠亲和性（无法阻止其他 Pod 进入）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;figcaption class="text-center mb-3"&gt;
表 4: 常见调度目标与推荐约束组合
&lt;/figcaption&gt;
&lt;p&gt;所有约束都只在&lt;strong&gt;调度时&lt;/strong&gt;评估。若运行后期望重新平衡（例如新增可用区后让副本分散过去），需要借助 &lt;a href="https://github.com/kubernetes-sigs/descheduler" target="_blank" rel="noopener"&gt;Descheduler&lt;/a&gt; 的 &lt;code&gt;RemovePodsViolatingTopologySpreadConstraint&lt;/code&gt; 等策略驱逐后重调度。&lt;/p&gt;
&lt;h2 id="排查调度失败"&gt;排查调度失败&lt;/h2&gt;
&lt;p&gt;Pod 因约束无法调度时会停留在 &lt;code&gt;Pending&lt;/code&gt;，&lt;code&gt;kubectl describe pod&lt;/code&gt; 的事件中会给出各插件的过滤结果：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Warning FailedScheduling 0/12 nodes are available: 3 node(s) didn&amp;#39;t match pod topology spread constraints,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;4 node(s) didn&amp;#39;t match Pod&amp;#39;s node affinity/selector, 5 node(s) had untolerated taint {dedicated: gpu}.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;preemption: 0/12 nodes are available: 12 Preemption is not helpful for scheduling.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;依据消息逐项核对标签、拓扑域与污点，通常即可定位。&lt;code&gt;kubectl get nodes -L topology.kubernetes.io/zone&lt;/code&gt; 可快速查看拓扑分布，&lt;code&gt;kubectl get pods -o wide --sort-by=.spec.nodeName&lt;/code&gt; 查看实际落点。&lt;/p&gt;
&lt;h2 id="总结"&gt;总结&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;nodeSelector&lt;/code&gt; 与节点亲和性回答&amp;quot;能去哪些节点&amp;quot;，Pod 亲和/反亲和回答&amp;quot;和谁在一起或分开&amp;quot;，拓扑分布约束回答&amp;quot;如何均匀铺开&amp;quot;。生产中最常见的高可用部署应以拓扑分布约束为主、辅以 &lt;code&gt;matchLabelKeys&lt;/code&gt; 避免滚动更新干扰，并把硬约束留给真正不可妥协的场景；对 GPU 等异构资源，则逐步把选择逻辑从节点标签迁移到 DRA 的属性选择器。&lt;/p&gt;
&lt;h2 id="参考文献"&gt;参考文献&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/" target="_blank" rel="noopener"&gt;Assigning Pods to Nodes - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/" target="_blank" rel="noopener"&gt;Pod Topology Spread Constraints - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/reference/labels-annotations-taints/" target="_blank" rel="noopener"&gt;Well-Known Labels, Annotations and Taints - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/reference/scheduling/config/" target="_blank" rel="noopener"&gt;Scheduler Configuration - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>Pod 优先级与抢占</title><link>https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/priority-and-preemption/</link><pubDate>Sun, 01 Nov 2026 00:00:00 +0800</pubDate><author>Jimmy Song</author><guid>https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/priority-and-preemption/</guid><description>介绍 PriorityClass 与 Pod 抢占机制：优先级如何影响调度队列顺序、资源不足时调度器如何选择牺牲者、preemptionPolicy: Never 的非抢占优先级、与 PDB 和优雅终止的交互、内建系统优先级类、异步抢占（v1.33 Beta）以及在批处理与多租户场景中的配额治理。</description><content:encoded>
&lt;blockquote&gt;
&lt;p&gt;优先级决定了资源紧张时谁先上车、谁被请下车；用好它能保护关键业务，用错了会让集群陷入互相抢占的内耗。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;集群资源总有耗尽的时候。没有优先级机制时，Pod 只能按到达顺序排队，一个低价值的批处理任务可能占着节点让核心服务的新副本永远 Pending。Pod 优先级（Priority）与抢占（Preemption）为此提供了两层能力：&lt;strong&gt;优先级&lt;/strong&gt;决定调度队列中的先后顺序，&lt;strong&gt;抢占&lt;/strong&gt;允许高优先级 Pod 在没有可用节点时驱逐低优先级 Pod 腾出空间。该机制自 v1.14 GA，是生产集群容量治理的基础设施。&lt;/p&gt;
&lt;h2 id="priorityclass"&gt;PriorityClass&lt;/h2&gt;
&lt;p&gt;优先级通过集群级资源 &lt;code&gt;PriorityClass&lt;/code&gt; 定义，Pod 用 &lt;code&gt;spec.priorityClassName&lt;/code&gt; 引用，准入控制器据此填充 &lt;code&gt;spec.priority&lt;/code&gt; 整数值：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;scheduling.k8s.io/v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;PriorityClass&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;business-critical&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1000000&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;globalDefault&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;preemptionPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;PreemptLowerPriority &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 默认值；设为 Never 则不抢占&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;面向客户的核心服务，资源不足时可抢占低优先级工作负载&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Pod&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;checkout-api&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;priorityClassName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;business-critical&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;api&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;checkout-api:2.3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;字段语义如下：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;字段&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;value&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;32 位整数，越大优先级越高；用户可用范围上限为 10 亿（1000000000），更高的值保留给系统&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;globalDefault&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;为 &lt;code&gt;true&lt;/code&gt; 时作为未指定 &lt;code&gt;priorityClassName&lt;/code&gt; 的 Pod 的默认优先级；集群中只能有一个，且只影响之后创建的 Pod&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;preemptionPolicy&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PreemptLowerPriority&lt;/code&gt;（默认，可抢占）或 &lt;code&gt;Never&lt;/code&gt;（只排队不抢占）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;description&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;供人阅读的用途说明&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;figcaption class="text-center mb-3"&gt;
表 1: PriorityClass 字段说明
&lt;/figcaption&gt;
&lt;p&gt;未设置 &lt;code&gt;globalDefault&lt;/code&gt; 时，没有指定优先级类的 Pod 优先级为 0。&lt;code&gt;PriorityClass&lt;/code&gt; 创建后 &lt;code&gt;value&lt;/code&gt; 不可修改；删除后已有 Pod 保留其整数优先级，新 Pod 引用该名称会被拒绝。&lt;/p&gt;
&lt;h3 id="内建系统优先级类"&gt;内建系统优先级类&lt;/h3&gt;
&lt;p&gt;Kubernetes 预置两个只允许在 &lt;code&gt;kube-system&lt;/code&gt; 命名空间使用的优先级类，值高于用户上限，保证控制面组件与关键插件不会被业务 Pod 抢占：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;名称&lt;/th&gt;
&lt;th&gt;值&lt;/th&gt;
&lt;th&gt;用途&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;system-node-critical&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2000001000&lt;/td&gt;
&lt;td&gt;节点正常运行所必需：kube-proxy、CNI 插件、CSI 节点插件等&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;system-cluster-critical&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2000000000&lt;/td&gt;
&lt;td&gt;集群正常运行所必需：CoreDNS、metrics-server、云控制器等&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;figcaption class="text-center mb-3"&gt;
表 2: 内建 PriorityClass
&lt;/figcaption&gt;
&lt;p&gt;自建的 Operator、监控代理若确属关键组件，应在 &lt;code&gt;kube-system&lt;/code&gt; 以外创建自己的高优先级类（如 &lt;code&gt;platform-critical: 900000000&lt;/code&gt;），而不是直接复用系统类。&lt;/p&gt;
&lt;h2 id="优先级对调度的影响"&gt;优先级对调度的影响&lt;/h2&gt;
&lt;p&gt;优先级首先影响&lt;strong&gt;调度队列&lt;/strong&gt;：待调度 Pod 按优先级降序排列，高优先级 Pod 先被尝试调度。这意味着即便不发生抢占，关键服务的新副本也总是先于批处理任务拿到刚释放的资源。&lt;/p&gt;
&lt;p&gt;其次影响&lt;strong&gt;kubelet 的准入与驱逐&lt;/strong&gt;：节点资源压力驱逐时，kubelet 在用量超出请求的 Pod 中优先驱逐低优先级者；节点优雅关机（&lt;code&gt;GracefulNodeShutdownBasedOnPodPriority&lt;/code&gt;）也按优先级分批终止 Pod，给关键 Pod 更长的宽限期。&lt;/p&gt;
&lt;h2 id="抢占机制"&gt;抢占机制&lt;/h2&gt;
&lt;p&gt;当高优先级 Pod P 找不到任何可调度节点时，调度器进入抢占流程：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;遍历节点，模拟&amp;quot;移除该节点上优先级低于 P 的 Pod&amp;quot;后 P 是否可调度，筛出候选节点&lt;/li&gt;
&lt;li&gt;在候选节点中选择代价最小者：优先选择违反 PDB 最少、被驱逐 Pod 最高优先级最低、被驱逐 Pod 总优先级和最小、被驱逐 Pod 数量最少、最新启动 Pod 最晚的节点&lt;/li&gt;
&lt;li&gt;只驱逐&lt;strong&gt;必要&lt;/strong&gt;的 Pod（按优先级从低到高，直到 P 能放下为止），对这些 Pod 发起优雅删除&lt;/li&gt;
&lt;li&gt;在 P 的 &lt;code&gt;status.nominatedNodeName&lt;/code&gt; 记录提名节点，被抢占的 Pod 走正常的 &lt;code&gt;terminationGracePeriodSeconds&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;节点资源释放后 P 重新进入调度；若此时出现了更合适的节点，P 仍可能落到其他节点，提名并非绑定&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;下图展示了抢占的决策过程：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;P (priority 1000000) 无可用节点
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ├─ 节点 A：驱逐 2 个 priority=100 的 Pod 可容纳 P，不违反 PDB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ├─ 节点 B：驱逐 1 个 priority=500 的 Pod 可容纳 P，但违反 PDB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └─ 节点 C：即使驱逐所有低优先级 Pod 也放不下
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; → 选择节点 A，优雅删除 2 个 Pod，P.status.nominatedNodeName = A&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;关于抢占的几个重要事实：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;抢占&lt;strong&gt;不会&lt;/strong&gt;驱逐优先级等于或高于 P 的 Pod&lt;/li&gt;
&lt;li&gt;抢占只在 P 完全无法调度时触发；若 P 因亲和性无法满足而非资源不足，抢占也无济于事，事件中会显示 &lt;code&gt;Preemption is not helpful for scheduling&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;被抢占的 Pod 若由 Deployment 等控制器管理，会在别处重建；裸 Pod 则直接消失&lt;/li&gt;
&lt;li&gt;调度器&lt;strong&gt;尽量&lt;/strong&gt;尊重 PDB，但 PDB 不是硬保证：当所有候选节点都会违反 PDB 时，仍会选择违反最少的那个&lt;/li&gt;
&lt;li&gt;v1.33 起 Beta 的异步抢占（&lt;code&gt;SchedulerAsyncPreemption&lt;/code&gt;）把驱逐 API 调用移出调度主循环，避免大规模抢占阻塞其他 Pod 的调度&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="非抢占优先级"&gt;非抢占优先级&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;preemptionPolicy: Never&lt;/code&gt; 定义的优先级类让 Pod 在队列中享受高优先级，但不会抢占任何运行中的 Pod。这对批处理与数据科学场景尤为重要：一个高优先级的训练任务应该比其他任务先拿到空闲 GPU，但不该把正在运行的长任务踢掉而浪费其已完成的计算。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;scheduling.k8s.io/v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;PriorityClass&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;high-priority-nonpreempting&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;500000&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;preemptionPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Never&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;高优先级排队但不抢占，用于批处理作业&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;非抢占 Pod 自身仍可能&lt;strong&gt;被&lt;/strong&gt;更高优先级的可抢占 Pod 驱逐。&lt;/p&gt;
&lt;h2 id="与其他机制的交互"&gt;与其他机制的交互&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;机制&lt;/th&gt;
&lt;th&gt;交互方式&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;PodDisruptionBudget&lt;/td&gt;
&lt;td&gt;抢占尽量不违反 PDB，但不保证；PDB 的 &lt;code&gt;DisruptionTarget&lt;/code&gt; 条件会标记被抢占的 Pod，Job 可据此不计入重试&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;优雅终止&lt;/td&gt;
&lt;td&gt;被抢占 Pod 按 &lt;code&gt;terminationGracePeriodSeconds&lt;/code&gt; 优雅退出，调度器会等待；因此抢占不是瞬时的&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ResourceQuota&lt;/td&gt;
&lt;td&gt;&lt;code&gt;scopeSelector&lt;/code&gt; 可按优先级类限制配额，例如禁止普通命名空间使用高优先级类&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;节点压力驱逐&lt;/td&gt;
&lt;td&gt;kubelet 驱逐与调度器抢占互相独立；两者都参考优先级&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kueue / 批调度器&lt;/td&gt;
&lt;td&gt;Kueue 在配额层面实现基于优先级的排队与抢占（&lt;code&gt;preemption.reclaimWithinCohort&lt;/code&gt;），通常把 Job 设为非抢占优先级，避免核心调度器与 Kueue 双重抢占&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;集群自动扩缩容&lt;/td&gt;
&lt;td&gt;Cluster Autoscaler 可配置 &lt;code&gt;--expendable-pods-priority-cutoff&lt;/code&gt;，低于该优先级的 Pending Pod 不触发扩容；Karpenter 的调度模拟同样尊重优先级&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;figcaption class="text-center mb-3"&gt;
表 3: 优先级与抢占同其他机制的交互
&lt;/figcaption&gt;
&lt;h3 id="用配额限制优先级类的使用"&gt;用配额限制优先级类的使用&lt;/h3&gt;
&lt;p&gt;若不加限制，任何用户都可以给自己的 Pod 指定最高优先级，抢占机制便失去意义。&lt;code&gt;ResourceQuota&lt;/code&gt; 的 &lt;code&gt;scopeSelector&lt;/code&gt; 可以把优先级类的使用权限定在特定命名空间：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ResourceQuota&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;critical-priority-quota&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;payments &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 只有该命名空间可用 business-critical&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;hard&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;pods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;50&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;scopeSelector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;matchExpressions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;In&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;scopeName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;PriorityClass&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="l"&gt;business-critical]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;配合 API Server 的 &lt;code&gt;--admission-control-config-file&lt;/code&gt; 中 &lt;code&gt;ResourceQuota&lt;/code&gt; 插件的 &lt;code&gt;limitedResources&lt;/code&gt; 配置，可以要求&amp;quot;凡使用 &lt;code&gt;business-critical&lt;/code&gt; 的 Pod 所在命名空间必须存在覆盖该优先级类的配额&amp;quot;，未配置配额的命名空间将无法使用该类。更灵活的做法是用 &lt;code&gt;ValidatingAdmissionPolicy&lt;/code&gt; 按命名空间标签校验 &lt;code&gt;priorityClassName&lt;/code&gt;。&lt;/p&gt;
&lt;h2 id="实践建议"&gt;实践建议&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;为集群设计 3 – 5 个层次清晰的优先级类（如 &lt;code&gt;platform-critical&lt;/code&gt;、&lt;code&gt;business-critical&lt;/code&gt;、&lt;code&gt;default&lt;/code&gt;、&lt;code&gt;batch&lt;/code&gt;、&lt;code&gt;best-effort&lt;/code&gt;），用 &lt;code&gt;globalDefault&lt;/code&gt; 把未声明的 Pod 归入 &lt;code&gt;default&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;批处理与训练任务使用 &lt;code&gt;preemptionPolicy: Never&lt;/code&gt; 的类，由 Kueue 等排队系统负责配额层面的抢占&lt;/li&gt;
&lt;li&gt;为所有关键工作负载配置 PDB，并把 &lt;code&gt;unhealthyPodEvictionPolicy&lt;/code&gt; 设为 &lt;code&gt;AlwaysAllow&lt;/code&gt;，降低抢占对可用性的影响&lt;/li&gt;
&lt;li&gt;用 ResourceQuota 的 &lt;code&gt;scopeSelector&lt;/code&gt; 或准入策略限制高优先级类的使用范围&lt;/li&gt;
&lt;li&gt;监控 &lt;code&gt;scheduler_preemption_attempts_total&lt;/code&gt; 与 &lt;code&gt;scheduler_preemption_victims&lt;/code&gt; 指标，抢占频繁意味着容量规划不足，而不是靠抢占常态化运转&lt;/li&gt;
&lt;li&gt;设计 &lt;code&gt;terminationGracePeriodSeconds&lt;/code&gt; 时考虑被抢占的可能，让应用能在宽限期内完成检查点保存&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="总结"&gt;总结&lt;/h2&gt;
&lt;p&gt;PriorityClass 让集群在资源紧张时有章可循：调度队列按优先级排序保证关键服务先行，抢占机制在必要时为其腾出空间，非抢占优先级则为批处理提供&amp;quot;先排队、不打断&amp;quot;的折中。优先级必须与 PDB、ResourceQuota、排队系统配合使用，并以容量规划为前提——抢占是最后的安全阀，而不是日常的调度手段。&lt;/p&gt;
&lt;h2 id="参考文献"&gt;参考文献&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/" target="_blank" rel="noopener"&gt;Pod Priority and Preemption - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/policy/resource-quotas/#resource-quota-per-priorityclass" target="_blank" rel="noopener"&gt;Resource Quotas: Resource Quota Per PriorityClass - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/tasks/administer-cluster/guaranteed-scheduling-critical-addon-pods/" target="_blank" rel="noopener"&gt;Guaranteed Scheduling For Critical Add-On Pods - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/blog/2025/04/23/kubernetes-v1-33-release/" target="_blank" rel="noopener"&gt;Kubernetes v1.33: Asynchronous Preemption in the Scheduler - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>服务质量等级（QoS）</title><link>https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/qos/</link><pubDate>Sat, 21 May 2022 00:00:00 +0800</pubDate><author>Jimmy Song</author><guid>https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/qos/</guid><description>详细介绍 Kubernetes 中 Pod 的服务质量等级（QoS）机制，包括 Guaranteed、Burstable 和 BestEffort 三种等级的配置方法和使用场景。</description><content:encoded>
&lt;blockquote&gt;
&lt;p&gt;合理配置 QoS 等级是保障 Kubernetes 集群资源高效利用与关键业务稳定运行的基础。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;在 Kubernetes 中，QoS（Quality of Service，服务质量等级）是作用于 Pod 的核心机制。Kubernetes 会根据容器的资源配置自动为 Pod 分配 QoS 等级，这直接影响调度优先级和资源回收策略。&lt;/p&gt;
&lt;h2 id="qos-等级分类"&gt;QoS 等级分类&lt;/h2&gt;
&lt;p&gt;Kubernetes 将 Pod 的 QoS 等级分为三类，分别适用于不同业务场景。下表总结了各等级的特征和适用场景。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;等级&lt;/th&gt;
&lt;th&gt;配置要求&lt;/th&gt;
&lt;th&gt;适用场景&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Guaranteed&lt;/td&gt;
&lt;td&gt;每个容器都设置 &lt;code&gt;limits&lt;/code&gt; 和 &lt;code&gt;requests&lt;/code&gt;，且值相等&lt;/td&gt;
&lt;td&gt;关键业务应用&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Burstable&lt;/td&gt;
&lt;td&gt;至少有一个容器设置了 &lt;code&gt;requests&lt;/code&gt; 或 &lt;code&gt;limits&lt;/code&gt;，但不完全相等&lt;/td&gt;
&lt;td&gt;一般业务、开发测试&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BestEffort&lt;/td&gt;
&lt;td&gt;所有容器都未设置 &lt;code&gt;limits&lt;/code&gt; 和 &lt;code&gt;requests&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;非关键、批处理任务&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;figcaption class="text-center mb-3"&gt;
表 1: Kubernetes QoS 等级对比
&lt;/figcaption&gt;
&lt;h3 id="guaranteed保证级"&gt;Guaranteed（保证级）&lt;/h3&gt;
&lt;p&gt;Guaranteed 等级要求 Pod 中每个容器都同时设置 CPU 和内存的 &lt;code&gt;limits&lt;/code&gt; 与 &lt;code&gt;requests&lt;/code&gt;，且两者数值完全一致。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;配置示例：&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;app&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;limits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;100m&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;128Mi&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;100m&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;128Mi&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="burstable突发级"&gt;Burstable（突发级）&lt;/h3&gt;
&lt;p&gt;Burstable 等级适用于部分资源有保障、部分可突发的场景。只要有一个容器设置了 &lt;code&gt;requests&lt;/code&gt; 或 &lt;code&gt;limits&lt;/code&gt;，但不满足 Guaranteed 的全部要求，即为 Burstable。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;配置示例：&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;app&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;limits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;180Mi&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;100Mi&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;50m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="besteffort尽力而为级"&gt;BestEffort（尽力而为级）&lt;/h3&gt;
&lt;p&gt;BestEffort 等级适用于资源要求最低的场景。所有容器都未设置任何 &lt;code&gt;limits&lt;/code&gt; 或 &lt;code&gt;requests&lt;/code&gt;，即为 BestEffort。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;配置示例：&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;app&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;{}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="qos-的作用机制"&gt;QoS 的作用机制&lt;/h2&gt;
&lt;p&gt;QoS 等级不仅影响调度优先级，还决定了资源回收的顺序。合理配置 QoS，有助于提升集群整体资源利用率和业务弹性。&lt;/p&gt;
&lt;h3 id="调度优先级"&gt;调度优先级&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Guaranteed：最高优先级，优先分配到资源充足的节点&lt;/li&gt;
&lt;li&gt;Burstable：中等优先级，满足基本资源需求后调度&lt;/li&gt;
&lt;li&gt;BestEffort：最低优先级，通常调度到剩余资源较多的节点&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="资源回收策略"&gt;资源回收策略&lt;/h3&gt;
&lt;p&gt;当节点资源不足时，kubelet 首先依据 Pod 的实际用量是否超出 &lt;code&gt;requests&lt;/code&gt; 以及 PriorityClass 决定驱逐顺序，QoS 等级在其中起到间接作用：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;首先回收 BestEffort 级别的 Pod（没有 &lt;code&gt;requests&lt;/code&gt;，任何用量都视为超额）&lt;/li&gt;
&lt;li&gt;其次回收超出 &lt;code&gt;requests&lt;/code&gt; 资源使用量的 Burstable 级别 Pod&lt;/li&gt;
&lt;li&gt;最后回收 Guaranteed 级别的 Pod（仅在系统组件需要资源时）&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;在内核层面，kubelet 还会为不同 QoS 的容器设置不同的 &lt;code&gt;oom_score_adj&lt;/code&gt;：Guaranteed 为 -997，BestEffort 为 1000，Burstable 介于两者之间并随 &lt;code&gt;requests&lt;/code&gt; 占比变化。节点触发内核 OOM 时，分值越高的进程越先被杀死。&lt;/p&gt;
&lt;h3 id="cgroup-v2-与内存-qos"&gt;cgroup v2 与内存 QoS&lt;/h3&gt;
&lt;p&gt;Kubernetes 自 v1.25 起将 cgroup v2 支持 GA，并在 v1.31 把 cgroup v1 置于维护模式，新的资源管理特性只面向 cgroup v2。v1.35 起 cgroup v1 被正式弃用，kubelet 默认拒绝在仅有 cgroup v1 的节点上启动（可用 &lt;code&gt;failCgroupV1: false&lt;/code&gt; 临时放行）。在 cgroup v2 节点上，kubelet 可启用内存 QoS（特性门控 &lt;code&gt;MemoryQoS&lt;/code&gt;，v1.37 Beta 并默认开启）：把 &lt;code&gt;requests.memory&lt;/code&gt; 映射为 &lt;code&gt;memory.min&lt;/code&gt; 以保护 Guaranteed/Burstable 容器的内存不被回收，并通过 &lt;code&gt;memory.high&lt;/code&gt; 在接近 &lt;code&gt;limits&lt;/code&gt; 时提前触发限流，而不是直接 OOM。&lt;/p&gt;
&lt;h3 id="与原地资源调整的关系"&gt;与原地资源调整的关系&lt;/h3&gt;
&lt;p&gt;Pod 的 QoS 等级在创建时确定且&lt;strong&gt;不可变&lt;/strong&gt;。自 v1.35 起 GA 的原地资源调整允许修改运行中容器的 &lt;code&gt;requests&lt;/code&gt;/&lt;code&gt;limits&lt;/code&gt;，但 API Server 会拒绝导致 QoS 等级变化的调整：Guaranteed Pod 调整后必须仍保持 &lt;code&gt;requests == limits&lt;/code&gt;，Burstable Pod 不能被调整为完全不设资源的 BestEffort。&lt;/p&gt;
&lt;h3 id="交换分区"&gt;交换分区&lt;/h3&gt;
&lt;p&gt;v1.34 起 kubelet 对 Linux swap 的支持进入 GA（&lt;code&gt;NodeSwap&lt;/code&gt;），默认行为为 &lt;code&gt;NoSwap&lt;/code&gt;，且仅支持 cgroup v2 节点。管理员可在 kubelet 配置中设置 &lt;code&gt;memorySwap.swapBehavior: LimitedSwap&lt;/code&gt;，此时&lt;strong&gt;仅 Burstable 级别的 Pod&lt;/strong&gt; 可以按其内存 &lt;code&gt;requests&lt;/code&gt; 占节点内存的比例使用 swap；Guaranteed 与 BestEffort Pod 均不允许使用 swap，以保证高优先级工作负载的性能可预测。&lt;/p&gt;
&lt;h2 id="查看-pod-的-qos-等级"&gt;查看 Pod 的 QoS 等级&lt;/h2&gt;
&lt;p&gt;可以通过以下命令查看 Pod 的 QoS 等级：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get pod &amp;lt;pod-name&amp;gt; -o yaml &lt;span class="p"&gt;|&lt;/span&gt; grep qosClass&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;或使用 &lt;code&gt;describe&lt;/code&gt; 命令：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl describe pod &amp;lt;pod-name&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="最佳实践"&gt;最佳实践&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;生产环境关键应用建议使用 Guaranteed 等级，确保资源稳定性&lt;/li&gt;
&lt;li&gt;开发测试环境可采用 Burstable 等级，提高资源利用率&lt;/li&gt;
&lt;li&gt;批处理任务适合使用 BestEffort 等级，充分利用集群闲置资源&lt;/li&gt;
&lt;li&gt;合理设置资源请求，避免设置过高的 &lt;code&gt;requests&lt;/code&gt; 值造成资源浪费&lt;/li&gt;
&lt;li&gt;为新节点统一启用 cgroup v2（主流发行版默认已启用），避免同一集群混用 v1/v2 导致资源语义不一致&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="总结"&gt;总结&lt;/h2&gt;
&lt;p&gt;Kubernetes QoS 机制通过资源配置自动分级，实现了资源分配的弹性与业务优先级保障。合理利用 QoS 等级，有助于提升集群资源利用率、保障关键业务稳定，并优化整体运维体验。&lt;/p&gt;
&lt;h2 id="参考文献"&gt;参考文献&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/quality-service-pod/" target="_blank" rel="noopener"&gt;配置 Pod 的服务质量 - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/" target="_blank" rel="noopener"&gt;Resource Management for Pods and Containers - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>ResourceQuota 与 LimitRange：命名空间级资源治理</title><link>https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/resource-quota-and-limitrange/</link><pubDate>Sun, 01 Nov 2026 00:00:00 +0800</pubDate><author>Jimmy Song</author><guid>https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/resource-quota-and-limitrange/</guid><description>介绍 Kubernetes 命名空间级资源治理的两大机制：ResourceQuota 限制命名空间内计算资源、存储、对象数量与扩展资源的总量，支持按 QoS、优先级类、跨命名空间 Pod 亲和等作用域；LimitRange 为单个 Pod/容器/PVC 设置默认值、最小/最大值与比例约束。涵盖配额与 LimitRange 的协作、对 GPU 等扩展资源的配额、常见错误与多租户实践。</description><content:encoded>
&lt;blockquote&gt;
&lt;p&gt;没有配额的多租户集群只是&amp;quot;大家一起用的集群&amp;quot;；ResourceQuota 划定每个团队的总盘子，LimitRange 保证每个 Pod 都带着合理的资源声明进来。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Kubernetes 用命名空间划分团队与环境，但命名空间本身并不限制资源使用——任何人都可以在自己的命名空间里创建无限多的 Pod、申请无限多的 CPU。ResourceQuota 与 LimitRange 这两个核心 API 对象补上了这块缺口：前者作用于&lt;strong&gt;命名空间总量&lt;/strong&gt;，后者作用于&lt;strong&gt;单个对象&lt;/strong&gt;。它们由同名的内建准入控制器实施，在对象创建或更新时同步校验，是多租户治理、成本控制与防止&amp;quot;吵闹邻居&amp;quot;的基础。&lt;/p&gt;
&lt;h2 id="resourcequota"&gt;ResourceQuota&lt;/h2&gt;
&lt;p&gt;ResourceQuota 为一个命名空间声明若干资源的硬上限，准入控制器在每次创建对象时累计已用量并拒绝超额请求。一个命名空间可以有多个 ResourceQuota，所有配额必须同时满足。&lt;/p&gt;
&lt;h3 id="可限制的资源"&gt;可限制的资源&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;类别&lt;/th&gt;
&lt;th&gt;资源名示例&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;计算资源&lt;/td&gt;
&lt;td&gt;&lt;code&gt;requests.cpu&lt;/code&gt;、&lt;code&gt;requests.memory&lt;/code&gt;、&lt;code&gt;limits.cpu&lt;/code&gt;、&lt;code&gt;limits.memory&lt;/code&gt;、&lt;code&gt;cpu&lt;/code&gt;（等价于 &lt;code&gt;requests.cpu&lt;/code&gt;）、&lt;code&gt;memory&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;统计所有非终态 Pod 的容器资源之和；Init 容器按最大值计入，Sidecar 容器按累加计入&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;扩展资源&lt;/td&gt;
&lt;td&gt;&lt;code&gt;requests.nvidia.com/gpu&lt;/code&gt;、&lt;code&gt;requests.hugepages-2Mi&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;扩展资源只能限制 &lt;code&gt;requests.&lt;/code&gt; 前缀（扩展资源不允许超售，requests 必等于 limits）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;存储&lt;/td&gt;
&lt;td&gt;&lt;code&gt;requests.storage&lt;/code&gt;、&lt;code&gt;persistentvolumeclaims&lt;/code&gt;、&lt;code&gt;&amp;lt;storageclass&amp;gt;.storageclass.storage.k8s.io/requests.storage&lt;/code&gt;、&lt;code&gt;&amp;lt;storageclass&amp;gt;.storageclass.storage.k8s.io/persistentvolumeclaims&lt;/code&gt;、&lt;code&gt;requests.ephemeral-storage&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;可按 StorageClass 分别限额，例如限制高性能 SSD 的总容量&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;对象数量&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pods&lt;/code&gt;、&lt;code&gt;services&lt;/code&gt;、&lt;code&gt;services.loadbalancers&lt;/code&gt;、&lt;code&gt;services.nodeports&lt;/code&gt;、&lt;code&gt;configmaps&lt;/code&gt;、&lt;code&gt;secrets&lt;/code&gt;、&lt;code&gt;persistentvolumeclaims&lt;/code&gt;、&lt;code&gt;replicationcontrollers&lt;/code&gt;、&lt;code&gt;resourcequotas&lt;/code&gt;；通用语法 &lt;code&gt;count/&amp;lt;resource&amp;gt;.&amp;lt;group&amp;gt;&lt;/code&gt;，如 &lt;code&gt;count/deployments.apps&lt;/code&gt;、&lt;code&gt;count/jobs.batch&lt;/code&gt;、&lt;code&gt;count/widgets.example.com&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;对象数量配额可以作用于任何内建或自定义资源&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;figcaption class="text-center mb-3"&gt;
表 1: ResourceQuota 可限制的资源类型
&lt;/figcaption&gt;
&lt;p&gt;以下示例为一个团队命名空间设置了典型配额：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ResourceQuota&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;team-a-quota&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;team-a&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;hard&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;requests.cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;40&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;requests.memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;160Gi&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;limits.cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;80&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;limits.memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;320Gi&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;requests.nvidia.com/gpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;8&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;requests.storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;2Ti&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;fast-ssd.storageclass.storage.k8s.io/requests.storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;500Gi&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;pods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;200&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;services.loadbalancers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;2&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;count/deployments.apps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;50&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;count/jobs.batch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;100&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;kubectl describe quota -n team-a&lt;/code&gt; 可查看每项资源的已用/上限；&lt;code&gt;kubectl get quota -o yaml&lt;/code&gt; 的 &lt;code&gt;status.used&lt;/code&gt; 字段同样包含实时用量。&lt;/p&gt;
&lt;h3 id="配额与资源请求的强制关系"&gt;配额与资源请求的强制关系&lt;/h3&gt;
&lt;p&gt;一旦命名空间对 &lt;code&gt;requests.cpu&lt;/code&gt;、&lt;code&gt;requests.memory&lt;/code&gt;、&lt;code&gt;limits.cpu&lt;/code&gt; 或 &lt;code&gt;limits.memory&lt;/code&gt; 任一项设置了配额，&lt;strong&gt;该命名空间内所有新建 Pod 的每个容器都必须显式声明对应的 requests/limits&lt;/strong&gt;，否则会被拒绝：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Error from server (Forbidden): pods &amp;#34;web&amp;#34; is forbidden: failed quota: team-a-quota:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;must specify limits.cpu for: app; limits.memory for: app&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;这正是 LimitRange 存在的理由之一——用默认值自动补齐，避免每个开发者都手写资源声明。&lt;/p&gt;
&lt;h3 id="配额作用域"&gt;配额作用域&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;scopes&lt;/code&gt; 与 &lt;code&gt;scopeSelector&lt;/code&gt; 让一个配额只统计特定类别的 Pod，从而实现差异化治理：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;作用域&lt;/th&gt;
&lt;th&gt;匹配的 Pod&lt;/th&gt;
&lt;th&gt;可限制的资源&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Terminating&lt;/code&gt; / &lt;code&gt;NotTerminating&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;设置了 / 未设置 &lt;code&gt;activeDeadlineSeconds&lt;/code&gt; 的 Pod（通常对应 Job 与长期服务）&lt;/td&gt;
&lt;td&gt;计算资源、&lt;code&gt;pods&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;BestEffort&lt;/code&gt; / &lt;code&gt;NotBestEffort&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;QoS 为 / 不为 BestEffort 的 Pod&lt;/td&gt;
&lt;td&gt;BestEffort 作用域只能限制 &lt;code&gt;pods&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;PriorityClass&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;通过 &lt;code&gt;scopeSelector&lt;/code&gt; 按优先级类名匹配（&lt;code&gt;In&lt;/code&gt;/&lt;code&gt;NotIn&lt;/code&gt;/&lt;code&gt;Exists&lt;/code&gt;/&lt;code&gt;DoesNotExist&lt;/code&gt;）&lt;/td&gt;
&lt;td&gt;计算资源、&lt;code&gt;pods&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CrossNamespacePodAffinity&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;使用了跨命名空间 Pod 亲和/反亲和（&lt;code&gt;namespaces&lt;/code&gt; 或 &lt;code&gt;namespaceSelector&lt;/code&gt;）的 Pod&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pods&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;figcaption class="text-center mb-3"&gt;
表 2: ResourceQuota 作用域
&lt;/figcaption&gt;
&lt;p&gt;以下示例限制 &lt;code&gt;team-a&lt;/code&gt; 中 BestEffort Pod 最多 20 个、批处理（Terminating）Pod 最多占用 10 核，并禁止使用跨命名空间亲和性：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ResourceQuota&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;besteffort-quota&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;team-a&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;hard&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;pods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;20&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;scopes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="l"&gt;BestEffort]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ResourceQuota&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;batch-quota&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;team-a&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;hard&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;requests.cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;scopes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="l"&gt;Terminating]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ResourceQuota&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;no&lt;/span&gt;-&lt;span class="l"&gt;cross-ns-affinity&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;team-a&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;hard&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;pods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;0&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;scopeSelector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;matchExpressions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;scopeName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;CrossNamespacePodAffinity&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Exists&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;CrossNamespacePodAffinity&lt;/code&gt; 作用域配合 API Server 准入配置中的 &lt;code&gt;limitedResources&lt;/code&gt;，可以在集群层面要求所有使用跨命名空间亲和的 Pod 必须被配额覆盖，防止租户通过反亲和&amp;quot;霸占&amp;quot;其他团队的节点。&lt;/p&gt;
&lt;h3 id="对象配额与-crd"&gt;对象配额与 CRD&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;count/&amp;lt;resource&amp;gt;.&amp;lt;group&amp;gt;&lt;/code&gt; 语法对自定义资源同样有效，这让平台团队可以限制每个租户能创建多少 &lt;code&gt;Application&lt;/code&gt;、&lt;code&gt;Certificate&lt;/code&gt; 或 &lt;code&gt;InferencePool&lt;/code&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;hard&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;count/certificates.cert-manager.io&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;20&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;count/inferencepools.inference.networking.k8s.io&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;5&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="limitrange"&gt;LimitRange&lt;/h2&gt;
&lt;p&gt;LimitRange 作用于命名空间内的&lt;strong&gt;单个&lt;/strong&gt; Pod、容器或 PVC，提供三种能力：为未声明资源的容器填充默认 requests/limits、限制单个对象的最小/最大值、约束 limits 与 requests 的比例。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;LimitRange&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;team-a-limits&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;team-a&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;limits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Container&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 未声明 limits 时的默认值&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;500m&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;512Mi&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;defaultRequest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 未声明 requests 时的默认值&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;100m&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;128Mi&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;min&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;50m&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;64Mi&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;max&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;8&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;32Gi&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;maxLimitRequestRatio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# limits 不得超过 requests 的 4 倍，抑制过度超售&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;4&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;2&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Pod&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;max&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 单个 Pod 所有容器之和的上限&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;16&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;64Gi&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;PersistentVolumeClaim&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;min&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;1Gi&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;max&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;1Ti&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;LimitRange 的生效规则需要特别留意：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;默认值只在容器&lt;strong&gt;完全未声明&lt;/strong&gt;对应字段时注入；若只声明了 &lt;code&gt;limits&lt;/code&gt; 而没有 &lt;code&gt;requests&lt;/code&gt;，Kubernetes 会把 &lt;code&gt;requests&lt;/code&gt; 设为与 &lt;code&gt;limits&lt;/code&gt; 相同，而不是使用 &lt;code&gt;defaultRequest&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;校验与注入发生在准入阶段，LimitRange 的修改&lt;strong&gt;不影响已存在的 Pod&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;min&lt;/code&gt;/&lt;code&gt;max&lt;/code&gt; 同时对注入后的默认值生效，因此 &lt;code&gt;default&lt;/code&gt; 必须落在 &lt;code&gt;[min, max]&lt;/code&gt; 区间内，否则所有未声明资源的 Pod 都会被拒绝&lt;/li&gt;
&lt;li&gt;&lt;code&gt;type: Pod&lt;/code&gt; 的约束按 Pod 内所有容器（含 Sidecar）之和计算&lt;/li&gt;
&lt;li&gt;一个命名空间可以有多个 LimitRange，但多个 LimitRange 对同一字段设置不同默认值时行为未定义，应避免&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="resourcequota-与-limitrange-的协作"&gt;ResourceQuota 与 LimitRange 的协作&lt;/h2&gt;
&lt;p&gt;两者通常成对出现：LimitRange 保证每个 Pod 都带着合理的资源声明进入集群，ResourceQuota 则把这些声明累加起来与团队总盘子比对。一个常见的落地模式是命名空间供给流程（GitOps 或 Operator）在创建命名空间时同时下发三件套——ResourceQuota、LimitRange 与默认 NetworkPolicy：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Namespace&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;team-a&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;pod-security.kubernetes.io/enforce&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;baseline&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;team&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;a&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;LimitRange&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;defaults&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;team-a&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;limits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Container&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;defaultRequest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;{&lt;span class="nt"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;100m, memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;128Mi}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;{&lt;span class="nt"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;1, memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;1Gi}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ResourceQuota&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;compute&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;team-a&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;hard&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;requests.cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;20&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;requests.memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;64Gi&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;limits.cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;40&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;limits.memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;128Gi&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;pods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;100&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;对集群级的层次化配额（例如&amp;quot;部门 → 团队&amp;quot;两级、团队之间可借用闲置配额），核心 API 没有提供，需要借助 Kueue 的 &lt;code&gt;ClusterQueue&lt;/code&gt;/&lt;code&gt;Cohort&lt;/code&gt;（面向批处理作业）、Hierarchical Namespace Controller 或 Capsule 等多租户项目（见 &lt;a href="../../security/multi-tenancy"&gt;多租户与虚拟集群&lt;/a&gt;）。&lt;/p&gt;
&lt;h2 id="常见问题"&gt;常见问题&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;现象&lt;/th&gt;
&lt;th&gt;原因&lt;/th&gt;
&lt;th&gt;处理&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Deployment 副本数不足但没有 Pending Pod&lt;/td&gt;
&lt;td&gt;ReplicaSet 创建 Pod 被配额拒绝，错误只出现在 ReplicaSet 事件中&lt;/td&gt;
&lt;td&gt;&lt;code&gt;kubectl describe rs&lt;/code&gt; 查看 &lt;code&gt;FailedCreate&lt;/code&gt; 事件&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;must specify limits.cpu&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;命名空间有计算配额但 Pod 未声明资源&lt;/td&gt;
&lt;td&gt;添加 LimitRange 默认值或在清单中声明&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;已删除 Pod 仍占用配额&lt;/td&gt;
&lt;td&gt;配额控制器异步同步，终态 Pod 不计入但有短暂延迟；带 finalizer 的 Pod 未真正删除&lt;/td&gt;
&lt;td&gt;等待同步或检查 finalizer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPU 配额设置 &lt;code&gt;limits.nvidia.com/gpu&lt;/code&gt; 无效&lt;/td&gt;
&lt;td&gt;扩展资源只支持 &lt;code&gt;requests.&lt;/code&gt; 前缀&lt;/td&gt;
&lt;td&gt;改为 &lt;code&gt;requests.nvidia.com/gpu&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PVC 扩容被拒&lt;/td&gt;
&lt;td&gt;&lt;code&gt;requests.storage&lt;/code&gt; 配额按 PVC 请求总量计算，扩容也计入&lt;/td&gt;
&lt;td&gt;调整配额或清理闲置 PVC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Job 的 Pod 因 &lt;code&gt;Terminating&lt;/code&gt; 作用域配额被拒&lt;/td&gt;
&lt;td&gt;设置了 &lt;code&gt;activeDeadlineSeconds&lt;/code&gt; 的 Pod 被归入 Terminating 作用域&lt;/td&gt;
&lt;td&gt;检查作用域配额是否合理&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;figcaption class="text-center mb-3"&gt;
表 3: 配额相关的常见问题与处理
&lt;/figcaption&gt;
&lt;h2 id="实践建议"&gt;实践建议&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;所有业务命名空间都应有 LimitRange 默认值，避免 BestEffort Pod 泛滥导致节点 OOM&lt;/li&gt;
&lt;li&gt;配额以 &lt;code&gt;requests&lt;/code&gt; 为主、&lt;code&gt;limits&lt;/code&gt; 为辅：调度与节点容量规划依据 requests，limits 配额主要用于抑制超售比例&lt;/li&gt;
&lt;li&gt;按 StorageClass 单独限制昂贵存储的容量，按 &lt;code&gt;services.loadbalancers&lt;/code&gt; 限制云负载均衡器数量以控制成本&lt;/li&gt;
&lt;li&gt;用 &lt;code&gt;PriorityClass&lt;/code&gt; 作用域配额防止租户滥用高优先级类&lt;/li&gt;
&lt;li&gt;把配额用量（&lt;code&gt;kube_resourcequota&lt;/code&gt; 指标）接入监控与告警，用量长期低于 50% 或接近 100% 都应触发容量评审&lt;/li&gt;
&lt;li&gt;配额变更通过 GitOps 审批，避免在集群中手工调整&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="总结"&gt;总结&lt;/h2&gt;
&lt;p&gt;ResourceQuota 与 LimitRange 是 Kubernetes 命名空间多租户的基石：LimitRange 在对象层面注入默认值并限定范围，ResourceQuota 在命名空间层面累计并设置上限，作用域机制则让配额可以按 QoS、优先级与作业类型差异化施策。二者配合 Pod 安全准入与 NetworkPolicy，构成了命名空间级隔离的&amp;quot;三件套&amp;quot;；更复杂的层次化与可借用配额，则交由 Kueue 等上层项目实现。&lt;/p&gt;
&lt;h2 id="参考文献"&gt;参考文献&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/policy/resource-quotas/" target="_blank" rel="noopener"&gt;Resource Quotas - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/policy/limit-range/" target="_blank" rel="noopener"&gt;Limit Ranges - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/tasks/administer-cluster/manage-resources/quota-memory-cpu-namespace/" target="_blank" rel="noopener"&gt;Configure Memory and CPU Quotas for a Namespace - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/" target="_blank" rel="noopener"&gt;Resource Management for Pods and Containers - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>kubelet 节点资源管理：资源预留、节点压力驱逐、垃圾回收与资源管理器</title><link>https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/kubelet-resource-management/</link><pubDate>Sun, 01 Nov 2026 00:00:00 +0800</pubDate><author>Jimmy Song</author><guid>https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/kubelet-resource-management/</guid><description>深入 kubelet 在节点侧的资源管理职责：Node Allocatable 与 kube-reserved/system-reserved/eviction 预留模型、节点压力驱逐的信号/阈值/Pod 选择顺序、镜像与容器垃圾回收、节点优雅关机，以及面向延迟敏感与 AI 负载的 CPU 管理器、内存管理器、拓扑管理器与 NUMA 对齐。</description><content:encoded>
&lt;blockquote&gt;
&lt;p&gt;调度器只看&amp;quot;节点声称有多少资源&amp;quot;，而节点能不能真的兑现这些承诺，取决于 kubelet 如何预留、如何驱逐、如何在 NUMA 之间摆放 CPU 和内存。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Kubernetes 的资源模型分两层：调度器在控制面按节点的&lt;strong&gt;可分配资源&lt;/strong&gt;（Allocatable）做全局决策，kubelet 在节点侧负责把这些决策落实到 cgroup，并在资源真正紧张时保护节点不被压垮。本文聚焦后者——kubelet 的资源预留、节点压力驱逐、垃圾回收、优雅关机以及 CPU/内存/拓扑三大资源管理器，这些配置决定了节点的稳定性，也是 AI 训练与低延迟应用性能调优的关键。&lt;/p&gt;
&lt;h2 id="node-allocatable-与资源预留"&gt;Node Allocatable 与资源预留&lt;/h2&gt;
&lt;p&gt;节点的物理容量（Capacity）不能全部交给 Pod：操作系统守护进程、kubelet、容器运行时都需要资源，还要为驱逐留出缓冲。kubelet 据此计算 &lt;strong&gt;Allocatable&lt;/strong&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Allocatable = Capacity − kube-reserved − system-reserved − eviction-threshold&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;三项预留通过 KubeletConfiguration 声明：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;kubelet.config.k8s.io/v1beta1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;KubeletConfiguration&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kubeReserved&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 为 kubelet、容器运行时等 Kubernetes 系统组件预留&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;500m&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;1Gi&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ephemeral-storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;5Gi&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;1000&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;systemReserved&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 为 sshd、journald 等操作系统守护进程预留&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;500m&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;1Gi&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;1000&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;evictionHard&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 硬驱逐阈值，同样从 Allocatable 中扣除&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;memory.available&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;500Mi&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;nodefs.available&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;10%&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;enforceNodeAllocatable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="l"&gt;pods] &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 只对 Pod 的 cgroup 强制执行 Allocatable 上限&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;enforceNodeAllocatable&lt;/code&gt; 默认只包含 &lt;code&gt;pods&lt;/code&gt;，即 kubelet 为所有 Pod 所在的顶层 cgroup（&lt;code&gt;kubepods&lt;/code&gt;）设置资源上限等于 Allocatable。若把 &lt;code&gt;kube-reserved&lt;/code&gt;/&lt;code&gt;system-reserved&lt;/code&gt; 也加入列表，kubelet 会为对应的 cgroup（需通过 &lt;code&gt;kubeReservedCgroup&lt;/code&gt;/&lt;code&gt;systemReservedCgroup&lt;/code&gt; 指定）设置上限；这会在系统进程超出预留时直接 OOM 它们，官方建议只有在非常清楚各守护进程实际用量时才启用。&lt;/p&gt;
&lt;p&gt;实际用量可用 &lt;code&gt;kubectl describe node&lt;/code&gt; 查看 &lt;code&gt;Capacity&lt;/code&gt;/&lt;code&gt;Allocatable&lt;/code&gt; 两组值，以及 &lt;code&gt;Allocated resources&lt;/code&gt; 中 Pod 请求的占用比例。云厂商托管节点池通常已按节点规格预设了阶梯式的预留公式，自建集群则需要依据节点上系统进程的实际用量压测后确定。&lt;/p&gt;
&lt;h2 id="节点压力驱逐"&gt;节点压力驱逐&lt;/h2&gt;
&lt;p&gt;当节点的内存、磁盘、inode 或 PID 低于阈值时，kubelet 会主动终止 Pod 回收资源，这一过程称为节点压力驱逐（Node-pressure Eviction）。它与 API 发起的驱逐（&lt;code&gt;kubectl drain&lt;/code&gt;、抢占）不同：&lt;strong&gt;不经过 API Server 的 Eviction 子资源，因此不受 PDB 约束&lt;/strong&gt;，Pod 会直接被置为 &lt;code&gt;Failed&lt;/code&gt; 并带上 &lt;code&gt;DisruptionTarget&lt;/code&gt; 条件。&lt;/p&gt;
&lt;h3 id="驱逐信号"&gt;驱逐信号&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;信号&lt;/th&gt;
&lt;th&gt;含义&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;memory.available&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;节点可用内存（Capacity − 工作集）&lt;/td&gt;
&lt;td&gt;基于 cgroup 的 &lt;code&gt;memory.workingSet&lt;/code&gt;，不含 &lt;code&gt;active_file&lt;/code&gt; 页缓存&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nodefs.available&lt;/code&gt; / &lt;code&gt;nodefs.inodesFree&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;kubelet 根目录所在文件系统（日志、emptyDir、可写层）的可用空间与 inode&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;imagefs.available&lt;/code&gt; / &lt;code&gt;imagefs.inodesFree&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;容器运行时存放镜像的文件系统&lt;/td&gt;
&lt;td&gt;与 nodefs 同盘时两者等价&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;containerfs.available&lt;/code&gt; / &lt;code&gt;containerfs.inodesFree&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;容器可写层所在文件系统（v1.31 起 Beta 的分离磁盘场景）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;KubeletSeparateDiskGC&lt;/code&gt; 允许镜像与可写层分别位于不同磁盘&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pid.available&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;节点剩余可用 PID 数&lt;/td&gt;
&lt;td&gt;防止 fork 炸弹耗尽进程号&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;figcaption class="text-center mb-3"&gt;
表 1: kubelet 驱逐信号
&lt;/figcaption&gt;
&lt;h3 id="硬阈值与软阈值"&gt;硬阈值与软阈值&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;硬阈值&lt;/strong&gt;（&lt;code&gt;evictionHard&lt;/code&gt;）一旦触及立即驱逐，Pod 不享受宽限期。Linux 节点的默认值为：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;evictionHard&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;memory.available&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;100Mi&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;nodefs.available&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;10%&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;imagefs.available&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;15%&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;nodefs.inodesFree&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;5%&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;imagefs.inodesFree&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;5%&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;需要特别注意：&lt;strong&gt;只要修改了其中任何一项，其余项的默认值都会被置为零而不是继承默认&lt;/strong&gt;，必须完整列出所有阈值；或者在 KubeletConfiguration 中设置 &lt;code&gt;mergeDefaultEvictionSettings: true&lt;/code&gt;，让未指定的信号继承默认值。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;软阈值&lt;/strong&gt;（&lt;code&gt;evictionSoft&lt;/code&gt;）触及后需持续超过 &lt;code&gt;evictionSoftGracePeriod&lt;/code&gt; 才触发驱逐，且 Pod 可获得最多 &lt;code&gt;evictionMaxPodGracePeriod&lt;/code&gt; 的终止宽限，适合把驱逐前移到更温和的水位：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;evictionSoft&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;memory.available&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;1Gi&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;nodefs.available&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;15%&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;evictionSoftGracePeriod&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;memory.available&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;1m30s&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;nodefs.available&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;2m&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;evictionMaxPodGracePeriod&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;60&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;evictionMinimumReclaim&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 每次驱逐至少回收的量，避免在阈值附近反复驱逐&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;memory.available&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;500Mi&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;nodefs.available&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;1Gi&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;evictionPressureTransitionPeriod&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;5m &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 节点条件从 Pressure 恢复的最短观察期，防止抖动&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="pod-选择顺序"&gt;Pod 选择顺序&lt;/h3&gt;
&lt;p&gt;kubelet 驱逐时先尝试回收节点级资源（删除已退出容器、未使用镜像），仍不足再按以下顺序选择 Pod：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;用量是否超过 requests&lt;/strong&gt;：超出请求的 Pod 排在前面；BestEffort Pod 没有 requests，任何用量都视为超额&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pod 优先级&lt;/strong&gt;：同为超额的 Pod 中，优先级低者先被驱逐&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;超出量相对 requests 的比例&lt;/strong&gt;：超出越多越先驱逐&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;因此 QoS 等级只是间接影响驱逐顺序：Guaranteed 与 Burstable Pod 只要用量不超过 requests，就不会因其他 Pod 的内存压力而被驱逐（系统守护进程超出预留的极端情况除外）。静态 Pod 与 &lt;code&gt;system-node-critical&lt;/code&gt; 优先级的 Pod 同样可能被驱逐，关键组件应设置准确的 requests 并避免超额使用。&lt;/p&gt;
&lt;p&gt;驱逐后的 Pod 处于 &lt;code&gt;Failed&lt;/code&gt; 状态并保留在 API 中供排障，由控制器在其他节点重建；节点会带上 &lt;code&gt;MemoryPressure&lt;/code&gt;/&lt;code&gt;DiskPressure&lt;/code&gt;/&lt;code&gt;PIDPressure&lt;/code&gt; 条件及对应污点，调度器在条件清除前不再向其调度 BestEffort（内存压力）或任何新 Pod（磁盘压力）。&lt;/p&gt;
&lt;h3 id="与内核-oom-的关系"&gt;与内核 OOM 的关系&lt;/h3&gt;
&lt;p&gt;驱逐是 kubelet 的主动行为，默认每 10 秒评估一次；若内存消耗在两次评估之间急剧飙升，内核 OOM Killer 会先于 kubelet 介入。OOM Killer 依据 &lt;code&gt;oom_score_adj&lt;/code&gt; 选择牺牲者，kubelet 为不同 QoS 的容器预设了该值：Guaranteed 为 −997、BestEffort 为 1000、Burstable 按 requests 占比在 2 – 999 之间。容器被 OOM 杀死后按 &lt;code&gt;restartPolicy&lt;/code&gt; 原地重启，不会迁移到其他节点。v1.37 起 Beta 并默认开启的内存 QoS（cgroup v2 的 &lt;code&gt;memory.min&lt;/code&gt;/&lt;code&gt;memory.high&lt;/code&gt;）可以在接近 limits 时提前限流，减少硬 OOM。&lt;/p&gt;
&lt;h2 id="垃圾回收"&gt;垃圾回收&lt;/h2&gt;
&lt;p&gt;kubelet 定期清理节点上不再使用的镜像与容器，防止磁盘耗尽。&lt;/p&gt;
&lt;h3 id="镜像垃圾回收"&gt;镜像垃圾回收&lt;/h3&gt;
&lt;p&gt;基于磁盘用量阈值：当镜像文件系统使用率超过 &lt;code&gt;imageGCHighThresholdPercent&lt;/code&gt;（默认 85%）时，按最近最少使用的顺序删除未被任何容器引用的镜像，直到降至 &lt;code&gt;imageGCLowThresholdPercent&lt;/code&gt;（默认 80%）。v1.35 GA 的 &lt;code&gt;imageMaximumGCAge&lt;/code&gt; 额外提供基于时间的回收：超过该时长未使用的镜像即使磁盘充足也会被删除。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;imageGCHighThresholdPercent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;85&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;imageGCLowThresholdPercent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;imageMinimumGCAge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;2m &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 镜像拉取后至少保留的时间&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;imageMaximumGCAge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;168h &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 一周未使用即回收（v1.35 GA，0 表示禁用）&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;运行大模型镜像的节点应结合镜像卷的使用情况调高阈值或禁用基于时间的回收，避免数十 GB 的模型层被反复拉取。&lt;/p&gt;
&lt;h3 id="容器垃圾回收"&gt;容器垃圾回收&lt;/h3&gt;
&lt;p&gt;已退出的容器实例按 &lt;code&gt;maxPerPodContainerCount&lt;/code&gt;（每个 Pod 每个容器保留的已退出实例数，默认 1）与 &lt;code&gt;maxContainerCount&lt;/code&gt;（节点总数，默认 −1 不限）清理，保留的实例用于 &lt;code&gt;kubectl logs --previous&lt;/code&gt; 查看崩溃日志。&lt;/p&gt;
&lt;h2 id="节点优雅关机"&gt;节点优雅关机&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;GracefulNodeShutdown&lt;/code&gt;（v1.21 起 Beta 并默认开启）让 kubelet 通过 systemd inhibitor 锁拦截节点关机，在 &lt;code&gt;shutdownGracePeriod&lt;/code&gt; 内按优先级分批终止 Pod：先终止普通 Pod，为 &lt;code&gt;shutdownGracePeriodCriticalPods&lt;/code&gt; 保留的时间内再终止关键 Pod。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;shutdownGracePeriod&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;60s&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;shutdownGracePeriodCriticalPods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;20s&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 或按优先级类精细分配（GracefulNodeShutdownBasedOnPodPriority）&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;shutdownGracePeriodByPodPriority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="nt"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2000000000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# system-cluster-critical 及以上&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;shutdownGracePeriodSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="nt"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1000000&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;shutdownGracePeriodSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="nt"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;shutdownGracePeriodSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;60&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;这对使用 Spot/抢占式实例的集群尤为重要：云厂商的回收通知通常只给 30 – 120 秒，优雅关机保证应用能在这一窗口内完成检查点与连接排空。&lt;/p&gt;
&lt;h2 id="资源管理器cpu内存与拓扑"&gt;资源管理器：CPU、内存与拓扑&lt;/h2&gt;
&lt;p&gt;默认情况下，Linux 的 CFS 调度器会让容器进程在所有 CPU 核之间漂移，内存也可能分配在任意 NUMA 节点上。对数据库、网络功能虚拟化、分布式训练等延迟敏感或带宽敏感的负载，跨 NUMA 访问内存与 PCIe 设备会带来显著的性能抖动。kubelet 提供三个协同工作的资源管理器解决这一问题，它们都只对 &lt;strong&gt;Guaranteed QoS 且 requests 为整数核&lt;/strong&gt; 的容器生效。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;管理器&lt;/th&gt;
&lt;th&gt;配置字段&lt;/th&gt;
&lt;th&gt;作用&lt;/th&gt;
&lt;th&gt;状态&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CPU 管理器&lt;/td&gt;
&lt;td&gt;&lt;code&gt;cpuManagerPolicy: static&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;为符合条件的容器分配独占 CPU 核（cpuset），其余容器共享剩余核&lt;/td&gt;
&lt;td&gt;GA（v1.26），策略选项 GA（v1.33）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;内存管理器&lt;/td&gt;
&lt;td&gt;&lt;code&gt;memoryManagerPolicy: Static&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;保证容器的内存与 hugepages 来自指定 NUMA 节点&lt;/td&gt;
&lt;td&gt;GA（v1.32）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;拓扑管理器&lt;/td&gt;
&lt;td&gt;&lt;code&gt;topologyManagerPolicy&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;协调 CPU、内存、设备插件/DRA 设备的 NUMA 亲和性，使它们落在同一 NUMA 节点&lt;/td&gt;
&lt;td&gt;GA（v1.27），策略选项 GA（v1.32）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;figcaption class="text-center mb-3"&gt;
表 2: kubelet 资源管理器
&lt;/figcaption&gt;
&lt;p&gt;典型的高性能节点配置如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;kubelet.config.k8s.io/v1beta1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;KubeletConfiguration&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;cpuManagerPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;static&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;cpuManagerPolicyOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;full-pcpus-only&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 只分配完整物理核，避免超线程兄弟核被其他容器占用&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;distribute-cpus-across-numa&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;reservedSystemCPUs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;0-1&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 系统与 kubelet 固定使用的核，与 kubeReserved/systemReserved 的 cpu 互斥&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;memoryManagerPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Static&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;reservedMemory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="nt"&gt;numaNode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;limits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;1Gi&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;topologyManagerPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;single-numa-node&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;topologyManagerScope&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;pod &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 以 Pod 为单位对齐，而非逐容器&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;topologyManagerPolicyOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;prefer-closest-numa-nodes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;拓扑管理器的四种策略决定了对齐失败时的行为：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;none&lt;/code&gt;：不做对齐（默认）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;best-effort&lt;/code&gt;：尽量对齐，失败也准入&lt;/li&gt;
&lt;li&gt;&lt;code&gt;restricted&lt;/code&gt;：要求首选对齐（如单 NUMA）可满足，否则拒绝 Pod（&lt;code&gt;TopologyAffinityError&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;single-numa-node&lt;/code&gt;：要求所有资源来自同一个 NUMA 节点，否则拒绝&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;拓扑管理器通过 Hint Provider 接口从 CPU 管理器、内存管理器和设备插件收集每种资源可用的 NUMA 位掩码，再求交集选出共同的 NUMA 节点。DRA 驱动可以在 &lt;code&gt;ResourceSlice&lt;/code&gt; 中以设备属性的形式暴露 NUMA 位置，但 DRA 与拓扑管理器的原生集成仍在 WG Device Management 推进中，当前需要由驱动或调度器插件自行处理对齐。&lt;code&gt;topologyManagerScope: pod&lt;/code&gt; 让多容器 Pod（如训练进程 + RDMA Sidecar）整体落在同一 NUMA 节点，是 AI 训练节点的推荐设置。&lt;/p&gt;
&lt;h3 id="与原地资源调整pod-级资源的关系"&gt;与原地资源调整、Pod 级资源的关系&lt;/h3&gt;
&lt;p&gt;使用静态 CPU 管理器或内存管理器策略的 Pod 目前不能原地调整资源（独占资源的在线调整在 v1.37 仍为 Alpha）。Pod 级资源（&lt;code&gt;spec.resources&lt;/code&gt;）与资源管理器的对齐需要开启 &lt;code&gt;PodLevelResourceManagers&lt;/code&gt;（v1.37 Beta，默认关闭），否则管理器仍按容器级资源计算。&lt;/p&gt;
&lt;h2 id="实践建议"&gt;实践建议&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;所有节点显式配置 &lt;code&gt;kubeReserved&lt;/code&gt;/&lt;code&gt;systemReserved&lt;/code&gt; 与完整的 &lt;code&gt;evictionHard&lt;/code&gt;，并开启 &lt;code&gt;mergeDefaultEvictionSettings&lt;/code&gt; 避免漏项&lt;/li&gt;
&lt;li&gt;为关键 Pod 设置准确的 requests 并避免运行时超额，这是免于节点压力驱逐的唯一保证&lt;/li&gt;
&lt;li&gt;增加 &lt;code&gt;evictionSoft&lt;/code&gt; 与 &lt;code&gt;evictionMinimumReclaim&lt;/code&gt;，让驱逐发生在仍有余量时并一次回收足够资源&lt;/li&gt;
&lt;li&gt;Spot 节点开启优雅关机并按优先级分配宽限期&lt;/li&gt;
&lt;li&gt;延迟敏感与 AI 节点池单独配置静态 CPU/内存管理器与 &lt;code&gt;single-numa-node&lt;/code&gt; 拓扑策略，普通节点池保持默认以免浪费核&lt;/li&gt;
&lt;li&gt;监控 &lt;code&gt;kubelet_evictions&lt;/code&gt;、&lt;code&gt;kubelet_pod_resources_endpoint_*&lt;/code&gt;、&lt;code&gt;container_oom_events_total&lt;/code&gt; 等指标，驱逐与 OOM 频发意味着预留或 requests 需要修正&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="总结"&gt;总结&lt;/h2&gt;
&lt;p&gt;kubelet 的资源管理决定了节点能否兑现调度器的承诺：预留模型划出系统与 Pod 的边界，驱逐机制在压力下有序牺牲低优先级与超额 Pod，垃圾回收与优雅关机维护节点的长期健康，CPU/内存/拓扑管理器则为高性能负载提供 NUMA 级的确定性。理解这些机制，才能把&amp;quot;节点有多少资源&amp;quot;与&amp;quot;应用实际能用多少&amp;quot;真正对齐。&lt;/p&gt;
&lt;h2 id="参考文献"&gt;参考文献&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/tasks/administer-cluster/reserve-compute-resources/" target="_blank" rel="noopener"&gt;Reserve Compute Resources for System Daemons - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/scheduling-eviction/node-pressure-eviction/" target="_blank" rel="noopener"&gt;Node-pressure Eviction - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/architecture/garbage-collection/#containers-images" target="_blank" rel="noopener"&gt;Garbage Collection: Containers and Images - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/cluster-administration/node-shutdown/" target="_blank" rel="noopener"&gt;Graceful Node Shutdown - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/tasks/administer-cluster/cpu-management-policies/" target="_blank" rel="noopener"&gt;Control CPU Management Policies on the Node - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/tasks/administer-cluster/topology-manager/" target="_blank" rel="noopener"&gt;Control Topology Management Policies on a Node - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/tasks/administer-cluster/memory-manager/" target="_blank" rel="noopener"&gt;Utilizing the NUMA-aware Memory Manager - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>Horizontal Pod Autoscaling</title><link>https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/hpa/</link><pubDate>Sat, 21 May 2022 00:00:00 +0800</pubDate><author>Jimmy Song</author><guid>https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/hpa/</guid><description>深入了解 Kubernetes HPA（Horizontal Pod Autoscaling）的工作原理、配置方法和自定义指标支持，包括基于 CPU、内存和自定义指标的自动扩缩容实现。</description><content:encoded>
&lt;blockquote&gt;
&lt;p&gt;HPA（Horizontal Pod Autoscaler）让 Kubernetes 集群中的 Pod 数量能够根据负载自动扩缩容，实现资源的弹性管理，是自动化运维的核心能力之一。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;应用的资源使用率通常都有高峰和低谷的时候，如何削峰填谷，提高集群的整体资源利用率，让 service 中的 Pod 个数自动调整呢？这就有赖于 Horizontal Pod Autoscaling 了，顾名思义，使 Pod 水平自动缩放。&lt;/p&gt;
&lt;p&gt;HPA 是最能体现 Kubernetes 相比传统运维价值的功能之一，不再需要手动扩容，真正实现了自动化运维，还可以基于自定义指标进行扩缩容。&lt;/p&gt;
&lt;h2 id="概述"&gt;概述&lt;/h2&gt;
&lt;p&gt;HPA 属于 Kubernetes 中的 &lt;strong&gt;autoscaling&lt;/strong&gt; SIG（Special Interest Group），其下有两个主要特性：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/kubernetes/features/issues/117" target="_blank" rel="noopener"&gt;Arbitrary/Custom Metrics in the Horizontal Pod Autoscaler#117&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/kubernetes/features/issues/118" target="_blank" rel="noopener"&gt;Monitoring Pipeline Metrics HPA API #118&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="版本演进"&gt;版本演进&lt;/h3&gt;
&lt;p&gt;Kubernetes HPA 的功能随着版本不断演进，主要里程碑如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Kubernetes 1.2&lt;/strong&gt;：引入 HPA 机制&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Kubernetes 1.6&lt;/strong&gt;：从 kubelet 获取指标转为通过 API server、Heapster 或 kube-aggregator 获取，并支持自定义指标&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Kubernetes 1.8&lt;/strong&gt;：Heapster 弃用，资源指标统一由 metrics-server 通过 &lt;code&gt;metrics.k8s.io&lt;/code&gt; 提供&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Kubernetes 1.23&lt;/strong&gt;：&lt;code&gt;autoscaling/v2&lt;/code&gt; API GA，&lt;code&gt;v2beta2&lt;/code&gt; 已于 1.26 移除&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Kubernetes 1.27&lt;/strong&gt;：支持按容器粒度的资源指标（&lt;code&gt;ContainerResource&lt;/code&gt;）GA&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Kubernetes 1.37&lt;/strong&gt;：&lt;code&gt;metrics.k8s.io&lt;/code&gt; API 规范在 Beta 近九年后定义 &lt;code&gt;v1&lt;/code&gt; 版本（metrics-server 需升级到提供 &lt;code&gt;v1&lt;/code&gt; 的版本才会注册）；HPA 扩缩容容差（默认 10%）可在单个 HPA 对象上通过 &lt;code&gt;behavior.scaleUp/scaleDown.tolerance&lt;/code&gt; 配置（v1.33 Alpha，v1.37 GA）；缩容到零（&lt;code&gt;minReplicas: 0&lt;/code&gt;，仅限自定义/外部指标）进入 Beta 并默认开启&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="架构原理"&gt;架构原理&lt;/h2&gt;
&lt;p&gt;Horizontal Pod Autoscaling 适用于任何实现了 &lt;code&gt;scale&lt;/code&gt; 子资源的工作负载，包括 Deployment、ReplicaSet、StatefulSet 以及启用了 scale 子资源的自定义资源（DaemonSet 除外），由 API server 和 controller 共同实现。&lt;/p&gt;
&lt;p&gt;下图展示了 HPA 的整体架构：&lt;/p&gt;
&lt;figure class="mx-auto text-center"&gt;
&lt;img src="https://assets.jimmysong.io/images/book/kubernetes-handbook/controllers/hpa/horizontal-pod-autoscaler.webp" data-img="https://assets.jimmysong.io/images/book/kubernetes-handbook/controllers/hpa/horizontal-pod-autoscaler.webp" alt="图 1: HPA 示意图" data-caption="图 1: HPA 示意图"
width="969"
height="554"
loading="lazy" decoding="async" class="image-loading"
onload="this.classList.remove('image-loading'); this.classList.add('image-loaded');"
onerror="handleImageError(this); this.classList.remove('image-loading');"&gt;
&lt;figcaption&gt;图 1: HPA 示意图&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id="工作机制"&gt;工作机制&lt;/h3&gt;
&lt;p&gt;HPA 通过控制循环实现自动扩缩容，循环周期由 controller manager 的 &lt;code&gt;--horizontal-pod-autoscaler-sync-period&lt;/code&gt; 参数指定（默认 30 秒）。&lt;/p&gt;
&lt;p&gt;每个周期内，controller manager 会执行以下步骤：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;查询指标&lt;/strong&gt;：从 resource metric API 或自定义 metric API 获取指标。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;计算利用率&lt;/strong&gt;：
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Resource metrics&lt;/strong&gt;：计算与容器 resource request 的百分比。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;自定义 metrics&lt;/strong&gt;：使用原始值进行比较。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Object metrics&lt;/strong&gt;：获取单个对象的指标与目标值比较。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;计算副本数&lt;/strong&gt;：基于所有指标计算新的副本数，取最大值。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;执行扩缩容&lt;/strong&gt;：通过 Scale 子资源调整副本数。&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="alert alert-note-container"&gt;
&lt;div class="alert-note-title px-2"&gt;
注意
&lt;/div&gt;
&lt;div class="alert-note px-2"&gt;
如果 Pod 的容器没有设置 resource request，则无法定义 CPU 利用率，HPA 不会对该指标采取任何操作。
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="支持的指标类型"&gt;支持的指标类型&lt;/h2&gt;
&lt;p&gt;Kubernetes HPA 支持多种指标类型，具体如下：&lt;/p&gt;
&lt;h3 id="api-版本对比"&gt;API 版本对比&lt;/h3&gt;
&lt;p&gt;下表对比了不同 API 版本下 HPA 支持的指标类型。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;API 版本&lt;/th&gt;
&lt;th&gt;支持的指标&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;autoscaling/v1&lt;/td&gt;
&lt;td&gt;CPU 利用率&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;autoscaling/v2&lt;/td&gt;
&lt;td&gt;CPU、内存、自定义指标、多指标组合&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;figcaption class="text-center mb-3"&gt;
表 1: HPA 不同 API 版本支持的指标类型
&lt;/figcaption&gt;
&lt;h3 id="指标获取方式"&gt;指标获取方式&lt;/h3&gt;
&lt;p&gt;HPA 控制器可通过以下两种方式获取指标：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;直接 Heapster 访问：通过 API 服务器的服务代理查询 Heapster。&lt;/li&gt;
&lt;li&gt;REST 客户端访问：通过 metrics API 获取指标。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="基本使用"&gt;基本使用&lt;/h2&gt;
&lt;p&gt;在实际运维中，HPA 的使用非常灵活，支持命令行和 YAML 配置两种方式。&lt;/p&gt;
&lt;h3 id="kubectl-命令"&gt;kubectl 命令&lt;/h3&gt;
&lt;p&gt;以下是常用的 HPA 管理命令：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 基本管理命令&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl create hpa
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get hpa
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl describe hpa
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl delete hpa
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 快速创建 HPA&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl autoscale deployment nginx --min&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; --max&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt; --cpu-percent&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="命令参数说明"&gt;命令参数说明&lt;/h3&gt;
&lt;p&gt;kubectl autoscale 命令的参数说明如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl autoscale &lt;span class="o"&gt;(&lt;/span&gt;-f FILENAME &lt;span class="p"&gt;|&lt;/span&gt; TYPE NAME &lt;span class="p"&gt;|&lt;/span&gt; TYPE/NAME&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;--min&lt;span class="o"&gt;=&lt;/span&gt;MINPODS&lt;span class="o"&gt;]&lt;/span&gt; --max&lt;span class="o"&gt;=&lt;/span&gt;MAXPODS &lt;span class="o"&gt;[&lt;/span&gt;--cpu-percent&lt;span class="o"&gt;=&lt;/span&gt;CPU&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;flags&lt;span class="o"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;示例&lt;/strong&gt;：为 Deployment foo 创建 autoscaler，CPU 利用率达到 80% 时扩缩容，副本数在 2-5 之间：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl autoscale deployment foo --min&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; --max&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt; --cpu-percent&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="yaml-配置示例"&gt;YAML 配置示例&lt;/h3&gt;
&lt;p&gt;通过 YAML 文件可以更灵活地配置 HPA，支持多指标扩缩容。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;autoscaling/v2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;HorizontalPodAutoscaler&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;nginx-hpa&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;scaleTargetRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;apps/v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Deployment&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;nginx&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;minReplicas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;maxReplicas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;metrics&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Resource&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;cpu&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Utilization&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;averageUtilization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Resource&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;memory&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Utilization&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;averageUtilization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="alert alert-warning-container"&gt;
&lt;div class="alert-warning-title px-2"&gt;
滚动更新注意事项
&lt;/div&gt;
&lt;div class="alert-warning px-2"&gt;
HPA 应绑定到 Deployment / StatefulSet 这类上层控制器，而不是直接绑定 ReplicaSet：滚动更新会创建新的 ReplicaSet，直接绑定旧 ReplicaSet 的 HPA 不会自动跟随。同时，使用 HPA 时不要在 Deployment 清单里写死 &lt;code&gt;replicas&lt;/code&gt;，否则每次 &lt;code&gt;kubectl apply&lt;/code&gt; 都会把副本数重置为清单值。
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="自定义指标配置"&gt;自定义指标配置&lt;/h2&gt;
&lt;p&gt;HPA 支持基于自定义指标的扩缩容，需满足一定的前提条件。&lt;/p&gt;
&lt;h3 id="前提条件"&gt;前提条件&lt;/h3&gt;
&lt;p&gt;要使用自定义指标，需完成如下配置：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Controller Manager 配置&lt;/strong&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;--horizontal-pod-autoscaler-use-rest-clients&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;--master&lt;span class="o"&gt;=&lt;/span&gt;http://API_SERVER_ADDRESS:8080&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;API Server 配置&lt;/strong&gt;（Kubernetes 1.7+）：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;--requestheader-client-ca-file&lt;span class="o"&gt;=&lt;/span&gt;/etc/kubernetes/ssl/ca.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;--requestheader-allowed-names&lt;span class="o"&gt;=&lt;/span&gt;aggregator
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;--requestheader-extra-headers-prefix&lt;span class="o"&gt;=&lt;/span&gt;X-Remote-Extra-
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;--requestheader-group-headers&lt;span class="o"&gt;=&lt;/span&gt;X-Remote-Group
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;--requestheader-username-headers&lt;span class="o"&gt;=&lt;/span&gt;X-Remote-User
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;--proxy-client-cert-file&lt;span class="o"&gt;=&lt;/span&gt;/etc/kubernetes/ssl/kubernetes.pem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;--proxy-client-key-file&lt;span class="o"&gt;=&lt;/span&gt;/etc/kubernetes/ssl/kubernetes-key.pem&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="apiservice-配置"&gt;APIService 配置&lt;/h3&gt;
&lt;p&gt;创建自定义指标 API 服务的 YAML 示例：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;apiregistration.k8s.io/v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;APIService&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;v1beta2.custom-metrics.metrics.k8s.io&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;insecureSkipTLSVerify&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;group&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;custom-metrics.metrics.k8s.io&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;groupPriorityMinimum&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;versionPriority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;custom-metrics-apiserver&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;custom-metrics&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;v1beta2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="prometheus-集成"&gt;Prometheus 集成&lt;/h3&gt;
&lt;p&gt;通过 Prometheus Operator 可以实现自定义指标的采集与暴露。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;部署 Prometheus Operator&lt;/strong&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl apply -f prometheus-operator.yaml&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;验证自定义指标 API&lt;/strong&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get --raw&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/apis/custom-metrics.metrics.k8s.io/v1beta2&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; jq .&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;自定义指标 HPA 示例&lt;/strong&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;autoscaling/v2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;HorizontalPodAutoscaler&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;nginx-custom-hpa&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;scaleTargetRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;apps/v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Deployment&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;nginx&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;minReplicas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;maxReplicas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;metrics&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Pods&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;pods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;metric&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;http_requests_per_second&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;AverageValue&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;averageValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;100&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Object&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;metric&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;requests-per-second&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;describedObject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;networking.k8s.io/v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Ingress&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;main-route&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Value&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;10k&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="多指标支持"&gt;多指标支持&lt;/h2&gt;
&lt;p&gt;Kubernetes 1.6 及以上版本支持基于多个指标的扩缩容。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;HPA 会根据每个指标分别计算所需副本数&lt;/li&gt;
&lt;li&gt;取所有指标计算结果中的最大值作为最终扩缩容结果&lt;/li&gt;
&lt;li&gt;需确保所有指标都满足要求&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="指标类型说明"&gt;指标类型说明&lt;/h3&gt;
&lt;p&gt;下表总结了 HPA 支持的指标类型及其用途。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;指标类型&lt;/th&gt;
&lt;th&gt;描述&lt;/th&gt;
&lt;th&gt;用途&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Resource&lt;/td&gt;
&lt;td&gt;CPU、内存等资源指标&lt;/td&gt;
&lt;td&gt;基础资源监控&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pods&lt;/td&gt;
&lt;td&gt;Pod 级别的自定义指标&lt;/td&gt;
&lt;td&gt;应用特定指标&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Object&lt;/td&gt;
&lt;td&gt;Kubernetes 对象指标&lt;/td&gt;
&lt;td&gt;外部资源监控&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;External&lt;/td&gt;
&lt;td&gt;外部系统指标&lt;/td&gt;
&lt;td&gt;云服务指标&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;figcaption class="text-center mb-3"&gt;
表 2: HPA 支持的指标类型及用途
&lt;/figcaption&gt;
&lt;h2 id="最佳实践"&gt;最佳实践&lt;/h2&gt;
&lt;p&gt;在实际生产环境中，建议遵循以下最佳实践：&lt;/p&gt;
&lt;h3 id="资源请求设置"&gt;资源请求设置&lt;/h3&gt;
&lt;p&gt;合理设置 Pod 的资源请求和限制，有助于 HPA 精确扩缩容。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;100m&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;128Mi&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;limits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;500m&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;512Mi&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="合理的扩缩容参数"&gt;合理的扩缩容参数&lt;/h3&gt;
&lt;p&gt;通过配置 behavior 字段，可以优化扩缩容的平滑性，避免频繁波动。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;behavior&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;scaleDown&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;stabilizationWindowSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;300&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;tolerance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0.05&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# v1.37：缩容容差 5%，覆盖集群默认的 10%&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;policies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Percent&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;periodSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;60&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;scaleUp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;stabilizationWindowSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;60&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;tolerance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0.02&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 扩容更敏感&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;policies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Percent&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;50&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;periodSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;60&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;tolerance&lt;/code&gt; 字段（特性门控 &lt;code&gt;HPAConfigurableTolerance&lt;/code&gt;）让&amp;quot;扩容要快、缩容要稳&amp;quot;这类不对称策略无需再修改 kube-controller-manager 全局参数即可实现。&lt;/p&gt;
&lt;h3 id="监控和告警"&gt;监控和告警&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;监控 HPA 状态和扩缩容事件&lt;/li&gt;
&lt;li&gt;设置合理的告警阈值&lt;/li&gt;
&lt;li&gt;定期检查指标的准确性&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="与其他弹性机制的配合"&gt;与其他弹性机制的配合&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;KEDA&lt;/strong&gt;：基于消息队列长度、HTTP 请求数等外部事件源驱动扩缩容，并支持缩容到 0；KEDA 在底层仍然创建并管理 HPA 对象&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;VPA 与原地资源调整&lt;/strong&gt;：v1.35 起 Pod 原地资源调整 GA，VPA 的 &lt;code&gt;InPlaceOrRecreate&lt;/code&gt; 模式可在不重建 Pod 的情况下调整 CPU/内存；同一工作负载上不要让 HPA 与 VPA 同时基于 CPU/内存做决策&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cluster Autoscaler / Karpenter&lt;/strong&gt;：HPA 扩出的 Pod 若无节点可调度，由节点级弹性组件补充节点&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="故障排除"&gt;故障排除&lt;/h2&gt;
&lt;p&gt;在使用 HPA 过程中，常见问题及排查方法如下：&lt;/p&gt;
&lt;h3 id="常见问题"&gt;常见问题&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;HPA 不生效&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;检查 Pod 是否设置了 resource requests&lt;/li&gt;
&lt;li&gt;验证 metrics-server 是否正常运行&lt;/li&gt;
&lt;li&gt;确认 HPA 配置正确&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;自定义指标无法获取&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;检查自定义指标 API 是否注册&lt;/li&gt;
&lt;li&gt;验证 APIService 配置&lt;/li&gt;
&lt;li&gt;确认指标数据源正常&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;频繁扩缩容&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;调整 &lt;code&gt;stabilizationWindowSeconds&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;优化指标阈值设置&lt;/li&gt;
&lt;li&gt;检查应用负载模式&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="调试命令"&gt;调试命令&lt;/h3&gt;
&lt;p&gt;以下命令可用于排查 HPA 相关问题：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 查看 HPA 状态&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl describe hpa &amp;lt;hpa-name&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 查看 HPA 事件&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get events --field-selector involvedObject.kind&lt;span class="o"&gt;=&lt;/span&gt;HorizontalPodAutoscaler
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 查看可用指标&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get --raw &lt;span class="s2"&gt;&amp;#34;/apis/metrics.k8s.io/v1beta1/nodes&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; jq . &lt;span class="c1"&gt;# metrics-server 提供 v1 后可改为 /v1/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl get --raw &lt;span class="s2"&gt;&amp;#34;/apis/custom-metrics.metrics.k8s.io/v1beta2&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; jq .&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="总结"&gt;总结&lt;/h2&gt;
&lt;p&gt;HPA 是 Kubernetes 自动化运维的核心能力之一，能够根据多种指标实现 Pod 的自动扩缩容。通过合理配置资源请求、自定义指标和扩缩容策略，可以显著提升集群资源利用率和应用弹性。实际生产中，建议结合监控和告警体系，持续优化 HPA 策略，确保系统稳定高效运行。&lt;/p&gt;
&lt;h2 id="参考文献"&gt;参考文献&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/" target="_blank" rel="noopener"&gt;HPA 官方文档 - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/" target="_blank" rel="noopener"&gt;HPA Walkthrough - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/kubernetes/metrics" target="_blank" rel="noopener"&gt;自定义指标开发 - github.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@marko.luksa/kubernetes-autoscaling-based-on-custom-metrics-without-using-a-host-port-b783ed6241ac" target="_blank" rel="noopener"&gt;Kubernetes autoscaling based on custom metrics - medium.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>自定义 Pod 自动扩缩容器</title><link>https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/custom-autoscaler/</link><pubDate>Mon, 27 Oct 2025 20:10:00 +0800</pubDate><author>Jimmy Song</author><guid>https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/custom-autoscaler/</guid><description>自定义 Pod 自动扩缩容器让你基于业务指标灵活定义扩缩容策略，突破标准 HPA 的局限，实现更智能的资源管理。</description><content:encoded>
&lt;blockquote&gt;
&lt;p&gt;只有理解业务，才能让自动扩缩容真正服务于系统弹性和成本优化。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;随着 Kubernetes 在云原生架构中的广泛应用，自动扩缩容（Autoscaling）成为了保障系统弹性和性能的关键机制。标准的 &lt;strong&gt;水平 Pod 自动扩缩容（Horizontal Pod Autoscaler，HPA）&lt;/strong&gt; 为基于 CPU 和内存的扩缩容提供了便捷方案。然而，随着业务场景的复杂化，单一资源维度的自动扩缩容往往难以满足实际需求。此时，&lt;strong&gt;自定义 Pod 自动扩缩容器（Custom Autoscaler）&lt;/strong&gt; 提供了灵活的工具，让用户能够根据业务指标自定义扩缩容策略，进一步扩展 Kubernetes 的自动化能力。&lt;/p&gt;
&lt;p&gt;本文将介绍如何通过自定义 Pod 自动扩缩容器扩展 Kubernetes 的标准自动扩缩容机制，并探讨如何在集群中实现更高效、动态的资源管理。&lt;/p&gt;
&lt;h2 id="概述"&gt;概述&lt;/h2&gt;
&lt;p&gt;自定义 Pod 自动扩缩容器基于 Kubernetes 的自定义指标（Custom Metrics）和事件进行扩缩容。它不仅支持标准的资源利用率（如 CPU、内存），还可以结合应用特定的指标（如请求数、响应时间等）实现自动扩缩容。通过扩展 Kubernetes 控制器和 API 机制，自定义扩缩容器能够支持更灵活的自动化管理和更智能的集群调度。&lt;/p&gt;
&lt;p&gt;Kubernetes 提供了多种扩展机制来实现自定义功能，包括自定义资源定义（Custom Resource Definition，CRD）、API 聚合层、Admission Webhook 等。开发者可以利用这些机制，将 Kubernetes 扩展为适应特定工作负载的自动化管理系统。&lt;/p&gt;
&lt;h2 id="工作原理"&gt;工作原理&lt;/h2&gt;
&lt;p&gt;自定义 Pod 自动扩缩容器的核心原理与 Kubernetes 内建的 HPA 类似，通常包括以下四个步骤：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;观察&lt;/strong&gt;：通过 Kubernetes 的监控组件（如 Prometheus、Metrics Server）获取集群中各类指标（如自定义应用指标）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;分析&lt;/strong&gt;：分析当前状态与期望状态的差异，判断是否需要扩展或缩减 Pod 副本。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;调节&lt;/strong&gt;：执行扩缩容操作，通过调整 Pod 副本数实现资源的自动调整。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;重复&lt;/strong&gt;：控制器持续循环上述过程，确保集群始终保持在期望的资源状态。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="自定义扩缩容的关键组件"&gt;自定义扩缩容的关键组件&lt;/h2&gt;
&lt;p&gt;自定义 Pod 自动扩缩容涉及多个核心组件，下面分别介绍其作用和实现方式。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;自定义资源定义（CRD）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;自定义资源定义（CRD）是扩展 Kubernetes API 的核心机制之一，允许用户创建新的资源类型并定义特定控制逻辑。通过 CRD，用户可以创建适合自身应用的扩展控制器，使其能够基于自定义指标进行扩缩容。&lt;/p&gt;
&lt;p&gt;例如，可以创建一个 CRD 定义 &lt;code&gt;AppMetrics&lt;/code&gt; 资源，用于描述应用的自定义监控数据。该 CRD 可包含如“请求数”“错误率”等业务特定指标，并将这些指标作为扩缩容的依据。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;APIService 与 Metrics Server&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Kubernetes 的 API 聚合层允许将外部 API 与主 API 集成。在自定义自动扩缩容场景中，APIService 用于注册新的 API 服务，如自定义指标 API 服务。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Metrics Server&lt;/strong&gt; 是获取集群资源使用情况的插件，通常与 HPA 等组件配合使用。在自定义扩缩容中，用户可结合自定义指标与标准资源指标，制定更灵活的扩缩容策略。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Admission Webhook 与 Validating Webhook&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Admission Webhook 是 Kubernetes 的扩展机制，用于拦截请求并在资源对象创建或修改时执行策略检查。通过自定义 Admission Webhook，可以在 Pod 创建时校验资源请求是否合理。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Validating Webhook&lt;/strong&gt; 可用于动态验证 Pod 配置，确保自定义指标满足扩缩容要求。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;控制器与 Operator 模式&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;控制器是 Kubernetes 实现自愈和自动化管理的核心。在自定义 Pod 自动扩缩容中，控制器负责监听指标变化、计算新副本数并调整 Pod 数量。结合 Operator 模式，可以将扩缩容逻辑与应用管理（如版本控制、故障恢复等）统一到一个自定义控制器中，实现更高层次的自动化。&lt;/p&gt;
&lt;h2 id="实现步骤"&gt;实现步骤&lt;/h2&gt;
&lt;p&gt;实现自定义 Pod 自动扩缩容器通常包括以下步骤：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;安装与配置 Metrics Server&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;首先需确保 Kubernetes 集群已安装并配置 Metrics Server，以便获取 Pod 资源使用情况（如 CPU、内存等）。这为集成自定义扩缩容提供基础数据支持。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;创建自定义指标&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;通过创建自定义 API 服务（如 &lt;code&gt;AppMetrics&lt;/code&gt; CRD），并结合 Prometheus 等监控工具收集、暴露自定义指标。这些指标可作为扩缩容决策的依据。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;定义自定义扩缩容策略&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;基于自定义指标，可以通过 YAML 配置文件定义自定义扩缩容器。例如，结合 &lt;code&gt;HorizontalPodAutoscaler&lt;/code&gt; 和 &lt;code&gt;autoscaling/v2&lt;/code&gt; API，可同时基于 CPU、内存与自定义指标进行扩缩容。&lt;/p&gt;
&lt;p&gt;下面的 YAML 示例展示了如何配置基于自定义指标和资源利用率的自动扩缩容策略：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;autoscaling/v2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;HorizontalPodAutoscaler&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;custom-hpa&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;scaleTargetRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;apps/v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Deployment&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;app-deployment&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;minReplicas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;maxReplicas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;metrics&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Pods&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;pods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;metric&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;http_requests_per_second&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;AverageValue&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;averageValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;100&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Resource&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;cpu&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Utilization&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;averageUtilization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;监控与告警&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;为确保系统高效运行，建议结合 Prometheus 进行全面监控，并设置合理的告警阈值。通过监控和告警配置，可以在资源使用异常时及时响应，保障系统稳定性。&lt;/p&gt;
&lt;h2 id="最佳实践"&gt;最佳实践&lt;/h2&gt;
&lt;p&gt;在实现自定义 Pod 自动扩缩容时，建议遵循以下最佳实践：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;合理设置资源请求和限制&lt;/strong&gt;：为每个 Pod 设置合适的资源请求（requests）和限制（limits），确保 HPA 基于准确数据进行扩缩容。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;定义平滑的扩缩容策略&lt;/strong&gt;：为避免频繁波动，建议在 &lt;code&gt;scaleUp&lt;/code&gt; 和 &lt;code&gt;scaleDown&lt;/code&gt; 策略中配置 &lt;code&gt;stabilizationWindowSeconds&lt;/code&gt; 等参数，平滑扩缩容过程。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;集成 Prometheus 和自定义指标&lt;/strong&gt;：结合 Prometheus 采集自定义指标，可实现更灵活的扩缩容策略，不局限于 CPU 和内存。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;定期检查和优化扩缩容配置&lt;/strong&gt;：随着负载模式变化，定期检查扩缩容策略并优化，以适应新的应用需求。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="总结"&gt;总结&lt;/h2&gt;
&lt;p&gt;自定义 Pod 自动扩缩容器为 Kubernetes 带来了更高的灵活性和可扩展性。通过自定义指标、外部系统和应用特定需求，能够自动调整集群资源，提高资源利用率，简化运维，减少手动干预。合理配置和持续优化自定义扩缩容，将为复杂业务场景提供强大支持。&lt;/p&gt;
&lt;h2 id="参考资料"&gt;参考资料&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/" target="_blank" rel="noopener"&gt;Kubernetes 官方文档 - Autoscaling&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.infoq.com/articles/proactive-autoscaling-edge-kubernetes/" target="_blank" rel="noopener"&gt;IProactive Autoscaling at the Edge with Kubernetes - infoq.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jthomperoo/custom-pod-autoscaler" target="_blank" rel="noopener"&gt;Custom Pod Autoscaler - github.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>VPA 与 KEDA：纵向扩缩与事件驱动扩缩</title><link>https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/vpa-and-keda/</link><pubDate>Sun, 01 Nov 2026 00:00:00 +0800</pubDate><author>Jimmy Song</author><guid>https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/vpa-and-keda/</guid><description>介绍 HPA 之外的两类工作负载自动扩缩：Vertical Pod Autoscaler 的推荐器/更新器/准入控制器架构、Off/Initial/Recreate/InPlaceOrRecreate/InPlace 更新模式及与原地资源调整的结合；KEDA 的 ScaledObject/ScaledJob 模型、70+ 事件源 Scaler、缩容到零与 HPA 的协作；以及三者的组合策略与冲突规避。</description><content:encoded>
&lt;blockquote&gt;
&lt;p&gt;HPA 回答&amp;quot;要几个副本&amp;quot;，VPA 回答&amp;quot;每个副本该多大&amp;quot;，KEDA 回答&amp;quot;该不该从零唤醒&amp;quot;——三者合在一起才是完整的工作负载弹性。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="../hpa"&gt;HPA&lt;/a&gt; 是 Kubernetes 内置的水平扩缩器，但它依赖 CPU/内存等资源指标或需要自建指标适配器，且副本数最少为 1（&lt;code&gt;HPAScaleToZero&lt;/code&gt; 在 v1.37 仍为 Beta 且默认关闭）。两个 SIG Autoscaling 与 CNCF 项目补足了这些空白：Vertical Pod Autoscaler（VPA）自动校准容器的资源 requests，KEDA 以事件源驱动水平扩缩并支持缩容到零。本文介绍两者的原理、配置与组合方式。&lt;/p&gt;
&lt;h2 id="vertical-pod-autoscaler"&gt;Vertical Pod Autoscaler&lt;/h2&gt;
&lt;p&gt;资源 requests 决定调度、驱逐顺序、配额与节点扩缩的一切计算，但大多数团队要么凭经验填写、要么长期不更新，导致集群整体利用率普遍只有 20% – 40%。VPA 通过观察容器的历史用量持续生成推荐值，并可选地自动应用。&lt;/p&gt;
&lt;h3 id="架构"&gt;架构&lt;/h3&gt;
&lt;p&gt;VPA 由三个组件组成：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Recommender&lt;/strong&gt;：从 metrics-server（或 Prometheus）读取各容器的 CPU/内存用量，用衰减直方图计算 P50/P90/P95 等分位数，生成 &lt;code&gt;target&lt;/code&gt;（推荐值）、&lt;code&gt;lowerBound&lt;/code&gt;、&lt;code&gt;upperBound&lt;/code&gt; 与 &lt;code&gt;uncappedTarget&lt;/code&gt;；OOM 事件会使内存推荐立即上调&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Updater&lt;/strong&gt;：比较运行中 Pod 的 requests 与推荐值，偏差超出阈值时驱逐 Pod（或在新模式下原地调整），遵守 PDB 与最小副本限制&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Admission Controller&lt;/strong&gt;：变更准入 Webhook，在 Pod 创建时把推荐值写入 requests（与 limits 按原比例缩放）&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;autoscaling.k8s.io/v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;VerticalPodAutoscaler&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;api&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;targetRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;apps/v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Deployment&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;api&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;updatePolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;updateMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;InPlaceOrRecreate&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Off | Initial | Recreate | InPlaceOrRecreate | InPlace&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;minReplicas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 至少保留 2 个副本不被同时驱逐&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;resourcePolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;containerPolicies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;containerName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;*&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;minAllowed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;{&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;100m, memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;128Mi }&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;maxAllowed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;{&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;4&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;, memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;8Gi }&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;controlledResources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;cpu&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;memory&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;controlledValues&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;RequestsAndLimits &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 或 RequestsOnly，保留手工设置的 limits&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;containerName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;istio-proxy&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Off&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 排除 Sidecar&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="更新模式"&gt;更新模式&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;模式&lt;/th&gt;
&lt;th&gt;行为&lt;/th&gt;
&lt;th&gt;适用&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Off&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;只生成推荐写入 &lt;code&gt;status.recommendation&lt;/code&gt;，不改变 Pod&lt;/td&gt;
&lt;td&gt;观察与容量规划，所有工作负载的起点&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Initial&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;仅在 Pod 创建时应用推荐，运行中不改&lt;/td&gt;
&lt;td&gt;不能容忍重启但部署频繁的服务&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Recreate&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;偏差过大时驱逐 Pod 让其以新 requests 重建&lt;/td&gt;
&lt;td&gt;批处理、可容忍重启的无状态服务&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;InPlaceOrRecreate&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;优先通过 &lt;a href="../../pod/in-place-pod-resize"&gt;原地资源调整&lt;/a&gt; 修改 requests，不可行时回退到驱逐（VPA 1.5+ Beta）&lt;/td&gt;
&lt;td&gt;大多数生产服务的推荐模式（Kubernetes 1.33+）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;InPlace&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;只做原地调整，永不驱逐，不可行时推迟重试（VPA 1.7+ Alpha，需 &lt;code&gt;--feature-gates=InPlace=true&lt;/code&gt;）&lt;/td&gt;
&lt;td&gt;完全不能接受中断的有状态服务&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;figcaption class="text-center mb-3"&gt;
表 1: VPA 更新模式
&lt;/figcaption&gt;
&lt;p&gt;&lt;code&gt;InPlaceOrRecreate&lt;/code&gt; 把 VPA 从&amp;quot;周期性重启应用的工具&amp;quot;变成了近乎无感的持续调优：对配置了 &lt;code&gt;resizePolicy: NotRequired&lt;/code&gt; 的容器，CPU 与内存上调不需要重启；内存 limit 下调在 &lt;code&gt;PreferNoRestart&lt;/code&gt; 策略下仍会回退到重建；若调整会改变 Pod 的 QoS 等级（如从 Burstable 变为 Guaranteed）、被 kubelet 判定不可行、推迟超过 5 分钟或进行中超过 1 小时，同样回退。&lt;code&gt;--in-place-skip-disruption-budget&lt;/code&gt; 标志允许对所有容器都无需重启的调整跳过 PDB 检查。&lt;/p&gt;
&lt;h3 id="使用要点"&gt;使用要点&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;VPA 与 HPA &lt;strong&gt;不能同时控制同一资源维度&lt;/strong&gt;：HPA 按 CPU 利用率扩缩时，VPA 调整 CPU requests 会改变利用率计算基准导致震荡；常见组合是 HPA 用自定义指标（QPS、队列长度）或 KEDA 控制副本数，VPA 只管 requests&lt;/li&gt;
&lt;li&gt;JVM 等启动时按固定堆大小分配内存的应用，内存推荐应配合 &lt;code&gt;minAllowed&lt;/code&gt; 并关注 &lt;code&gt;upperBound&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;推荐值基于至少 8 天的历史（可配置），新部署的工作负载前几天的推荐不可靠&lt;/li&gt;
&lt;li&gt;Recommender 默认依赖 metrics-server，大集群建议改用 Prometheus 作为历史存储（&lt;code&gt;--storage=prometheus&lt;/code&gt;）以在 Recommender 重启后保留历史&lt;/li&gt;
&lt;li&gt;&lt;code&gt;kubectl describe vpa api&lt;/code&gt; 可查看推荐与各容器的上下界，Goldilocks 等工具提供集群级仪表盘&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="keda事件驱动扩缩"&gt;KEDA：事件驱动扩缩&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://keda.sh/" target="_blank" rel="noopener"&gt;KEDA&lt;/a&gt;（Kubernetes Event-driven Autoscaling，CNCF 毕业项目，当前 v2.21）让工作负载按外部事件源的指标扩缩——消息队列积压、数据库行数、HTTP 请求率、云监控指标、Cron 时间表等——并支持缩容到零与从零激活。它不替代 HPA，而是作为 HPA 的外部指标提供者：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;KEDA Operator 监听 &lt;code&gt;ScaledObject&lt;/code&gt;，为目标工作负载自动创建并管理一个 HPA（&lt;code&gt;minReplicaCount&lt;/code&gt; 到 &lt;code&gt;maxReplicaCount&lt;/code&gt; 区间）&lt;/li&gt;
&lt;li&gt;KEDA Metrics Server 把各 Scaler 的指标通过 &lt;code&gt;external.metrics.k8s.io&lt;/code&gt; 聚合 API 暴露给 HPA&lt;/li&gt;
&lt;li&gt;在 0 与 1 副本之间的切换由 KEDA 自己完成（HPA 不能管理 0 副本）：事件源出现待处理项时 KEDA 把副本从 0 拉到 1（激活），之后交给 HPA；无事件持续 &lt;code&gt;cooldownPeriod&lt;/code&gt; 后再缩回 0&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;keda.sh/v1alpha1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ScaledObject&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;order-worker&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;prod&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;scaleTargetRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;order-worker &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Deployment / StatefulSet / 任意带 scale 子资源的 CR&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;pollingInterval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 查询事件源的间隔（秒）&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cooldownPeriod&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;300&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 最后一次活跃后多久缩到 0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;idleReplicaCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 空闲时的副本数（必须小于 minReplicaCount）&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;minReplicaCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;maxReplicaCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;50&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 事件源不可达时的保底副本数&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;failureThreshold&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;replicas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;advanced&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;horizontalPodAutoscalerConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;behavior&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 直接透传给 HPA 的 behavior&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;scaleDown&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;stabilizationWindowSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;120&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;triggers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;kafka&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;bootstrapServers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;kafka.prod.svc:9092&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;consumerGroup&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;order-worker&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;orders&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;lagThreshold&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;100&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 每副本期望处理的积压量&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;activationLagThreshold&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;1&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 积压 ≥ 1 即从 0 激活&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;authenticationRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;kafka-creds&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;prometheus&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;serverAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;http://prometheus.monitoring.svc:9090&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;sum(rate(http_requests_total{service=&amp;#34;order-worker&amp;#34;}[2m]))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;threshold&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;50&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;keda.sh/v1alpha1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;TriggerAuthentication&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;kafka-creds&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;prod&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;secretTargetRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;parameter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;sasl&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;kafka-secret&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;sasl&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;parameter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;username&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;kafka-secret&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;username&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;parameter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;password&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;kafka-secret&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;password&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;多个触发器默认取各自计算出的副本数的最大值，&lt;code&gt;advanced.scalingModifiers&lt;/code&gt; 可用公式组合多个指标。&lt;code&gt;TriggerAuthentication&lt;/code&gt;/&lt;code&gt;ClusterTriggerAuthentication&lt;/code&gt; 把凭据从 ScaledObject 中分离，支持 Secret、环境变量、Vault、云 Pod 身份（AWS IRSA/Pod Identity、Azure Workload Identity、GCP Workload Identity）。&lt;/p&gt;
&lt;h3 id="scaledjob"&gt;ScaledJob&lt;/h3&gt;
&lt;p&gt;对&amp;quot;每条消息一个任务&amp;quot;的批处理模式，&lt;code&gt;ScaledJob&lt;/code&gt; 按队列长度直接创建 Job 而非扩缩 Deployment：每个 Job 处理完即退出，不存在长驻消费者被缩容时打断处理的问题，适合视频转码、报表生成、AI 批量推理等长任务。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;keda.sh/v1alpha1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ScaledJob&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;transcode&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;jobTargetRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;parallelism&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;backoffLimit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;restartPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Never&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;worker&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;registry.example.com/transcoder:1.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;pollingInterval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;15&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;maxReplicaCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;successfulJobsHistoryLimit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;scalingStrategy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;strategy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;accurate &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 按队列长度减去运行中 Job 数精确创建&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;triggers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;aws-sqs-queue&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;queueURL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;https://sqs.us-west-2.amazonaws.com/123456789012/transcode&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;queueLength&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;1&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;awsRegion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;us-west-2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;authenticationRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;aws-pod-identity&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="常用-scaler"&gt;常用 Scaler&lt;/h3&gt;
&lt;p&gt;KEDA 内置 70 余种 Scaler，覆盖消息系统（Kafka、RabbitMQ、NATS、Pulsar、SQS、Azure Service Bus、Pub/Sub）、数据库（PostgreSQL、MySQL、MongoDB、Redis、Elasticsearch）、监控系统（Prometheus、Datadog、CloudWatch、Azure Monitor、Stackdriver）、CI 系统（GitHub Runner、GitLab Runner、Azure Pipelines）、以及 &lt;code&gt;cron&lt;/code&gt;（按时间表预扩）、&lt;code&gt;cpu&lt;/code&gt;/&lt;code&gt;memory&lt;/code&gt;（与 HPA 相同的资源指标）和 &lt;code&gt;kubernetes-workload&lt;/code&gt;（按另一个工作负载的 Pod 数）。HTTP 请求驱动的缩容到零需要额外的 &lt;a href="https://github.com/kedacore/http-add-on" target="_blank" rel="noopener"&gt;KEDA HTTP Add-on&lt;/a&gt;，它在请求路径上插入拦截器缓冲冷启动期间的请求——这与 Knative Serving 的 Activator 思路相同，后者在 &lt;a href="../../serverless/knative"&gt;Serverless&lt;/a&gt; 章节介绍。&lt;/p&gt;
&lt;h2 id="三者的组合策略"&gt;三者的组合策略&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;需求&lt;/th&gt;
&lt;th&gt;方案&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;按 CPU/内存利用率扩缩副本&lt;/td&gt;
&lt;td&gt;HPA（或 KEDA 的 cpu/memory Scaler，便于统一管理）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;按队列积压、请求率、业务指标扩缩&lt;/td&gt;
&lt;td&gt;KEDA（自动创建 HPA）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;空闲时缩到零&lt;/td&gt;
&lt;td&gt;KEDA（&lt;code&gt;idleReplicaCount: 0&lt;/code&gt;）；HTTP 服务加 HTTP Add-on 或改用 Knative&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;校准 requests、消除过度申请&lt;/td&gt;
&lt;td&gt;VPA（&lt;code&gt;Off&lt;/code&gt; 观察 → &lt;code&gt;InPlaceOrRecreate&lt;/code&gt; 自动）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;副本数与 requests 同时自动化&lt;/td&gt;
&lt;td&gt;KEDA/HPA 用非资源指标控制副本，VPA 控制 requests，避免同一维度冲突&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;批处理任务按事件创建&lt;/td&gt;
&lt;td&gt;KEDA ScaledJob，或 Kueue 配合 &lt;a href="../../controllers/job-advanced"&gt;Job&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;定时预扩容应对可预期高峰&lt;/td&gt;
&lt;td&gt;KEDA &lt;code&gt;cron&lt;/code&gt; Scaler 叠加其他触发器&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;figcaption class="text-center mb-3"&gt;
表 2: HPA、VPA 与 KEDA 的分工
&lt;/figcaption&gt;
&lt;p&gt;所有工作负载层的扩缩最终都要落到节点容量上，副本增加导致 Pending 时由 &lt;a href="../node-autoscaling"&gt;节点自动扩缩&lt;/a&gt; 补充节点；VPA 上调 requests 同样可能触发节点扩容。把 VPA 的 &lt;code&gt;maxAllowed&lt;/code&gt; 设在节点可分配资源以内，可以避免推荐出任何节点都放不下的 Pod。&lt;/p&gt;
&lt;h2 id="总结"&gt;总结&lt;/h2&gt;
&lt;p&gt;VPA 与 KEDA 分别从纵向与事件两个维度补全了 Kubernetes 的工作负载弹性：VPA 用持续观测取代手工估算 requests，借助原地资源调整在不重启的前提下自动校准；KEDA 让副本数跟随业务事件而非资源利用率变化，并补上 HPA 缺失的缩容到零能力。实践中应以&amp;quot;HPA/KEDA 控制副本数、VPA 控制单副本大小、两者不触碰同一指标&amp;quot;为原则，再由节点自动扩缩兜底容量，形成从事件到节点的完整弹性链路。&lt;/p&gt;
&lt;h2 id="参考文献"&gt;参考文献&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler" target="_blank" rel="noopener"&gt;Vertical Pod Autoscaler - github.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/kubernetes/autoscaler/blob/master/vertical-pod-autoscaler/docs/features.md" target="_blank" rel="noopener"&gt;VPA Features: In-Place Updates - github.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://keda.sh/docs/" target="_blank" rel="noopener"&gt;KEDA Documentation - keda.sh&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://keda.sh/docs/latest/reference/scaledobject-spec/" target="_blank" rel="noopener"&gt;KEDA ScaledObject specification - keda.sh&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://keda.sh/docs/latest/scalers/" target="_blank" rel="noopener"&gt;KEDA Scalers - keda.sh&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/kedacore/http-add-on" target="_blank" rel="noopener"&gt;KEDA HTTP Add-on - github.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/" target="_blank" rel="noopener"&gt;Horizontal Pod Autoscaling - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>节点自动扩缩：Cluster Autoscaler 与 Karpenter</title><link>https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/node-autoscaling/</link><pubDate>Sun, 01 Nov 2026 00:00:00 +0800</pubDate><author>Jimmy Song</author><guid>https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/node-autoscaling/</guid><description>讲解节点层的自动扩缩：扩容（为 Pending Pod 供应节点）与整合（回收低利用率节点）两个方向的原理，Cluster Autoscaler 的节点组模型与扩展器策略，Karpenter 的 NodePool/NodeClass 模型、整合策略与中断预算，两者的选型对比，与 HPA/VPA/KEDA 的配合，以及 GPU 节点、Spot 实例与 PDB 等生产注意事项。</description><content:encoded>
&lt;blockquote&gt;
&lt;p&gt;工作负载自动扩缩解决&amp;quot;要多少 Pod&amp;quot;，节点自动扩缩解决&amp;quot;这些 Pod 放在哪台机器上&amp;quot;——后者直接决定账单。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="../vpa-and-keda"&gt;HPA、VPA 与 KEDA&lt;/a&gt; 调整的是 Pod 的数量与大小，而当集群现有节点容纳不下新的 Pod 时，就需要节点自动扩缩器（Node Autoscaler）向云平台申请新节点；反过来，当节点长期空闲或低利用率时，自动缩容与整合是云上成本优化最直接的手段。SIG Autoscaling 目前维护两个节点自动扩缩实现：Cluster Autoscaler 与 Karpenter。&lt;/p&gt;
&lt;h2 id="节点自动扩缩的两个方向"&gt;节点自动扩缩的两个方向&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;扩容&lt;/strong&gt;（Provisioning）由 Pending 状态的 Pod 驱动。自动扩缩器监听带有 &lt;code&gt;Unschedulable&lt;/code&gt; 条件的 Pod，用调度器相同的约束（资源 requests、节点选择器、亲和性、污点容忍、拓扑分布）模拟判断&amp;quot;如果新增某种节点，这些 Pod 能否被调度&amp;quot;，然后向云平台发起创建请求。节点就绪并注册后，调度器正常把 Pod 调度上去。这意味着：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;自动扩缩器只看 &lt;strong&gt;requests&lt;/strong&gt;，不看实际用量——requests 设置失真会直接导致扩容过度或不足&lt;/li&gt;
&lt;li&gt;不满足任何节点类型约束的 Pod（如请求的 GPU 类型没有对应节点池）会一直 Pending&lt;/li&gt;
&lt;li&gt;扩容延迟 = 决策周期（10 秒级） + 云平台创建实例（1 – 3 分钟） + 节点引导与镜像拉取&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;整合&lt;/strong&gt;（Consolidation）则试图在满足所有 Pod 约束的前提下减少节点数或替换为更便宜的节点。自动扩缩器会选择候选节点、模拟其上的 Pod 能否全部迁移到其他节点（或迁移到一台新的更小节点），通过则先设置污点、再逐个驱逐 Pod（遵守 PDB），最后删除节点。整合的激进程度与业务中断风险直接相关，是最需要精细配置的部分。&lt;/p&gt;
&lt;h2 id="cluster-autoscaler"&gt;Cluster Autoscaler&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler" target="_blank" rel="noopener"&gt;Cluster Autoscaler&lt;/a&gt;（CA）是最早的实现，版本号与 Kubernetes 小版本对齐（v1.37 集群对应 CA 1.37.x），支持 30 余种云平台与 Cluster API。它的核心抽象是&lt;strong&gt;节点组&lt;/strong&gt;（Node Group）：预先定义的、同构的实例集合（AWS Auto Scaling Group、GCP MIG、Azure VMSS、Cluster API 的 MachineDeployment），每个节点组有最小/最大节点数，CA 只在这些边界内调整数量。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 以 AWS 为例的关键启动参数&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;./cluster-autoscaler&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- --&lt;span class="l"&gt;cloud-provider=aws&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- --&lt;span class="l"&gt;node-group-auto-discovery=asg:tag=k8s.io/cluster-autoscaler/enabled,k8s.io/cluster-autoscaler/my-cluster&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- --&lt;span class="l"&gt;expander=least-waste &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 多个节点组都能容纳时的选择策略&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- --&lt;span class="l"&gt;balance-similar-node-groups &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 跨可用区的同构节点组均衡扩容&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- --&lt;span class="l"&gt;skip-nodes-with-local-storage=false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- --&lt;span class="l"&gt;scale-down-utilization-threshold=0.5 &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 利用率低于 50% 的节点成为缩容候选&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- --&lt;span class="l"&gt;scale-down-unneeded-time=10m &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 持续低利用 10 分钟后缩容&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- --&lt;span class="l"&gt;scale-down-delay-after-add=10m &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 扩容后 10 分钟内不缩容&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- --&lt;span class="l"&gt;max-node-provision-time=15m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;扩展器（Expander）决定多个节点组都能满足时选哪个：&lt;code&gt;random&lt;/code&gt;、&lt;code&gt;most-pods&lt;/code&gt;、&lt;code&gt;least-waste&lt;/code&gt;（浪费最少的资源）、&lt;code&gt;price&lt;/code&gt;（最便宜，需云平台支持）、&lt;code&gt;priority&lt;/code&gt;（按 ConfigMap 中的优先级正则），可用逗号组合形成多级决策。CA 的缩容基于利用率阈值且只能删除整台节点，不会主动把两台半满的节点合并到一台更合适的机型上。&lt;/p&gt;
&lt;p&gt;CA 的优势在于成熟、云平台覆盖广、与托管服务（EKS Managed Node Groups、GKE 节点池、AKS 节点池）深度集成——GKE 与 AKS 的内置自动扩缩即基于 CA。它的局限是&amp;quot;节点组&amp;quot;模型要求管理员预先枚举机型组合：要支持 10 种机型 × 3 个可用区 × 按需/Spot 就需要 60 个节点组，且每个节点组内部不能混用机型。&lt;/p&gt;
&lt;h2 id="karpenter"&gt;Karpenter&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://karpenter.sh/" target="_blank" rel="noopener"&gt;Karpenter&lt;/a&gt; 由 AWS 发起、2023 年捐赠给 SIG Autoscaling，核心库 &lt;code&gt;kubernetes-sigs/karpenter&lt;/code&gt; 当前为 v1.15，云平台实现包括 AWS（GA）、Azure（GA）以及社区维护的 GCP、阿里云、Cluster API 等。它放弃了节点组，直接面向云平台的实例 API 做&amp;quot;即时供应&amp;quot;：根据 Pending Pod 的聚合需求，在允许的机型范围内挑选最合适、最便宜的实例类型逐台创建，并用 &lt;code&gt;NodeClaim&lt;/code&gt; 对象跟踪每个节点的生命周期。&lt;/p&gt;
&lt;p&gt;两个核心 CRD 是 &lt;code&gt;NodePool&lt;/code&gt;（供应约束与中断策略，云无关）与云平台特定的 &lt;code&gt;NodeClass&lt;/code&gt;（如 &lt;code&gt;EC2NodeClass&lt;/code&gt;，定义 AMI、子网、安全组、磁盘）：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;karpenter.sh/v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;NodePool&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;general&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;team&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;platform&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;nodeClassRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;group&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;karpenter.k8s.aws&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;EC2NodeClass&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;default&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;requirements&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 允许的机型范围，Karpenter 在其中按价格择优&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;karpenter.sh/capacity-type&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;In&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;spot&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;on-demand&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;kubernetes.io/arch&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;In&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;amd64&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;arm64&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;karpenter.k8s.aws/instance-category&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;In&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;c&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;m&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;r&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;karpenter.k8s.aws/instance-generation&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Gt&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;5&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;expireAfter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;720h &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 节点最长存活 30 天，强制轮换以更新 AMI&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;terminationGracePeriod&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;48h &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 中断时给 Pod 的最长排空时间&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;disruption&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;consolidationPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;WhenEmptyOrUnderutilized&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;consolidateAfter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;1m&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;budgets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;10%&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 任意时刻最多中断 10% 节点&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;schedule&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;0 9 * * mon-fri&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 工作日白天禁止主动整合&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;8h&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;0&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;limits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;1000&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;4000Gi&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;karpenter.k8s.aws/v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;EC2NodeClass&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;default&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;amiSelectorTerms&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;al2023@latest&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;KarpenterNodeRole-my-cluster&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;subnetSelectorTerms&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;{&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;karpenter.sh/discovery&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;my-cluster }&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;securityGroupSelectorTerms&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;{&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;karpenter.sh/discovery&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;my-cluster }&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;blockDeviceMappings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;deviceName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;/dev/xvda&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ebs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;{&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;volumeSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;100Gi, volumeType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;gp3, encrypted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Karpenter 的几个关键特性：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;装箱式供应&lt;/strong&gt;：一批 Pending Pod 会被聚合后选择一台或少数几台恰好容纳的实例，而不是按固定机型逐台加；Spot 场景下自动在多种机型中选择中断率低、价格优的组合&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;主动整合&lt;/strong&gt;：&lt;code&gt;WhenEmptyOrUnderutilized&lt;/code&gt; 策略下，Karpenter 会持续评估能否删除节点或把节点替换为更便宜的机型（如把 &lt;code&gt;m5.2xlarge&lt;/code&gt; 换成当前更便宜的 &lt;code&gt;m6a.xlarge&lt;/code&gt; + 迁移 Pod），&lt;code&gt;Balanced&lt;/code&gt; 则在成本与中断之间折中；配合 &lt;code&gt;budgets&lt;/code&gt; 控制速度与时间窗口&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;节点到期与漂移&lt;/strong&gt;：&lt;code&gt;expireAfter&lt;/code&gt; 强制定期轮换节点以应用新的 AMI 与补丁；修改 &lt;code&gt;NodeClass&lt;/code&gt; 后现有节点被标记为&amp;quot;漂移&amp;quot;（Drift）并按预算逐步替换，实现声明式的节点生命周期管理&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Spot 中断处理&lt;/strong&gt;：通过云平台事件（EC2 Spot 中断通知、计划维护）提前排空节点，与 &lt;a href="../kubelet-resource-management"&gt;节点优雅关机&lt;/a&gt; 配合&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="选型对比"&gt;选型对比&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;维度&lt;/th&gt;
&lt;th&gt;Cluster Autoscaler&lt;/th&gt;
&lt;th&gt;Karpenter&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;节点模型&lt;/td&gt;
&lt;td&gt;预定义节点组，组内同构&lt;/td&gt;
&lt;td&gt;无节点组，按约束范围即时选择机型&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;扩容速度&lt;/td&gt;
&lt;td&gt;依赖节点组 API，通常 2 – 4 分钟&lt;/td&gt;
&lt;td&gt;直接调用实例 API，通常 1 – 2 分钟&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;机型灵活性&lt;/td&gt;
&lt;td&gt;需为每种机型/区/容量类型建组&lt;/td&gt;
&lt;td&gt;一个 NodePool 覆盖数百种机型&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;缩容/整合&lt;/td&gt;
&lt;td&gt;按利用率阈值删除整台节点&lt;/td&gt;
&lt;td&gt;删除或替换为更便宜机型，预算与时间窗控制&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;节点生命周期&lt;/td&gt;
&lt;td&gt;不管理，由节点组/托管服务负责&lt;/td&gt;
&lt;td&gt;到期轮换、漂移替换、AMI 声明式更新&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;云平台支持&lt;/td&gt;
&lt;td&gt;30+（含私有云、Cluster API）&lt;/td&gt;
&lt;td&gt;AWS、Azure GA；GCP、阿里云、CAPI 等社区实现&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;与托管服务集成&lt;/td&gt;
&lt;td&gt;GKE/AKS 内置；EKS Managed Node Groups&lt;/td&gt;
&lt;td&gt;EKS Auto Mode 内置；AKS Node Autoprovisioning（NAP）内置&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;成熟度&lt;/td&gt;
&lt;td&gt;2016 年起，极为成熟&lt;/td&gt;
&lt;td&gt;2021 年起，AWS 上大规模生产验证&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;figcaption class="text-center mb-3"&gt;
表 1: Cluster Autoscaler 与 Karpenter 对比
&lt;/figcaption&gt;
&lt;p&gt;实践中的建议：在 AWS 或 Azure 上的新集群优先选择 Karpenter，其机型灵活性与整合能力带来的成本节省通常在 20% – 40%；多云、私有云或依赖 Cluster API 的环境使用 CA；GKE 直接使用内置的节点自动供应（NAP）即可。两者可以共存但不应管理同一批节点，常见组合是系统组件所在的固定节点池由 CA/托管服务管理，弹性工作负载由 Karpenter 供应。&lt;/p&gt;
&lt;h2 id="与工作负载扩缩的配合"&gt;与工作负载扩缩的配合&lt;/h2&gt;
&lt;p&gt;节点扩缩与 Pod 扩缩是两个独立但相互触发的回路：HPA/KEDA 增加副本 → 新 Pod Pending → 节点扩容；HPA 减少副本 → 节点利用率下降 → 整合回收。配合时需注意：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;requests 准确性&lt;/strong&gt;是一切的前提，&lt;a href="../vpa-and-keda"&gt;VPA&lt;/a&gt; 推荐模式可持续校准&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;扩容预热&lt;/strong&gt;：对延迟敏感的服务，可部署低优先级（负 &lt;code&gt;PriorityClass&lt;/code&gt; 值）的&amp;quot;占位 Pod&amp;quot;预留一台空闲节点，真正的业务 Pod 到来时抢占占位 Pod 立即调度，节点扩缩器随后为被抢占的占位 Pod 补充节点，详见 &lt;a href="../priority-and-preemption"&gt;优先级与抢占&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PDB&lt;/strong&gt; 是整合时的安全网，没有 PDB 的多副本应用可能在整合中被同时驱逐；但过于严格的 PDB（如 &lt;code&gt;maxUnavailable: 0&lt;/code&gt;）会让节点永远无法回收，Karpenter 与 CA 都会在日志与事件中报告被 PDB 阻塞的节点&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DaemonSet 与系统 Pod&lt;/strong&gt; 不会阻止缩容；带本地存储（&lt;code&gt;emptyDir&lt;/code&gt; 外的 hostPath/local PV）的 Pod、未被控制器管理的裸 Pod、以及带 &lt;code&gt;cluster-autoscaler.kubernetes.io/safe-to-evict: &amp;quot;false&amp;quot;&lt;/code&gt; 或 &lt;code&gt;karpenter.sh/do-not-disrupt: &amp;quot;true&amp;quot;&lt;/code&gt; 注解的 Pod 会阻止其所在节点被回收&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="gpu-与-ai-工作负载"&gt;GPU 与 AI 工作负载&lt;/h2&gt;
&lt;p&gt;GPU 节点昂贵且启动慢（驱动与 CUDA 镜像拉取），自动扩缩需要额外考虑：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在 NodePool/节点组上设置 &lt;code&gt;nvidia.com/gpu&lt;/code&gt; 等污点，确保只有显式请求 GPU 的 Pod 落到 GPU 节点；Karpenter 可按 &lt;code&gt;karpenter.k8s.aws/instance-gpu-name&lt;/code&gt; 等标签精确约束 GPU 型号&lt;/li&gt;
&lt;li&gt;扩容器依赖设备插件或 DRA 驱动在节点上报告 GPU 容量；节点就绪到 GPU 可用之间有延迟，CA 需配置 &lt;code&gt;--gpu-total&lt;/code&gt; 相关的节点组标签让其在模拟时预知 GPU 数量，Karpenter 则从实例类型元数据直接获知&lt;/li&gt;
&lt;li&gt;训练任务通常以 Job/JobSet 形式成组启动，配合 &lt;a href="../../controllers/job-advanced"&gt;Kueue&lt;/a&gt; 等队列系统做准入后再触发节点扩容，避免部分 Pod 就绪、部分等待节点的&amp;quot;半启动&amp;quot;浪费；GenericWorkload/成组调度的进展也将改善这一点&lt;/li&gt;
&lt;li&gt;GPU 节点的整合要格外保守：训练中的 Pod 被驱逐意味着丢失检查点以来的进度，应设置 &lt;code&gt;karpenter.sh/do-not-disrupt&lt;/code&gt; 注解或更长的 &lt;code&gt;terminationGracePeriod&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="总结"&gt;总结&lt;/h2&gt;
&lt;p&gt;节点自动扩缩把&amp;quot;有多少机器&amp;quot;从容量规划变成了由工作负载需求实时驱动的闭环。Cluster Autoscaler 以节点组为单位稳健地增减节点，覆盖几乎所有基础设施；Karpenter 则跳过节点组直接按 Pod 需求选择最优实例，并以到期、漂移与整合预算实现声明式的节点生命周期管理。无论选择哪一个，准确的资源 requests、合理的 PDB 与明确的中断预算，都是让自动扩缩既省钱又不伤业务的前提。&lt;/p&gt;
&lt;h2 id="参考文献"&gt;参考文献&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/cluster-administration/node-autoscaling/" target="_blank" rel="noopener"&gt;Node Autoscaling - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/FAQ.md" target="_blank" rel="noopener"&gt;Cluster Autoscaler FAQ - github.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://karpenter.sh/docs/" target="_blank" rel="noopener"&gt;Karpenter Documentation - karpenter.sh&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://karpenter.sh/docs/concepts/nodepools/" target="_blank" rel="noopener"&gt;Karpenter NodePools - karpenter.sh&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://karpenter.sh/docs/concepts/disruption/" target="_blank" rel="noopener"&gt;Karpenter Disruption - karpenter.sh&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/kubernetes-sigs/karpenter" target="_blank" rel="noopener"&gt;kubernetes-sigs/karpenter - github.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>Volcano：Kubernetes 上的批处理和高性能计算调度器</title><link>https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/volcano/</link><pubDate>Thu, 20 Jun 2024 08:00:00 +0000</pubDate><author>Jimmy Song</author><guid>https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/volcano/</guid><description>Volcano 是一个专为高性能计算（HPC）和大规模批处理任务设计的 Kubernetes 调度器扩展，提供先进的调度策略和资源管理功能。</description><content:encoded>
&lt;blockquote&gt;
&lt;p&gt;Volcano 是 Kubernetes 生态中专为批处理和高性能计算（HPC）场景设计的调度器扩展，支持 Gang 调度、资源公平分配和多种插件机制，极大提升了集群在 AI、科研和大数据领域的调度能力。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="项目背景与设计目标"&gt;项目背景与设计目标&lt;/h2&gt;
&lt;p&gt;Kubernetes 默认调度器主要面向服务型负载，存在以下局限：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每个 Pod 独立调度，缺乏任务组（JobGroup）概念；&lt;/li&gt;
&lt;li&gt;不支持 Gang Scheduling（成组调度）和资源公平共享（Fair Share）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Volcano 通过自定义资源（CRD）和可插拔调度插件，补齐了这些短板，目标是为 AI/ML 分布式训练、HPC 批处理、大数据计算和科研仿真等场景提供原生支持。&lt;/p&gt;
&lt;h2 id="架构总览"&gt;架构总览&lt;/h2&gt;
&lt;p&gt;Volcano 控制平面由多个组件构成，负责批量任务调度、资源分配与生命周期管理。下图展示了主要架构组件及其交互关系。&lt;/p&gt;
&lt;figure class="mx-auto text-center"&gt;
&lt;img src="https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/volcano/volcano-architecture.svg" data-img="/zh/book/kubernetes-handbook/scheduling/volcano/volcano-architecture.svg"
alt="图 1: Volcano 架构总览" data-caption="图 1: Volcano 架构总览" loading="lazy" decoding="async"
width="2440"
height=" 1340"
onerror="handleImageError(this); this.classList.remove('image-loading');"
onload="this.classList.remove('image-loading'); this.classList.add('image-loaded');"
class="image-loading"
style="width: 100%; height: auto;"&gt;
&lt;figcaption&gt;图 1: Volcano 架构总览&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;组件&lt;/th&gt;
&lt;th&gt;作用&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;vc-scheduler&lt;/td&gt;
&lt;td&gt;主调度器，负责 Pod 分配、抢占、回收等动作&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;vc-controller-manager&lt;/td&gt;
&lt;td&gt;管理 CRD 生命周期（Job、Queue、PodGroup）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;vc-webhook-manager&lt;/td&gt;
&lt;td&gt;Admission 校验与变更&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;vc-agent&lt;/td&gt;
&lt;td&gt;节点级管理（部分版本可选）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;figcaption class="text-center mb-3"&gt;
表 1: Volcano 核心组件职责
&lt;/figcaption&gt;
&lt;h2 id="自定义资源crd模型"&gt;自定义资源（CRD）模型&lt;/h2&gt;
&lt;p&gt;Volcano 通过自定义资源扩展了 Kubernetes 的原生对象模型。下图展示了各 CRD 之间的关系。&lt;/p&gt;
&lt;figure class="mx-auto text-center"&gt;
&lt;img src="https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/volcano/volcano-crd-model.svg" data-img="/zh/book/kubernetes-handbook/scheduling/volcano/volcano-crd-model.svg"
alt="图 2: Volcano CRD 模型" data-caption="图 2: Volcano CRD 模型" loading="lazy" decoding="async"
width="2080"
height=" 1000"
onerror="handleImageError(this); this.classList.remove('image-loading');"
onload="this.classList.remove('image-loading'); this.classList.add('image-loaded');"
class="image-loading"
style="width: 100%; height: auto;"&gt;
&lt;figcaption&gt;图 2: Volcano CRD 模型&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;资源类型&lt;/th&gt;
&lt;th&gt;功能说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Job&lt;/td&gt;
&lt;td&gt;定义批量任务、任务组、资源需求&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PodGroup&lt;/td&gt;
&lt;td&gt;实现 Gang Scheduling，保证任务组原子调度&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Queue&lt;/td&gt;
&lt;td&gt;定义资源配额与优先级&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JobFlow&lt;/td&gt;
&lt;td&gt;支持任务依赖与有向执行图（DAG）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JobTemplate&lt;/td&gt;
&lt;td&gt;模板化任务定义，方便重用&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;figcaption class="text-center mb-3"&gt;
表 2: Volcano CRD 功能说明
&lt;/figcaption&gt;
&lt;h2 id="调度流程与执行机制"&gt;调度流程与执行机制&lt;/h2&gt;
&lt;p&gt;Volcano 的调度流程分为多个阶段，确保批量任务高效分配和资源利用。下图展示了调度循环的主要流程。&lt;/p&gt;
&lt;figure class="mx-auto text-center"&gt;
&lt;img src="https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/volcano/volcano-scheduling-flow.svg" data-img="/zh/book/kubernetes-handbook/scheduling/volcano/volcano-scheduling-flow.svg"
alt="图 3: Volcano 调度流程" data-caption="图 3: Volcano 调度流程" loading="lazy" decoding="async"
width="2400"
height=" 1480"
onerror="handleImageError(this); this.classList.remove('image-loading');"
onload="this.classList.remove('image-loading'); this.classList.add('image-loaded');"
class="image-loading"
style="width: 100%; height: auto;"&gt;
&lt;figcaption&gt;图 3: Volcano 调度流程&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;调度循环（Scheduling Cycle）包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Enqueue：将待调度的 Job 加入队列&lt;/li&gt;
&lt;li&gt;Allocate：根据 Queue 配额分配资源&lt;/li&gt;
&lt;li&gt;Preempt：抢占低优先级任务&lt;/li&gt;
&lt;li&gt;Reclaim：回收闲置资源&lt;/li&gt;
&lt;li&gt;Bind：分配 Pod 至节点&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="插件体系plugin-system"&gt;插件体系（Plugin System）&lt;/h2&gt;
&lt;p&gt;Volcano 的插件系统高度可扩展，支持在调度周期多个阶段注入自定义逻辑。下图展示了插件分类及其与核心框架的关系。&lt;/p&gt;
&lt;figure class="mx-auto text-center"&gt;
&lt;img src="https://jimmysong.io/zh/book/kubernetes-handbook/scheduling/volcano/volcano-plugin-system.svg" data-img="/zh/book/kubernetes-handbook/scheduling/volcano/volcano-plugin-system.svg"
alt="图 4: Volcano 插件体系" data-caption="图 4: Volcano 插件体系" loading="lazy" decoding="async"
width="2240"
height=" 1040"
onerror="handleImageError(this); this.classList.remove('image-loading');"
onload="this.classList.remove('image-loading'); this.classList.add('image-loaded');"
class="image-loading"
style="width: 100%; height: auto;"&gt;
&lt;figcaption&gt;图 4: Volcano 插件体系&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;插件&lt;/th&gt;
&lt;th&gt;功能说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Gang&lt;/td&gt;
&lt;td&gt;实现任务组全量调度&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DRF&lt;/td&gt;
&lt;td&gt;多资源公平共享&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Proportion&lt;/td&gt;
&lt;td&gt;队列配额分配&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Predicates&lt;/td&gt;
&lt;td&gt;节点资源匹配&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NodeOrder&lt;/td&gt;
&lt;td&gt;节点优先级排序&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BinPack&lt;/td&gt;
&lt;td&gt;紧密打包，提升利用率&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Overcommit&lt;/td&gt;
&lt;td&gt;超卖调度&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Topology&lt;/td&gt;
&lt;td&gt;NUMA / 网络拓扑感知&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;figcaption class="text-center mb-3"&gt;
表 3: 常见内置插件功能
&lt;/figcaption&gt;
&lt;h2 id="安装与使用"&gt;安装与使用&lt;/h2&gt;
&lt;p&gt;Volcano 支持 Helm 和原生 YAML 安装方式。安装后会在 volcano-system 命名空间创建核心组件。&lt;/p&gt;
&lt;h3 id="通过-helm-安装"&gt;通过 Helm 安装&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;helm repo add volcano-sh https://volcano-sh.github.io/helm-charts
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;helm install volcano volcano-sh/volcano -n volcano-system --create-namespace&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="使用原生-yaml-安装"&gt;使用原生 YAML 安装&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubectl apply -f https://raw.githubusercontent.com/volcano-sh/volcano/master/installer/volcano-development.yaml&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;安装后主要组件包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;volcano-scheduler&lt;/li&gt;
&lt;li&gt;volcano-controllers&lt;/li&gt;
&lt;li&gt;volcano-admission&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="典型使用场景"&gt;典型使用场景&lt;/h2&gt;
&lt;p&gt;Volcano 适用于多种批处理和高性能计算场景。下表列举了典型应用框架及其调度特性。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;场景&lt;/th&gt;
&lt;th&gt;框架&lt;/th&gt;
&lt;th&gt;调度特性&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;AI 训练&lt;/td&gt;
&lt;td&gt;TensorFlow、PyTorch、Ray&lt;/td&gt;
&lt;td&gt;Gang 调度 + GPU 绑定&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;大数据计算&lt;/td&gt;
&lt;td&gt;Spark、Flink&lt;/td&gt;
&lt;td&gt;队列隔离 + Fair Share&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HPC 仿真&lt;/td&gt;
&lt;td&gt;MPI、Horovod&lt;/td&gt;
&lt;td&gt;NUMA 拓扑 + 低延迟通信&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bioinformatics&lt;/td&gt;
&lt;td&gt;Cromwell、KubeGene&lt;/td&gt;
&lt;td&gt;工作流依赖调度&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ML Pipeline&lt;/td&gt;
&lt;td&gt;Kubeflow、Argo&lt;/td&gt;
&lt;td&gt;JobFlow + 模板复用&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;figcaption class="text-center mb-3"&gt;
表 4: Volcano 典型使用场景
&lt;/figcaption&gt;
&lt;blockquote&gt;
&lt;p&gt;使用时，只需在 Pod 或 Job 中指定 &lt;code&gt;schedulerName: volcano&lt;/code&gt;，即可启用 Volcano 调度。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="与原生-kubernetes-的区别"&gt;与原生 Kubernetes 的区别&lt;/h2&gt;
&lt;p&gt;下表对比了 Volcano 与 kube-scheduler 的主要差异。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;对比维度&lt;/th&gt;
&lt;th&gt;kube-scheduler&lt;/th&gt;
&lt;th&gt;Volcano&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;调度粒度&lt;/td&gt;
&lt;td&gt;Pod&lt;/td&gt;
&lt;td&gt;Job / PodGroup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;资源公平性&lt;/td&gt;
&lt;td&gt;基于优先级&lt;/td&gt;
&lt;td&gt;支持 DRF、比例调度&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;调度策略&lt;/td&gt;
&lt;td&gt;简单优先级&lt;/td&gt;
&lt;td&gt;Gang、Backfill、Preemption&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CRD 支持&lt;/td&gt;
&lt;td&gt;无&lt;/td&gt;
&lt;td&gt;Job / Queue / PodGroup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;插件扩展&lt;/td&gt;
&lt;td&gt;有限&lt;/td&gt;
&lt;td&gt;完整可插拔插件系统&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;应用场景&lt;/td&gt;
&lt;td&gt;长期服务&lt;/td&gt;
&lt;td&gt;批处理 / HPC / AI 训练&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;figcaption class="text-center mb-3"&gt;
表 5: Volcano 与 kube-scheduler 对比
&lt;/figcaption&gt;
&lt;h2 id="总结"&gt;总结&lt;/h2&gt;
&lt;p&gt;Volcano 让 Kubernetes 从“服务编排平台”进化为“通用计算平台”，特别适用于分布式训练、资源公平调度、异构硬件感知和大规模批量作业管理。结合 Argo、Kubeflow、Ray 等生态系统，Volcano 使 Kubernetes 成为统一的高性能计算基础设施。&lt;/p&gt;
&lt;h2 id="参考文献"&gt;参考文献&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://volcano.sh/" target="_blank" rel="noopener"&gt;Volcano 官方文档 - volcano.sh&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/" target="_blank" rel="noopener"&gt;Kubernetes 官方文档 - kubernetes.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/volcano-sh/volcano" target="_blank" rel="noopener"&gt;Volcano GitHub 仓库 - github.com&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</content:encoded></item></channel></rss>