ARTICLE DETAIL

资讯详情

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

Kubernetes资源调度全解析:从调度原理到Pod Pending排查实战

Kubernetes资源调度全解析:从调度原理到Pod Pending排查实战 有没有遇到过这种场景生产集群里创建了一个 DeploymentReplicaSet 也建好了但 Pod 一直卡在 Pending怎么等都起不来。查 Events翻来覆去就是那一行0/5 nodes are available: 1 node(s) didnt match node selector, 4 node(s) had taint...。如果没研究过 Kubernetes 的资源调度你根本不知道这行报错背后意味着什么只能靠猜。Kubernetes 里的资源调度本质上就是回答一个问题一个新创建的 Pod该放到集群里哪个节点上。这个决策由kube-scheduler负责但它背后牵扯到资源请求、节点亲和、污点容忍、拓扑分布、优先级抢占、配额限制等一系列机制。把这些机制弄懂很多Pod 起不来流量打不均衡某个节点快被压垮的问题都能迎刃而解。这篇内容是我在实际维护多套集群过程中对调度这部分经验的整理从调度器的决策逻辑讲起逐步拆解资源请求、节点选择、污点和容忍、拓扑分布、优先级与配额最后聊一聊 Pending 问题的排查链路。无论你是刚接触 Kubernetes 的运维还是已经维护过一阵子集群的开发者这里面的坑和思路应该都能直接用得上。1. 调度决策的完整链路Pod 从创建到落在节点上发生了什么很多人的认知是把 YAML apply 进去Pod 就会被分配到某个节点启动。实际上从提交到真正运行有一段你没看到的流程。理解这段流程是排查所有调度问题的第一步。1.1 调度器的工作模型过滤、打分、绑定kube-scheduler是 Kubernetes 默认的调度器它通过 watch API Server 监听那些还没有被调度的 Podspec.nodeName为空并循环执行三个步骤过滤Filtering / Predicates先筛掉完全不满足条件的节点。比如节点资源不够、节点上有污点而 Pod 没有对应容忍、节点标签不匹配nodeSelector等。这一步结束后得到一个可行节点集合。打分Scoring / Priorities在可行节点集合里通过一系列打分函数给每个节点打分。比如节点剩余资源多的分数高、Pod 所需镜像是否已经存在、节点上已有同类 Pod 的数量等等。最后选总分最高的节点。绑定Binding调度器把选中的结果写回 API Server生成一个 Binding 对象将 Pod 的nodeName字段设置为目标节点。之后kubelet看到 Pod 被绑定到自己的节点才开始拉镜像、创建容器。我在维护集群时经常把调度比作面试招人过滤环节是简历筛选不符合硬性条件的直接 pass打分环节是面试评分综合考虑谁最合适绑定环节是发录用通知。缺了任何一环Pod 都不会被正确调度。1.2 调度周期与绑定周期为什么调度不是实时的调度器内部把一个 Pod 的完整调度流程分为两个阶段调度周期Scheduling Cycle和绑定周期Binding Cycle。调度周期从调度队列中弹出 Pod 开始依次执行过滤、打分、抢占等逻辑。如果调度周期内发现无法找到合适节点Pod 会被放回队列并重试或者前置于队列头部以实现抢占。绑定周期则负责将调度结果应用到集群包括调用外部调度器扩展Extender或异步绑定。绑定周期是异步的所以调度器可以同时处理多个 Pod 的调度周期提升吞吐量。这里的实战意义在于如果你发现 Pod 一直 Pending 但集群资源明明很充足可以去观察调度器日志和事件的时间戳。有时候是因为集群节点状态频繁抖动导致节点缓存更新不及时新创建的 Pod 拿不到最新信息。这时候kube-scheduler的--node-informer-sync-period、--scheduler-name这些参数就有调优空间了。1.3 事件与日志从调度结果反推判断链路判断调度是否正常最快的途径是看 Event。kubectl describe pod pod-name输出的 Events 里会有两类关键信息Scheduled调度器成功完成了绑定事件里会标明Successfully assigned namespace/pod to node。FailedScheduling调度器尝试了但没找到合适的节点事件里会列出每个节点被拒绝的原因比如Insufficient cpu、Untolerated taint、NodeUnschedulable。有一次我排查一个 Pending 的 PodEvents 里显示0/3 nodes are available: 1 Insufficient memory, 2 node(s) didnt match node selector。问题一下就清楚了节点内存不够而且的大部分节点因为标签不匹配被过滤。这时候不必折腾调度器只需要增加节点资源或者调整nodeSelector就行。所以看到一个 Pending 的 Pod别慌先看事件。调度器把为什么失败写得明明白白关键在于你是否读得懂。2. 资源请求与限制调度计算的真正依据调度器最基础的决策依据是资源请求。很多人分不清requests和limits在调度时的作用结果不是资源浪费就是节点被打爆。2.1 requests 和 limits 的职责边界在 Pod 容器定义里有两种资源参数参数作用调度器是否使用requests指定容器启动运行时需要预留的资源是调度和节点资源分配的依据。是调度器按照 requests 的总和来判断节点是否放得下。limits指定容器最多能使用的资源上限用于运行时限制CPU 配额和内存 OOM 判定。否调度时只看 requests不看 limits。这带来一个常见坑你给容器设置了limits.cpu: 4但没设置requests则 Kubernetes 会默认requests等于limits取决于 LimitRange 或默认行为调度器会按 4 核去计算导致节点明明很空闲却调度不上去。反过来如果只设置了requests不设limits调度器会正常调度但容器实际可能消耗超过 requests 的资源造成节点资源争抢。2.2 CPU 和内存的单位换算YAML 中 CPU 和内存的单位经常让人混淆CPU 单位是核数可以用小数或整数也支持mmillicore 毫核。100m等于 0.1 核。内存单位包括Mi十进制 10241024 字节、M十进制 10001000 字节容易混淆、Gi、Ki等。生产环境推荐使用Mi和Gi避免换算错误。我在一个项目里看到有人把内存写成了memory: 1024没有单位Kubernetes 默认按字节解析那就是 1KB。容器启动后直接 OOMKilled。这种低级错误只要记住一条不能省略单位Memory 用Mi/GiCPU 用核数或m。2.3 QoS 等级资源回收时谁先被牺牲如果同一个节点上的容器内存超用节点会被挤爆这时 kubelet 会按照 QoS 等级决定先杀掉哪些容器。QoS 等级由你是否设置了 requests/limits 决定QoS 等级条件节点内存压力时的表现GuaranteedPod 内每个容器都设置了 requests 和 limits且两者相等优先级最高最后被驱逐BurstablePod 内至少一个容器设置了 requests但不满足 Guaranteed中等可能被驱逐BestEffort没有任何容器设置 requests 和 limits最先被驱逐实战中对于核心业务容器强烈建议把 requests 和 limits 设为相同值至少让核心 Pod 的 QoS 为 Guaranteed。虽然这样会牺牲一些弹性但换来的稳定性在大型促销、流量突增场景下非常值得。我曾在一个共享集群里见过 BestEffort 的批处理任务把内存占满导致同节点上的 Web 容器频繁 OOMKilled后来给所有工作负载区分了 QoS 等级问题立刻缓解。2.4 合理设置 requests 的经验设置 requests 不是越低越好也不是越高越好。过低会导致节点超卖严重过高会导致资源碎片化和浪费。我的经验是先基于容器实际运行 7 天的监控数据取 P95 或 P99 的用量作为 requests。对于延迟敏感型应用requests 可以略高于平均值对于批处理任务requests 可以低于期望值配合优先级让它在空闲时抢占资源。需要制作一个资源分配率看板集群总可分配资源除以所有 Pod 的 requests 总和。正常情况下保持 100% 到 150% 之间超过 150% 就要小心了。超卖不是不行但要有监控和驱逐策略兜底。3. 用节点选择控制 Pod 位置nodeSelector 到 NodeAffinity调度器要放置 Pod 的节点类型往往受业务约束。比如 GPU 任务必须落在带 GPU 的节点支付服务最好和数据库同节点减少延迟某些敏感任务不能和其他业务混部。这时候需要主动干预调度位置。3.1 nodeSelector简单但够用nodeSelector是最简单的节点选择方式给节点打上标签然后在 Pod 里指定nodeSelector。例如# 给节点打标签 # kubectl label node node-01 disktypessd apiVersion: v1 kind: Pod metadata: name: nginx spec: nodeSelector: disktype: ssd containers: - name: nginx image: nginxnodeSelector 的缺点是只能做精确匹配无法表达最好在 A 节点其次在 B 节点这种带偏好的逻辑。而且如果存在多个需求比如既要 SSD 又要 GPU它只会做 AND 匹配没有提供更丰富运算符。它适合简单的业务分类场景但生产环境往往需要更强表达能力。3.2 nodeAffinity从 required 到 preferrednodeAffinity节点亲和性在 nodeSelector 基础上扩展了两类规则requiredDuringSchedulingIgnoredDuringExecution硬性要求Pod 必须调度到满足规则的节点等价于 nodeSelector 的升级版。preferredDuringSchedulingIgnoredDuringExecution软偏好调度器会尽量满足但实在没有符合条件的节点也会调度到其他节点。配置示例spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: topology.kubernetes.io/zone operator: In values: - us-east-1a - us-east-1b preferredDuringSchedulingIgnoredDuringExecution: - weight: 80 preference: matchExpressions: - key: node-role.kubernetes.io/gpu operator: Exists这里required强制 Pod 必须调度到 us-east-1a 或 us-east-1b 的节点preferred表示如果节点上存在node-role.kubernetes.io/gpu标签则额外加 80 分。权重值范围是 1 到 100多个 preference 可以叠加。3.3 运算符与表达式逻辑nodeAffinity 支持的运算符包括Invalue 列表中的任意一个匹配即满足NotInvalue 列表中都不匹配Exists只要节点存在该 key 标签即满足DoesNotExist节点上不存在该 keyGt/Lt值大于/小于某个数值适合按节点剩余资源量打标签的场景多个matchExpressions之间是 AND 关系多个nodeSelectorTerms之间是 OR 关系。这是很容易混淆的一点。我见过有人在同一nodeSelectorTerms下写了两个条件期望满足任一即可结果一个 Pod 永远调度不上去。正确做法是把条件放到不同nodeSelectorTerms下。3.4 结合节点池管理与标签规范在云环境或内部私有云中通常会把节点分成不同的节点池普通计算节点池、内存型节点池、GPU 节点池、高吞吐网络节点池。给每个节点池打上统一前缀的标签比如pool-typecpu、pool-typegpu然后在工作负载上通过 nodeAffinity 精确选择。实际踩坑经验节点标签是随节点生命周期同步管理的如果你用自动伸缩cluster-autoscaler动态扩缩容节点池一定要保证扩出来的节点带上了正确标签。否则扩容节点是空闲了但 Pod 带着 nodeSelector 还是可望不可及。4. 污点与容忍节点主动拒绝Pod 的开关nodeSelector 和 nodeAffinity 解决的是Pod 想选哪些节点但某些节点需要主动拒绝一些 Pod。比如节点要维护、节点带有特殊硬件、或者我想把某个节点保留给特定应用的灾备资源。这时候就用污点Taint和容忍Toleration。4.1 系统污点节点异常时的自我保护Kubernetes 会自动给异常节点打上几种污点污点效果触发条件node.kubernetes.io/not-ready不调度新 Pod已运行的 Pod 逐步驱逐节点心跳超时NotReadynode.kubernetes.io/unreachable不调度新 Pod已运行 Pod 选择性驱逐节点网络隔离node.kubernetes.io/out-of-disk不调度新 Pod已运行 Pod 可能被驱逐节点磁盘压力node.kubernetes.io/memory-pressure调度器会优先避开节点内存压力node.kubernetes.io/disk-pressure同上节点磁盘压力node.kubernetes.io/network-unavailable不调度新 Pod网络插件未就绪默认情况下Pod 对大部分系统污点有一定的自动容忍如tolerationSeconds300这是kube-controller-manager自动加上的用于在节点异常 5 分钟内保留 Pod等网络恢复。但如果你设置了严格的NoExecute策略则可能需要显式加容忍。4.2 自定义污点建设专有节点池给节点添加自定义污点没有任何限制。比如我有一批高配物理机只允许跑数据库类的 Pod# 给节点添加污点 kubectl taint nodes physical-db-01 dedicateddb:NoSchedule然后在这台机器上的 Pod 里加上对应的容忍spec: tolerations: - key: dedicated operator: Equal value: db effect: NoSchedule这样没有容忍的 Pod 永远不会调度到这台机器。注意equal容忍必须同时匹配 key、value、effect 三个字段才算真正匹配如果只想容忍 key 而不管 value可用operator: Exists且不写 value。4.3 NoSchedule、NoExecute 和 PreferNoSchedule 的区别污点 effect 有三种它们的威慑力完全不同NoSchedule新的 Pod 不允许调度到该节点但不影响节点上已经运行的 Pod。NoExecute不仅不允许新 Pod 调度还会驱逐节点上所有没有对应容忍的已运行 Pod。PreferNoSchedule调度时尽量避免但不强制属于软性规则。NoExecute还有个参数tolerationSeconds表示可以容忍这个污点多少秒。超过时间后如果节点还在驱逐状态Pod 就会被删除。这里有个实用技巧在节点维护前给业务 Pod 设置一个较长的tolerationSeconds可以避免维护操作一执行Pod 立刻被清走给业务留出优雅退出的时间。4.4 节点维护排空与污点结合运维节点时内核升级、硬件维修标准的流程是给节点打上污点NoScheduleNoExecute防止新 Pod 上来。执行kubectl drain --ignore-daemonsets node驱逐该节点上的 Pod。维护完成后删除污点然后执行kubectl uncordon node让节点重新参与调度。排空时有个坑如果 Pod 使用本地存储emptyDir、hostPath或者由 DaemonSet 管理的 Pod驱逐会失败。需要加--delete-emptydir-data和--ignore-daemonsets参数确认你接受数据丢失和 DaemonSet 重新调度的结果。5. 保证 Pod 分布均匀拓扑分布约束与反亲和默认调度器打分时会把 Pod 尽量分散到不同节点但这是基于节点维度的。如果你有多个可用区或机架默认调度器可不会管那么多。要避免所有副本挤在一个可用区需要使用拓扑分布约束和 Pod 反亲和。5.1 默认调度为什么 不保证高可用我曾经在一个跨可用区的集群里部署了一个三副本应用明明有三个可用区各有多台节点结果三个副本中的两个都落在同一个可用区。为什么因为默认打分函数SelectorSpreadPriority只会尽量让同属一个 ReplicaSet 的 Pod 分散到不同节点但对节点分布在哪些可用区一无所知。一旦那一个可用区出问题整个服务就挂了两个副本。5.2 topologySpreadConstraints 配置拆解topologySpreadConstraints是 Kubernetes 1.19 以后原生支持的分布约束它可以指定 Pod 在某个拓扑域可用区、节点、机架上的分布情况。常见配置如下spec: topologySpreadConstraints: - maxSkew: 1 topologyKey: topology.kubernetes.io/zone whenUnsatisfiable: DoNotSchedule labelSelector: matchLabels: app: web关键参数含义参数作用topologyKey指定拓扑域的标签 key通常用topology.kubernetes.io/zone表示可用区用kubernetes.io/hostname表示节点。maxSkew允许不同拓扑域中 Pod 数量的最大差异。maxSkew: 1意味着分布最均衡差异不超过 1。whenUnsatisfiable如果不满足约束时的行为DoNotSchedule表示硬性约束Pod 无法调度ScheduleAnyway表示软约束尽量满足但可以不满足。labelSelector匹配要统计和分布的目标 Pod 的标签。这个配置我最常用的场景是跨可用区多副本部署三副本maxSkew: 1DoNotSchedule这样三个 Pod 会分别落在三个可用区任何一个可用区挂了都不至于全部丢失。5.3 Pod 亲和与反亲和控制 Pod 之间的远近Pod 亲和性和反亲和性控制同一组 Pod 是否希望调度到同一个拓扑域。比如希望把互相访问频繁的两个服务比如 web 和 cache放到同一个节点/可用区减少网络延迟用podAffinity。希望把两个高负载服务的副本尽量分开避免互相干扰用podAntiAffinity。配置示例spec: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - web topologyKey: kubernetes.io/hostname这个配置强制保证不同节点上的appweb的 Pod 不能共存每个节点最多一个。很多高可用组件如 Cassandra、Zookeeper都建议这么配。注意podAntiAffinity的硬约束在大规模场景容易导致调度失败比如集群只有 3 个节点却要求 5 个副本且每节点只能放 1 个那 Pod 必然 Pending。所以反亲和尽量使用preferred软约束或者提前评估副本数量与节点容量。5.4 多约束叠加的注意点当同时使用podAntiAffinity和topologySpreadConstraints时约束是多次过滤和联合打分的配置不当可能互相矛盾。例如topologySpreadConstraints要求每个可用区最多 1 个副本而podAntiAffinity又要求同一可用区不得部署两个不同应用如果可用区数量不够就会导致不可调度。我的习惯是先画一张拓扑图明确有哪些拓扑域、每域几个节点、放置哪些工作负载然后逐步添加约束并模拟测试而不是一次性堆满所有条件。6. 资源竞争下的秩序优先级、配额与限制范围集群资源永远不够用当资源紧张时谁有资格抢占资源谁应该被先挤走这就是优先级、配额与 QoS 一起决定的事。6.1 PriorityClass定义重要程度PriorityClass是全局资源对象用来给 Pod 设置优先级数值。值越高表示越重要。apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: high-priority value: 1000000 globalDefault: false description: 用于核心生产业务Pod 里声明spec: priorityClassName: high-priority有了优先级之后高优先级 Pod 在队列中会排到低优先级前面并且在节点没有足够资源时可以触发抢占Preemption把低优先级 Pod 挤走。6.2 抢占机制是怎么工作的当一个新的高优先级 Pod 无法被调度时调度器不是立刻放弃而是会尝试找到一些节点在这些节点上杀掉一批低优先级 Pod释放资源来安放高优先级 Pod。这个过程称为抢占。调度器会将低优先级 Pod 从节点驱逐并在事件中记录类似Preempting the pod victim-pod。被抢占的 Pod 会被重建但如果其控制器是 Deployment则会在其他节点或该节点重新调度。这里有几个经验不要给所有 Pod 都设高优先级否则等于都没有优先级。抢占只会在必要的时候发生但频繁抢占会导致系统抖动。如果发现集群中抢占事件很多说明资源长期紧张应该扩容而不是依赖抢占。对无状态应用可以容忍被抢占但有状态应用数据库要设置较高的优先级或者使用 PDBPodDisruptionBudget保护最小可用副本数。6.3 ResourceQuota限制命名空间的资源上限多人协作的集群里最怕某个团队一口气创建 100 个 16 核的 Pod把集群资源耗尽。ResourceQuota可以限制命名空间内的资源总量。apiVersion: v1 kind: ResourceQuota metadata: name: team-a-quota namespace: team-a spec: hard: requests.cpu: 20 requests.memory: 100Gi limits.cpu: 40 limits.memory: 200Gi count/pods: 100这样命名空间team-a里所有 Pod 的 requests.cpu 总和不能超过 20 核否则 API Server 会直接拒绝创建新的 Pod。需要注意ResourceQuota校验的是已创建成功 Pod的 requests 之和不是当前调度的数量。如果你创建了一个 Pending 的 Pod它同样计入配额。6.4 LimitRange给单个 Pod 设定资源边界ResourceQuota管的是总量LimitRange则限定单个 Pod/容器的最小、最大资源数还能设置默认 requests/limits。apiVersion: v1 kind: LimitRange metadata: name: default-limit-range namespace: team-a spec: limits: - default: cpu: 500m memory: 512Mi defaultRequest: cpu: 100m memory: 128Mi max: cpu: 4 memory: 8Gi min: cpu: 50m memory: 64Mi type: Container在没有requests和limits的 Pod 里LimitRange 会自动注入默认值同时限制单容器最大/最小规模。推荐在生产命名空间统一配置 LimitRange防止有人忘写资源限制导致整节点被打爆。6.5 组合使用优先级 PDB 配额实现资源治理实际生产环境我一向建议三层组合ResourceQuota防止命名空间资源无度扩张LimitRange为单个容器兜底确保每个容器有明确的 requests/limitsPriorityClass PDB 为核心业务提供保障当资源真正紧张时低优先级无状态任务先被挤走核心数据库有 PDB 保护至少保持可服务副本数。这套组合在多人共享集群中尤其重要。没有配额和优先级隔离最终的结果往往是谁先跑起来谁占资源后到的核心业务反而被饿死。7. 遇到 Pod 卡在 Pending完整排查链路与常见原因不管前面理论掌握得多熟实战中总会遇到 Pod 起不来。掌握一套排查链路能省下大量时间。7.1 排查顺序从事件开始逐步深入我的固定排查步骤如下kubectl describe pod pod查看 Events看调度器给出的拒绝原因。如果事件不完整kubectl get events --all-namespaces --sort-by.lastTimestamp按时间找调度相关事件。检查命名空间资源配额kubectl describe quota -n ns看是不是触发了ResourceQuota限制。检查节点状态和资源量kubectl top nodes和kubectl describe node的 Allocatable 与已分配 requests。检查节点上的污点kubectl describe node | grep -A10 Taints。如果还是查不到看kube-scheduler日志kubectl logs -n kube-system scheduler-pod -n kube-system或通过审计日志找FailedScheduling。7.2 常见 Pending 原因及对策原因排查点处理方式资源不足Insufficient cpu/memory纵向扩容节点或降低 Pod requests不满足节点选择didnt match node selector/node affinity核对节点标签与 Pod 设置节点污点unTolerated taint添加容忍或移除污点节点不可调度node(s) were unschedulable检查节点是否被cordon配额限制exceeded quota事件调整 ResourceQuota 或不创建多余 PodPV 绑定失败waiting for volume to be created检查 PVC/PV 状态与 StorageClass优先级抢占失败preemption failed查看是否有 PDB 保护导致无法抢占节点有系统 Pod 限制例如 Evicted查看节点压力增加资源很多时候一个 Pod Pending 可能是多个原因叠加比如节点同时有污点和标签不匹配Events 里会把所有失败原因都列出来按列表逐条解决即可。7.3 自定义调度器与调度框架扩展思路默认调度器能满足大多数需求但如果你遇到把 Pod 调度到和某个服务网络延迟最低的节点优先调度到满足数据本地性的节点这类复杂逻辑可以考虑扩展调度器。Kubernetes 提供了两种扩展方式Scheduler Extender调度器扩展程序调度器在过滤和打分阶段会调用外部 HTTP 服务返回额外判决和分数。Scheduling Framework调度框架通过 plugin 监听调度各周期可以在过滤、打分、绑定前后注入自定义逻辑是更被推荐的方式。我实践过用 Scheduling Framework 写过一个优先调度到特定 GPU 型号的插件大致是在打分阶段读取节点上的 GPU 类型 label然后根据型号给出不同分数。整个过程不算复杂关键是理解插件生命周期和扩展点的调用顺序。如果业务有强烈的特殊调度需求不妨研究一下。8. 几个实战调优建议最后分享几个我在生产集群里验证过颇有价值的调优方向和细节。8.1 调度器性能参数回应大规模集群集群节点数量上千时默认调度器参数可能会成为瓶颈。几个值得关注的参数--kube-api-qps和--kube-api-burst默认kube-scheduler请求 API Server 的 QPS 有限增大这两个值可以提升调度吞吐。--policy-config-file可以通过 Policy 文件定义自定义过滤器/打分器的权重但新版本推荐使用调度框架。--percentage-of-nodes-to-score当集群节点很多时调度器不一定给所有节点打分这个参数控制打分节点比例。默认基于集群规模自适应。你可以调节它来平衡精度和性能。8.2 利用kubectl explain和模拟工具写调度相关 YAML 时我习惯先用kubectl explain pod.spec.affinity确认字段定义避免记错字段。也可以用kubectl create --dry-runclient做语法校验但--dry-runserver能真正校验准入和配额限制。如果要做更大规模的调度模拟可以用kube-scheduler的--write-config-to导出配置再结合descheduler检查集群中是否存在不合理的调度结果。8.3 定期检查调度分布与驱逐事件我用 Prometheus 收集调度相关指标如scheduler_pending_pods、scheduler_preemption_victims、cluster_autoscaler_*等并设置了告警当 Pending Pods 数量长时间大于 0 或抢占频率增加时触发通知。调度问题很多是慢慢累积的节点资源碎片、标签不一致、配额接近上限。不定时体检可能哪一天一个大版本更新就有一堆 Pod 挤不上去了。Kubernetes 的资源调度说到底是把资源高效地分配给合适的工作负载。这里面需要权衡的点非常多既要防止资源浪费又要防止过度超卖既要实现高可用又要避免调度决策过于死板。我自己的经验是别指望一蹴而就先把默认调度行为摸透再结合业务场景逐步增加约束和策略。每改一个调度配置都在测试环境里跑一轮观察它对现有工作负载的影响再上生产。这样踩过的坑才是你真正的效率工具。
返回列表