Kubernetes调度机制与策略实验详解
作者:π大星星️
实验目的
通过实际操作,理解 Kubernetes 调度机制的核心原理和常用调度策略的配置方法,包括节点选择、亲和性与反亲和性、污点与容忍等。
实验环境
- Kubernetes 集群(至少包含一个 Master 节点和两个 Worker 节点)。
- kubectl 命令行工具。
- Docker 镜像(如
nginx或其他简单应用镜像)。
实验步骤
步骤 1:查看集群节点信息
目的:了解集群中可用的节点及其状态。
kubectl get nodes -o wide
输出示例:
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME k8s-master Ready control-plane 1d v1.28.0 192.168.1.10 <none> Ubuntu 22.04 5.15.0-46-generic docker://20.10.12 k8s-node1 Ready <none> 1d v1.28.0 192.168.1.11 <none> Ubuntu 22.04 5.15.0-46-generic docker://20.10.12 k8s-node2 Ready <none> 1d v1.28.0 192.168.1.12 <none> Ubuntu 22.04 5.15.0-46-generic docker://20.10.12
说明:确保所有节点状态为 Ready,表示集群正常运行。
步骤 2:使用nodeName调度 Pod
目的:理解 nodeName 的作用,即直接指定 Pod 调度到特定节点。
创建 Pod 配置文件 (pod-nodeName.yaml):
apiVersion: v1
kind: Pod
metadata:
name: pod-node1
spec:
nodeName: k8s-node1
containers:
- name: nginx
image: nginx应用配置文件:
kubectl apply -f pod-nodeName.yaml
验证 Pod 是否运行在指定节点:
kubectl get pods -o wide
输出示例:

说明:nodeName 是最简单的调度方式,适用于调试或测试场景。
步骤 3:使用nodeSelector调度 Pod
目的:理解 nodeSelector 的作用,即通过节点标签选择目标节点。
为节点添加标签:
kubectl label nodes k8s-node1 disk=ssd kubectl label nodes k8s-node2 disk=hdd
创建 Pod 配置文件 (pod-nodeSelector.yaml):
apiVersion: v1
kind: Pod
metadata:
name: pod-ssd
spec:
nodeSelector:
disk: ssd
containers:
- name: nginx
image: nginx应用配置文件:
kubectl apply -f pod-nodeSelector.yaml
验证 Pod 是否运行在带有指定标签的节点:
kubectl get pods -o wide
输出示例:

说明:nodeSelector 是基于节点标签的调度方式,适用于根据节点特性(如硬件类型)进行调度。
步骤 4:使用节点亲和性(nodeAffinity)调度 Pod
目的:理解节点亲和性的作用,即通过复杂的标签匹配规则选择目标节点。
kubectl label pod pod-node-affinity role=frontend
创建 Pod 配置文件 (pod-nodeAffinity.yaml):
这个配置文件的目的是创建一个名为 pod-node-affinity 的 Pod,并通过节点亲和性规则将它调度到带有 disk=ssd 标签的节点上
apiVersion: v1 # 指定 Kubernetes API 的版本,这里使用的是 v1 版本。
kind: Pod # 指定资源类型,这里是 Pod。
metadata: # 定义 Pod 的元数据,包括名称、标签等。
name: pod-node-affinity # Pod 的名称,用于标识这个 Pod。
spec: # 定义 Pod 的规格,包括调度策略和容器配置。
affinity: # 定义 Pod 的亲和性规则,用于控制调度行为。
nodeAffinity: # 节点亲和性规则,用于根据节点的标签选择目标节点。
requiredDuringSchedulingIgnoredDuringExecution: # 必须满足的节点亲和性约束。
nodeSelectorTerms: # 定义节点选择条件的列表,调度器会检查这些条件。
- matchExpressions: # 定义匹配表达式,用于匹配节点标签。
- key: disk # 节点标签的键,这里匹配节点的 "disk" 标签。
operator: In # 操作符,表示 "包含在",即节点的 "disk" 标签值必须在 values 列表中。
values: # 定义允许的标签值列表。
- ssd # 允许的标签值之一,表示节点的 "disk" 标签值为 "ssd"。
containers: # 定义 Pod 中的容器列表。
- name: nginx # 容器的名称,这里是 "nginx"。
image: nginx # 容器使用的镜像,这里是官方的 nginx 镜像。应用配置文件:
kubectl apply -f pod-nodeAffinity.yaml
验证 Pod 是否运行在符合条件的节点:
kubectl get pods -o wide
- 输出示例:

说明:节点亲和性比 nodeSelector 更灵活,支持复杂的匹配规则。
步骤 5:使用 Pod 亲和性与反亲和性调度 Pod
目的:理解 Pod 亲和性与反亲和性的作用,即通过 Pod 标签选择调度位置。
kubectl label pod pod-node-affinity role=frontend
创建带有亲和性的 Pod 配置文件 (pod-affinity.yaml):
这个配置文件的目的是创建一个名为 pod-affinity 的 Pod,并通过 Pod 亲和性 规则将它调度到与已存在的、带有 role=frontend 标签的 Pod 相同的节点上。
关键点解释
apiVersion: v1 # 指定 Kubernetes API 的版本,这里使用的是 v1 版本。
kind: Pod # 指定资源类型为 Pod。
metadata: # 定义 Pod 的元数据。
name: pod-affinity # Pod 的名称,用于标识这个 Pod。
labels: # Pod 的标签,用于标识 Pod 的角色或其他属性。
role: frontend # 定义一个标签,键为 "role",值为 "frontend"。
spec: # 定义 Pod 的规格,包括调度策略和容器配置。
affinity: # 定义 Pod 的亲和性规则。
podAffinity: # 定义 Pod 亲和性规则,用于根据其他 Pod 的标签选择调度位置。
requiredDuringSchedulingIgnoredDuringExecution: # 必须满足的 Pod 亲和性约束。
- labelSelector: # 定义用于选择目标 Pod 的标签选择器。
matchExpressions: # 定义匹配表达式,用于匹配目标 Pod 的标签。
- key: role # 目标 Pod 的标签键,这里匹配 "role" 标签。
operator: In # 操作符,表示 "包含在",即目标 Pod 的 "role" 标签值必须在 values 列表中。
values: # 定义允许的标签值列表。
- frontend # 允许的标签值之一,表示目标 Pod 的 "role" 标签值为 "frontend"。
topologyKey: kubernetes.io/hostname # 定义亲和性约束的拓扑域,这里是节点的主机名。
containers: # 定义 Pod 中的容器列表。
- name: nginx # 容器的名称,这里是 "nginx"。
image: nginx # 容器使用的镜像,这里是官方的 nginx 镜像。创建带有反亲和性的 Pod 配置文件 (pod-antiAffinity.yaml):
这个配置文件的目的是创建一个名为 pod-anti-affinity 的 Pod,并通过 Pod 反亲和性 规则将其调度到与带有 role=frontend 标签的 Pod 不同 的节点上。
apiVersion: v1 # 指定使用的 Kubernetes API 版本为 v1。
kind: Pod # 指定资源类型为 Pod。
metadata: # 定义 Pod 的元数据,包括名称和标签。
name: pod-anti-affinity # Pod 的名称,用于标识这个 Pod。
labels: # 定义 Pod 的标签。
role: backend # 为 Pod 添加一个标签,键为 "role",值为 "backend"。
spec: # 定义 Pod 的规格,包括容器配置和调度策略。
affinity: # 定义 Pod 的亲和性规则。
podAntiAffinity: # 定义 Pod 的反亲和性规则。
requiredDuringSchedulingIgnoredDuringExecution: # 定义必须满足的反亲和性约束。
- labelSelector: # 定义用于选择目标 Pod 的标签选择器。
matchExpressions: # 定义匹配表达式,用于匹配目标 Pod 的标签。
- key: role # 目标 Pod 的标签键,这里匹配 "role" 标签。
operator: In # 操作符,表示 "包含在",即目标 Pod 的 "role" 标签值必须在 values 列表中。
values: # 定义允许的标签值列表。
- frontend # 允许的标签值之一,表示目标 Pod 的 "role" 标签值为 "frontend"。
topologyKey: kubernetes.io/hostname # 定义反亲和性约束的拓扑域,这里是节点的主机名。
containers: # 定义 Pod 中的容器列表。
- name: nginx # 定义容器的名称,这里是 "nginx"。
image: nginx # 定义容器使用的镜像,这里是官方的 nginx 镜像。应用配置文件:
kubectl apply -f pod-affinity.yaml kubectl apply -f pod-antiAffinity.yaml
验证 Pod 是否运行在符合条件的位置:
kubectl get pods -o wide
输出示例:

说明:Pod 亲和性用于将 Pod 调度到与指定 Pod 相同的节点,而 Pod 反亲和性用于避免将 Pod 调度到与指定 Pod 相同的节点。
步骤 6:使用污点与容忍调度 Pod
目的:理解污点与容忍的作用,即通过节点上的污点限制 Pod 调度,并通过容忍允许 Pod 调度到带有特定污点的节点。
为节点添加污点:
kubectl taint nodes k8s-node1 special=true:NoSchedule
创建带有容忍的 Pod 配置文件 (pod-tolerations.yaml):
这个配置文件的目的是创建一个名为 pod-tolerations 的 Pod,并通过 容忍(Tolerations) 规则使其能够被调度到带有特定污点(special=true:NoSchedule)的节点上。
apiVersion: v1 # 指定 Kubernetes API 的版本,这里使用的是 v1。
kind: Pod # 指定资源类型为 Pod。
metadata: # 定义 Pod 的元数据。
name: pod-tolerations # Pod 的名称,用于标识这个 Pod。
spec: # 定义 Pod 的规格,包括容器配置和调度策略。
containers: # 定义 Pod 中的容器列表。
- name: nginx # 容器的名称,这里是 "nginx"。
image: nginx # 容器使用的镜像,这里是官方的 nginx 镜像。
tolerations: # 定义 Pod 的容忍(Tolerations)规则。
- key: "special" # 容忍的键,表示节点上污点的键。
operator: "Equal" # 操作符,表示容忍的条件是键值对相等。
value: "true" # 容忍的值,表示节点上污点的值。
effect: "NoSchedule" # 容忍的效果,表示容忍节点上的 "NoSchedule" 污点。应用配置文件:
kubectl apply -f pod-tolerations.yaml
验证 Pod 是否运行在带有污点的节点:
kubectl get pods -o wide
输出示例:

说明:污点与容忍用于实现灵活的调度策略,例如隔离特殊节点或允许 Pod 调度到带有特定污点的节点。
步骤 7:使用调度优先级(Priority Classes)调度 Pod
目的:理解调度优先级的作用,即为 Pod 分配优先级,高优先级的 Pod 优先调度。
创建优先级类 (priority-class.yaml):
这个配置文件的目的是创建一个名为 high-priority 的 优先级类(PriorityClass),其优先级值为 1000000。
优先级类用于定义 Pod 的调度优先级,调度器会根据 Pod 的优先级来决定调度顺序
apiVersion: scheduling.k8s.io/v1 # 指定使用的 Kubernetes API 版本,这里使用的是 scheduling.k8s.io/v1,适用于优先级类。 kind: PriorityClass # 指定资源类型为 PriorityClass,用于定义 Pod 的优先级。 metadata: # 定义优先级类的元数据。 name: high-priority # 优先级类的名称,用于标识这个优先级类。 value: 1000000 # 定义优先级的数值,数值越大,优先级越高。这里设置为 1000000,表示这是一个高优先级。
应用优先级类:
kubectl apply -f priority-class.yaml
创建带有高优先级的 Pod 配置文件 (pod-priority.yaml):
这个配置文件的目的是创建一个名为 pod-priority 的 Pod,并为其设置一个高优先级。调度器在调度 Pod 时会根据其优先级进行排序,优先级高的 Pod 会优先调度。如果集群资源有限,高优先级的 Pod 甚至可以抢占低优先级的 Pod。
apiVersion: v1 # 指定 Kubernetes API 的版本,这里使用的是 v1,适用于 Pod 资源。
kind: Pod # 指定资源类型为 Pod,即 Kubernetes 中的最小部署单元。
metadata: # 定义 Pod 的元数据,包括名称和其他标识信息。
name: pod-priority # Pod 的名称,用于标识这个 Pod。在同一个命名空间中,Pod 的名称必须是唯一的。
spec: # 定义 Pod 的规格,包括容器配置和调度策略。
priorityClassName: high-priority # 引用一个名为 "high-priority" 的优先级类(PriorityClass)。
# 这个优先级类必须已经存在于集群中,否则 Pod 无法正常调度。
# 优先级类定义了 Pod 的调度优先级,数值越高,优先级越高。
containers: # 定义 Pod 中的容器列表,一个 Pod 可以包含一个或多个容器。
- name: nginx # 定义容器的名称,这里是 "nginx"。
image: nginx # 定义容器使用的镜像,这里是官方的 nginx 镜像。应用配置文件:
kubectl apply -f pod-priority.yaml
验证 Pod 是否优先调度:
kubectl get pods -o wide
输出示例:

说明:调度优先级允许为 Pod 分配优先级,高优先级的 Pod 会优先调度。
步骤 8:清理实验环境
目的:清理实验中创建的资源,恢复集群的初始状态。
删除创建的 Pod:
kubectl delete pod pod-node1 pod-ssd pod-node-affinity pod-anti-affinity pod-tolerations pod-priority
删除优先级类:
kubectl delete priorityclass high-priority
删除节点标签和污点:
kubectl label nodes k8s-node1 disk- kubectl label nodes k8s-node2 disk- kubectl taint nodes k8s-node1 special:NoSchedule-
实验总结
通过以上实验,我们详细验证了 Kubernetes 调度机制的核心原理和常用调度策略的实际应用。以下是关键知识点的总结:
调度器的作用:将 Pod 分配到合适的节点,确保资源合理利用和应用高可用性。
调度方法:
- nodeName:直接指定节点,适用于调试或测试。
- nodeSelector:通过节点标签选择目标节点,适用于根据硬件类型或地理位置调度。
- 节点亲和性(nodeAffinity):支持复杂的标签匹配规则,更灵活。
- Pod 亲和性与反亲和性(podAffinity/podAntiAffinity):根据 Pod 标签选择调度位置。
- 污点与容忍(Taints & Tolerations):通过污点限制调度,并通过容忍允许调度到带有特定污点的节点。
- 调度优先级(Priority Classes):为 Pod 分配优先级,高优先级的 Pod 优先调度。
- 调度器优化:通过调整调度策略文件或参数优化调度器性能。
- 监控调度器:使用 Prometheus 和 Grafana 监控调度器性能指标。
通过实践这些调度策略,你可以根据应用需求优化 Kubernetes 集群的资源分配和应用部署。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
