网站源码区别,120救护车收费价格表,音乐网站怎么做外链,网站图标素材今天我们来实验 pod 亲和性。官网描述如下#xff1a; 假设有如下三个节点的 K8S 集群#xff1a; k8s31master 是控制节点 k8s31node1、k8s31node2 是工作节点 容器运行时是 containerd 一、镜像准备
1.1、镜像拉取
docker pull tomcat:8.5-jre8-alpine
docker pull nginx…今天我们来实验 pod 亲和性。官网描述如下 假设有如下三个节点的 K8S 集群 k8s31master 是控制节点 k8s31node1、k8s31node2 是工作节点 容器运行时是 containerd 一、镜像准备
1.1、镜像拉取
docker pull tomcat:8.5-jre8-alpine
docker pull nginx:1.14.2 1.2、镜像导出
docker save -o tomcat-8.5-jre8-alpine.tar.gz docker.io/library/tomcat:8.5-jre8-alpine
docker save -o nginx-1.14.2.tar.gz docker.io/library/nginx:1.14.2 1.3、镜像导入工作节点 containerd
# k8s31node1 执行
[rootk8s31node1 ~]# ctr -nk8s.io images import tomcat-8.5-jre8-alpine.tar.gz
[rootk8s31node1 ~]# ctr -nk8s.io images import nginx-1.14.2.tar.gz
[rootk8s31node1 ~]# ctr -nk8s.io images ls|grep tomcat
[rootk8s31node1 ~]# ctr -nk8s.io images ls|grep nginx# k8s31node2 执行
[rootk8s31node2 ~]# ctr -nk8s.io images import tomcat-8.5-jre8-alpine.tar.gz
[rootk8s31node2 ~]# ctr -nk8s.io images import nginx-1.14.2.tar.gz
[rootk8s31node2 ~]# ctr -nk8s.io images ls|grep tomcat
[rootk8s31node2 ~]# ctr -nk8s.io images ls|grep nginx说明: ctr 是 containerd 命令ctr images import导入镜像-nk8s.ioK8S 镜像存储命名空间 1.4、亲和性介绍
亲和性affinity属性位于 pod.spec.affinity它有三种亲和性
kubectl explain pod.spec.affinity 分别是 nodeAffinity节点亲和性、podAffinitypod间亲和性、podAntiAffinitypod间反亲和性它们可以分为两类 节点亲和性功能类似于 nodeSelector 字段但它的表达能力更强并且允许你指定软规则。Pod 间亲和性/反亲和性允许你根据其他 Pod 的标签来约束 Pod。 简单来说 nodeAffinity 定义了 pod 倾向于亲和被调度到哪些节点上。 podAffinity 定义了 pod 倾向于亲和跟哪些 pod 调度在一起。 podAntiAffinity 定义 pod 倾向于不反亲和跟哪些 pod 调度在一起。 二、nodeAffinity节点亲和性
查看帮助文档
kubectl explain pod.spec.affinity.nodeAffinity 节点亲和性概念上类似于 nodeSelector 它使你可以根据节点上的标签来约束 Pod 可以调度到哪些节点上。 节点亲和性有两种 requiredDuringSchedulingIgnoredDuringExecution 调度器只有在规则被满足的时候才能执行调度。此功能类似于 nodeSelector 但其语法表达能力更强。preferredDuringSchedulingIgnoredDuringExecution 调度器会尝试寻找满足对应规则的节点。如果找不到匹配的节点调度器仍然会调度该 Pod。 在上述类型中IgnoredDuringExecution 意味着如果节点标签在 Kubernetes 调度 Pod 后发生了变更Pod 仍将继续运行。 简单来说 required 表示必须有节点满足这个位置定义的亲和性这是个硬性条件硬亲和性。 preferred 表示有节点尽量满足这个位置定义的亲和性这不是一个必须的条件软亲和性。 2.1、required 硬亲和性
查看 requiredDuringSchedulingIgnoredDuringExecution
kubectl explain pod.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution 它有一个必填字段 nodeSelectorTerms。 查看 nodeSelectorTerms
kubectl explain pod.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms 它是 NodeSelectorTerm 数组 NodeSelectorTerm 定义了两种匹配模式 matchExpressions 数组matchFields 数组 2.1.1、matchExpressions matchExpressions它允许你使用表达式来匹配节点的标签。例如你可以使用 In、NotIn、Exists、DoesNotExist、Gt、Lt 等操作符来创建复杂的标签匹配规则。 kubectl explain pod.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms.matchExpressions key标签名称。 operator匹配操作。 values值列表。[] 或 - 形式都可以。 编写资源文件
pod-node-affinity-required-match-expressions-demo.yaml
apiVersion: v1
kind: Pod
metadata:name: pod-node-affinity-required-match-expressions
spec:affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:- matchExpressions:- key: zoneoperator: Invalues:- east- southcontainers:- name: tomcatimage: tomcat:8.5-jre8-alpineimagePullPolicy: IfNotPresentports:- containerPort: 8080 matchExpressions 表达式的意思是寻找具有 label key 为 zone值为 east 或 south 的节点把 pod 绑定上去。 运行并查看
kubectl apply -f pod-node-affinity-required-match-expressions-demo.yaml
kubectl get pod -owide 会发现 pod 并没有被正确调度。 因为我现在工作节点上并没有一个节点有 zone 标签值为 east 或 south。 required 是硬亲和性必须满足表达式pod 才能被正确调度。 查看 pod 日志
kubectl describe pod pod-node-affinity-required-match-expressions 也能发现报 node affinity 错误。 给 k8s31node1 打上标签 zoneeast
kubectl label node k8s31node1 zoneeast
kubectl get node --show-labels 观察 pod 现在可以正常调度了 如果这个时候我们变更 k8s31node1 的标签
kubectl label node k8s31node1 zone-
# zone- 表示删除标签 zone
kubectl get pod -owide 会发现 pod 并没有被驱逐。 2.1.2、matchFields matchFields它允许你根据资源的非标签字段进行匹配例如资源的名称、状态等。 kubectl explain pod.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms.matchFields matchFields 跟 matchExpressions 匹配模式一样。 key标签名称。 operator匹配操作。 values值列表。[] 或 - 形式都可以。 编写资源文件
pod-node-affinity-required-match-fields-demo.yaml
apiVersion: v1
kind: Pod
metadata:name: pod-node-affinity-required-match-fields
spec:affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:- matchFields:- key: metadata.nameoperator: Invalues: [k8s31node2]containers:- name: tomcatimage: tomcat:8.5-jre8-alpineimagePullPolicy: IfNotPresentports:- containerPort: 8080 matchFields 表达式的意思是寻找节点具有 metadata.name 属性且值是 k8s31node2 的节点把 pod 绑定上去。 怎么看 node 节点具有哪些属性 # 以 json 格式或 yaml 格式输出 节点信息
kubectl get node k8s31node2 -o json
kubectl get node k8s31node2 -o yaml 运行并查看
kubectl apply -f pod-node-affinity-required-match-fields-demo.yaml
kubectl get pod -owide 可以发现它被正确调度到 k8s31node2 上。 2.2、preferred 软亲和性
查看 preferredDuringSchedulingIgnoredDuringExecution
kubectl explain pod.spec.affinity.nodeAffinity.preferredDuringSchedulingIgnoredDuringExecution 有两个必填字段 preference偏好。偏好 也是一个 NodeSelectorTerm所以也会有 matchExpressions 和 matchFields。 weight权重。1-100 的数weight 是相对权重权重越高pod 调度的几率越大。 2.2.1、matchExpressions
编写资源文件
pod-node-affinity-preferred-match-expressions-demo.yaml
apiVersion: v1
kind: Pod
metadata: name: pod-node-affinity-preferred-match-expressions
spec:affinity:nodeAffinity:preferredDuringSchedulingIgnoredDuringExecution:- preference:matchExpressions:- key: diskoperator: Invalues: [SSD]weight: 20- preference:matchExpressions:- key: diskoperator: Invalues: [HDD]weight: 10containers:- name: tomcatimage: tomcat:8.5-jre8-alpineimagePullPolicy: IfNotPresentports:- containerPort: 8080 preferred 匹配的意思是 将 pod 节点优先调度到有标签 diskSSD 的节点上。因为 diskSSD 的 weight 数值更大优先级更高。 业务含义是将 pod 节点优先调度到拥有固态硬盘的节点上没有固态硬盘的话调度到拥有机械硬盘的节点上。 运行并查看
kubectl apply -f pod-node-affinity-preferred-match-expressions-demo.yaml
kubectl get pod -owide 虽然我们现在系统上并没有 diskSSD 与 diskHDD 的节点但是 pod 依然可以正常调度。这是因为 preferred 是一种软亲和性即使找不到符合条件的节点调度器 scheduler 依然会调度该 pod。 给节点打标签
# 给 k8s31node1 节点打上 diskHDD
kubectl label node k8s31node1 diskHDD
# 给 k8s31node2 节点打上 diskSSD
kubectl label node k8s31node2 diskSSD
# 查看节点信息
kubectl get node --show-labels 删除原来的 pod 并运行
kubectl delete -f pod-node-affinity-preferred-match-expressions-demo.yaml
kubectl apply -f pod-node-affinity-preferred-match-expressions-demo.yaml
kubectl get pod -owide可以看到 pod 被优先调度到 k8s31node2因为它标签是 diskSSD权重最高。 如果这个时候我们变更 k8s31node2 的标签
kubectl label node k8s31node2 disk-
kubectl get pod -owide 会发现 pod 并没有被驱逐。 matchFields 的情况与 required 类似就不举例了。 2.3、节点亲和性总结 节点亲和性 nodeAffinity 包括 required 和 preferredrequired 是硬亲和性只有条件满足pod 才会被调度。preferred 是软亲和性条件匹配优先按条件调度条件不匹配按默认算法调度。matchExpressions 是按节点标签表达式来进行匹配。matchFields 是按节点属性来进行匹配。无论 required 还是 preferred在 pod 运行期标签变更pod 不会被驱逐。 2.4、还原实验环境
删除 default 命名空间下所有 pod
删除节点所有标签为下一个实验做准备。 三、podAffinitypod间亲和性 podAffinity 定义了 pod 倾向于亲和跟哪些 pod 调度在同一个位置。 查看帮助文档
kubectl explain pod.spec.affinity.podAffinity 与节点亲和性类似Pod 的亲和性与反亲和性也有两种类型 requiredDuringSchedulingIgnoredDuringExecutionpreferredDuringSchedulingIgnoredDuringExecution 例如你可以使用 requiredDuringSchedulingIgnoredDuringExecution 亲和性来告诉调度器将两个服务的 Pod 放到同一个云提供商可用区内因为它们彼此之间通信非常频繁。 类似地你可以使用 preferredDuringSchedulingIgnoredDuringExecution 反亲和性来将同一服务的多个 Pod 分布到多个云提供商可用区中。 3.1、required 硬亲和性
查看 requiredDuringSchedulingIgnoredDuringExecution
kubectl explain pod.spec.affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution 它是 PodAffinityTerm 数组。 PodAffinityTerm 它有三个比较重要的字段 toplogyKey拓扑键必填。我们在定义 pod 间亲和性时有一个前提就是 B pod 想调度到跟 A pod 同一个位置那么怎么定义这个位置就是以这个字段来定义的。其取值是系统用来标示域的节点标签键。也就是说不同节点具有相同标签 key且 key 所对应的 value 也相同则它们被定义为同一个位置。 假设有如下服务器集群在可用区A中有节点 node1、node2它们拥有相同的节点标签zoneA则 node1 与 node2 被定义为同一个位置。node3 因为拥有不同的节点标签zoneB所以 node3 被视为不同位置。 toplogyKey 它是一个拓扑的概念同一个机架、可用区、地域里面所有节点都可以被 K8S 视为同一个位置而被统一调度。 labelSelector标签选择器。通过 labelSelector 选取一组能作为亲和对象的已存在的 pod 资源。它定义了两种匹配模式 matchExpressions []LabelSelectorRequirementmatchLabels map[string]string namespaces名称空间。pod 在 Kubernetes 中是名称空间作用域的对象因此 pod 的标签也隐式地具有名称空间属性。 针对 pod 标签的所有 标签选择器 都要指定名称空间Kubernetes 会在指定的名称空间内寻找标签。 如果不指定 namespaces那么 标签选择器 就是在当前要创建的 pod 的名称空间里查找符合条件的一组 pod。 3.1.1、matchExpressions matchExpressions它允许你使用表达式来匹配 Pod 的标签。例如你可以使用 In、NotIn、Exists、DoesNotExist 等操作符来创建复杂的标签匹配规则。 kubectl explain pod.spec.affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution.labelSelector.matchExpressions key标签名称。 operator匹配操作。 values值列表。[] 或 - 形式都可以。 实验准备
使用 kubeadm join 往集群中加入一个新的工作节点 k8s31node3: 镜像准备
# 将 tomcat、nginx 镜像也导入到 k8s31node3
# k8s31node3 执行
[rootk8s31node3 ~]# ctr -nk8s.io images import tomcat-8.5-jre8-alpine.tar.gz
[rootk8s31node3 ~]# ctr -nk8s.io images import nginx-1.14.2.tar.gz
[rootk8s31node3 ~]# ctr -nk8s.io images ls|grep tomcat
[rootk8s31node3 ~]# ctr -nk8s.io images ls|grep nginx 资源文件编写
假设我们现在有两个 podnginx 跟 tomcatnginx 反向代理 tomcat它们之间要频繁通信所以我们希望 pod-nginx 跟 pod-tomcat 能调度到同一个可用区内。
pod-pod-affinity-required-match-expressions-tomcat.yaml
apiVersion: v1
kind: Pod
metadata:name: tomcatlabels:app: tomcat
spec:containers:- name: tomcatimage: tomcat:8.5-jre8-alpineimagePullPolicy: IfNotPresentports:- containerPort: 8080
运行并查看
kubectl apply -f pod-pod-affinity-required-match-expressions-tomcat.yaml
kubectl get pod -owide tomcat 被调度到 k8s31node3 节点上。 资源文件编写
pod-pod-affinity-required-match-expressions-nginx.yaml
apiVersion: v1
kind: Pod
metadata:name: nginx
spec:affinity:podAffinity:requiredDuringSchedulingIgnoredDuringExecution:- topologyKey: zonelabelSelector:matchExpressions:- {key: app, operator: In, values: [tomcat]}containers:- name: nginximage: nginx:1.14.2imagePullPolicy: IfNotPresentports:- containerPort: 80
运行并查看
kubectl apply -f pod-pod-affinity-required-match-expressions-nginx.yaml
kubectl get pod -owide 发现 nginx 无法被调度。 查看 pod 日志 kubectl describe pod nginx 报 pod 亲和性不符合。 原因是我们现在所有节点上并没有定义 topologyKeyzone 这个键而 required 是属于硬亲和性在节点调度期找不到符合调度规则的节点系统不会对 pod 进行调度。 给节点打标签
kubectl label node k8s31node1 zoneA
kubectl label node k8s31node2 zoneB
kubectl label node k8s31node3 zoneB
kubectl get pod -owide 可以看到 nginx 被调度到 tomcat 所在的节点 k8s31node3 上了。 倘若这个时候我们起一个 nginx
pod-pod-affinity-required-match-expressions-nginx2.yaml
就只是把上一个 nginx.yaml 改了一下 metadata.name 为 nginx2 而已。
apiVersion: v1
kind: Pod
metadata:name: nginx2
spec:affinity:podAffinity:requiredDuringSchedulingIgnoredDuringExecution:- topologyKey: zonelabelSelector:matchExpressions:- {key: app, operator: In, values: [tomcat]}containers:- name: nginximage: nginx:1.14.2imagePullPolicy: IfNotPresentports:- containerPort: 80
kubectl apply -f pod-pod-affinity-required-match-expressions-nginx2.yaml
kubectl get pod -owide 会发现 nginx2 被调度到 k8s31node2 上了。 分析
整个的部署图如下 tomcat 首先被调度到 node3这个过程是随机的scheduler 调度器根据自己内部的调度算法来决定的。nginx 被调度时因为 nginx 跟 tomcat podAffinity所以它要被调度到跟 tomcat 具有相同 topologyKey 的节点上这个时候 node3 跟 node2 都满足要求node1 因为 topologyKey 的值是 A所以不满足要求scheduler 调度器觉得 node3 这个时候的负载不高所以也把 nginx 调度到 node3 上。nginx2 被调度时走 nginx 一样的逻辑所以 node3 跟 node2 都满足要求但此时 node3 负载已经很高了跑着两个 pod所以 scheduler 调度器决定将 nginx2 调度到 node2。 还原实验环境
删除 nginx 跟 nginx2 以便进行下面的实验。
kubectl delete pod nginx
kubectl delete pod nginx2 3.1.2、matchLabels matchLabels 的匹配方式相对于 matchExpressions 更简单它是以 键值对 的方式进行匹配的。 kubectl explain pod.spec.affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution.labelSelector.matchLabels 编写资源文件
pod-pod-affinity-required-match-labels-nginx.yaml
apiVersion: v1
kind: Pod
metadata:name: nginx
spec:affinity:podAffinity:requiredDuringSchedulingIgnoredDuringExecution:- topologyKey: zonelabelSelector:matchLabels:app: tomcatcontainers:- name: nginximage: nginx:1.14.2imagePullPolicy: IfNotPresentports:- containerPort: 80 pod-pod-affinity-required-match-labels-nginx2.yaml
俩个文件之间的差异只在 metadata.name
apiVersion: v1
kind: Pod
metadata:name: nginx2
spec:affinity:podAffinity:requiredDuringSchedulingIgnoredDuringExecution:- topologyKey: zonelabelSelector:matchLabels:app: tomcatcontainers:- name: nginximage: nginx:1.14.2imagePullPolicy: IfNotPresentports:- containerPort: 80 运行并查看
kubectl apply -f pod-pod-affinity-required-match-labels-nginx.yaml
kubectl apply -f pod-pod-affinity-required-match-labels-nginx2.yaml
kubectl get pod -owide 可以看到跟 matchExpressions 是一样的效果。 节点标签变更
倘如我们这个时候将所有节点的 zone 标签删除看看会有什么效果。
kubectl label node k8s31node1 zone-
kubectl label node k8s31node2 zone-
kubectl label node k8s31node3 zone-
kubectl get pod -owide 可以看到 pod 并不会被驱逐。 还原实验环境 删除 tomcat、nginx 跟 nginx2 以便进行下面的实验。
kubectl delete pod tomcat
kubectl delete pod nginx
kubectl delete pod nginx2 3.2、preferred 软亲和性
查看 preferredDuringSchedulingIgnoredDuringExecution
kubectl explain pod.spec.affinity.podAffinity.preferredDuringSchedulingIgnoredDuringExecution 它是 WeightedPodAffinityTerm 数组。 WeightedPodAffinityTerm 它有两个必填字段 podAffinityTermPodAffinityTerm 对象。它跟上面 required 是一模一样的。所以也必然有 toplogyKey、labelSelector、namespaces。 weight权重。1-100 的数weight 是相对权重权重越高pod 调度的几率越大。 假设现在有如下部署图 node1、node2、node3 分别有标签 zoneA、zoneB、zoneC表示它们分别位于可用区 A B C。 node1、node2、node3 上分别运行着 pod tomcat1、tomcat2、tomcat3。 tomcat1、tomcat2、tomcat3 分别有标签 apptomcat1、apptomcat2、apptomcat3它们的权重分别是 10、30、20。 现在有一个新的 pod-nginx加入进来我们看看 K8S 是如何调度的-- 编写 tomcat 配置文件
pod-pod-affinity-preferred-match-expressions-tomcat1.yaml
apiVersion: v1
kind: Pod
metadata:name: tomcat1labels:app: tomcat1
spec:nodeName: k8s31node1containers:- name: tomcatimage: tomcat:8.5-jre8-alpineimagePullPolicy: IfNotPresentports:- containerPort: 8080 nodeName 指定它运行在 node1 节点上。 pod-pod-affinity-preferred-match-expressions-tomcat2.yaml
apiVersion: v1
kind: Pod
metadata:name: tomcat2labels:app: tomcat2
spec:nodeName: k8s31node2containers:- name: tomcatimage: tomcat:8.5-jre8-alpineimagePullPolicy: IfNotPresentports:- containerPort: 8080 nodeName 指定它运行在 node2 节点上。 pod-pod-affinity-preferred-match-expressions-tomcat3.yaml
apiVersion: v1
kind: Pod
metadata:name: tomcat3labels:app: tomcat3
spec:nodeName: k8s31node3containers:- name: tomcatimage: tomcat:8.5-jre8-alpineimagePullPolicy: IfNotPresentports:- containerPort: 8080 nodeName 指定它运行在 node3 节点上。 启动 tomcat
kubectl apply -f pod-pod-affinity-preferred-match-expressions-tomcat1.yaml
kubectl apply -f pod-pod-affinity-preferred-match-expressions-tomcat2.yaml
kubectl apply -f pod-pod-affinity-preferred-match-expressions-tomcat3.yaml
kubectl get pod -owide --show-labels 给节点打标签
kubectl label node k8s31node1 zoneA
kubectl label node k8s31node2 zoneB
kubectl label node k8s31node3 zoneC
kubectl get node --show-labels 编写 nginx 配置文件
pod-pod-affinity-preferred-match-expressions-nginx.yaml
apiVersion: v1
kind: Pod
metadata:name: nginx
spec:affinity:podAffinity:preferredDuringSchedulingIgnoredDuringExecution:- weight: 10podAffinityTerm: topologyKey: zonelabelSelector:matchExpressions:- {key: app, operator: In, values: [tomcat1]}- weight: 30podAffinityTerm:topologyKey: zonelabelSelector:matchExpressions:- {key: app, operator: In, values: [tomcat2]}- weight: 20podAffinityTerm:topologyKey: zonelabelSelector:matchExpressions:- {key: app, operator: In, values: [tomcat3]}containers:- name: nginximage: nginx:1.14.2imagePullPolicy: IfNotPresentports:- containerPort: 80 apptomcat2 的权重最高所以 nginx 需要被调度到跟 tomcat2 相同 zone 下的服务器上因为该 zone 只有一个 node2所以 nginx 被调度到 node2 上。 删掉 nginx并修改所有 pod label
kubectl delete pod nginx
kubectl label pod tomcat1 apptomcat --overwritetrue
kubectl label pod tomcat2 apptomcat --overwritetrue
kubectl label pod tomcat3 apptomcat --overwritetrue
# --overwritetrue 表示覆盖原来 label 的值
kubectl get pod -owide --show-labels 重新运行 nginx我们看看会发生什么
kubectl apply -f pod-pod-affinity-preferred-match-expressions-nginx.yaml
kubectl get pod -owide --show-labels 现在没有一个 pod 的标签符合 标签选择器 的规则但是 nginx 还是能被正常的调度因为 preferred 是一种软亲和性。标签选择器的规则不匹配scheduler 调度器会根据内部的算法选择合适的节点来绑定pod。 3.3、pod 间亲和性总结 pod 间亲和性 podAffinity 包括 required 和 preferredrequired 是硬亲和性只有条件满足pod 才会被调度。preferred 是软亲和性条件匹配优先按条件调度条件不匹配按默认算法调度。matchExpressions 是按 pod 标签表达式来进行匹配。matchLabels 也是按 pod 标签来进行匹配不过它是以键值对的方式来表示匹配规则。无论 required 还是 preferred在 pod 运行期不管是 节点 标签变更还是被亲和的 pod 标签变更pod 都不会被驱逐。podAffinity 中有一个很重要的概念是 toplogyKey理解它对于理解 pod 调度非常重要。 3.4、还原实验环境
删除 nginx tomcat1 tomcat2 tomcat3
kubectl delete pod nginx tomcat1 tomcat2 tomcat3 --force --grace-period0 保留 node1、node2、node3 的 zone label 四、podAntiAffinitypod间反亲和性 podAntiAffinity 定义了 pod 倾向于不跟哪些 pod 调度在同一个位置。 查看帮助文档
kubectl explain pod.spec.affinity.podAntiAffinity 可以看到它跟 podAffinity 的定义几乎是一摸一样的。 可以猜到K8S 内部在进行调度的时候应该是采用一种取反的操作。 筛选出不想亲和的 pod 所具有的 toplogyKey然后在剩下的 toplogyKey 里选择节点进行绑定。 下面是 podAffinity 的定义。 4.1、required 硬亲和性 这一节我们只演示 required其他大同小异。 假设现在有如下部署图 node1、node2、node3 分别有标签 zoneA、zoneB、zoneC表示它们分别位于可用区 A B C。 node3 运行着 tomcat1它有标签 apptomcat。 现在再来一个 tomcat2我们不希望它跟 tomcat1 在同一个可用区下。 在实际业务中相同的可用区往往意味着同一个机房而部署同一个应用往往不希望它们在同一个节点、或者同一个可用区下因为这样容易导致 单点故障。从而让整个服务不可用。 我们看看这在 K8S 中要怎么实现-- 编写 tomcat1 资源文件
pod-pod-antiaffinity-required-match-expressions-tomcat1.yaml
apiVersion: v1
kind: Pod
metadata:name: tomcat1labels:app: tomcat
spec:nodeName: k8s31node3containers:- name: tomcatimage: tomcat:8.5-jre8-alpineimagePullPolicy: IfNotPresentports:- containerPort: 8080 nodeName 指定它运行在 node3 节点上。 编写 tomcat2 资源文件
pod-pod-antiaffinity-required-match-expressions-tomcat2.yaml
apiVersion: v1
kind: Pod
metadata:name: tomcat2labels:app: tomcat
spec:affinity:podAntiAffinity:requiredDuringSchedulingIgnoredDuringExecution:- topologyKey: zonelabelSelector:matchExpressions:- {key: app, operator: In, values: [tomcat]}containers:- name: tomcatimage: tomcat:8.5-jre8-alpineimagePullPolicy: IfNotPresentports:- containerPort: 8080 运行并查看
kubectl apply -f pod-pod-antiaffinity-required-match-expressions-tomcat1.yaml
kubectl apply -f pod-pod-antiaffinity-required-match-expressions-tomcat2.yaml
kubectl get pod -owide --show-labels 可以看到 tomcat2 被调度到跟 tomcat1 不同的 zone 的服务器上node1、node2 都可以。