接上文写的Node亲和性调度https://blog.csdn.net/soso678/article/details/144777397
Pod 间的亲和性和反亲和性(Affinity/AntiAffinity)调度
Pod 间亲和性与反亲和性使你可以基于已经在节点上运行的 Pod 的标签来约束 Pod 可以调度到的节点,而不是基于节点上的标签。
2.1.Pod 亲和性核心概念
Pod 亲和性用于定义 Pod 之间的调度规则,确保某些 Pod 靠近运行 (亲和性)或远离运行(反亲和性)。典型场景包括:
- 亲和性:将同一服务的多个 Pod 调度到同一区域(减少网络延迟)。
- 反亲和性:避免同一服务的 Pod 集中在同一节点(提高容灾能力)。
2.1.1核心配置参数
-
requiredDuringSchedulingIgnoredDuringExecution
- 硬性要求:必须满足的条件,否则 Pod 无法调度。Pod必须与目标pod部署在同一个拓扑域,否则无法调度
-
preferredDuringSchedulingIgnoredDuringExecution
- 软性偏好:调度器会优先尝试将Pod与目标pod部署在同一个拓扑域,但不强制。
-
topologyKey
:定义Pod分布的颗粒度,节点机器的标签的key和value都相等的机器,就是同一个拓扑域。- 拓扑域:定义调度的作用范围(如
zone
、rack
、hostname
)。常见取值范围: kubernetes.io/hostname
:同一物理节点。failure-domain.beta.kubernetes.io/zone
:同一云服务区域(AWS 的 AZ、GCP 的 Zone)。failure-domain.beta.kubernetes.io/region
:同一云服务地区(如us-east
)。- 自定义标签:如
rack
(机架)、cluster
(集群)。
- 拓扑域:定义调度的作用范围(如
-
labelSelector
- 标签选择器:匹配目标 Pod 的标签。
- 示例:选择带有
app=myapp
标签的 Pod。
2.2.pod的亲和性
Pod亲和性场景,k8s集群的节点分布在不同的区域或者不同的机房,当服务A和服务B要求部署在同一个区域或者同一机房的时候,我们就需要亲和性调度了
bash
[root@master nodeaffinity]# cd ..
[root@master Affinity]# mkdir podaffinity
[root@master Affinity]# cd podaffinity/
[root@master podaffinity]# cat pod-required-affinity.yaml
apiVersion: v1 #先创建一个pod,随机调度
kind: Pod
metadata:
name: pod-1
labels:
app: myapp
tier: frontend
spec:
containers:
- name: redis
image: redis
imagePullPolicy: IfNotPresent
ports:
- containerPort: 6379
---
apiVersion: v1 #在创建一个pod,使用pod的亲和性调度
kind: Pod
metadata:
name: pod-2
labels:
app: db
tier: db
spec:
containers:
- name: mysql
image: mysql:5.7
imagePullPolicy: IfNotPresent
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
value: Mysql@123!
affinity:
podAffinity: #pod的亲和性
requiredDuringSchedulingIgnoredDuringExecution: #硬亲和
- labelSelector: #pod的标签选择器
matchExpressions: #匹配pod标签的表达式
- key: app #带有app这个key
operator: "In" #包含
values:
- "myapp" #key的值
topologyKey: kubernetes.io/hostname #拓扑域,同一个节点
[root@master podaffinity]# kubectl apply -f pod-required-affinity.yaml
pod/pod-1 created
pod/pod-2 created
#通过查看发现两个pod运行在同一个节点
[root@master podaffinity]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-1 1/1 Running 0 19m 10.244.1.107 node-2 <none> <none>
pod-2 1/1 Running 0 2s 10.244.1.109 node-2 <none> <none>
这个例子为将新创建的pod调度到与运行带有app=myapp这个标签的pod同一个节点。
3.pod的反亲和性
3.1Pod 反亲和性核心概念
Pod 反亲和性 用于确保某些 Pod 不会共存于同一拓扑域(如同一节点、同一区域)。典型场景包括:
- 避免单点故障:同一服务的多个 Pod 分散到不同节点或区域。
- 资源均衡:防止资源密集型 Pod 集中在同一节点。
- 安全隔离:敏感服务 Pod 避免与其他服务共存。
3.2核心配置参数
requiredDuringSchedulingIgnoredDuringExecution
- 硬性要求 :Pod 必须不调度到存在目标 Pod 的拓扑域,否则无法运行。
preferredDuringSchedulingIgnoredDuringExecution
- 软性偏好 :尽量避免调度到存在目标 Pod 的拓扑域,但不强制。
topologyKey
- 拓扑域 :定义反亲和性作用范围(如
kubernetes.io/hostname
表示同一节点)。
- 拓扑域 :定义反亲和性作用范围(如
labelSelector
- 标签选择器:匹配需要避开的 Pod 标签。
3.3案例
3.3.1.Pod反亲和性场景,当应用服务A和数据库服务B要求尽量不要在同一台节点上的时候。
bash
[root@master podaffinity]# kubectl delete -f pod-required-affinity.yaml
pod "pod-1" deleted
pod "pod-2" deleted
[root@master podaffinity]# cat pod-required-affinity.yaml
apiVersion: v1 #先创建一个pod,随机调度
kind: Pod
metadata:
name: pod-1
labels:
app: myapp
tier: frontend
spec:
containers:
- name: redis
image: redis
imagePullPolicy: IfNotPresent
ports:
- containerPort: 6379
---
apiVersion: v1 #在创建一个pod使用反亲和性调度
kind: Pod
metadata:
name: pod-2
labels:
app: db
tier: db
spec:
containers:
- name: mysql
image: mysql:5.7
imagePullPolicy: IfNotPresent
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
value: Mysql@123!
affinity:
podAntiAffinity: #pod的反亲和性调度
requiredDuringSchedulingIgnoredDuringExecution: #硬反亲和要求
- labelSelector:
matchExpressions:
- key: app
operator: "In"
values:
- "myapp"
topologyKey: kubernetes.io/hostname #拓扑域,节点级别
[root@master podaffinity]# kubectl apply -f pod-required-affinity.yaml
pod/pod-1 created
pod/pod-2 created
[root@master podaffinity]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-1 1/1 Running 0 9m21s 10.244.1.110 node-2 <none> <none>
pod-2 1/1 Running 0 9m21s 10.244.2.63 node-1 <none> <none>
#发现两个pod的分开在不同的node节点上的
这个例子表示创建的pod-2不能调度到运行带有app=myapp这个标签的pod同一个节点上。
3.3.2.硬性反亲和性(同一节点不运行相同服务的 Pod)
bash
[root@master podaffinity]# cat pod-antaffinity-test.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-server
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app # 匹配标签键
operator: In # 操作符
values: [web] # 标签值
topologyKey: kubernetes.io/hostname # 拓扑域为节点级别
containers:
- name: web
image: nginx
[root@master podaffinity]# kubectl apply -f pod-antaffinity-test.yml
deployment.apps/web-server created
[root@master podaffinity]# kubectl get pod -o wide -l app=web
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web-server-7cbc8598bc-jkvnv 1/1 Running 0 2m58s 10.244.1.112 node-2 <none> <none>
web-server-7cbc8598bc-jm2mq 1/1 Running 0 2m58s 10.244.2.69 node-1 <none> <none>
调度逻辑:
- 每个
app=web
的 Pod 必须运行在不同节点(topologyKey: kubernetes.io/hostname
)。 - 如果集群节点数少于副本数(如 2 个节点部署 3 个 Pod),多余的 Pod 将处于
Pending
状态。
场景 1:高可用数据库集群
- 目标:确保每个数据库实例(如 MySQL)运行在不同节点。
- 配置:硬性反亲和性 +
topologyKey: kubernetes.io/hostname
场景 2:敏感服务隔离
- 目标:避免监控服务与核心业务服务共存于同一节点。
- 配置:硬性反亲和性匹配监控 Pod 标签 +
topologyKey: kubernetes.io/hostname
3.3.3.软性反亲和性(优先分散到不同区域)
场景 :多区域负载均衡
- 目标:优先将服务的 Pod 分散到不同区域。
- 配置 :软性反亲和性 +
topologyKey: failure-domain.beta.kubernetes.io/zone
。
ini
[root@master ~]# kubectl label node node-2 zone=beijing
node/node-2 labeled
[root@master podaffinity]# cat pod-antaffinity-pre.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-server-1
spec:
replicas: 1
selector:
matchLabels:
app: web-app
template:
metadata:
labels:
app: web-app
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100 # 权重越高,优先级越高
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values: [web-app]
topologyKey: zone # 拓扑域为区域级别
[root@master podaffinity]# kubectl get pod -l app=web-app -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web-server-1-86458fdf55-p5rsz 1/1 Running 0 55s 10.244.1.113 node-2 <none> <none>
调度逻辑:
- 优先将
app=web-app
的 Pod 分散到不同区域(如zone=beijing
和zone=shanghai
)。 - 若无法满足(如只有单区域),仍会调度,但可能集中。
常见问题与解决
问题 1:Pod 处于 Pending 状态
- 原因:硬性反亲和性规则无法满足(如节点不足)。
- 解决 :
- 增加集群节点数量。
- 放宽反亲和性规则(如改用软性偏好)。
问题 2:软性反亲和性未生效
- 原因:权重过低或其他偏好条件优先级更高。
- 解决 :调整
weight
值或减少冲突的偏好规则。