文章目录
- 环境
- Kubernetes 部署
- Kubernetes Pod 调度策略
- Kubernetes Pod 调度策略对照表
- 调度流程经历阶段
- 案例展示
- 生成yaml文件
- 默认调度
- 节点选择器
- 为节点添加标签
- 编写 Deployment 配置文件
- 应用资源并查看调度结果
- Node Affinity(节点亲和性)
- 为节点添加标签
- 硬约束(Required)
- 软约束(Preferred)
- 先不设置标签
- 设置标签
- 运算符支持的类型
- 污点与容忍(Taints & Tolerations)
- 污点(Taint)
- 添加污点的命令:
- 容忍(Toleration)
- 示例 YAML:
- 三种 Effect 类型(效果)
- 案例演示
- 给所有节点打上污点
- 没有容忍的 Pod(会调度失败)
- 有容忍的 Pod(调度成功)
- Pod Affinity(Pod 亲和性)与 Pod Anti-Affinity(反亲和性)
- Pod Affinity(亲和性)
- 示例:调度到和标签为 app=nginx 的 Pod 相同节点的 Pod 上(硬约束)
- Pod Anti-Affinity(反亲和性)
- 示例:调度到与标签为 app=nginx 的 Pod 不同节点上(软约束)
- 拓扑域 TopologyKey 说明
- 总结
- ✅ 默认调度策略
- ✅ NodeSelector
- ✅ Node Affinity(节点亲和性)
- ✅ Pod Affinity / Anti-Affinity(Pod 间亲和/反亲和)
- ✅ Taints and Tolerations(污点与容忍)
- ✅ 自定义调度器(Custom Scheduler)
- 📌 建议使用场景总结
环境
[root@10-255-101-217 ~]# kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
10-255-101-152 Ready <none> 24h v1.22.0 10.255.101.152 <none> CentOS Linux 7 (Core) 4.18.9-1.el7.elrepo.x86_64 containerd://1.4.3
10-255-101-216 Ready <none> 24h v1.22.0 10.255.101.216 <none> CentOS Linux 7 (Core) 4.18.9-1.el7.elrepo.x86_64 containerd://1.4.3
10-255-101-217 Ready control-plane,master 24h v1.22.0 10.255.101.217 <none> CentOS Linux 7 (Core) 4.18.9-1.el7.elrepo.x86_64 containerd://1.4.3
10-255-101-82 Ready <none> 24h v1.22.0 10.255.101.82 <none> CentOS Linux 7 (Core) 4.18.9-1.el7.elrepo.x86_64 containerd://1.4.3
[root@10-255-101-217 ~]#
Kubernetes 部署
一台 Master 多节点玩转 Kubernetes:sealos 一键部署实践
下边的案例基于这个部署方式以及环境进行演示
Kubernetes Pod 调度策略
-
默认调度(Default Scheduling)
在没有额外配置的情况下,kube-scheduler
会根据 Pod 的资源请求(requests)和节点的可用资源(allocatable)进行自动调度。这是大多数常规应用场景的默认策略,适合无需精细控制资源分配的情况。 -
节点选择器(NodeSelector)
通过在 Pod 规格中设置nodeSelector: { key: value }
,可以强制 Pod 仅被调度到具有指定标签的节点。这是一种硬性匹配策略,适用于将 Pod 部署到具有特定硬件、特定配置或专用节点的场景。 -
节点亲和性(Node Affinity)
节点亲和性允许用户基于节点的标签进行更复杂的软/硬约束。它包含两种类型:requiredDuringSchedulingIgnoredDuringExecution
(硬性约束):要求 Pod 只能被调度到满足条件的节点上。preferredDuringSchedulingIgnoredDuringExecution
(软性偏好):Pod 会尝试被调度到满足条件的节点上,但若无法满足条件,仍会被调度到其他节点。
这种方法可以让调度策略更加灵活,特别是在需要对节点进行复杂匹配或按优先级排序时。
-
污点与容忍(Taints & Tolerations)
通过在节点上添加污点,防止不容忍的 Pod 被调度到该节点。Pod 需要配置tolerations
,以接受特定污点。这是一种细粒度的控制机制,广泛应用于专用节点的隔离、故障剔除、热点节点流量控制等场景。 -
Pod 亲和性与反亲和性(Pod Affinity & Anti-Affinity)
- Pod Affinity:确保相关 Pod 部署在同一节点或拓扑域内,以提升性能或数据本地性。
- Pod Anti-Affinity:确保相关 Pod 不部署在同一节点,适用于高可用性要求,避免单点故障。
使用 Pod 亲和性和反亲和性可以精确控制 Pod 的分布策略,增强系统的弹性和容错性。
-
自定义调度器与调度扩展(Custom Scheduler & Scheduler Extenders)
如果 Kubernetes 的默认调度器无法满足特定需求,可以通过自定义调度器或扩展插件来实现个性化调度。例如,可以指定schedulerName: <your-scheduler>
,或使用调度扩展与外部系统进行集成,适用于特殊资源(如 GPU、Spot 实例)或复杂调度逻辑的场景。
Kubernetes Pod 调度策略对照表
策略中文名称 | 策略英文术语 | 简要描述 | 适用场景 | 配置方式(简化) |
---|---|---|---|---|
默认调度 | Default Scheduling | kube-scheduler 根据资源需求和节点可用性自动分配 Pod | 无特殊调度需求的常规应用 | 无需配置 |
节点选择器 | NodeSelector | 通过节点标签(Label)进行硬性匹配,Pod 只会被调度到指定标签的节点上 | 将 Pod 部署到具备特定硬件或配置的节点 | nodeSelector: { key: value } |
节点亲和性 | Node Affinity | 基于节点标签的软/硬约束,支持更灵活的偏好与必选规则 | 对节点标签有复杂匹配需求,需在节点间进行偏好排序 | 使用 affinity.nodeAffinity 配置 |
污点与容忍 | Taints & Tolerations | 节点通过污点阻止不容忍的 Pod 被调度,Pod 通过容忍接受污点 | 专用节点隔离、故障节点剔除、热点节点流控等 | 节点 taint + Pod tolerations |
Pod 亲和性 | Pod Affinity | 控制 Pod 之间的协同部署,确保相关 Pod 被调度到同一节点或拓扑域中 | 提高性能或数据本地性,相关服务部署在一起 | 使用 affinity.podAffinity 配置 |
Pod 反亲和性 | Pod Anti-Affinity | 控制 Pod 之间的分散部署,避免相关 Pod 被调度到同一节点 | 高可用场景下避免单点故障,确保 Pod 分布在不同节点上 | 使用 affinity.podAntiAffinity 配置 |
自定义调度器(未进行实践,博文无案例 ) | Custom Scheduler / Extenders | 使用插件或替换方案,支持 GPU、Spot 实例等特殊资源的定制调度逻辑 | 企业级集群,需自定义调度算法或集成外部调度系统 | schedulerName: 自定义调度器名称 |
调度流程经历阶段
- PreFilter(预处理):收集 Pod 相关信息,检查必须满足的前置条件。
- Filter(过滤):通过各类 Filter 插件 排除不符合条件的节点,例如资源不足、NodeSelector、Node Affinity、Taints 等规则。
- PostFilter(后过滤,可选):当没有可行节点时触发,如抢占(Preemption)机制,尝试腾出资源。
- PreScore:为 Score 插件 准备共享状态。
- Score(打分):对剩余节点执行各类 Score 插件,根据算法(如资源均衡、拓扑感知等)对节点进行打分。
- NormalizeScore:将各插件打分归一化到 0–100。
- Reserve:暂时保留选中的节点,防止并发 Pod 冲突。
- Permit:最终审批,可用于等待或速率限制等场景。
- PreBind → Bind(绑定):将 Pod.spec.nodeName 设置为选定节点,完成调度。
- PostBind(绑定后,可选):信息收集或清理工作。
仅供参考
案例展示
生成yaml文件
kubectl create deployment test-nginx \--image=nginx \--replicas=2 \--port=80 \-n default\--dry-run=client \-o yaml \> nginx-deploy.yaml
各参数含义
参数 | 作用说明 |
---|---|
kubectl create deployment | 创建一个 Deployment 资源 |
test-nginx | Deployment 的名称 |
--image=nginx | 指定容器镜像为 nginx |
--replicas=2 | 设置副本数为 2 个 Pod |
--port=80 | 指定容器对外暴露的端口(虽然这个参数不一定反映在 YAML 中) |
-n default | 指定命名空间为 default |
--dry-run=client | 客户端验证,不真正创建资源 |
-o yaml | 以 YAML 格式输出资源清单 |
> nginx-deploy.yaml | 将输出重定向到文件 nginx-deploy.yaml 中 |
生成的yaml文件
apiVersion: apps/v1
kind: Deployment
metadata:creationTimestamp: nulllabels:app: test-nginxname: test-nginxnamespace: default
spec:replicas: 2selector:matchLabels:app: test-nginxstrategy: {}template:metadata:creationTimestamp: nulllabels:app: test-nginxspec:containers:- image: nginxname: nginxports:- containerPort: 80resources: {}
status: {}
YAML 关键字段说明
字段路径 | 含义说明 |
---|---|
spec.replicas: 2 | 定义 Deployment 期望运行 2 个 Pod 实例 |
spec.selector.matchLabels | 用于匹配 Pod 标签,Deployment 用于关联控制的 Pod |
spec.template.metadata.labels | Pod 模板的标签,与 selector 匹配 |
spec.template.spec.containers | 定义容器镜像、端口、资源等关键参数 |
ports.containerPort: 80 | 定义容器对外开放的端口 |
默认调度
[root@10-255-101-217 ~]# kubectl get pods
No resources found in default namespace.
[root@10-255-101-217 ~]# kubectl apply -f nginx-deploy.yaml
deployment.apps/test-nginx created
[root@10-255-101-217 ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
test-nginx-6f5d5f6564-gbgc6 1/1 Running 0 13s 192.168.154.1 10-255-101-82 <none> <none>
test-nginx-6f5d5f6564-jpbhl 1/1 Running 0 13s 192.168.154.65 10-255-101-152 <none> <none>
[root@10-255-101-217 ~]#
kube-scheduler
默认调度器会根据集群中各节点的资源使用情况(如 CPU、内存等),自动选择最合适的节点部署 Pod。上例中,两个 Pod 被均衡地调度到不同节点上,体现了默认调度的负载均衡策略。
节点选择器
使用 NodeSelector 指定节点调度
为节点添加标签
我们可以通过 kubectl label
命令给某个节点添加标签,方便后续在 Pod 调度时进行筛选。
kubectl label nodes 10-255-101-82 disktype=ssd
此命令为节点
10-255-101-82
添加了一个标签:disktype=ssd
编写 Deployment 配置文件
创建名为 ssd.yaml
的 Deployment 文件,指定 nodeSelector
字段:
apiVersion: apps/v1
kind: Deployment
metadata:name: test-nginx-nodeselectornamespace: defaultlabels:app: test-nginx
spec:replicas: 2selector:matchLabels:app: test-nginxtemplate:metadata:labels:app: test-nginxspec:nodeSelector:disktype: ssdcontainers:- name: nginximage: nginxports:- containerPort: 80
status: {}
在
spec.template.spec.nodeSelector
中声明节点标签disktype: ssd
,表示仅在拥有该标签的节点上运行 Pod。
应用资源并查看调度结果
kubectl apply -f ssd.yaml
查看 Pod 分布情况:
kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
test-nginx-6f5d5f6564-gbgc6 1/1 Running 0 18m 192.168.154.1 10-255-101-82 <none> <none>
test-nginx-6f5d5f6564-jpbhl 1/1 Running 0 18m 192.168.154.65 10-255-101-152 <none> <none>
test-nginx-nodeselector-7cfb54fc6b-9grcj 1/1 Running 0 5s 192.168.154.3 10-255-101-82 <none> <none>
test-nginx-nodeselector-7cfb54fc6b-q5m72 1/1 Running 0 5s 192.168.154.2 10-255-101-82 <none> <none>
从结果可以看到,test-nginx-nodeselector
这两个 Pod 均调度到了节点 10-255-101-82
上,符合我们通过 NodeSelector
限定的调度条件。
Node Affinity(节点亲和性)
为节点添加标签
我们可以通过 kubectl label
命令给某个节点添加标签,方便后续在 Pod 调度时进行筛选。
kubectl label nodes 10-255-101-152 10-255-101-216 nodeaffinity=test
此命令为节点
10-255-101-152 10-255-101-216
添加了一个标签:nodeaffinity=test
在 Kubernetes 中,Node Affinity(节点亲和性) 是一种调度策略,用于控制 Pod 应该调度到哪些具有特定标签的节点上。它是对传统 nodeSelector
的增强版,提供了更灵活、更强大的表达能力。
Node Affinity 分为两种:
- 硬约束:
requiredDuringSchedulingIgnoredDuringExecution
→ 必须匹配,否则无法调度。 - 软约束:
preferredDuringSchedulingIgnoredDuringExecution
→ 尽量匹配,不匹配也能调度。
硬约束(Required)
apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-hard-affinitynamespace: default
spec:replicas: 2selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:- matchExpressions:- key: nodeaffinityoperator: Invalues:- testcontainers:- name: nginximage: nginxports:- containerPort: 80
含义
- Pod 只能被调度到那些带有
nodeaffinity=test
标签的节点上。 - 如果没有满足条件的节点,Pod 不会被创建,调度器也不会“妥协”。
- 用于强制性约束,适用于:必须部署到某类节点,例如有 GPU、有 SSD 的节点。
字段说明
字段 | 说明 |
---|---|
requiredDuringSchedulingIgnoredDuringExecution | 硬约束:调度时必须满足,执行时不再检查 |
nodeSelectorTerms | 多个条件之间是“或”(OR)关系 |
matchExpressions | 条件表达式数组,内部是“与”(AND)关系 |
key | 节点的标签键,例如 disktype |
operator | 条件运算符,如 In、NotIn、Exists 等 |
values | 标签值列表 |
软约束(Preferred)
只是多了 weight
先不设置标签
apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-soft-affinitynamespace: default
spec:replicas: 2selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:affinity:nodeAffinity:preferredDuringSchedulingIgnoredDuringExecution:- weight: 100preference:matchExpressions:- key: kkkoperator: Invalues:- vvvcontainers:- name: nginximage: nginxports:- containerPort: 80
含义
- Pod 优先调度到带有
kkk=vvv
标签的节点上,如果没有这样的节点,也可以调度到别的节点。 - 属于“加分项”或者“倾向性偏好”。
- 可以设置多个条件,调度器会根据
weight
评估权重。
字段说明
字段 | 说明 |
---|---|
preferredDuringSchedulingIgnoredDuringExecution | 软约束,调度时尽量满足,执行时不检查 |
weight | 权重值(1-100),用于排序优先级 |
preference | 匹配条件,与 required 内部结构相同 |
截屏查看都到216了
设置标签
kubectl label nodes 10-255-101-152 kkk=vvv
运算符支持的类型
运算符 | 含义 |
---|---|
In | 键的值必须在列表中 |
NotIn | 键的值不能在列表中 |
Exists | 键存在即可,不关心值 |
DoesNotExist | 键不存在 |
Gt | 键的值大于指定值(整数) |
Lt | 键的值小于指定值(整数) |
污点与容忍(Taints & Tolerations)
在 Kubernetes 中,污点(Taint) 是给节点“贴标签”,表示这个节点不希望被调度 Pod;而 容忍(Toleration) 是对 Pod 设置“通行证”,告诉调度器:我可以接受这个污点,允许调度到这个节点。
🚧 说白了,就是节点用 Taint 拒绝普通 Pod,而 Pod 用 Toleration 表示“我不怕”,可以进去。
污点(Taint)
添加污点的命令:
kubectl taint nodes <节点名> key=value:effect
例子:
kubectl taint nodes node1 disktype=ssd:NoSchedule
这表示 node1
节点上有个污点,键为 disktype
,值为 ssd
,调度器将不再把普通 Pod 安排到这个节点上。
容忍(Toleration)
Pod 通过 tolerations
字段声明可以容忍哪些污点。
示例 YAML:
apiVersion: v1
kind: Pod
metadata:name: toleration-pod
spec:tolerations:- key: "disktype"operator: "Equal"value: "ssd"effect: "NoSchedule"containers:- name: nginximage: nginx
📌 含义:
- 这个 Pod 可以调度到被
disktype=ssd:NoSchedule
污染的节点。 - 如果节点没有这个污点,Pod 也能正常调度。
三种 Effect 类型(效果)
Effect 类型 | 含义说明 |
---|---|
NoSchedule | 不允许没有容忍的 Pod 被调度 |
PreferNoSchedule | 尽量不调度,没有强制性 |
NoExecute | 不仅不调度,还会驱逐正在运行但不容忍的 Pod |
案例演示
给所有节点打上污点
kubectl taint nodes 10-255-101-152 10-255-101-216 10-255-101-82 key1=value1:NoSchedule
没有容忍的 Pod(会调度失败)
apiVersion: apps/v1
kind: Deployment
metadata:name: pod-without-tolerationnamespace: default
spec:replicas: 2selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:containers:- name: nginximage: nginxports:- containerPort: 80
这个 Pod 不会调度成功,因为它无法容忍污点。
有容忍的 Pod(调度成功)
apiVersion: apps/v1
kind: Deployment
metadata:name: pod-with-tolerationnamespace: default
spec:replicas: 2selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:tolerations:- key: "key1"operator: "Equal"value: "value1"effect: "NoSchedule"containers:- name: nginximage: nginxports:- containerPort: 80
字段解析
字段 | 说明 |
---|---|
key | 与节点上污点的键匹配。这个例子中是 key1 |
operator | 表示比较方式,这里是 Equal ,意思是 key=key1 且 value=value1 |
value | 必须与节点污点的值相同。 |
effect | 表示容忍哪种类型的污点效果,这里是 NoSchedule ,表示可以调度到原本不允许的节点上。 |
Pod Affinity(Pod 亲和性)与 Pod Anti-Affinity(反亲和性)
Pod 亲和性用于指定一个 Pod 应该调度到和哪些 Pod 同节点或同拓扑域的节点上;而反亲和性则用于指定 不应该调度到和某些 Pod 同节点上的节点上。这在某些实际场景中非常有用,比如将应用组件部署在一起或故意分散部署。
Pod Affinity 和 Node Affinity 类似,也分为:
- 硬约束:
requiredDuringSchedulingIgnoredDuringExecution
- 软约束:
preferredDuringSchedulingIgnoredDuringExecution
Pod Affinity(亲和性)
示例:调度到和标签为 app=nginx 的 Pod 相同节点的 Pod 上(硬约束)
apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-pod-affinitynamespace: default
spec:replicas: 2selector:matchLabels:app: nginx-affinitytemplate:metadata:labels:app: nginx-affinityspec:affinity:podAffinity:requiredDuringSchedulingIgnoredDuringExecution:- labelSelector:matchExpressions:- key: appoperator: Invalues:- nginxtopologyKey: kubernetes.io/hostnamecontainers:- name: nginximage: nginxports:- containerPort: 80
说明:
labelSelector
:匹配目标 Pod 的标签topologyKey
:指定拓扑域,一般用kubernetes.io/hostname
表示同一节点
Pod Anti-Affinity(反亲和性)
示例:调度到与标签为 app=nginx 的 Pod 不同节点上(软约束)
apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-pod-antiaffinitynamespace: default
spec:replicas: 2selector:matchLabels:app: nginx-antiaffinitytemplate:metadata:labels:app: nginx-antiaffinityspec:affinity:podAntiAffinity:preferredDuringSchedulingIgnoredDuringExecution:- weight: 100podAffinityTerm:labelSelector:matchExpressions:- key: appoperator: Invalues:- nginxtopologyKey: kubernetes.io/hostnamecontainers:- name: nginximage: nginxports:- containerPort: 80
这个配置表示:“尽量避免和已有的 nginx Pod 被调度到同一节点”。
拓扑域 TopologyKey 说明
拓扑键 | 含义说明 |
---|---|
kubernetes.io/hostname | 节点级别,同一 Node |
topology.kubernetes.io/zone | 同一可用区(适用于云平台) |
topology.kubernetes.io/region | 同一区域(适用于云平台) |
总结
在 Kubernetes 中,Pod 的调度策略直接关系到集群资源的利用率和业务运行的稳定性。通过本篇博文,我们从多个维度深入了解了 Pod 的调度机制:
✅ 默认调度策略
Kubernetes 默认调度器会基于资源可用性、亲和性、污点容忍等信息,为 Pod 自动选择最合适的节点。这种方式适合大多数通用业务场景。
✅ NodeSelector
最简单的调度约束方式,通过指定 nodeSelector
键值对,将 Pod 调度到拥有对应标签的节点上,配置简单,逻辑清晰。
✅ Node Affinity(节点亲和性)
提供了更强大、灵活的调度表达能力,支持软约束(preferred)和硬约束(required)两种模式,并支持多种匹配运算符如 In
、Exists
、Gt
等,更适合复杂调度场景。
✅ Pod Affinity / Anti-Affinity(Pod 间亲和/反亲和)
允许调度决策考虑其他 Pod 的位置关系。例如可以将某些 Pod 调度到相同或不同节点,以实现高可用、节点隔离、业务分层部署等目的,是构建微服务间拓扑结构的重要手段。
✅ Taints and Tolerations(污点与容忍)
用于限制某些节点只接受特定 Pod,反向实现“节点选择”的效果,常用于控制特殊硬件资源节点的使用,例如 GPU 节点、安全节点等。
✅ 自定义调度器(Custom Scheduler)
当内置调度逻辑无法满足需求时,可通过编写并部署自定义调度器,灵活实现业务定制的调度策略,具备最高的自由度和扩展性。
📌 建议使用场景总结
需求类型 | 推荐策略 |
---|---|
简单节点筛选 | nodeSelector |
灵活的节点规则匹配 | nodeAffinity |
根据其他 Pod 的位置调度 | podAffinity / podAntiAffinity |
限制 Pod 访问某些节点 | taints and tolerations |
实现复杂定制调度逻辑 | 自定义调度器(Custom Scheduler) |
Kubernetes 的调度机制具有极高的可扩展性和可编程性,在实际生产中,合理地选择调度策略不仅能提高资源利用效率,更能保障服务的高可用性与运行稳定性。
如果你掌握了这些策略,也就掌握了 Kubernetes 调度的灵魂。