在运营Kubernetes时,总会遇到“咦?这怎么会出现在这里?”的时刻。最常见的误解就是认为“Pod会均匀地(Round-Robin)分布到各个节点上”。
今天,我将通过亲身经历的“Pod集中现象”,深入剖析Kubernetes调度器是如何实际评分并选择节点的,揭示其看不见的逻辑。🚀

0. 问题情况:“明明有多个节点,但…”
为了测试,我依次创建了MySQL、Nginx和httpd的Pod。我们理所当然的期望是“它们会友好地分配到1号节点、2号节点、3号节点…对吧?”
但现实并非如此。
$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
mysql 1/1 Running 0 66m 10.16.2.12 gke-cluster-1-default-pool-rr03
nx 1/1 Running 0 16m 10.16.2.13 gke-cluster-1-default-pool-rr03
nx1 1/1 Running 0 6s 10.16.2.14 gke-cluster-1-default-pool-rr03
httpd 1/1 Running 0 4s 10.16.2.15 gke-cluster-1-default-pool-rr03
正如您所看到的,mysql、nx,甚至不同的镜像httpd,都持续不断地创建在名为rr03的同一个节点上。而其他节点却空空如也!😱
这是为什么呢?调度器坏了吗?
1. 消除误解:调度器不懂ABC顺序 ❌
很多人认为调度器采用“轮询(Round-Robin)”方式,就会按照节点名称顺序(A->B->C)进行部署。但Kubernetes调度器是完全基于“分数(Score)”运作的。
- Filtering: 淘汰不符合条件的节点
- Scoring: 对剩余节点进行评分 (0~100分)
- Ranking: 选择得分最高的节点
也就是说,rr03节点之所以持续被选中,并非因为顺序,而是因为在调度器看来,rr03一直都是“最佳候选”。
2. 罪魁祸首分析:为什么已满的节点会成为第一名? 🤔
在有空节点的情况下,一个已经有3个Pod的节点却成为第一名,这是两种设置共同作用的结果。
① 未设置资源请求(Requests)= 被视为“透明人”
我在创建Pod时没有设置resources.requests(CPU/内存请求量)。
- 调度器的视角: “这个Pod使用0 CPU,0内存?”
- 判断: 无论rr03节点上有100个还是1000个Pod,如果只有未设置Request的Pod,调度器认为该节点的利用率仍然是“0%”。
- 结果: “空节点和rr03反正都一样空闲?(资源分数平局)”
② 决定性因素:镜像本地性(Image Locality)与层共享
这引出了一个疑问:“如果分数平局,应该随机选择啊,为什么偏偏去了rr03?”
罪魁祸首是ImageLocality加分项。
- 部署Nginx时: 因为mysql的镜像已经下载到rr03节点,去那里更快,所以选择了rr03(可以理解)
- 部署Httpd时: “咦?这是一个新镜像啊?”
- 但Docker镜像是分层(Layer)结构。
- mysql、nginx、httpd虽然不同,但它们极有可能共享底层基础镜像(Debian、Alpine等)或公共库层。
- 最终判定:
- 空节点: “需要从头开始下载所有基础层” -> 无加分
- rr03节点: “咦?旁边的Pod用的基础层已经有了?赚到了!” -> 获得加分 (+)
最终,资源分数平局(0点影响),但在镜像缓存分数上rr03略胜一筹,从而成为了一个不断吸纳Pod的黑洞。🕳️
3. 解决方案:如何让Pod分散开来? 🛠️
如何阻止这种现象,让Pod均匀地分布到整个集群中呢?
✅ 方法1: 明确指定资源请求(Requests)(推荐)
给Pod贴上“我需要这么多资源!”的标签。
resources:
requests:
cpu: "200m" # 请求0.2核心
这样,调度器就会正常判断“啊,rr03已经满了。应该发送到空节点!”并启动负载均衡(Least Allocated)逻辑。
✅ 方法2: 设置反亲和性(Anti-Affinity)
这是一种强制设置“我不喜欢和跟我一样的Pod待在一起!”的方法。
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector: ...
使用此选项,无论分数计算如何,Pod都将强制不重叠地部署。
4. 结论 📝
- Kubernetes调度器不按ABC顺序部署。
- 如果不设置requests,调度器会将Pod的大小视为“0”。
- 在这种情况下,即使只有少量镜像层已存在的节点也会获得加分,导致Pod集中在一个地方。
- 为了稳定运行,设置Resource Requests不是可选项,而是必需项!
今天的摸索到此结束!希望这能帮助您理解这位高傲的调度器的心思。👋
发表回复