Kubernetes 集群调度
目录
3. Pod 创建与调度全流程(基于 List-Watch)
方式 1:nodeName(强制绑定节点,跳过 Scheduler)
方式 2:nodeSelector(基于节点标签匹配,强制约束)
5.2 容忍(Toleration):Pod 的 “例外许可”
Kubernetes 集群调度核心组件与协作机制
Kubernetes 集群调度的核心是通过 List-Watch 机制 实现组件间解耦与实时数据同步,确保 Pod 高效、合规地调度到目标节点。
1. 关键组件及职责
| 组件 | 核心职责 |
|---|---|
| kubectl / API 客户端 | 向 APIServer 发起资源创建 / 管理请求(如创建 Pod、Deployment),是用户操作入口。 |
| APIServer | 集群控制核心入口,负责权限校验、API 调用转发、与 etcd 交互存储集群状态。 |
| etcd | 分布式键值存储,保存集群所有资源(Pod、Node、配置等)的最终状态。 |
| Controller Manager | 维护集群状态一致性,如通过 ReplicaSet 确保 Pod 副本数、执行自愈(重建故障 Pod)。 |
| Scheduler | 调度器,为未绑定节点的 Pod 选择合适节点,核心逻辑是 “过滤 - 优选” 算法。 |
| kubelet | 节点代理,运行在每个 Node 上,负责 Pod 生命周期管理(拉取镜像、启动容器、状态上报)。 |
2. List-Watch 工作机制(组件协作核心)
List-Watch 是 Kubernetes 组件间同步状态的 “事件驱动模型”,流程如下:
- 启动监听:Controller Manager、Scheduler、kubelet 启动后,通过 HTTPS 持续监听 APIServer(6443 端口)的资源事件(如 Pod 创建、Node 状态变更)。
- 事件触发:当用户通过
kubectl apply创建 Pod 时,APIServer 校验请求后将 Pod 信息写入 etcd,etcd 触发Create事件并同步给 APIServer。 - 组件响应:APIServer 将事件广播给监听的组件,各组件根据职责处理:
- Controller Manager:监听副本控制器(如 Deployment),确保 Pod 副本数达标;
- Scheduler:监听 “未绑定节点的 Pod”,执行调度逻辑分配节点;
- kubelet:监听 “分配到本节点的 Pod”,启动容器并上报状态。
3. Pod 创建与调度全流程(基于 List-Watch)
(1)用户发起请求
用户通过 kubectl apply -f pod.yaml 向 APIServer 提交 Pod 创建请求。
(2)APIServer 处理与存储
- APIServer 校验请求合法性(如权限、资源格式),通过后将 Pod 元数据写入 etcd。
- etcd 确认写入后,返回 “创建成功” 给 APIServer,APIServer 再反馈给用户。
(3)事件广播与组件响应
- etcd 触发
Pod Create事件,同步给 APIServer; - APIServer 将事件广播给 Scheduler、Controller Manager、kubelet:
- Controller Manager:若 Pod 由 Deployment 管理,检查副本数,确保符合
replicas配置; - Scheduler:监听到 “未绑定节点的 Pod”(
spec.nodeName == ""),启动调度流程。
- Controller Manager:若 Pod 由 Deployment 管理,检查副本数,确保符合
(4)Scheduler 调度流程(过滤→优选)
Scheduler 核心任务是为 Pod 选择 “最优节点”,分两步执行:
① 过滤阶段(Predicate:排除不满足条件的节点)
通过预设算法筛选出 “能运行 Pod 的节点”,常见过滤规则:
| 过滤算法 | 功能描述 |
|---|---|
PodFitsResources |
节点剩余 CPU / 内存是否满足 Pod 需求 |
PodFitsHost |
若 Pod 指定 nodeName,匹配节点名 |
PodFitsHostPorts |
节点端口是否被占用(避免端口冲突) |
PodSelectorMatches |
节点标签是否匹配 Pod 的 nodeSelector |
NoDiskConflict |
节点挂载的 Volume 是否与 Pod 需求冲突 |
- 若无节点满足条件,Pod 会一直处于 Pending 状态,直到有节点符合条件。
② 优选阶段(Priorities:对可行节点打分排序)
对过滤后的节点按 “优先级权重” 排序,选择得分最高的节点,常见优选规则:
| 优选规则 | 描述 |
|---|---|
LeastRequestedPriority |
节点资源(CPU / 内存)使用率越低,得分越高(均衡资源分配)。 |
BalancedResourceAllocation |
CPU 与内存使用率越接近,得分越高(避免单资源过载)。 |
ImageLocalityPriority |
节点已缓存 Pod 所需镜像,得分越高(减少镜像拉取时间,提升启动速度)。 |
(5)绑定节点与 Pod 启动
- Scheduler 将选中的节点信息写入 APIServer,APIServer 更新 etcd 中 Pod 的
spec.nodeName字段; - 目标节点的 kubelet 监听到 “分配给自己的 Pod”,调用容器运行时(Docker/containerd):
- 拉取 Pod 所需镜像;
- 创建并启动容器;
- 将 Pod 状态(Running/Failed)上报给 APIServer;
- APIServer 更新 etcd 中 Pod 的状态,集群状态同步完成,Pod 正式进入 Running 状态。
4. 指定调度节点的 4 种方式
方式 1:nodeName(强制绑定节点,跳过 Scheduler)
- 原理:直接在 Pod 模板中指定
spec.nodeName: 目标节点名,Pod 绕过 Scheduler,由目标节点的 kubelet 直接创建。 - 特点:强制生效,不经过调度算法;若节点不存在或不可用,Pod 会一直 Pending。
- 配置示例:
apiVersion: apps/v1 kind: Deployment metadata: name: myapp spec: replicas: 3 selector: matchLabels: app: myapp template: metadata: labels: app: myapp spec: nodeName: node1 # 强制调度到 node1 containers: - name: myapp image: nginx:latest - 验证:
kubectl describe pod <pod-name>无Successfully assigned by default-scheduler事件,直接由 kubelet 启动容器。
方式 2:nodeSelector(基于节点标签匹配,强制约束)
- 原理:通过 Pod 的
spec.nodeSelector匹配节点标签,Scheduler 仅调度到符合标签的节点。 - 特点:强制约束,需先给节点打标签;若无匹配标签的节点,Pod 会 Pending。
- 操作步骤:
- 给节点打标签:
kubectl label nodes node1 yjs=a(给 node1 打yjs=a标签); - 配置 Pod 的
nodeSelector:spec: nodeSelector: yjs: a # 仅调度到有 `yjs=a` 标签的节点(如 node1)
- 给节点打标签:
- 标签管理命令:
- 查看节点标签:
kubectl get nodes --show-labels; - 修改标签:
kubectl label nodes node1 yjs=b --overwrite; - 删除标签:
kubectl label nodes node1 yjs-。
- 查看节点标签:
方式 3:亲和性调度(节点亲和、Pod 亲和)
nodeSelector 仅支持 “精确标签匹配”,亲和性(Affinity)支持更灵活的调度规则,可基于 “节点标签” 或 “已运行 Pod 的标签”,且分为 硬策略(必须满足) 和 软策略(优先满足)。
3.1 节点亲和性(NodeAffinity)
- 原理:基于 节点标签 调度 Pod,支持复杂匹配逻辑(如
In/NotIn/Exists)。 - 核心配置字段:
spec: affinity: nodeAffinity: # 硬策略:必须满足,否则 Pod Pending requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname # 节点标签键(节点名) operator: NotIn # 匹配方式:不在 values 列表中 values: - node2 # 排除 node2,仅调度到其他节点 # 软策略:优先满足,不满足也可调度到其他节点 preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 # 权重(0-100,数值越大优先级越高) preference: matchExpressions: - key: yjs # 节点标签键 operator: In values: - a # 优先调度到 `yjs=a` 的节点(如 node1) - 操作符说明:
操作符 含义 示例 In标签值在列表中 key: yjs, operator: In, values: [a]NotIn标签值不在列表中 key: hostname, operator: NotIn, values: [node2]Exists节点存在该标签(无需值) key: env, operator: ExistsDoesNotExist节点不存在该标签 key: debug, operator: DoesNotExistGt/Lt标签值大于 / 小于指定数值 key: version, operator: Gt, values: [3]
3.2 Pod 亲和性(PodAffinity)
- 原理:基于 已运行 Pod 的标签 调度新 Pod,让 “相关 Pod” 聚堆到同一拓扑域(如同一节点、同一可用区),减少网络延迟。
- 核心配置字段(需指定
topologyKey定义拓扑域范围):spec: affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app # 已运行 Pod 的标签键 operator: In values: - db # 匹配标签为 `app=db` 的 Pod topologyKey: kubernetes.io/hostname # 拓扑域:同一节点(按节点名划分) - 场景示例:让 Web 服务 Pod(
app=web)与数据库 Pod(app=db)调度到同一节点,减少跨节点网络开销。
方式 4:反亲和性调度(PodAntiAffinity)
- 原理:与 Pod 亲和性相反,让新 Pod 避免 调度到 “已运行指定标签 Pod 的拓扑域”,实现 Pod 分散部署,提升高可用。
- 核心配置字段:
spec: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app # 已运行 Pod 的标签键 operator: In values: - web # 避免与 `app=web` 的 Pod 同节点 topologyKey: kubernetes.io/hostname # 拓扑域:同一节点 - 场景示例:多个 Web 服务 Pod(
app=web)分散到不同节点,避免单点故障(若一个节点宕机,其他节点的 Web Pod 仍可用)。
5. 污点(Taint)与容忍(Toleration)
亲和性是 “吸引 Pod 到节点”,污点是 “排斥 Pod 远离节点”,容忍则是 “让 Pod 可以忽略污点,调度到有污点的节点”。
5.1 污点(Taint):节点的 “排斥标签”
-
作用:给节点添加污点后,不满足 “容忍” 条件的 Pod 无法调度到该节点;支持 3 种效果(
effect):污点效果 作用 NoSchedule仅阻止新 Pod 调度到该节点,不影响已运行的 Pod(如节点维护时临时阻止新 Pod)。 NoExecute阻止新 Pod 调度,且驱逐节点上已运行但无容忍的 Pod(如节点故障时强制迁移 Pod)。 PreferNoSchedule软策略,尽量阻止新 Pod 调度,无其他节点时仍可调度(如非核心节点优先保留资源)。 -
污点管理命令:
# 给 node1 添加污点:key1=value1:NoSchedule kubectl taint node node1 key1=value1:NoSchedule # 查看节点污点(Taints 字段) kubectl describe node node1 | grep Taints # 移除节点污点(末尾加 `-`) kubectl taint node node1 key1:NoSchedule-
5.2 容忍(Toleration):Pod 的 “例外许可”
- 作用:给 Pod 添加容忍配置,让其可以忽略节点的指定污点,调度到该节点。
- 核心配置字段(需与污点的
key/value/effect匹配):spec: tolerations: - key: "key1" # 匹配污点的 key operator: "Equal" # 匹配方式:Equal(需 value 一致)或 Exists(忽略 value) value: "value1" # 匹配污点的 value effect: "NoSchedule" # 匹配污点的 effect tolerationSeconds: 3600 # 仅 NoExecute 生效:Pod 被驱逐前可保留的时间(秒) - 常见容忍场景:
- 容忍所有污点:
tolerations: - operator: "Exists"(不指定 key,忽略所有污点); - 容忍指定 key 的所有效果:
tolerations: - key: "key1", operator: "Exists"(忽略该 key 的所有 effect); - Master 节点容忍:默认 Master 有
node-role.kubernetes.io/master:NoSchedule污点,给 Pod 加容忍可调度到 Master(仅测试环境使用)。
- 容忍所有污点:
6. 节点维护操作:cordon & drain
节点需要升级、检修时,需避免新 Pod 调度并安全迁移已运行 Pod,核心命令如下:
| 命令 | 作用 |
|---|---|
kubectl cordon <node> |
标记节点为 “不可调度”(SchedulingDisabled),阻止新 Pod 调度,不影响已运行 Pod。 |
kubectl drain <node> --ignore-daemonsets --delete-local-data --force |
驱逐节点上所有 Pod(忽略 DaemonSet Pod,删除本地数据),等价于 “cordon + 驱逐”。 |
kubectl uncordon <node> |
取消 “不可调度” 标记,恢复节点可调度状态。 |
- 场景示例:节点升级前执行
drain,确保 Pod 迁移到其他节点,避免业务中断。
7. Pod 生命周期阶段(调度相关状态)
Pod 调度过程中会经历不同生命周期阶段,核心状态与调度的关系如下:
| 阶段 | 含义 | 调度相关原因 |
|---|---|---|
| Pending | Pod 已创建,但未调度到节点,或正在拉取镜像。 | 1. 无满足条件的节点(如污点未容忍、资源不足);2. 镜像拉取缓慢。 |
| Running | Pod 已调度到节点,且所有容器正常运行。 | 调度成功,kubelet 启动容器完成。 |
| Failed | Pod 中所有容器终止,且至少一个容器异常退出(非 0 状态)。 | 容器启动失败(如镜像错误、命令错误),与调度无关。 |
| Unknown | 无法获取 Pod 状态(如 kubelet 与 APIServer 通信故障)。 | 节点网络异常,需排查节点连通性。 |
8. 调度故障排查核心命令
| 排查目标 | 命令 | 关键查看点 |
|---|---|---|
| Pod 调度事件 | kubectl describe pod <pod-name> |
Events 字段:是否有 FailedScheduling(调度失败原因,如污点未容忍、资源不足)。 |
| 节点污点与标签 | kubectl describe node <node-name> |
Taints(污点)、Labels(标签):确认是否与 Pod 配置匹配。 |
| 节点资源使用情况 | kubectl top node |
CPU / 内存使用率:是否因资源不足导致调度失败。 |
| kubelet 运行日志 | journalctl -xefu kubelet |
节点级故障(如容器启动失败、镜像拉取错误)。 |
| 集群整体状态 | kubectl get nodes、kubectl cluster-info |
节点是否 Ready、APIServer/etcd 是否正常运行。 |
9. 调度策略优先级总结
Kubernetes 调度按以下优先级筛选节点,优先级从高到低:
nodeName:强制绑定节点,跳过 Scheduler;- 污点与容忍:有污点的节点仅允许有对应容忍的 Pod 调度;
- 亲和性 / 反亲和性:硬策略优先满足,再满足软策略;
nodeSelector:匹配节点标签;- Scheduler 过滤 - 优选:默认调度算法(资源均衡、镜像本地化等)。
核心思维总结
调度的本质是 “让 Pod 按规则找到合适节点”,核心逻辑可概括为:“调度是吸引(亲和性),污点是排斥(Taint),容忍是例外(Toleration),硬策略必须满足,软策略灵活优先”。
更多推荐


所有评论(0)