文章目录
- [一、Kubernetes 集群调度核心体系](#一、Kubernetes 集群调度核心体系)
-
- [1.1 集群组件协作与List-Watch机制](#1.1 集群组件协作与List-Watch机制)
-
- [1.1.1 核心组件及职责](#1.1.1 核心组件及职责)
- [1.1.2 List-Watch 工作机制](#1.1.2 List-Watch 工作机制)
- [1.2 Pod 创建完整流程(基于List-Watch)](#1.2 Pod 创建完整流程(基于List-Watch))
- [1.3 Scheduler 调度流程](#1.3 Scheduler 调度流程)
-
- [1.3.1 核心目标](#1.3.1 核心目标)
- [1.3.2 调度两阶段](#1.3.2 调度两阶段)
-
- [1.3.2.1 过滤阶段(Predicate)](#1.3.2.1 过滤阶段(Predicate))
- [1.3.2.2 优选阶段(Priorities)](#1.3.2.2 优选阶段(Priorities))
- [1.4 指定调度节点的方式](#1.4 指定调度节点的方式)
-
- [1.4.1 nodeName(强制绑定)](#1.4.1 nodeName(强制绑定))
-
- [1.4.1.1 功能说明](#1.4.1.1 功能说明)
- [1.4.1.2 配置示例及解释](#1.4.1.2 配置示例及解释)
- [1.4.1.3 执行命令及验证](#1.4.1.3 执行命令及验证)
- [1.4.2 nodeSelector(标签强制匹配)](#1.4.2 nodeSelector(标签强制匹配))
-
- [1.4.2.1 功能说明](#1.4.2.1 功能说明)
- [1.4.2.2 操作步骤及配置示例](#1.4.2.2 操作步骤及配置示例)
- [1.4.2.3 标签管理常用命令](#1.4.2.3 标签管理常用命令)
- [1.5 亲和性与反亲和性调度](#1.5 亲和性与反亲和性调度)
-
- [1.5.1 核心概念](#1.5.1 核心概念)
- [1.5.2 节点亲和性(NodeAffinity)](#1.5.2 节点亲和性(NodeAffinity))
-
- [1.5.2.1 硬策略示例](#1.5.2.1 硬策略示例)
- [1.5.2.2 软策略示例](#1.5.2.2 软策略示例)
- [1.5.2.3 软硬策略结合示例](#1.5.2.3 软硬策略结合示例)
- [1.5.3 Pod 亲和性与反亲和性](#1.5.3 Pod 亲和性与反亲和性)
-
- [1.5.3.1 Pod 亲和性示例](#1.5.3.1 Pod 亲和性示例)
- [1.5.3.2 Pod 反亲和性示例](#1.5.3.2 Pod 反亲和性示例)
- [1.6 污点(Taint)与容忍(Tolerations)](#1.6 污点(Taint)与容忍(Tolerations))
-
- [1.6.1 污点核心概念](#1.6.1 污点核心概念)
- [1.6.2 污点常用命令](#1.6.2 污点常用命令)
- [1.6.3 容忍配置示例](#1.6.3 容忍配置示例)
- [1.7 节点维护操作](#1.7 节点维护操作)
-
- [1.7.1 核心命令及说明](#1.7.1 核心命令及说明)
- [1.7.2 应用场景](#1.7.2 应用场景)
- [1.8 Pod 生命周期阶段](#1.8 Pod 生命周期阶段)
- [1.9 调度故障排查命令](#1.9 调度故障排查命令)
- [1.10 核心调度策略总结](#1.10 核心调度策略总结)
一、Kubernetes 集群调度核心体系
1.1 集群组件协作与List-Watch机制
1.1.1 核心组件及职责
| 组件 | 职责 |
|---|---|
| kubectl / API 客户端 | 向 APIServer 发起资源创建或管理请求 |
| APIServer | 负责 API 调用、权限校验、存储交互,是集群控制的核心入口 |
| etcd | 存储集群所有状态信息 |
| Controller Manager | 维持副本数、执行自愈逻辑(扩容、重建等) |
| Scheduler | 调度器,将未分配节点的 Pod 分配到合适的 Node |
| kubelet | 节点代理,负责 Pod 生命周期管理和容器运行状态上报 |
1.1.2 List-Watch 工作机制
Kubernetes 各核心组件(Controller Manager、Scheduler、kubelet)启动后,会通过 HTTPS 6443 端口监听 APIServer 的资源事件变化:
- Controller Manager:监听 ReplicaSet、Deployment 等副本控制类对象
- Scheduler:监听未调度的 Pod
- kubelet:监听分配到本节点的 Pod
当 etcd 中资源发生变更(如创建 Pod),会触发事件并同步至 APIServer,各组件通过监听感知变化并执行对应逻辑。
1.2 Pod 创建完整流程(基于List-Watch)
- 用户通过
kubectl apply -f pod.yaml向 APIServer 发送创建 Pod 请求; - APIServer 校验请求后,将 Pod 元数据写入 etcd;
- etcd 触发 Create 事件并同步至 APIServer;
- Controller Manager 监听到事件后,通过 RC/ReplicaSet 保证 Pod 副本数;
- APIServer 更新 Pod 详细信息至 etcd,etcd 再次触发更新事件;
- Scheduler 监听至 Pending 状态的 Pod,通过调度算法选择目标 Node;
- Scheduler 将 Node 绑定信息写入 APIServer,同步至 etcd;
- 目标节点的 kubelet 监听到 Pod 分配事件,调用容器运行时拉取镜像、创建并启动容器;
- kubelet 将 Pod 运行状态上报至 APIServer,最终同步至 etcd,Pod 进入 Running 状态。
1.3 Scheduler 调度流程
1.3.1 核心目标
公平性(节点资源均衡)、高效性(资源最大化利用)、效率(批量调度性能)、灵活性(支持自定义策略)。
1.3.2 调度两阶段
1.3.2.1 过滤阶段(Predicate)
过滤掉不满足条件的节点,常见算法:
| 算法名 | 功能描述 |
|---|---|
| PodFitsResources | 检查节点剩余资源是否满足 Pod 需求 |
| PodFitsHost | 检查 NodeName 是否匹配 |
| PodFitsHostPorts | 检查端口冲突 |
| PodSelectorMatches | label 匹配 |
| NoDiskConflict | Volume 挂载冲突检测 |
无满足条件节点时,Pod 持续 Pending 并重试调度。
1.3.2.2 优选阶段(Priorities)
对过滤后的节点打分排序,常见算法:
| 优先级项 | 描述 |
|---|---|
| LeastRequestedPriority | 资源使用率越低,权重越高 |
| BalancedResourceAllocation | CPU 与内存使用率越接近越好(通常与上一算法配合使用) |
| ImageLocalityPriority | 优先选择已有目标镜像的节点 |
最终选择权重最高的节点完成调度。
1.4 指定调度节点的方式
1.4.1 nodeName(强制绑定)
1.4.1.1 功能说明
直接将 Pod 绑定到指定 Node,跳过 Scheduler 调度逻辑,由 kubelet 直接启动容器。
1.4.1.2 配置示例及解释
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp # Deployment 名称
spec:
replicas: 3 # 副本数
selector:
matchLabels:
app: myapp # 匹配Pod标签
template:
metadata:
labels:
app: myapp # Pod标签
spec:
nodeName: node01 # 强制绑定到node01节点
containers:
- name: myapp # 容器名称
image: soscscs/myapp:v1 # 容器镜像
ports:
- containerPort: 80 # 容器暴露端口
1.4.1.3 执行命令及验证
bash
# 应用配置文件
kubectl apply -f myapp.yaml
# 查看Pod分布(所有Pod都会运行在node01)
kubectl get pods -o wide
# 查看Pod事件(无Scheduler调度记录)
kubectl describe pod <Pod名称>
1.4.2 nodeSelector(标签强制匹配)
1.4.2.1 功能说明
通过 Node 标签匹配选择节点,由 Scheduler 执行调度,属于强制约束。
1.4.2.2 操作步骤及配置示例
- 给 Node 设置标签:
bash
# 给node01设置标签yjs=a
kubectl label nodes node01 yjs=a
# 给node02设置标签yjs=b
kubectl label nodes node02 yjs=b
# 查看节点标签
kubectl get nodes --show-labels
- 配置 Pod 的 nodeSelector:
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp1
spec:
replicas: 3
selector:
matchLabels:
app: myapp1
template:
metadata:
labels:
app: myapp1
spec:
nodeSelector:
yjs: a # 仅匹配标签yjs=a的节点
containers:
- name: myapp1
image: soscscs/myapp:v1
ports:
- containerPort: 80
- 执行命令及验证:
bash
kubectl apply -f myapp1.yaml
kubectl get pods -o wide # 所有Pod运行在node01
kubectl describe pod <Pod名称> # 可看到Scheduler调度记录
1.4.2.3 标签管理常用命令
bash
# 修改标签(需加--overwrite)
kubectl label nodes node02 yjs=c --overwrite
# 删除标签(key后加-)
kubectl label nodes node02 yjs-
# 按标签筛选节点
kubectl get node -l yjs=a
1.5 亲和性与反亲和性调度
1.5.1 核心概念
| 调度策略 | 匹配对象 | 操作符 | 拓扑域支持 | 调度目标 |
|---|---|---|---|---|
| nodeAffinity | 节点标签 | In/NotIn/Exists等 | ❌ | 指定节点 |
| podAffinity | Pod标签 | In/NotIn/Exists等 | ✅ | 与指定Pod同拓扑域 |
| podAntiAffinity | Pod标签 | In/NotIn/Exists等 | ✅ | 与指定Pod不同拓扑域 |
- 硬策略:
requiredDuringSchedulingIgnoredDuringExecution(必须满足,否则Pod Pending) - 软策略:
preferredDuringSchedulingIgnoredDuringExecution(优先满足,不满足也可调度)
1.5.2 节点亲和性(NodeAffinity)
1.5.2.1 硬策略示例
yaml
apiVersion: v1
kind: Pod
metadata:
name: affinity
labels:
app: node-affinity-pod
spec:
containers:
- name: with-node-affinity
image: soscscs/myapp:v1
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution: # 硬策略
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname # 匹配节点标签键
operator: NotIn # 标签值不在指定列表
values:
- node02 # 排除node02节点
验证:Pod 只会调度到非node02的节点,若所有节点都不满足,Pod 持续 Pending。
1.5.2.2 软策略示例
yaml
apiVersion: v1
kind: Pod
metadata:
name: affinity
labels:
app: node-affinity-pod
spec:
containers:
- name: with-node-affinity
image: soscscs/myapp:v1
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution: # 软策略
- weight: 1 # 权重(多策略时数值越高优先级越高)
preference:
matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- node03 # 优先调度到node03,无则调度到其他节点
1.5.2.3 软硬策略结合示例
yaml
apiVersion: v1
kind: Pod
metadata:
name: affinity
labels:
app: node-affinity-pod
spec:
containers:
- name: with-node-affinity
image: soscscs/myapp:v1
affinity:
nodeAffinity:
# 先满足硬策略:排除node02
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: NotIn
values:
- node02
# 再满足软策略:优先选择yjs=a的节点
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: yjs
operator: In
values:
- a
1.5.3 Pod 亲和性与反亲和性
1.5.3.1 Pod 亲和性示例
- 先创建基准 Pod:
yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp01
labels:
app: myapp01 # 基准Pod标签
spec:
containers:
- name: with-node-affinity
image: soscscs/myapp:v1
- 配置 Pod 亲和性(与基准Pod同拓扑域):
yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp02
labels:
app: myapp02
spec:
containers:
- name: myapp02
image: soscscs/myapp:v1
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- myapp01 # 匹配基准Pod标签
topologyKey: yjs # 拓扑域(同yjs标签值的节点为同一域)
效果:myapp02 仅调度到与 myapp01 同yjs标签的节点。
1.5.3.2 Pod 反亲和性示例
yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp10
labels:
app: myapp10
spec:
containers:
- name: myapp10
image: soscscs/myapp:v1
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100 # 权重
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- myapp01 # 匹配基准Pod标签
topologyKey: kubernetes.io/hostname # 拓扑域为节点名称
效果:myapp10 尽量不调度到运行myapp01的节点。
1.6 污点(Taint)与容忍(Tolerations)
1.6.1 污点核心概念
-
格式:
key=value:effect -
Effect 类型:
类型 描述 NoSchedule 不调度新Pod到该节点 PreferNoSchedule 尽量避免调度新Pod到该节点 NoExecute 不调度新Pod + 驱逐已运行的Pod
1.6.2 污点常用命令
bash
# 给node01设置污点(NoSchedule)
kubectl taint node node01 key1=value1:NoSchedule
# 查看节点污点(Taints字段)
kubectl describe node node01
# 去除污点(key后加effect-)
kubectl taint node node01 key1:NoSchedule-
# 给node02设置NoExecute污点(驱逐已有Pod)
kubectl taint node node02 check=mycheck:NoExecute
1.6.3 容忍配置示例
yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp01
labels:
app: myapp01
spec:
containers:
- name: with-node-affinity
image: soscscs/myapp:v1
tolerations:
- key: "check" # 匹配污点的key
operator: "Equal" # 匹配规则(Equal需值匹配,Exists仅需key存在)
value: "mycheck" # 匹配污点的value
effect: "NoExecute" # 匹配污点的effect
tolerationSeconds: 3600 # 驱逐前保留时间(仅NoExecute生效)
特殊配置:
- 容忍所有污点:
tolerations: - operator: "Exists"- 容忍所有effect:
tolerations: - key: "key" operator: "Exists"
1.7 节点维护操作
1.7.1 核心命令及说明
| 命令 | 功能说明 |
|---|---|
kubectl cordon <node> |
标记节点为不可调度(新Pod不调度到该节点,已有Pod保留) |
kubectl drain <node> --ignore-daemonsets --delete-local-data --force |
驱逐节点上的Pod(忽略守护进程集、删除本地数据、强制驱逐),等价于cordon+驱逐 |
kubectl uncordon <node> |
恢复节点可调度状态 |
1.7.2 应用场景
- 节点升级/维护前:先执行
drain驱逐Pod,避免业务中断; - 临时禁用节点调度:执行
cordon,维护完成后执行uncordon恢复。
1.8 Pod 生命周期阶段
| 阶段 | 说明 |
|---|---|
| Pending | 已创建但未调度,或正在拉取镜像 |
| Running | 容器已启动,至少一个容器运行/启动/重启中 |
| Succeeded | 所有容器正常终止(如Job类任务) |
| Failed | 至少一个容器非0状态退出/异常终止 |
| Unknown | 无法获取状态(kubelet与APIServer通信异常) |
1.9 调度故障排查命令
bash
# 查看Pod事件(定位调度失败原因)
kubectl describe pod <Pod名称>
# 查看Pod日志(容器启动失败时)
kubectl logs <Pod名称> [-c 容器名]
# 进入容器排查
kubectl exec -it <Pod名称> bash
# 查看集群状态
kubectl cluster-info
# 查看节点状态
kubectl get nodes
# 查看kubelet日志(节点层面故障)
journalctl -xefu kubelet
1.10 核心调度策略总结
- nodeName:直接绑定节点,跳过调度器;
- nodeSelector:基于标签强制匹配节点;
- 亲和性:按节点/Pod标签设置调度偏好(硬/软策略);
- 污点&容忍:节点排斥Pod,容忍的Pod可例外调度;
- cordon/drain:节点维护时的Pod迁移与调度控制。
核心逻辑:调度是吸引,污点是排斥,亲和性是偏好,容忍是例外。