k8s中的schedule
所有的新建pod都需要走scheduler
一个非MasterNode上可以运行多个Pod,只要资源足够
-
Node 的本质
一个 Node = 一台物理机 或 虚拟机。
它有自己的 CPU、内存、存储和网络资源。
Pod 就是运行在 Node 上的“工作负载单元”。 -
Node 和 Pod 的关系
一个 Node 可以运行多个 Pod(只要资源足够)。
Pod 调度到 Node 上时,Scheduler 会检查 Node 是否有足够的 CPU / 内存 / 存储 / 网络资源。
限制因素:
Node 的总资源容量
Pod 的 requests 和 limits 配置
节点污点(Taint)和 Pod 的容忍(Toleration)
Pod 的亲和性/反亲和性规则
👉 所以,不是 Node 限制 Pod 数量,而是 资源和调度策略决定一个 Node 能跑多少 Pod。 -
举例
假设一个 Node 有 16 核 CPU,64Gi 内存:
Pod A 需要 2 核 + 8Gi
Pod B 需要 1 核 + 4Gi
Pod C 需要 4 核 + 16Gi
👉 只要资源允许,可以同时跑很多 Pod。
在大规模集群中,一个 Node 上运行 几十个甚至上百个 Pod 是非常常见的。
Scheduler
1. Scheduler 的位置
- Scheduler 是 控制平面(Control Plane) 的核心组件。
- 运行在 Master Node 上。
- 作用:为新创建的 未调度 Pod 选择合适的 Node。(唯一作用)
2. 工作流程
-
Pod 创建
- 用户通过
kubectl
或 API Server 提交 Pod。 - Pod 信息写入 etcd,此时
spec.nodeName
为空(表示未调度)。
- 用户通过
-
监听 Pending Pod
- Scheduler 通过 API Server watch 新的 Pod。
- 当发现 Pod 处于
Pending
状态时,开始调度。
-
调度决策
调度分两步:- 预选(Filtering):过滤掉不符合条件的节点
- 节点资源不足(CPU/内存不够)
- 节点打了 Taint(污点)
- 不满足 Pod 的 NodeSelector、NodeAffinity 等约束
- 优选(Scoring):对剩余节点打分,选择最优节点
- 负载均衡
- 节点剩余资源利用率
- 拓扑结构(跨可用区分布等)
- 预选(Filtering):过滤掉不符合条件的节点
-
绑定 Pod 到节点
- Scheduler 通过 API Server 发起 Bind 请求。
- API Server 更新 Pod 的
spec.nodeName
,写入 etcd。
-
kubelet 启动容器
- 目标 Node 上的 kubelet 通过API Server发现 Pod 被分配给自己。
- kubelet 调用容器运行时(containerd/Docker)拉取镜像并启动容器。
3. 关键点总结
- Scheduler 不直接写 etcd,只通过 API Server 更新信息。
- 触发调度的条件:发现有新的 Pending Pod。
- 调度结果是 Pod 被绑定到某个 Node。
- 最终由 kubelet 通过API server发现需要启动pod,并且在该 Node 上实际启动 Pod。
Kubernetes Scheduler 选 Node 依据规则
1. 过滤阶段(Predicates / Filter)
目的:排除不满足条件的 Node
- 资源要求:CPU、内存、GPU 等是否足够
- 节点标签/污点:NodeSelector、Node Affinity、Taints/Tolerations
- 存储需求:PVC 是否能绑定到 Node 的 PV
- 端口冲突:Pod 端口是否已被占用
2. 打分阶段(Priorities / Score)
目的:在候选 Node 中选择最优 Node
- 资源利用率:Prefer evenly distributed / Least requested
- 拓扑亲和:PodAffinity / PodAntiAffinity
- 数据局部性:调度靠近所需 PV 或缓存数据
- 自定义调度策略:Scheduler Extender、插件策略
3. 最终选择
- 计算每个 Node 的总得分 → 选择最高分 Node
- 若有多 Node 得分相同 → 随机选一个