Kubernetes 集群调度与PV和PVC
前言
在 Kubernetes(K8s)集群管理中,调度机制决定了 Pod 如何高效分配到节点,而存储管理则解决了容器数据持久化与共享的核心痛点。本文将结合理论原理与实战案例,详细拆解 K8s 集群调度流程、核心策略以及 PV/PVC 持久化存储机制,帮助开发者和运维人员快速掌握关键技能。
一、Kubernetes 集群调度:Pod 的"智能分配"之道
K8s 调度的核心目标是将未绑定节点的 Pod 合理分配到集群节点,实现资源均衡利用、高可用性与灵活性。其背后依赖 List-Watch 组件协作机制与分层调度策略。
1. 核心组件与协作流程
K8s 通过 List-Watch 机制实现组件解耦与数据实时同步,关键组件分工如下:
| 组件 | 核心职责 |
|---|---|
| kubectl/API 客户端 | 发起资源创建/管理请求 |
| APIServer | 集群控制入口,负责权限校验、存储交互 |
| etcd | 存储集群所有状态信息 |
| Controller Manager | 维持副本数、执行自愈逻辑(扩容/重建) |
| Scheduler | 核心调度器,为 Pod 选择合适节点 |
| kubelet | 节点代理,管理 Pod 生命周期与状态上报 |
Pod 创建完整流程(List-Watch 模型)
- 三大组件(Controller Manager、Scheduler、kubelet)启动后,通过 HTTPS 6443 端口监听 APIServer 资源事件;
- 用户通过
kubectl apply -f pod.yaml发送创建请求,APIServer 校验后将 Pod 元数据写入 etcd; - etcd 触发 Create 事件,Controller Manager 监听后通过 RC/ReplicaSet 保证副本数;
- Scheduler 发现处于 Pending 状态的 Pod,经调度算法选择节点并更新绑定信息;
- kubelet 监听分配给自己的 Pod,拉取镜像、创建并启动容器,最后上报状态至 APIServer;
- APIServer 更新 etcd 中 Pod 状态,集群同步完成,Pod 进入 Running 状态。
2. Scheduler 调度核心流程
Scheduler 的调度过程分为「过滤」和「优选」两个阶段,确保筛选出最优节点:
(1)过滤阶段(Predicate):排除不满足条件的节点
通过一系列算法筛选出符合 Pod 基础需求的节点,常见过滤规则:
- PodFitsResources:节点剩余资源满足 Pod 需求;
- PodFitsHost:匹配指定 NodeName;
- PodFitsHostPorts:检查端口是否冲突;
- PodSelectorMatches:节点标签与 Pod 选择器匹配;
- NoDiskConflict:避免 Volume 挂载冲突。
若无符合条件的节点,Pod 会持续处于 Pending 状态并重试。
(2)优选阶段(Priorities):对可行节点打分排序
对过滤后的节点按优先级权重排序,常见优选规则:
- LeastRequestedPriority:资源使用率越低,权重越高;
- BalancedResourceAllocation:CPU 与内存使用率越接近越好;
- ImageLocalityPriority:优先选择已存在目标镜像的节点。
最终选择权重最高的节点完成调度。
3. 常用调度策略:从简单绑定到智能亲和
(1)直接指定节点
- nodeName:强制绑定节点,跳过 Scheduler 调度,适用于特殊场景:
spec:
nodeName: node01 # 直接调度到 node01
- nodeSelector:基于节点标签匹配,属于强制约束:
spec:
nodeSelector:
yjs: a # 匹配标签 yjs=a 的节点
需先为节点设置标签:kubectl label nodes node01 yjs=a。
(2)亲和性与反亲和性:更灵活的调度规则
亲和性分为「节点亲和性」和「Pod 亲和性/反亲和性」,支持「硬策略」(必须满足)和「软策略」(优先满足),操作符包括 In、NotIn、Exists、Gt 等。
- 节点亲和性示例(软硬结合):
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution: # 硬策略:排除 node02
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: NotIn
values: ["node02"]
preferredDuringSchedulingIgnoredDuringExecution: # 软策略:优先选择 yjs=a 的节点
- weight: 1
preference:
matchExpressions:
- key: yjs
operator: In
values: ["a"]
- Pod 亲和性:让新 Pod 与指定 Pod 处于同一拓扑域(如同一标签节点):
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values: ["myapp01"]
topologyKey: yjs # 基于 yjs 标签划分拓扑域
- Pod 反亲和性:避免新 Pod 与指定 Pod 处于同一拓扑域,常用于分散部署提高可用性。
(3)污点(Taint)与容忍(Toleration):节点的"排斥与例外"
污点让节点排斥特定 Pod,容忍则允许 Pod 突破排斥,两者配合实现节点隔离。
-
污点格式:
key=value:effect,effect 支持三种类型:- NoSchedule:不调度新 Pod 到该节点;
- PreferNoSchedule:尽量避免调度;
- NoExecute:不调度且驱逐已存在的 Pod。
-
常用命令:
# 给 node01 设置污点:不允许未容忍的 Pod 调度
kubectl taint node node01 key1=value1:NoSchedule
# 去除污点
kubectl taint node node01 key1:NoSchedule-
# 给 Pod 设置容忍
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoSchedule"
4. 节点维护与 Pod 驱逐
当需要升级节点或维护时,可通过以下命令安全迁移 Pod:
kubectl cordon <node>:标记节点为不可调度;kubectl drain <node> --ignore-daemonsets --delete-local-data:驱逐节点上所有 Pod;kubectl uncordon <node>:恢复节点可调度状态。
二、PV 与 PVC:K8s 持久化存储解决方案
容器文件系统是临时的,Pod 重启或删除会导致数据丢失。K8s 通过 Volume 抽象解决该问题,而 PV/PVC 则进一步实现了存储资源的"申请-分配"解耦。
1. 基础存储卷类型对比
| 存储类型 | 生命周期 | 共享性 | 持久性 | 典型场景 |
|---|---|---|---|---|
| emptyDir | Pod 生命周期 | 同 Pod 内容器 | ❌ | 临时缓存、容器间共享 |
| hostPath | 节点生命周期 | 单节点 | ✅ | 节点级持久化(如日志存储) |
| NFS | 独立服务 | 多节点 | ✅ | 集群共享存储 |
(1)emptyDir 示例:Pod 内容器共享数据
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html/
- name: busybox
image: busybox:latest
volumeMounts:
- name: html
mountPath: /data/
command: ['/bin/sh','-c','while true;do echo $(date) >> /data/index.html;sleep 2;done']
volumes:
- name: html
emptyDir: {}
(2)NFS 示例:多节点共享存储
- 部署 NFS 服务端:
yum install -y nfs-utils rpcbind
mkdir /data/volumes && chmod 777 /data/volumes
echo "/data/volumes 192.168.10.0/24(rw,no_root_squash)" > /etc/exports
systemctl start rpcbind nfs
- Pod 挂载 NFS:
volumes:
- name: html
nfs:
path: /data/volumes
server: stor01 # NFS 服务端地址
2. PV 与 PVC 核心概念
- PV(Persistent Volume):持久化存储卷,由运维人员定义,描述底层存储资源(如 NFS 路径、容量、访问模式);
- PVC(Persistent Volume Claim):存储资源请求,由开发者创建,指定所需存储的容量、访问模式等,K8s 自动匹配符合条件的 PV;
- StorageClass:动态 PV 模板,可自动创建 PV,适用于大规模部署。
PV 与 PVC 生命周期
Provisioning(配置)→ Binding(绑定)→ Using(使用)→ Releasing(释放)→ Recycling(回收)
- PV 状态:Available(可用)→ Bound(已绑定)→ Released(已释放)→ Failed(失败);
- 回收策略:
- Retain:保留数据,需手动清理;
- Delete:自动删除存储资源(云存储如 AWS EBS 支持);
- Recycle:清空数据后重新可用(仅 NFS/HostPath 支持)。
3. PV + PVC 实战(NFS 后端)
(1)定义 PV(5 个示例 PV)
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv003
spec:
nfs:
path: /data/volumes/v3
server: stor01
accessModes: ["ReadWriteMany", "ReadWriteOnce"] # 支持多路读写和单Pod读写
capacity:
storage: 2Gi # 容量2Gi
persistentVolumeReclaimPolicy: Retain # 保留策略
(2)定义 PVC + Pod
# PVC 申请 2Gi 多路读写存储
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mypvc
spec:
accessModes: ["ReadWriteMany"]
resources:
requests:
storage: 2Gi
# Pod 挂载 PVC
apiVersion: v1
kind: Pod
metadata:
name: pod-vol-pvc
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
persistentVolumeClaim:
claimName: mypvc # 关联 PVC
(3)验证
kubectl apply -f pv-demo.yaml && kubectl apply -f pod-vol-pvc.yaml
# 在 NFS 服务端写入测试数据
echo "welcome to use pv3" > /data/volumes/v3/index.html
# 访问 Pod 验证
curl $(kubectl get pod pod-vol-pvc -o jsonpath='{.status.podIP}')
4. StorageClass 动态存储(进阶)
手动创建 PV 效率低下,通过 StorageClass 可实现 PV 自动创建,适用于大规模集群。
(1)部署 NFS Provisioner(存储分配器)
需先创建 RBAC 权限、配置 NFS 服务,再部署 Provisioner 组件(负责自动创建 PV 与 NFS 挂载点关联)。
(2)创建 StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-client-storageclass
provisioner: nfs-storage # 与 Provisioner 名称一致
parameters:
archiveOnDelete: "false" # 删除 PVC 时自动删除数据
(3)测试动态存储
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: test-nfs-pvc
spec:
accessModes: ["ReadWriteMany"]
storageClassName: nfs-client-storageclass # 关联 StorageClass
resources:
requests:
storage: 1Gi
创建 PVC 后,K8s 会自动创建对应的 PV 并绑定,NFS 服务端也会生成对应的存储目录。
三、核心总结
- 调度机制:以 Scheduler 为核心,通过「过滤-优选」流程实现 Pod 智能分配,配合亲和性、污点/容忍策略满足复杂场景需求;
- 存储方案:从临时存储(emptyDir)到集群共享(NFS),再到生产级持久化(PV/PVC),StorageClass 进一步简化大规模部署;
- 关键原则:“调度是吸引,污点是排斥,亲和性是偏好,容忍是例外”;PV 是"存储资源池",PVC 是"资源申请单",解耦运维与开发职责。
通过本文的理论与实战,相信你已掌握 K8s 调度与存储的核心能力。在实际生产中,需根据业务场景选择合适的调度策略与存储方案,兼顾性能、可用性与可维护性。
更多推荐



所有评论(0)