1.简介:
Pod 亲和性(podAffinity)主要解决 Pod 可以和哪些 Pod 部署在同一个拓扑域中的问题(其中拓扑域用主机标签实现,可以是单个主机,也可以是多个主机组成的 cluster、zone 等等),而 Pod 反亲和性主要是解决 Pod 不能和哪些 Pod 部署在同一个拓扑域中的问题,它们都是处理的 Pod 与 Pod 之间的关系,比如一个 Pod 在一个节点上了,那么我这个也得在这个节点,或者你这个 Pod 在节点上了,那么我就不想和你待在同一个节点上。
由于我们这里只有一个集群,并没有区域或者机房的概念,所以我们这里直接使用主机名来作为拓扑域,把 Pod 创建在同一个主机上面。
apiVersion: apps/v1
kind: Deployment
metadata:
name: pod-affinity
labels:
app: pod-affinity
spec:
replicas: 3
selector:
matchLabels:
app: pod-affinity
template:
metadata:
labels:
app: pod-affinity
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
name: nginxweb
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution: # 硬策略
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- busybox-pod
topologyKey: kubernetes.io/hostname
上面这个例子中的 Pod 需要调度到某个指定的节点上,并且该节点上运行了一个带有 app=busybox-pod 标签的 Pod。我们可以查看有标签 app=busybox-pod 的 pod 列表:
[root@k8s-master01 ~]# kubectl get pod -l app=busybox-pod -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
test-busybox 1/1 Running 0 10m 172.27.14.239 k8s-node02 <none> <none>
我们看到这个 Pod 运行在了 k8s-node2 的节点上面,所以按照上面的亲和性来说,上面我们部署的3个 Pod 副本也应该运行在 k8s-node2 节点上:
[root@k8s-master01 ~]# kubectl apply -f pod-affinity-demo.yaml
deployment.apps/pod-affinity configured
[root@k8s-master01 ~]# kubectl get pod -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
busybox 1/1 Running 263 11d 172.17.125.9 k8s-node01 <none> <none>
nginx-68db656dd8-mprnc 1/1 Running 0 65m 172.17.125.13 k8s-node01 <none> <none>
nginx-68db656dd8-znwgp 1/1 Running 1 11d 172.18.195.11 k8s-master03 <none> <none>
pod-affinity-6967f7785-94zwr 1/1 Running 0 15m 172.27.14.242 k8s-node02 <none> <none>
pod-affinity-6967f7785-9gzqf 1/1 Running 0 24s 172.27.14.244 k8s-node02 <none> <none>
pod-affinity-6967f7785-rlqkl 1/1 Running 0 15m 172.27.14.241 k8s-node02 <none> <none>
pod-affinity-6967f7785-xlhkv 1/1 Running 0 15m 172.27.14.240 k8s-node02 <none> <none>
test-busybox 1/1 Running 0 13m 172.27.14.239 k8s-node02 <none> <none>
web 2/2 Running 0 3d19h 172.18.195.14 k8s-master03 <none> <none>
如果我们把上面的 test-busybox 和 pod-affinity 这个 Deployment 都删除,然后重新创建 pod-affinity 这个资源,看看能不能正常调度呢:
[root@k8s-master01 ~]# kubectl delete -f node-selector-demo.yaml
pod "test-busybox" deleted
[root@k8s-master01 ~]# kubectl delete -f pod-affinity-demo.yaml
deployment.apps "pod-affinity" deleted
[root@k8s-master01 ~]# kubectl apply -f pod-affinity-demo.yaml
deployment.apps/pod-affinity created
[root@k8s-master01 ~]# kubectl get pods -o wide -l app=pod-affinity
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-affinity-587f9b5b58-bbfgr 0/1 Pending 0 18s <none> <none> <none> <none>
pod-affinity-587f9b5b58-lwc8n 0/1 Pending 0 18s <none> <none> <none> <none>
pod-affinity-587f9b5b58-pc7ql 0/1 Pending 0 18s <none> <none> <none> <none>
我们可以看到都处于 Pending 状态了,这是因为现在没有一个节点上面拥有 app=busybox-pod 这个标签的 Pod,而上面我们的调度使用的是硬策略,所以就没办法进行调度了,大家可以去尝试下重新将 test-busybox 这个 Pod 调度到其他节点上,观察下上面的3个副本会不会也被调度到对应的节点上去。
我们这个地方使用的是 kubernetes.io/hostname 这个拓扑域,意思就是我们当前调度的 Pod 要和目标的 Pod 处于同一个主机上面,因为要处于同一个拓扑域下面,为了说明这个问题,我们把拓扑域改成 beta.kubernetes.io/os,同样的我们当前调度的 Pod 要和目标的 Pod 处于同一个拓扑域中,目标的 Pod 是拥有 beta.kubernetes.io/os=linux 的标签,而我们这里所有节点都有这样的标签,这也就意味着我们所有节点都在同一个拓扑域中,所以我们这里的 Pod 可以被调度到任何一个节点,重新运行上面的 app=busybox-pod 的 Pod,然后再更新下我们这里的资源对象:
[root@k8s-master01 ~]# kubectl get pod -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
busybox 1/1 Running 264 11d 172.17.125.9 k8s-node01 <none> <none>
nginx-68db656dd8-mprnc 1/1 Running 0 69m 172.17.125.13 k8s-node01 <none> <none>
nginx-68db656dd8-znwgp 1/1 Running 1 11d 172.18.195.11 k8s-master03 <none> <none>
pod-affinity-5f77cbd686-hpc4n 1/1 Running 0 60s 172.25.244.215 k8s-master01 <none> <none>
pod-affinity-5f77cbd686-tr5lq 1/1 Running 0 41s 172.25.92.101 k8s-master02 <none> <none>
pod-affinity-5f77cbd686-zw4ql 1/1 Running 0 60s 172.17.125.15 k8s-node01 <none> <none>
test-busybox 1/1 Running 0 17m 172.27.14.239 k8s-node02 <none> <none>
web 2/2 Running 0 3d19h 172.18.195.14 k8s-master03 <none> <none>
可以看到现在是分别运行在3个节点下面的,因为他们都属于 beta.kubernetes.io/os 这个拓扑域。