Kubernetes 核心特性实战:亲和性调度、污点容忍与 emptyDir 存储卷
目录
二、Pod 亲和性与反亲和性:让 Pod “结伴” 或 “避嫌”
前言
在 Kubernetes 集群管理中,Pod 调度的合理性和容器存储的稳定性是保障应用高效运行的关键。本文将聚焦 节点亲和性与 Pod 亲和性、污点与容忍、驱逐机制 以及 emptyDir 存储卷,通过通俗解释 + 实操案例,帮你快速掌握这些核心特性的用法与场景。
一、节点亲和性:让 Pod “偏好” 特定节点
节点亲和性(NodeAffinity)是 Pod 的一种属性,用于让 Pod 被 “吸引” 到一类特定节点上,支持 硬策略(必须满足)和 软策略(优先满足),比 nodeSelector 更灵活。
1. 核心概念
- 硬策略(requiredDuringSchedulingIgnoredDuringExecution):Pod 必须调度到满足条件的节点,否则处于 Pending 状态。
- 软策略(preferredDuringSchedulingIgnoredDuringExecution):Pod 优先调度到满足条件的节点,无满足节点时可调度到其他节点。
- 操作符:用于定义标签匹配规则,支持 6 种类型:
| 运算符 | 通俗解释 | 应用场景 | 示例 |
|---|---|---|---|
| In | 标签值在指定列表中 | 筛选符合条件的节点 | env In (dev, test) |
| NotIn | 标签值不在指定列表中 | 排除特定节点 | env NotIn (prod) |
| Gt | 标签值大于指定数值 | 选择数值更大的节点 | version Gt 3 |
| Lt | 标签值小于指定数值 | 选择数值更小的节点 | version Lt 3 |
| Exists | 节点存在该标签(不论值) | 筛选带有特定标签的节点 | Exists zone |
| DoesNotExist | 节点不存在该标签 | 筛选无该标签的节点 | DoesNotExist debug |
2. 实操案例
案例 1:硬策略(排除特定节点)
需求:Pod 不能调度到 kubernetes.io/hostname=node02 的节点上。
1.查看节点标签:
kubectl get nodes --show-labels
2.编写 Pod 配置(pod1.yaml):
apiVersion: v1
kind: Pod
metadata:
name: affinity-hard
spec:
containers:
- name: myapp
image: soscscs/myapp:v1
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: NotIn
values:
- node02
3.部署并验证:
kubectl apply -f pod1.yaml
kubectl get pods -o wide # 查看 Pod 是否调度到 node01
注意:若无满足条件的节点,Pod 会一直处于 Pending 状态。
案例 2:软策略(优先特定节点)
需求:Pod 优先调度到 node03,无 node03 时调度到其他节点。
1.编写配置(pod2.yaml):
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
2.部署验证:
kubectl apply -f pod2.yaml
kubectl get pods -o wide # 确认 Pod 运行在 node01 或 node02 上
案例 3:软硬结合策略
需求:Pod 不能调度到 node02(硬策略),优先调度到 yjs=a 的节点(软策略)。
apiVersion: v1
kind: Pod
metadata:
name: affinity-mix
spec:
containers:
- name: myapp
image: soscscs/myapp:v1
affinity:
nodeAffinity:
# 硬性要求:必须不在 node02 上运行
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: NotIn
values:
- node02
# 软性偏好:优先选择带有 yjs=a 标签的节点
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: yjs
operator: In
values:
- a
二、Pod 亲和性与反亲和性:让 Pod “结伴” 或 “避嫌”
Pod 亲和性(PodAffinity)/ 反亲和性(PodAntiAffinity)基于已运行 Pod 的标签进行调度,支持 拓扑域(如节点、机架、区域),实现 Pod 间的 “聚集” 或 “分散” 部署。
1. 核心区别
调度策略匹配对象支持拓扑域核心目标
| 策略类型 | 匹配对象 | 支持拓扑域 | 核心目标 |
|---|---|---|---|
| PodAffinity | 其他 Pod | ✅ | 新 Pod 与指定 Pod 同拓扑域 |
| PodAntiAffinity | 其他 Pod | ✅ | 新 Pod 与指定 Pod 不同拓扑域 |
拓扑域由 topologyKey 定义(如节点标签 yjs、kubernetes.io/hostname),相同 topologyKey 值的节点属于同一拓扑域。
2. 实操案例
案例 1:Pod 亲和性(同拓扑域部署)
需求:新 Pod 必须与 app=myapp01 的 Pod 处于 yjs 标签相同的拓扑域。
1,先创建参考 Pod(myapp01):
apiVersion: v1
kind: Pod
metadata:
name: myapp01
labels:
app: myapp01
spec:
containers:
- name: myapp
image: soscscs/myapp:v1
kubectl apply -f pod3.yaml
kubectl get pods -o wide
2.编写亲和性 Pod 配置(pod4.yaml):
apiVersion: v1
kind: Pod
metadata:
name: myapp02
spec:
containers:
- name: myapp
image: soscscs/myapp:v1
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- myapp01
topologyKey: yjs
3.验证:
kubectl apply -f pod4.yaml
kubectl get pods -o wide
案例 2:Pod 反亲和性(不同节点部署)
需求:新 Pod 避免与 app=myapp01 的 Pod 部署在同一节点。
apiVersion: v1
kind: Pod
metadata:
name: myapp10
spec:
containers:
- name: myapp
image: soscscs/myapp:v1
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- myapp01
topologyKey: kubernetes.io/hostname
三、污点与容忍:让节点 “拒绝” 或 “接纳” Pod
污点(Taint)是节点的属性,用于排斥特定 Pod;容忍(Tolerations)是 Pod 的属性,用于 “忽略” 节点的污点,两者配合实现 Pod 调度的精准控制。
1. 污点核心概念
- 格式:
key=value:effect(value 可空) - Effect(污点作用):
NoSchedule:禁止新 Pod 调度至该节点(已运行的 Pod 不受影响)
PreferNoSchedule:尽量避免新 Pod 调度至该节点(非强制性)
NoExecute:禁止新 Pod 调度并驱逐已运行且不容忍该污点的 Pod
2.污点操作命令
# 给节点 node01 添加 NoSchedule 污点(阻止新 Pod 调度)
kubectl taint node node01 app=backend:NoSchedule
# 检查节点污点状态
kubectl describe node node01 | grep -i taints
# 移除 node01 的 NoSchedule 污点
kubectl taint node node01 app:NoSchedule-
# 给节点 node02 添加 NoExecute 污点(立即驱逐非容忍 Pod)
kubectl taint node node02 maintenance=true:NoExecute
3. 容忍配置案例
需求:Pod 可容忍节点 node01 的 check=mycheck:NoExecute 污点。
1.node01 设置污点:
kubectl taint node node01 check=mycheck:NoExecute
2.编写带容忍的 Pod 配置(pod-tolerate.yaml):
apiVersion: v1
kind: Pod
metadata:
name: myapp-tolerate
spec:
containers:
- name: myapp
image: soscscs/myapp:v1
tolerations:
- key: "check"
operator: "Equal"
value: "mycheck"
effect: "NoExecute"
tolerationSeconds: 3600
3.验证:
kubectl apply -f pod-tolerate.yaml
kubectl get pods -o wide
四、驱逐机制:安全迁移 Pod
驱逐(Eviction)是将运行中的 Pod 从节点迁移到其他节点的过程,用于节点维护、资源不足等场景,核心命令如下:
命令功能:
kubectl cordon <node>
将节点标记为不可调度状态(不影响已运行的 Pod)
kubectl drain <node> --ignore-daemonsets --delete-local-data
驱逐节点上所有 Pod(跳过 DaemonSet 管理的 Pod,并清理本地数据)
kubectl uncordon <node>
恢复节点的可调度状态
驱逐流程
- Kubernetes 向 Pod 发送
SIGTERM信号,通知 Pod 优雅终止。 - 等待一段时间(默认 30 秒),若 Pod 未终止,发送
SIGKILL强制终止。 - 若 Pod 由 Deployment/StatefulSet 管理,会在其他节点自动重建,维持副本数。
五、emptyDir 存储卷:Pod 内容器共享临时存储
容器文件系统是临时的(崩溃重启后数据丢失),emptyDir 是 Kubernetes 提供的临时存储卷,解决 Pod 内多容器数据共享 和 临时数据持久化 问题。
1. 核心特点
- 生命周期与 Pod 一致:Pod 调度到节点时自动创建,Pod 删除时数据销毁。
- 存储介质:默认使用节点本地磁盘,也可使用内存(性能更高)。
- 适用场景:临时缓存、Pod 内容器数据共享。
2. 实操案例:双容器共享数据
需求:Pod 内两个容器(nginx + busybox)共享 emptyDir 卷,busybox 持续写入日期,nginx 提供访问。
1.编写配置(pod-emptydir.yaml):
apiVersion: v1
kind: Pod
metadata:
name: pod-emptydir
spec:
containers:
# nginx 容器:提供 web 访问
- name: nginx
image: ikubernetes/myapp:v1
ports:
- containerPort: 80
volumeMounts:
- name: html # 挂载卷名称(与下方 volumes 一致)
mountPath: /usr/share/nginx/html # 容器内挂载路径
# busybox 容器:持续写入日期到共享文件
- 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"]
# 定义 emptyDir 存储卷
volumes:
- name: html
emptyDir: {} # 临时存储卷(默认磁盘存储)
2.部署并验证:
# 部署 Pod
kubectl apply -f pod-emptydir.yaml
# 检查 Pod 状态(确保 STATUS 显示为 Running)
kubectl get pods -o wide
# 获取 Pod IP 并测试数据共享
POD_IP=$(kubectl get pod shared-storage-pod -o jsonpath='{.status.podIP}')
curl $POD_IP
总结
本文介绍的特性可总结为:
- 亲和性:让 Pod “主动选择” 节点(节点亲和性)或 “追随” 其他 Pod(Pod 亲和性)。
- 污点与容忍:让节点 “被动拒绝” Pod,容忍则是 Pod 的 “例外申请”。
- 驱逐:安全迁移 Pod,保障节点维护时业务不中断。
- emptyDir:解决 Pod 内容器临时共享存储问题。
这些特性是 Kubernetes 调度与存储的基础,灵活运用可实现集群资源的高效利用和应用的稳定运行。后续将继续分享 PV/PVC、StorageClass 等持久化存储方案,敬请关注!
更多推荐



所有评论(0)