前言
在 K8s 集群管理中,Pod 的调度约束——亲和性(Affinity)与反亲和性(Anti-Affinity)这两种机制允许管理员精细控制 Pod 在集群内的分布方式,以适应多样化的业务需求和运维策略。本篇将介绍 K8s 集群中 Pod 调度的亲和与反亲和的概念以及相关案例。
目录
一、Pod 生命周期
1. 概述
Pod 的生命周期是指从 Pod 被创建到最终被销毁的整个过程,涉及多个阶段和状态转换,以及可能执行的各种操作。
2. 图示
3. 介绍
Pod 生命周期/启动过程
① 首先,由 pid 为1的 init 容器(pause容器)管理整个容器的初始化
② 接着,init 容器串行启动
③ 容器启动时执行 postStart 操作
④ 随后启动存活探针和就绪探针
⑤ 根据资源限制的 request 和 limit 启动应用容器
⑥ 最后,在容器退出时执行 preStop 操作
二、调度约束
1. 概述
Kubernetes 中各组件通过 List-Watch 机制协作,保持数据同步且解耦。用户通过 kubectl 向 APIServer 发送命令,在 Node 节点上创建 Pod 和 Container。部署过程需要 Controller Manager、Scheduler 和 kubelet 协同工作。所有部署信息存储在 etcd 中,etcd 向 APIServer 发送 Create 事件,实现信息同步和协作。
2. Pod 启动典型创建过程(工作机制)
2.1 图示
2.2 创建过程
(1)客户端发出创建指令 ReplicaSet(控制器),通过 kube-apiserver 接口
(2)kube-apiserver 服务将创建 pod 模板这条信息发给 etcd 存储
(3)etcd 发送 create 事件至 kube-apiserver
(4)kube-apiserver 发送 create 事件至 kube-controller-manager 管理控制器
(5)kube-controller-manager 会根据需要创建的 pod 清单(副本项/容器的内容),并发送创建 cretae pod 的需求至 kube-controller-manager
(6)kube-controller-manager 会将需要创建的信息保存在 etcd 中
(7)etcd 会将发来的事件(数据清单)发送给 kube-apiserver
(8)kube-apiserver 会将 etcd 发出的事件(创建 pod 的事件)给 kube-scheduler 资源调度器
(9)kube-scheduler 通过调度算法(预选、优选)筛选 node 调度 pod,并将调度完成的信息传给 kube-apiserver
(10)kube-apiserver 会将调度完成的信息保存在 etcd 中
(11)etcd 会发出更新的 pod 事件至 kube-apiserver
(12)kube-apiserver 会发出更新的 pod 事件至 kubelet
(13)kubelet 会跟容器进行交互创建 pod 及容器,并将 pod 容器的状态通过 kube-apiserver 存储到 etcd 中
(14)最终 etcd 确认信息结束流程
注意:
① 整个过程中,上方的命令、组件均通过 https 6443 监听 kube-apiserver 接口;
② 在创建 pod 的工作就已经完成了后,kubelet 依然保持监听。如:扩充 Pod 副本数量、镜像文件升级等需求。
三、调度过程介绍
1. 关注的问题
Scheduler 是 kubernetes 的调度器,主要的任务是把定义的 pod 分配到集群的节点上。其主要考虑的问题如下:
- 公平:如何保证每个节点都能被分配资源
- 资源高效利用:集群所有资源最大化被使用
- 效率:调度的性能要好,能够尽快地对大批量的 pod 完成调度工作
- 灵活:允许用户根据自己的需求控制调度的逻辑
Scheduler 作为独立程序运行,持续监听 APIServer,检索 spec.nodeName 为空的 Pod,并为每个 Pod 创建一个绑定 binding(API 对象),指定其应放置在哪个节点上。
2. 调度策略
2.1 分类
预选策略:首先是过滤掉不满足条件的节点,这个过程称为预算策略(predicate);
优选策略:然后对通过的节点按照优先级排序,这个是优选策略(priorities);
优先级:最后从中选择优先级最高的节点。若中间步骤有误,返回错误。
2.2 Predicate(预选)常见算法
Predicate 是一种策略函数,用于评估节点是否适合放置特定的 Pod。Predicate 函数会检查节点的特性和 Pod 的要求,以确定是否可以将 Pod 放置在该节点上
PodFitsResources
- 节点上剩余的资源是否大于 pod 请求的资源nodeName,检查节点名称是否和 NodeName 匹配。
PodFitsHost
- 如果 pod 指定了 NodeName,检查节点名称是否和 NodeName 匹配。
PodFitsHostPorts
- 节点上已经使用的 port 是否和 pod 申请的 port 冲突。
PodSelectorMatches
- 过滤掉和 pod 指定的 label 不匹配的节点。
NoDiskConflict
- 已经 mount 的 volume 和 pod 指定的 volume 不冲突,除非它们都是只读。
如果在 predicate(预选)过程中没有合适的节点,pod 会一直在 pending(等待 running)状态,不断重试调度,直到有节点满足条件。 经过这个步骤,如果有多个节点满足条件,就继续 priorities(优选)过程:按照优先级大小对节点排序。
2.3 priorities(优选)常见算法
优先级由一系列键值对组成,键是该优先级项的名称,值是它的权重(该项的重要性)。常见的优先级选项包括:
LeastRequestedPriority
- 通过计算CPU和Memory的使用率来决定权重,使用率越低权重越高。也就是说,这个优先级指标倾向于资源使用比例更低的节点。
BalancedResourceAllocation
- 节点上 CPU 和 Memory 使用率越接近,权重越高。这个一般和上面的一起使用,不单独使用。比如 node01 的 CPU 和 Memory 使用率 20:60,node02 的 CPU 和 Memory 使用率 50:50,虽然 node01 的总使用率比 node02 低,但 node02 的 CPU 和 Memory 使用率更接近,从而调度时会优选 node02。
ImageLocalityPriority
- 倾向于已经有要使用镜像的节点,镜像总大小值越大,权重越高。
通过算法对所有的优先级项目和权重进行计算,得出最终的结果。
3. 指定调度节点
3.1 nodeName 调度
pod.spec.nodeName 将 Pod 直接调度到指定的 Node 节点上,会跳过 Scheduler 的调度策略,该匹配规则是强制匹配
示例:
3.2 nodeSelector 调度
pod.spec.nodeSelector:通过 kubernetes 的 label-selector 机制选择节点,由调度器调度策略匹配 label,然后调度 Pod 到目标节点,该匹配规则属于强制约束
示例:
3.3 区别
① nodeName 只能指定单个node节点,nodeSelector 可以指定有相同标签的多个 node 节点
② nodeName 强制调度,不需要经过 scheduler 资源调度器;nodeSelector 经过 scheduler 资源调度器
4. k8s 节点的标签管理
增加标签:
kubectl label [ -n 命名空间 ] 资源类型 资源名称 标签键名=键值
删除标签:
kubectl label [ -n 命名空间 ] 资源类型 资源名称 标签键名-(减号不能忽略)
修改标签:
kubectl label [ -n 命名空间 ] 资源类型 资源名称 标签键名=新的键值 --overwrite
查询标签:
kubectl get [ -n 命名空间 ] 资源类型 --show-label [ -l 标签键名 ]或[ -l 标签键名=键值 ](筛选)
5. node 亲和性
5.1 概述
节点亲和性允许你指定Pod应当(preferred)或必须(required)调度到具有某些标签的节点上,可以实现Pod调度的精细化控制,确保Pod被安排在具有特定特性的节点上,从而满足应用的部署需求或优化资源利用。
5.1.1 节点亲和性(Node Affinity)
节点亲和性指定了 Pod 可以被调度到哪些节点上。
pod.spec.nodeAffinity
● preferredDuringSchedulingIgnoredDuringExecution:软策略
● requiredDuringSchedulingIgnoredDuringExecution:硬策略
5.1.2 Pod 亲和性(Pod Affinity)
Pod 亲和性指定了 Pod 应该与哪些其他 Pod 一起调度到同一节点上。
pod.spec.affinity.podAffinity/podAntiAffinity
● preferredDuringSchedulingIgnoredDuringExecution:软策略
● requiredDuringSchedulingIgnoredDuringExecution:硬策略
5.2 硬策略和软策略
5.2.1 硬策略
硬策略,正式名称为 requiredDuringSchedulingIgnoredDuringExecution,表示必须满足的条件。如果无法找到满足条件的节点来调度 Pod,则 Pod 将不会被调度。这意味着硬策略是强制性的。
5.2.2 软策略
软策略,正式名称为 preferredDuringSchedulingIgnoredDuringExecution,表示倾向于满足但不是必须的条件。与硬策略不同,即使没有节点完全符合软策略的所有偏好,Pod仍然会被调度。
软策略通常会附带一个权重值(范围1~100),用来表示偏好的强度。当存在多个节点可以选择时,调度器会根据这些偏好和它们的权重来决定最佳的调度位置。
5.3 键值运算关系
- In:label 的值在某个列表中 pending
- NotIn:label 的值不在某个列表中
- Gt:label 的值大于某个值
- Lt:label 的值小于某个值
- Exists:某个 label 存在
- DoesNotExist:某个 label 不存在
5.4 示例
示例1:node 硬策略
指定 Kubernetes 调度器在部署这个 Pod 时,要求 Pod 不会被调度到主机名为"node02"的节点上。
① 编辑 yaml 文件
[root@master01 affinity]# vim pod1.yaml
apiVersion: v1 # Kubernetes API版本
kind: Pod # 资源类型为Pod
metadata: # Pod的元数据信息
name: affinity # Pod的名称为
labels: # 为Pod定义了标签
app: node-affinity-pod
spec: # 定义了Pod的规格,包括容器和亲和性设置
containers: # 定义了Pod中的容器
- name: with-node-affinity # 容器的名称
image: soscscs/myapp:v1 # 容器要运行的镜像
affinity: # 定义了Pod的亲和性设置
nodeAffinity: # 指定了节点亲和性
requiredDuringSchedulingIgnoredDuringExecution: # 硬策略
nodeSelectorTerms: # 节点选择器的条件
- matchExpressions: # 指定了匹配表达式,用于匹配节点的标签
- key: kubernetes.io/hostname # 指定了要匹配的节点标签的键值
operator: NotIn # 表示不在指定的值列表中
values:
- node02
# 指定了不在值列表["node02"]中的节点,即Pod不会被调度到主机名为"node02"的节点上
② 启动 pod
[root@master01 affinity]# kubectl apply -f pod1.yaml
pod/affinity created
③ 查看 pod 节点详情信息
[root@master01 affinity]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
affinity 1/1 Running 0 5s 10.244.1.30 node01 <none> <none>
由于集群中就两个 node 节点(),所有新建的 pod 会被调度到 node01 上。 另外,如果硬策略不满足条件,Pod 状态一直会处于 Pending 状态,比如: operator: In values: [node03]
示例2:node 软策略
设置了节点亲和性,优先选择主机名为"node03"的节点来调度这个 Pod。
① 节点增加标签
[root@master01 affinity]# kubectl label nodes node01 fql=a
node/node01 labeled
[root@master01 affinity]# kubectl label nodes node02 fql=b
node/node02 labeled
[root@master01 affinity]# kubectl get nodes --show-labels
NAME STATUS ROLES AGE VERSION LABELS
master01 Ready control-plane,master 12d v1.20.11 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=master01,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=
node01 Ready <none> 11d v1.20.11 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,fql=a,kubernetes.io/arch=amd64,kubernetes.io/hostname=node01,kubernetes.io/os=linux
node02 Ready <none> 11d v1.20.11 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,fql=b,kubernetes.io/arch=amd64,kubernetes.io/hostname=node02,kubernetes.io/os=linux
② 编辑 yaml 文件
[root@master01 affinity]# vim pod2.yaml
apiVersion: v1
kind: Pod
metadata:
name: affinity
labels:
app: node-affinity-pod
spec:
containers:
- name: with-node-affinity
image: soscscs/myapp:v1
affinity: # 定义了Pod的亲和性设置
nodeAffinity: # 指定了节点亲和性
preferredDuringSchedulingIgnoredDuringExecution: # 软策略
- weight: 1 # 权重为1
preference: # 定义了节点亲和性的偏好设置
matchExpressions: # 定义了匹配表达式,用于指定节点选择的条件
- key: fql # 指定了匹配的键
operator: In # 节点的主机名必须在指定的值列表中
values:
- a
# 指定了匹配的值列表,这里只有一个值"node03",表示偏好选择主机名为"node03"的节点
③ 启动 pod
[root@master01 affinity]# kubectl delete -f pod1.yaml
④ 查看 pod 节点详情信息
[root@master01 affinity]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
affinity 1/1 Running 0 8s 10.244.1.31 node01 <none> <none>
⑤ 修改 volume 值
values:
- c # 实际上不存在c
⑥ 启动 pod 并查看详情信息
[root@master01 affinity]# kubectl apply -f pod2.yaml
pod/affinity created
[root@master01 affinity]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
affinity 1/1 Running 0 4s 10.244.1.32 node01 <none> <none>
这里得到的结果并不明显,软策略下无法选择主机名为"node03"的节点来调度这个,会选择其他可用的节点。
示例3:node 软策略权重配置
设置多条软策略不同的权重,查看调用情况。
对应调度标签键值为:fql:a 的权重为10;对应调度标签键值为:fql:b 的权重为20;
① 编辑 yaml 文件
[root@master01 affinity]# vim pod3.yaml
apiVersion: v1
kind: Pod
metadata:
name: affinity
labels:
app: node-affinity-pod
spec:
containers:
- name: with-node-affinity
image: soscscs/myapp:v1
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 10
preference:
matchExpressions:
- key: fql
operator: In
values:
- a
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 20
preference:
matchExpressions:
- key: fql
operator: In
values:
- b
② 创建 pod
[root@master01 affinity]# kubectl apply -f pod3.yaml
pod/affinity created
③ 查看 pod 详情信息
[root@master01 affinity]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
affinity 1/1 Running 0 3s 10.244.2.11 node02 <none> <none>
由此可见,即使标签键值为:fql:b 的调度任务在 yaml 文件下面,只要权重大,则会被调用。
示例4:node 硬策略软策略组合
硬策略对应调度标签键值为:fql:a 的 node;软策略对应调度标签键值为:fql:b 的 node;
① 编辑 yaml 文件
[root@master01 affinity]# vim pod4.yaml
apiVersion: v1
kind: Pod
metadata:
name: affinity
labels:
app: node-affinity-pod
spec:
containers:
- name: with-node-affinity
image: soscscs/myapp:v1
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: fql
operator: In
values:
- a
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: fql
operator: In
values:
- b
② 创建 pod
[root@master01 affinity]# kubectl apply -f pod4.yaml
pod/affinity created
[root@master01 affinity]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
affinity 1/1 Running 0 3s 10.244.1.33 node01 <none> <none>
由于优先满足硬策略,可以看见调到到 node01上。
③ 再次创建新的 pod
[root@master01 affinity]# vim pod4.yaml
metadata:
name: affinity-01
[root@master01 affinity]# kubectl apply -f pod4.yaml
pod/affinity-01 created
[root@master01 affinity]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
affinity 1/1 Running 0 27s 10.244.1.33 node01 <none> <none>
affinity-01 1/1 Running 0 3s 10.244.1.34 node01 <none> <none>
[root@master01 affinity]# vim pod1.yaml
由于优先满足硬策略,可以看见并未轮询调度,依然调到到 node01上。
示例5:node 硬策略软策略组合,硬策略条件不满足
硬策略对应调度标签键值为:fql:c 的 node(实际并不存在);软策略对应调度标签键值为:fql:b 的 node;
① 编辑 yaml 文件
[root@master01 affinity]# kubectl delete -f pod4.yaml
[root@master01 affinity]# kubectl delete -f pod4.yaml
[root@master01 affinity]# vim pod4.yaml
apiVersion: v1
kind: Pod
metadata:
name: affinity
labels:
app: node-affinity-pod
spec:
containers:
- name: with-node-affinity
image: soscscs/myapp:v1
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: fql
operator: In
values:
- c
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: fql
operator: In
values:
- b
② 创建 pod
[root@master01 affinity]# kubectl apply -f pod4.yaml
pod/affinity created
③ 查看 pod 详情信息
[root@master01 affinity]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
affinity 0/1 Pending 0 3s <none> <none> <none> <none>
如果把硬策略和软策略合在一起使用,则要先满足硬策略之后才会满足软策略;这里硬策略不满足,所以处于 Pending 状态。
6. Pod 亲和性与反亲和性
6.1 概述
在 Kubernetes 中,亲和性是一种指导 Pod 如何与节点进行交互的机制。亲和性可以帮助您控制 Pod 的调度行为,包括节点亲和性(Node Affinity)、Pod 亲和性(Pod Affinity)。可以约束一个 Pod 以便限制其只能在特定的节点上运行, 或优先在特定的节点上运行。
节点反亲和性与节点亲和性相反,它用来避免 Pod 被调度到具有特定标签的节点上,这有助于实现高可用性和资源隔离。
6.2 node 亲和性、pod 亲和性与反亲和性对比
调度策略 | 匹配标签 | 操作符 | 拓扑域支持 | 调度目标 |
nodeAffinity | 主机 | In, NotIn, Exists,DoesNotExist, Gt, Lt | 否 | 指定主机 |
podAffinity | Pod | In, NotIn, Exists,DoesNotExist | 是 | Pod与指定Pod同一拓扑域 |
podAntiAffinity | Pod | In, NotIn, Exists,DoesNotExist | 是 | Pod与指定Pod不在同一拓扑域 |
6.3 亲和性示例
使用 Pod 亲和性调度,创建多个 Pod 资源。
topologyKey 是节点标签的键。如果两个节点使用此键标记并且具有相同的标签值,则调度器会将这两个节点视为处于同一拓扑域中。 调度器试图在每个拓扑域中放置数量均衡的 Pod。
① 创建一个标签为 app=myapp01 的 Pod
创建一个带有标签的 Pod,观察调度在哪个节点上。
[root@master01 affinity]# vim demo01.yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp01
labels:
app: myapp01
spec:
containers:
- name: with-node-affinity
image: soscscs/myapp:v1
② 启动 pod myapp01
[root@master01 affinity]# kubectl apply -f demo01.yaml
pod/myapp01 created
[root@master01 affinity]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp01 1/1 Running 0 3s 10.244.1.35 node01 <none> <none>
③ 采用硬策略关联标签为 app: myapp01 的 pod
Pod 之间的调度约束,要求在调度 Pod 时,必须满足以下条件:Pod 的标签中包含 app=myapp01。这样的设置可以确保在调度 Pod 时,只有满足特定标签条件的节点才会被考虑。
[root@master01 affinity]# vim demo02.yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp02
labels:
app: myapp02
spec:
containers:
- name: myapp02
image: soscscs/myapp:v1
affinity: # Pod的亲和性设置,用于指定Pod的调度约束
podAffinity: # Pod的亲和性规则
requiredDuringSchedulingIgnoredDuringExecution: # 硬策略
- labelSelector: # 用于选择标签的规则
matchExpressions: # 这是匹配表达式的列表
- key: app # 要匹配的标签键
operator: In # 匹配标签键值中的任意一个
values: # 匹配的标签值列表
- myapp01 # 要匹配的标签值
topologyKey: fql # 用于指定拓扑域的键,用于确定在哪些节点上进行亲和性约束
④ 启动 pod myapp02
[root@master01 affinity]# kubectl apply -f demo02.yaml
pod/myapp02 created
[root@master01 affinity]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp01 1/1 Running 0 35m 10.244.1.35 node01 <none> <none>
myapp02 1/1 Running 0 3s 10.244.1.36 node01 <none> <none>
⑤ 再次创建新的 pod myapp03
[root@master01 affinity]# vim demo02.yaml
metadata:
name: myapp03
[root@master01 affinity]# kubectl apply -f demo02.yaml
pod/myapp03 created
[root@master01 affinity]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp01 1/1 Running 0 38m 10.244.1.35 node01 <none> <none>
myapp02 1/1 Running 0 3m10s 10.244.1.36 node01 <none> <none>
myapp03 1/1 Running 0 2s 10.244.1.37 node01 <none> <none>
⑥ 修改 node02 标签,使得与 node01 在同一拓扑域
[root@master01 affinity]# kubectl label nodes node02 --overwrite fql=a
node/node02 labeled
[root@master01 affinity]# kubectl get node --show-labels
NAME STATUS ROLES AGE VERSION LABELS
master01 Ready control-plane,master 12d v1.20.11 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=master01,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=
node01 Ready <none> 12d v1.20.11 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,fql=a,kubernetes.io/arch=amd64,kubernetes.io/hostname=node01,kubernetes.io/os=linux
node02 Ready <none> 12d v1.20.11 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,fql=a,kubernetes.io/arch=amd64,kubernetes.io/hostname=node02,kubernetes.io/os=linux
⑦ 再次创建新的 pod myapp04,观察调度情况
[root@master01 affinity]# kubectl apply -f demo02.yaml
pod/myapp04 created
[root@master01 affinity]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp01 1/1 Running 0 49m 10.244.1.35 node01 <none> <none>
myapp02 1/1 Running 0 13m 10.244.1.36 node01 <none> <none>
myapp03 1/1 Running 0 10m 10.244.1.37 node01 <none> <none>
myapp04 1/1 Running 0 6s 10.244.2.12 node02 <none> <none>
在同一拓扑域,按照轮询的机制,此时新的 pod 将调度到 node02。
6.4 反亲和性示例
Pod 反亲和性(Pod Anti-Affinity)是用来确保 Kubernetes 中的 Pod 不会与某些特定标签的 Pod 调度到同一节点上的规则。
示例1:软策略
① 创建 yaml
[root@master01 affinity]# vim demo03.yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp10
labels:
app: myapp10
spec:
containers:
- name: myapp10
image: soscscs/myapp:v1
affinity: # 定义了Pod之间的亲和性设置
podAntiAffinity: # Pod之间的反亲和性规则
preferredDuringSchedulingIgnoredDuringExecution: # 软策略
- weight: 100 # 优先级权重为100
podAffinityTerm: # 指定了关于Pod亲和性的条件
labelSelector: # 标签选择器,用于选择具有特定标签的Pod
matchExpressions: # 匹配表达式列表
- key: app # 要匹配的标签键为app
operator: In # 标签的值必须在指定的值列表中
values:
- myapp01 # 标签的值必须为myapp01
topologyKey: fql # 指定拓扑域的键
② 创建 pod
[root@master01 affinity]# kubectl label nodes node02 --overwrite fql=b
[root@master01 affinity]# kubectl apply -f demo03.yaml
[root@master01 affinity]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp01 1/1 Running 0 51s 10.244.1.41 node01 <none> <none>
myapp02 1/1 Running 0 24s 10.244.1.42 node01 <none> <none>
myapp10 1/1 Running 0 4s 10.244.2.13 node02 <none> <none>
如果节点处于 Pod 所在的同一拓扑域且具有键“app”和值“myapp01”的标签, 则该 pod 不应将其调度到该节点上。 (如果 topologyKey 为 fql,则意味着当节点和具有键 “app”和值“myapp01”的 Pod 处于相同的拓扑域,Pod 不能被调度到该节点上。)
示例2:硬策略
① 创建 yaml
[root@master01 affinity]# vim demo4.yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp20
labels:
app: myapp20
spec:
containers:
- name: myapp20
image: soscscs/myapp:v1
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- myapp01
topologyKey: fql
② 创建 pod
[root@master01 affinity]# kubectl label nodes node02 --overwrite fql=a
[root@master01 affinity]# kubectl apply -f demo4.yaml
pod/myapp20 created
[root@master01 affinity]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp01 1/1 Running 0 9m2s 10.244.1.41 node01 <none> <none>
myapp02 1/1 Running 0 8m35s 10.244.1.42 node01 <none> <none>
myapp10 1/1 Running 0 8m15s 10.244.2.13 node02 <none> <none>
myapp20 0/1 Pending 0 5s <none> <none> <none> <none>
由于指定 Pod 所在的 node01 节点上具有带有键 fql 和标签值 a 的标签,node02 也有这个 kgc=a的标签,所以 node01 和 node02 是在一个拓扑域中,反亲和要求新 Pod 与指定 Pod 不在同一拓扑域,所以新 Pod 没有可用的 node 节点,即为 Pending 状态。