知其然,知其所以然
Kubernetes 2026-10-10

节点压力驱逐:谁先被驱逐

在独立的 kind 集群里把工作节点的 evictionHard.memory.available 调到比当前可用量低 900 MiB,让四个不同 QoS 的 Pod 同时占内存 1400 MiB:先被驱逐的是用量远超 requests 的 BestEffort 与 Burstable,用量低于 requests 的 Burstable 和 Guaranteed Pod 一直存活;驱逐 message 写明阈值、可用量、容器用量和 requests;节点出现 MemoryPressure=True 与 memory-pressure 污点,压力消失 20 秒后才恢复。

Kubernetes 节点压力驱逐 eviction MemoryPressure QoS kubelet 真实验证 动画演示
Kubernetes 2026-10-10

CPU limit 与节流:requests 和 limits 在 cgroup 里的映射

在 kind 节点的 cgroup v2 里实测 requests 与 limits 对 CPU 的影响:limit 200m 的死循环 10.3 秒只用 2.06 秒 CPU,79 个周期被限流;没有 limit 的容器用到 3.99 个核而 limit 1 核的只有 1.00 个核;只有 requests 时竞争按 cpu.weight 分(100m:400m 的实测用量比 1:3.08);同样的计算在无 limit、500m、100m 下分别花 4.3、8.4、54.8 秒。

Kubernetes CPU limit 限流 throttling cgroup cpu.max cpu.weight 真实验证 动画演示
Kubernetes 2026-10-10

OOMKilled:limit 和容器内进程的真实关系

在 kind 节点的 cgroup v2 里实测内存 limit 与 OOM:limit 64Mi 对应 memory.max=67108864,容器 cgroup 的 memory.oom.group=1,python 分配 100 MiB 后容器 OOMKilled(exitCode 137,oom_group_kill 计数增加);sh 作 1 号进程、python 是子进程时整个容器仍一起被杀(oom_kill 4);写内存型 emptyDir 占用的内存重启后不释放,导致 StartError: container init was OOM-killed,而写磁盘的页缓存可回收;在线把 limit 调到 256Mi 后进程不重启就继续跑到 150 MiB。

Kubernetes OOMKilled memory limit cgroup memory.oom.group 内存型 emptyDir 真实验证 动画演示
Kubernetes 2026-10-10

LimitRange:默认值和上下限怎么注入

在 kind 集群里实测 LimitRange:没写 resources 的 Pod 在准入时被补上默认 request/limit(并留下 limit-ranger 注解),默认值自己若违反 maxLimitRequestRatio 会让所有未写的 Pod 被拒绝;只写 limit 时 request 取 limit 的值;超出 max、低于 min、limit/request 比过大的 Pod 与超出范围的 PVC 都被拒绝并写明数值;修改 LimitRange 不影响已有的 Pod。

Kubernetes LimitRange 默认资源 准入控制 limit request 比 真实验证 动画演示
Kubernetes 2026-10-10

ResourceQuota:超额创建被拒绝的时机

在 kind 集群里实测 ResourceQuota:创建 Pod 时 status.used 立即累加;requests.cpu、pods 等超限的 Pod 在创建那一刻被拒绝(exceeded quota: …, requested/used/limited),Deployment 能创建但 ReplicaSet 创建 Pod 被拒、READY 只有 2/5;配额里有 requests/limits 时 Pod 必须写明,配合 LimitRange 补默认值才能通过;count/configmaps 限制个数;scopes: [BestEffort] 只统计 BestEffort Pod,删除后用量立即归零。

Kubernetes ResourceQuota 资源配额 准入控制 scopes count 配额 真实验证 动画演示
Kubernetes 2026-10-10

优先级与抢占:低优先级 Pod 被驱逐的流程

在 kind 集群里实测优先级与抢占:PriorityClass 在准入时写入 pod.spec.priority(没写是 0,不存在的类被拒绝);两个 worker 被低优先级 Pod 占满后,高优先级 Pod 先得到 nominatedNodeName,受害者 low3 被设上 deletionTimestamp、事件 Preempted、条件 DisruptionTarget(PreemptionByScheduler),等它 12 秒宽限期结束后高优先级 Pod 才在第 13.1 秒 Running;受害者选优先级最低的;preemptionPolicy: Never 的 Pod 不抢占。

Kubernetes PriorityClass 优先级 抢占 preemption 调度器 真实验证 动画演示
Kubernetes 2026-10-10

PodDisruptionBudget:drain 时怎么被尊重

在 kind 集群里实测 PodDisruptionBudget:5 个 Pod 下 minAvailable 2 / 50% / maxUnavailable 1 / 50% / 100% 分别允许中断 3 / 2 / 1 / 3 / 0 个(百分比向上取整);Eviction API 在预算用完时返回 429 TooManyRequests,替代 Pod 就绪(6.0 秒)后才恢复;kubectl drain 被 PDB 拦住时每 5 秒重试、共用 6 秒,而 kubectl delete pod 绕过 PDB;unhealthyPodEvictionPolicy 为 AlwaysAllow 时不健康的 Pod 可以被驱逐,默认的 IfHealthyBudget 则返回 429。

Kubernetes PodDisruptionBudget PDB 驱逐 drain Eviction API 真实验证 动画演示
Kubernetes 2026-10-10

拓扑分布约束:maxSkew 怎么计算

在独立的 5 节点 kind 集群(4 个 worker 分到 zone a/a/b/c)里实测 topologySpreadConstraints:maxSkew=1 时 6 个副本在三个 zone 里 2/2/2(无约束时是 4/1/1);已有的失衡不会被纠正,新 Pod 只是避开多的 zone;DoNotSchedule 遇到带污点的空 zone 会让 4 个副本 Pending,nodeTaintsPolicy: Honor 或 ScheduleAnyway 可以解决;zone 与 hostname 同时约束时 9 个副本只放下 7 个。

Kubernetes 拓扑分布约束 topologySpreadConstraints maxSkew 调度 真实验证 动画演示
Kubernetes 2026-10-10

亲和与反亲和:required 与 preferred 的差别

在 5 节点 kind 集群里实测亲和与反亲和:nodeAffinity required 是硬条件(matchExpressions 内 AND、多个 nodeSelectorTerms 之间 OR、支持 Gt/NotIn),preferred zone=c 的 8 个副本全部去了 worker4;podAntiAffinity required(hostname)5 个副本在 4 个 worker 上只放下 4 个,第 5 个 Pending;preferred 反亲和永远能调度(1/1/1/2、2/2/2/3);IgnoredDuringExecution 意味着删除被亲和的 Pod 或节点标签后已运行的 Pod 不动,只有新副本 Pending。

Kubernetes 亲和 反亲和 nodeAffinity podAntiAffinity required preferred 真实验证 动画演示
Kubernetes 2026-10-10

污点与容忍:NoSchedule、NoExecute 的效果

在 5 节点 kind 集群里实测污点与容忍:NoSchedule 只挡新调度、不动已有 Pod,Equal 要 value 也匹配而 Exists 只看 key、空 key 的 Exists 容忍一切;PreferNoSchedule 让 12 个副本避开该节点但 Pod 只能去它时仍会调度;NoExecute 会驱逐运行中的 Pod:无容忍 0.1 秒、tolerationSeconds=8 时 8.4 秒、不写秒数则一直留着;准入会自动补 not-ready/unreachable 各 300 秒的容忍,控制面的 NoSchedule 污点需要显式容忍才能调度上去。

Kubernetes 污点 容忍 taint toleration NoSchedule NoExecute 真实验证 动画演示
Kubernetes 2026-10-10

nodeSelector 与节点标签:调度不上的原因怎么看

在 5 节点 kind 集群里实测 nodeSelector 与节点标签:worker 默认只有 5 个标签(hostname、arch、os 与 beta 版),nodeSelector 的多个键是 AND;没有匹配节点时 Pending 并给出 didn't match Pod's node affinity/selector,节点打上标签后 0.2 秒内被调度,标签后来消失不赶走已运行的 Pod;nodeName 绕过调度器(不检查 cordon,资源不够时 kubelet 以 OutOfcpu 拒绝);读懂 Pending 的 message:每个节点只记在第一个淘汰它的原因里。

Kubernetes nodeSelector 节点标签 nodeName 调度 Pending 真实验证 动画演示
Kubernetes 2026-10-10

DaemonSet:每个节点一个 Pod 的调度和更新

在 5 节点 kind 集群里实测 DaemonSet:每个符合条件的 worker 一个 Pod,控制器给 Pod 加 matchFields metadata.name 的 nodeAffinity 和 6 个自带容忍;nodeSelector 限定范围时给节点打标签 0.1 秒内 Pod 出现、去掉标签 0.1 秒内被删;NoSchedule 污点不动已有 Pod,NoExecute 污点 0.1 秒内驱逐且 DaemonSet 不再重建(desired 4 → 3);RollingUpdate maxUnavailable=1 的更新耗时 27.2 秒、maxUnavailable=2 耗时 13.9 秒,OnDelete 不改动 Pod 直到手动删除。

Kubernetes DaemonSet 滚动更新 maxUnavailable OnDelete 真实验证 动画演示
京ICP备2026067502号-1京公网安备11010502063487号