当前位置: 首页 > news >正文

16、Kubernetes核心技术 - 节点选择器、亲和和反亲和

目录

一、概述

二、节点名称 - nodeName

二、节点选择器 - nodeSelector

三、节点亲和性和反亲和性

3.1、亲和性和反亲和性

3.2、节点硬亲和性

3.3、节点软亲和性

3.4、节点反亲和性

3.5、注意点

四、Pod亲和性和反亲和性

4.1、亲和性和反亲和性

4.2、Pod亲和性/反亲和性

五、总结


一、概述

在 Kubernetes 中 Pod 的调度都是由kube-scheduler组件来完成的,整个调度过程都是自动完成的,也就是说我们并不能确定 Pod 最终被调度到了哪个节点上。而在实际环境中,可能需要将Pod调度到指定的节点上。例如可能会遇到如下一些场景:

  1. 机器学习相关应用希望调度到有 GPU 硬件的节点上;
  2. 数据库应用需要调度到有 SSD 的节点上;
  3. 为了保证应用的高可用性,需要将同一应用的不同Pod分散在不同的节点上,以防节点所在机器出现宕机等情况导致Pod重建;
  4. 两个不同的应用需要调度到同一个节点上;

为了满足如上一些场景,k8s提供了一些功能帮助我们干预Pod节点的调度,这些功能包括:指定节点名称、节点选择器、节点亲和性/反亲和性、Pod亲和性和反亲和性。

二、节点名称 - nodeName

nodeName即节点名称,如果对应Pod资源清单中,用户明确定义了nodeName字段,则表示不使用调度器调度,此时调度器也不会调度此类Pod资源,原因是对应nodeName非空,调度器认为该Pod是已经调度过了,nodeName是用户手动将Pod绑定至某个节点上运行

$ kubectl get nodes
NAME           STATUS   ROLES           AGE   VERSION
controlplane   Ready    control-plane   25d   v1.26.0
node01         Ready    <none>          25d   v1.26.0

创建Pod资源清单。vim node-name-pod.yaml

apiVersion: apps/v1
kind: Deployment
metadata:name: nginx
spec:replicas: 1selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:nodeName: node01   # 指定pod调度到node01节点上containers:- name: nginximage: nginx

创建并查看Pod:

$ kubectl apply -f node-name-pod.yaml 
deployment.apps/nginx created$ kubectl get pod -o wide
NAME                     READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
nginx-86dcc5bdc6-wwrzx   1/1     Running   0          26s   192.168.1.3   node01   <none>           <none>

可以看到,Pod确实是落在了node01节点上,使用 nodeName 来选择节点的方式有一些局限性:

  • 如果所指代的节点不存在,则 Pod 无法运行,而且在某些情况下可能会被自动删除。
  • 如果所指代的节点无法提供用来运行 Pod 所需的资源,Pod 会失败, 而其失败原因中会给出是否因为内存或 CPU 不足而造成无法运行。
  • 在云环境中的节点名称并不总是可预测的,也不总是稳定的。

所以,生产环境一般不使用nodeName。

二、节点选择器 - nodeSelector

nodeSelector即节点选择器,它是将Pod调度到包含指定标签的node上面,只有符合对应node标签选择器定义的标签的node才能运行对应Pod,如果没有节点满足节点选择器的规则,则对应的Pod就会一直处于Pending状态。

下面我们通过一个简单的案例说明nodeSelector是如何使用的。首先创建Pod资源清单:

vim node-selector-pod.yaml

apiVersion: apps/v1
kind: Deployment
metadata:name: nginx
spec:replicas: 1selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:containers:- name: nginximage: nginxnodeSelector:role: master   # 选择具有role=master标签的那些node

我们指定Pod需要调度到具有role=master标签的那些节点上。创建Pod:

# 查看节点存在的标签
$ kubectl get nodes --show-labels
NAME           STATUS   ROLES           AGE   VERSION   LABELS
controlplane   Ready    control-plane   25d   v1.26.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=controlplane,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node.kubernetes.io/exclude-from-external-load-balancers=
node01         Ready    <none>          25d   v1.26.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=node01,kubernetes.io/os=linux$ kubectl apply -f node-selector-pod.yaml 
deployment.apps/nginx created$ kubectl get pod 
NAME                    READY   STATUS    RESTARTS   AGE
nginx-cc84c8d74-79dqx   0/1     Pending   0          11s

我们可以看到Pod的状态是Pending,由于目前并不存在role=master标签的node节点,所以Pod是调度不上去的,我们可以查看Pod的事件:  

# 查看pod的详细描述信息
$ kubectl describe pod nginx-cc84c8d74-79dqx
Name:             nginx-cc84c8d74-79dqx
Namespace:        default
Priority:         0
Service Account:  default
Node:             <none>
Labels:           app=nginxpod-template-hash=cc84c8d74
Annotations:      <none>
Status:           Pending
IP:               
IPs:              <none>
Controlled By:    ReplicaSet/nginx-cc84c8d74
Containers:nginx:Image:        nginxPort:         <none>Host Port:    <none>Environment:  <none>Mounts:/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-rk2mj (ro)
Conditions:Type           StatusPodScheduled   False 
Volumes:kube-api-access-rk2mj:Type:                    Projected (a volume that contains injected data from multiple sources)TokenExpirationSeconds:  3607ConfigMapName:           kube-root-ca.crtConfigMapOptional:       <nil>DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              role=master
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300snode.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:Type     Reason            Age    From               Message----     ------            ----   ----               -------Warning  FailedScheduling  2m25s  default-scheduler  0/2 nodes are available: 2 node(s) didn't match Pod's node affinity/selector. preemption: 0/2 nodes are available: 2 Preemption is not helpful for scheduling..

可以看到,最下边的FailedScheduling表示的就是调度失败,原因是当前没有节点满足nodeSelector或者nodeAffinity(节点亲和性)的规则。那么下面我们给node01节点添加role=master标签:

# 给node01节点打上role=master的标签
$ kubectl label nodes node01 role=master
node/node01 labeled# 查看node01节点的标签
$ kubectl get node/node01 --show-labels
NAME     STATUS   ROLES    AGE   VERSION   LABELS
node01   Ready    <none>   25d   v1.26.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=node01,kubernetes.io/os=linux,role=master

打完标签后我们再次查看Pod的状态以及事件:

$ kubectl get pod
NAME                    READY   STATUS    RESTARTS   AGE
nginx-cc84c8d74-79dqx   1/1     Running   0          4m45s

此时我们可以看到,Pod已经成功被调度到node01节点上了,这就是nodeSelector节点选择器的作用。

注意,nodeSelector指定的条件是必须满足的,如果没有找到满足条件的节点,那么这个Pod就会一直处于Pending状态,直到能找到满足nodeSelector条件的节点,才能调度上。

三、节点亲和性和反亲和性

3.1、亲和性和反亲和性

k8s目前支持的节点亲和性有两种:

  • 1、requiredDuringSchedulingIgnoredDuringExecution(硬亲和性)

硬亲和性表示指定的条件必须满足,如果不满足,那就调度不上,比较强硬,硬亲和性更多地表示Pod必须被调度到满足条件的节点上。

  • 2)、preferredDuringSchedulingIgnoredDuringExecution(软亲和性)

软亲和性表示指定的条件尽量满足,不保证总是满足,也就是说能满足最好,不满足那也不影响调度,软亲和性更多地表示希望Pod被调度到满足条件的节点上。

注意,处于正在运行中的Pod,如果节点标签发送变化的话,并不会驱逐因节点标签变更导致不再符合亲和/反亲和条件的Pod。

在k8s中,节点的亲和性通过Pod Spec的affinity字段下的nodeAffinity字段进行指定,操作符支持In、NotIn、Exists、DoesNotExist、Gt、Lt,反亲和性通过NotIn和DoesNotExist实现。操作符说明如下:

  • In:判断对应标签的值是否在某个集合中;
  • NotIn:判断对应标签的值是否不在某个集合中;
  • Gt:判断标签值是否大于某个值,用于字符串比较;
  • Lt:判断标签值是否小于某个值,用于字符串比较;
  • Exists:判断判断某个标签的key是否存在;
  • DoesNotExist:某个标签的key是否不存在;

3.2、节点硬亲和性

我们可以使用节点硬亲和性来实现前面nodeSelector节点选择器相同的功能,首先我们定义Pod的资源清单:

vim hard-node-affinity.yaml

apiVersion: apps/v1
kind: Deployment
metadata:name: nginx
spec:replicas: 1selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:affinity:nodeAffinity:  # 节点亲和性requiredDuringSchedulingIgnoredDuringExecution:  # 硬亲和性nodeSelectorTerms:  # node节点选择的条件:必须包含role=master的label- matchExpressions:- key: roleoperator: Invalues:- mastercontainers:- name: nginximage: nginx

我们通过requiredDuringSchedulingIgnoredDuringExecution下的nodeSelectorTerms属性指定了Pod的硬亲和性是必须满足role=master的那些node节点。

创建并查看Pod:

$ kubectl apply -f hard-node-affinity.yaml 
deployment.apps/nginx created$ kubectl get pod 
NAME                     READY   STATUS    RESTARTS   AGE
nginx-798c8486f6-rft9w   0/1     Pending   0          7s$ kubectl describe pod nginx-798c8486f6-rft9w
Name:             nginx-798c8486f6-rft9w
Namespace:        default
Priority:         0
Service Account:  default
Node:             <none>
Labels:           app=nginxpod-template-hash=798c8486f6
Annotations:      <none>
Status:           Pending
IP:               
IPs:              <none>
Controlled By:    ReplicaSet/nginx-798c8486f6
Containers:nginx:Image:        nginxPort:         <none>Host Port:    <none>Environment:  <none>Mounts:/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-nxwvb (ro)
Conditions:Type           StatusPodScheduled   False 
Volumes:kube-api-access-nxwvb:Type:                    Projected (a volume that contains injected data from multiple sources)TokenExpirationSeconds:  3607ConfigMapName:           kube-root-ca.crtConfigMapOptional:       <nil>DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300snode.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:Type     Reason            Age   From               Message----     ------            ----  ----               -------Warning  FailedScheduling  20s   default-scheduler  0/2 nodes are available: 2 node(s) didn't match Pod's node affinity/selector. preemption: 0/2 nodes are available: 2 Preemption is not helpful for scheduling..# 当前没有node节点存在role=master的标签
$ kubectl get node --show-labels
NAME           STATUS   ROLES           AGE   VERSION   LABELS
controlplane   Ready    control-plane   25d   v1.26.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=controlplane,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node.kubernetes.io/exclude-from-external-load-balancers=
node01         Ready    <none>          25d   v1.26.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=node01,kubernetes.io/os=linux

可以看到,Pod又是处于Pending状态,原因还是因为没有找到role=master的node节点,所以调度不上。同样的,我们给node01节点打上role=master的标签,再次查看Pod的状态:

$ kubectl label nodes node01 role=master
node/node01 labeled$ kubectl get node node01 --show-labels
NAME     STATUS   ROLES    AGE   VERSION   LABELS
node01   Ready    <none>   25d   v1.26.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=node01,kubernetes.io/os=linux,role=master$ kubectl get pod 
NAME                     READY   STATUS    RESTARTS   AGE
nginx-798c8486f6-rft9w   1/1     Running   0          3m29s$ kubectl describe pod nginx-798c8486f6-rft9w
Name:             nginx-798c8486f6-rft9w
Namespace:        default
Priority:         0
Service Account:  default
Node:             node01/172.30.2.2
Start Time:       Tue, 17 Jan 2023 01:51:48 +0000
Labels:           app=nginxpod-template-hash=798c8486f6
Annotations:      cni.projectcalico.org/containerID: c13cf68653c462145216fbf2cd94c8b6e7ce55b0c9969eeb21ce153d94ad24afcni.projectcalico.org/podIP: 192.168.1.3/32cni.projectcalico.org/podIPs: 192.168.1.3/32
Status:           Running
IP:               192.168.1.3
IPs:IP:           192.168.1.3
Controlled By:  ReplicaSet/nginx-798c8486f6
Containers:nginx:Container ID:   containerd://7ce8f5d9048b2272ac51c4358b2c142bfae28ca7144b1958836223f9b0857711Image:          nginxImage ID:       docker.io/library/nginx@sha256:b8f2383a95879e1ae064940d9a200f67a6c79e710ed82ac42263397367e7cc4ePort:           <none>Host Port:      <none>State:          RunningStarted:      Tue, 17 Jan 2023 01:51:54 +0000Ready:          TrueRestart Count:  0Environment:    <none>Mounts:/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-nxwvb (ro)
Conditions:Type              StatusInitialized       True Ready             True ContainersReady   True PodScheduled      True 
Volumes:kube-api-access-nxwvb:Type:                    Projected (a volume that contains injected data from multiple sources)TokenExpirationSeconds:  3607ConfigMapName:           kube-root-ca.crtConfigMapOptional:       <nil>DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300snode.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:Type     Reason            Age    From               Message----     ------            ----   ----               -------Warning  FailedScheduling  3m37s  default-scheduler  0/2 nodes are available: 2 node(s) didn't match Pod's node affinity/selector. preemption: 0/2 nodes are available: 2 Preemption is not helpful for scheduling..Normal   Scheduled         27s    default-scheduler  Successfully assigned default/nginx-798c8486f6-rft9w to node01Normal   Pulling           26s    kubelet            Pulling image "nginx"Normal   Pulled            21s    kubelet            Successfully pulled image "nginx" in 5.200031738s (5.200036683s including waiting)Normal   Created           21s    kubelet            Created container nginxNormal   Started           21s    kubelet            Started container nginx

当我们给node01添加完role=master标签后,Pod立马就被调度上去了,这就是requiredDuringSchedulingIgnoredDuringExecution硬亲和性,必须找到满足条件的node,Pod才会被调度上。

3.3、节点软亲和性

首先我们定义Pod的资源清单:vim soft-node-affinity.yaml

apiVersion: apps/v1
kind: Deployment
metadata:name: nginx
spec:replicas: 1selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:affinity:nodeAffinity: # 节点亲和性preferredDuringSchedulingIgnoredDuringExecution:    # 软亲和- weight: 1   # 权重,多个条件权重加起来最高的node被调度的优先级越高preference:matchExpressions:- key: roleoperator: Invalues:- slavecontainers:- name: nginximage: nginx

我们通过nodeAffinity下的preferredDuringSchedulingIgnoredDuringExecution属性指定了Pod调度的软亲和条件就是尽量去找那些包含role=slave标签的节点,并通过weight指定权重为1,weight表示的是计算权重,当我们指定了多个条件的时候,多个条件权重加起来分数最高的node被调度的优先级最高

创建并查看Pod:

$ kubectl get nodes --show-labels
NAME           STATUS   ROLES           AGE   VERSION   LABELS
controlplane   Ready    control-plane   25d   v1.26.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=controlplane,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node.kubernetes.io/exclude-from-external-load-balancers=
node01         Ready    <none>          25d   v1.26.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=node01,kubernetes.io/os=linux,role=master$ vim soft-node-affinity.yaml 
$ kubectl apply -f soft-node-affinity.yaml 
deployment.apps/nginx created$ kubectl get pod 
NAME                     READY   STATUS    RESTARTS   AGE
nginx-649b779d98-cd9rd   1/1     Running   0          6s$ kubectl describe pod nginx-649b779d98-cd9rd
Name:             nginx-649b779d98-cd9rd
Namespace:        default
Priority:         0
Service Account:  default
Node:             node01/172.30.2.2
Start Time:       Tue, 17 Jan 2023 02:03:27 +0000
Labels:           app=nginx
pod-template-hash=649b779d98
Annotations:      cni.projectcalico.org/containerID: a512d1c7f0b3fd9d690a3ad1c68909d36a80abe50c91522f16e0a01f65d4f9ca
cni.projectcalico.org/podIP: 192.168.1.5/32
cni.projectcalico.org/podIPs: 192.168.1.5/32
Status:           Running
IP:               192.168.1.5
IPs:
IP:           192.168.1.5
Controlled By:  ReplicaSet/nginx-649b779d98
Containers:
nginx:
Container ID:   containerd://20b43750d4323d92b4b5f27c4ffbc917fbed2d92e5bc94d69db3127b43a62dff
Image:          nginx
Image ID:       docker.io/library/nginx@sha256:b8f2383a95879e1ae064940d9a200f67a6c79e710ed82ac42263397367e7cc4e
Port:           <none>
Host Port:      <none>
State:          Running
Started:      Tue, 17 Jan 2023 02:03:29 +0000
Ready:          True
Restart Count:  0
Environment:    <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-sw59z (ro)
Conditions:
Type              Status
Initialized       True 
Ready             True 
ContainersReady   True 
PodScheduled      True 
Volumes:
kube-api-access-sw59z:
Type:                    Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds:  3607
ConfigMapName:           kube-root-ca.crt
ConfigMapOptional:       <nil>
DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type    Reason     Age   From               Message
----    ------     ----  ----               -------
Normal  Scheduled  20s   default-scheduler  Successfully assigned default/nginx-649b779d98-cd9rd to node01
Normal  Pulling    19s   kubelet            Pulling image "nginx"
Normal  Pulled     19s   kubelet            Successfully pulled image "nginx" in 480.824291ms (480.831812ms including waiting)
Normal  Created    19s   kubelet            Created container nginx
Normal  Started    18s   kubelet            Started container nginx

可以看到,当前集群中两个节点node01、controlplane都不包含role=slave的标签,但是我们的Pod也能成功调度上,这就是软亲和性preferredDuringSchedulingIgnoredDuringExecution,尽量去找满足条件的节点,如果找不到,那也不会影响Pod被调度。

3.4、节点反亲和性

节点反亲和性就是通过NotIn和DoesNotExist实现,配置如下:

spec:affinity:nodeAffinity:  	# 节点反亲和性requiredDuringSchedulingIgnoredDuringExecution:  # 硬亲和性nodeSelectorTerms:- matchExpressions:		- key: roleoperator: NotIn   # Pod尽量不要去选择包含role=master的那些节点values:- master

 3.5、注意点

  • 1、如果你同时指定了 nodeSelector 和 nodeAffinity,两者必须都要满足,才能将 Pod 调度到候选节点上
# 对应pod必须运行在节点上有节点标签key为a的节点并且对应节点上还有role=master节点标签
affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:- matchExpressions:- key: aoperator: Existsvalues: []
nodeSelector:role: master
  •  2、如果你在与 nodeAffinity 类型关联的 nodeSelectorTerms 中指定多个条件, 只要其中一个 nodeSelectorTerms 满足(各个条件按逻辑或操作组合)的话,Pod 就可以被调度到节点上
# pod节点必须运行在对应节点上有节点标签key为a或key为role的节点
affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:- matchExpressions:- key: aoperator: Existsvalues: []- matchExpressions:- key: roleoperator: Existsvalues: []
  •  3、如果你在与nodeSelectorTerms 中的条件相关联的单个 matchExpressions 字段中指定多个表达式, 则只有当所有表达式都满足(各表达式按逻辑与操作组合)时,Pod 才能被调度到节点上 
# pod必须运行在节点标签key为a和节点标签key为role的节点上
affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:- matchExpressions:- key: aoperator: Existsvalues: []- key: roleoperator: Existsvalues: []

四、Pod亲和性和反亲和性

4.1、亲和性和反亲和性

Pod Affinity即节点亲和,是用来定义Pod与Pod间的亲和性,所谓Pod与Pod的亲和性是指,Pod更愿意和哪些Pod在一起;与之相反的也有Pod更不愿意和哪些Pod在一起,这种叫做Pod Anti Affinity,即Pod与Pod间的反亲和性。

所谓在一起是指和对应Pod在同一个位置,这个位置可以是按主机名划分,也可以按照区域划分,这样一来我们要定义Pod和Pod在一起或不在一起,定义位置就显得尤为重要,也是评判对应Pod能够运行在哪里的标准;例如:我们可以控制两个Pod运行在同一个node上,也可以控制两个Pod运行在不同的region上面,topologyKey就是来控制这个划分规则的,最常用的值为kubernetes.io/hostname

同样的,Pod亲和也有两种: requiredDuringSchedulingIgnoredDuringExecution(硬亲和性)和preferredDuringSchedulingIgnoredDuringExecution(软亲和性)。

pod亲和与反亲和性通过PodSpec的affinity字段下的podAffinity(Pod亲和性)和podAntiAffinity(Pod反亲和性)字段指定,操作符仅支持In、NotIn、Exists、DoesNotExist。

4.2、Pod亲和性/反亲和性

首先运行一个包含app=tomcat的Pod:vim tomcat-pod.yaml

apiVersion: apps/v1
kind: Deployment
metadata:name: tomcat
spec:replicas: 1selector:matchLabels:app: tomcattemplate:metadata:labels:app: tomcatspec:containers:- name: tomcatimage: tomcat:8.5-jre10-slimports:- containerPort: 8080

创建并查看tomcat Pod:

$ kubectl apply -f tomcat.yaml 
deployment.apps/tomcat created$ kubectl get pod -o wide --show-labels
NAME                     READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES   LABELS
tomcat-ff7c8b896-fh9zb   1/1     Running   0          22s   192.168.1.5   node01   <none>           <none>            app=tomcat,pod-template-hash=ff7c8b896

可以看到,当前tomcat Pod运行在node01节点上。

接下来,我们定义一个nginx Pod,指定Pod的亲和性和反亲和性配置: vim pod-anti-affinity.yaml

apiVersion: apps/v1
kind: Deployment
metadata:name: nginx
spec:replicas: 2selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:affinity:podAffinity:    # Pod亲和性requiredDuringSchedulingIgnoredDuringExecution:   # 硬亲和   调度的节点上必须有labels包含app=tomcat的pod,如果没有这样的pod则调度失败。- labelSelector:matchExpressions:- key: appoperator: Invalues:- tomcattopologyKey: kubernetes.io/hostname   # 指定节点标签,通过该标签可以确定哪些节点上的 Pod 有指定标签,以此来做区分。podAntiAffinity:  # Pod反亲和性requiredDuringSchedulingIgnoredDuringExecution:   # 硬亲和  任意两个nginx pod不得调度在同一个node上面,即如果节点上有labels包含app=nginx的pod,则pod不应该调度到该节点上- labelSelector:matchExpressions:- key: appoperator: Invalues:- nginxtopologyKey: kubernetes.io/hostnamecontainers:- name: nginximage: nginx

在资源清单中,我们通过podAffinity配置了nginx Pod的硬亲和规则就是必须调度到包含app=tomcat标签并且目前正在运行中的tomcat Pod所在的那些node上面【即node01】,通过podAntiAffinity配置nginx Pod的硬反亲和规则是任意两个nginx Pod不得调度在同一个node上面。

运行并查看Pod:

$ kubectl apply -f pod-anti-affinity.yaml
deployment.apps/nginx created$ kubectl get pod -o wide --show-labels
NAME                     READY   STATUS    RESTARTS   AGE     IP            NODE     NOMINATED NODE   READINESS GATES   LABELS
nginx-5689b4dd7-6twt8    0/1     Pending   0          34s     <none>        <none>   <none>           <none>            app=nginx,pod-template-hash=5689b4dd7
nginx-5689b4dd7-z8m2j    1/1     Running   0          34s     192.168.1.6   node01   <none>           <none>            app=nginx,pod-template-hash=5689b4dd7
tomcat-ff7c8b896-fh9zb   1/1     Running   0          5m19s   192.168.1.5   node01   <none>           <none>            app=tomcat,pod-template-hash=ff7c8b896

在资源清单中,我们指定了nginx的副本数为2,并且一个处于Running,一个处于Pending。

  • 处于Running是因为,它满足了我们配置了Pod亲和/反亲和性规则,nginx-5689b4dd7-z8m2j这个Pod它首先会去挑选当前包含app=tomcat标签并且正在运行中的Pod所在的节点,这里就是node01;然后再判断反亲和性规则,同一个节点不能同时运行两个nginx Pod,目前node01上并没有运行nginx Pod,所以nginx-5689b4dd7-z8m2j它就会被调度到node01上。
  • 处于Pending是因为,它满足了我们配置了Pod亲和/反亲和性规则,nginx-5689b4dd7-6twt8这个Pod它首先会去挑选当前包含app=tomcat标签并且正在运行中的Pod所在的节点,这里就是node01;然后再判断反亲和性规则,同一个节点不能同时运行两个nginx Pod,因为node01上已经运行了一个nginx Pod【nginx-5689b4dd7-z8m2j】,所以nginx-5689b4dd7-6twt8这个Pod就不能再被调度到node01上了,不满足反亲和规则,故nginx-5689b4dd7-6twt8这个Pod一直处于Pending状态。

五、总结

不管是node的亲和/反亲和,还是Pod和Pod的亲和/反亲和,如果我们指定的规则过于精细的话,都需要大量计算处理和条件过滤, 依赖大量的Pod和node状态信息, 如果k8s集群很大的话,会显著减慢scheduler的调度速度,因此k8s官方不建议在超过数百个节点的集群中使用它们,如果节点较多,过滤规则不应该设置的过于精细。

参考:将 Pod 指派给节点 | Kubernetes

相关文章:

16、Kubernetes核心技术 - 节点选择器、亲和和反亲和

目录 一、概述 二、节点名称 - nodeName 二、节点选择器 - nodeSelector 三、节点亲和性和反亲和性 3.1、亲和性和反亲和性 3.2、节点硬亲和性 3.3、节点软亲和性 3.4、节点反亲和性 3.5、注意点 四、Pod亲和性和反亲和性 4.1、亲和性和反亲和性 4.2、Pod亲和性/反…...

面试算法96:字符串交织

题目 输入3个字符串s1、s2和s3&#xff0c;请判断字符串s3能不能由字符串s1和s2交织而成&#xff0c;即字符串s3的所有字符都是字符串s1或s2中的字符&#xff0c;字符串s1和s2中的字符都将出现在字符串s3中且相对位置不变。例如&#xff0c;字符串"aadbbcbcac"可以由…...

什么是Vue.js的响应式系统(reactivity system)?如何实现数据的双向绑定?

Vue.js的响应式系统是指一种能够跟踪数据变化并实时更新相关界面的机制。它是Vue.js框架的核心特性之一。 在Vue.js中&#xff0c;你可以使用数据绑定语法将数据绑定到DOM元素上。当绑定的数据发生变化时&#xff0c;Vue.js会自动监听这些变化并更新相关的DOM元素。 Vue.js实…...

力扣labuladong一刷day52天LRU算法

力扣labuladong一刷day52天LRU算法 文章目录 力扣labuladong一刷day52天LRU算法概念一、146. LRU 缓存思路一&#xff1a;使用双向链表加map来手动实现。思路二&#xff1a;使用LinkedHashMap 概念 LRU的全称为Least Recently Used&#xff0c;翻译出来就是最近最少使用的意思…...

CCNP课程实验-06-EIGRP-Trouble-Shooting

目录 实验条件网络拓朴 环境配置开始排错错误1&#xff1a;没有配置IP地址&#xff0c;IP地址宣告有误错误2&#xff1a;R3配置了与R1不同的K值报错了。错误3&#xff1a;R4上的AS号配置错&#xff0c;不是1234错误4&#xff1a;R2上配置的Key-chain的R4上配置的Key-chain不一致…...

判断完全数-第11届蓝桥杯省赛Python真题精选

[导读]&#xff1a;超平老师的Scratch蓝桥杯真题解读系列在推出之后&#xff0c;受到了广大老师和家长的好评&#xff0c;非常感谢各位的认可和厚爱。作为回馈&#xff0c;超平老师计划推出《Python蓝桥杯真题解析100讲》&#xff0c;这是解读系列的第27讲。 判断完全数&#…...

【Bootstrap5学习 day12】

Bootstrap5 导航 Bootstrap5提供了一种简单快捷的方法来创建基本导航&#xff0c;它提供了非常灵活和优雅的选项卡和Pills等组件。Bootstrap5的所有导航组件&#xff0c;包括选项卡和Pillss&#xff0c;都通过基本的.nav类共享相同的基本标记和样式。 创建基本导航 要创建简单…...

算法训练第五十九天|503. 下一个更大元素 II、42. 接雨水

503. 下一个更大元素 II&#xff1a; 题目链接 给定一个循环数组 nums &#xff08; nums[nums.length - 1] 的下一个元素是 nums[0] &#xff09;&#xff0c;返回 nums 中每个元素的 下一个更大元素 。 数字 x 的 下一个更大的元素 是按数组遍历顺序&#xff0c;这个数字之…...

mysql之数据类型、建表以及约束

目录 一. CRUD 1.1 什么是crud 1.2 select(查询) 1.3 INSERT(新增) 1.4 UPDATE(修改&#xff09; 1.5 DELETE(删除) 二. 函数 2.1 常见函数 2.2 流程控制函数 2.3聚合函数 三. union与union all 3.1 union 3.2 union all 3.3 具体不同 3.4 结论 四、思维导图 一. CRUD 1.1…...

复试 || 就业day04(2024.01.05)项目一

文章目录 前言线性回归房价预测加载数据数据查看数据拆分数据建模模型的验证、应用模型的评估 总结 前言 &#x1f4ab;你好&#xff0c;我是辰chen&#xff0c;本文旨在准备考研复试或就业 &#x1f4ab;本文内容来自某机构网课&#xff0c;是我为复试准备的第一个项目 &#…...

华为机试真题实战应用【赛题代码篇】-最小传输时延(附python、C++和JAVA代码实现)

目录 问题描述 输入描述: 输出描述: 知识储备 解题思路 思路一...

C++ 运算符重载

&#xff08;Operator&#xff09; 加分 减法 []的重载 #include <iostream> using namespace std;class time1 {public:time1(){shi0;fen0;miao0;}time1(int shi, int fen, int miao){this->shi shi;this->fen fen;this->miao miao;}time1 operator (ti…...

vue3学习 【2】vite起步和开发工具基本配置

vite的简介 官方文档 刚起步学习&#xff0c;所以我们只需要按照官方文档的入门流程即可。推荐阅读一下官网的为什么使用vite vite目前需要的node版本是18&#xff0c;可以参考上一篇文章的安装nvm&#xff0c;用来进行多版本的node管理。 vite安装与使用 npm create vitela…...

计算机创新协会冬令营——暴力枚举题目06

我给大家第一阶段的最后一道题就到这里了&#xff0c;下次得过段时间了。所以这道题简单一点。但是足够经典 下述题目描述和示例均来自力扣&#xff1a;两数之和 题目描述 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target …...

单片机快速入门

参考连接&#xff1a; 安装MinGW-64&#xff08;在win10上搭建C/C开发环境&#xff09;https://zhuanlan.zhihu.com/p/85429160MinGW-64; 链接&#xff1a;https://pan.baidu.com/s/1oE1FmjyK7aJPnDC8vASmCg?pwdy1mz 提取码&#xff1a;y1mz --来自百度网盘超级会员V7的分享C…...

Eureka相关问题及答案(2024)

1、什么是Eureka&#xff1f; Eureka是一个由Netflix开发的服务发现&#xff08;Service Discovery&#xff09;工具&#xff0c;它是Spring Cloud生态系统中的一个关键组件。服务发现是微服务架构中的一个重要概念&#xff0c;它允许服务实例在启动时注册自己&#xff0c;以便…...

Django 7 实现Web便签

一、效果图 二、会用到的知识 目录结构与URL路由注册request与response对象模板基础与模板继承ORM查询后台管理 三、实现步骤 1. terminal 输入 django-admin startapp the_10回车 2. 注册&#xff0c; 在 tutorial子文件夹settings.py INSTALLED_APPS 中括号添加 "the…...

Jenkins集成部署java项目

文章目录 Jenkins简介安装 Jenkins简介 Jenkins能实时监控集成中存在的错误&#xff0c;提供详细的日志文件和提醒功能&#xff0c;还能用图表的形式形象的展示项目构建的趋势和稳定性。 官网 安装 在官网下载windows版本的Jenkins 但是我点击这里浏览器没有反应&#xff0…...

FFmpeg之——获取上传视频的尺寸(长、宽)

获取上传视频的尺寸&#xff1a; 获取视频尺寸通常需要借助第三方库FFmpeg。 首先&#xff0c;确保你的系统中已安装了FFmpeg&#xff0c;并且FFmpeg的可执行文件路径已经添加到你的系统环境变量中。 1.官网下载ffmpeg 进入 链接: ffmpeg官网 网址&#xff0c;点击下载wind…...

Ajax学习

文章目录 AjaxAjax 是什么Ajax 经典应用场景Ajax 原理示意图ajax的异步请求的方法ajax的逻辑:应用实例-验证用户名是否存在思路框架图:需求分析: 到数据库去验证用户名是否可用思路框架图大功告成:使用JQuery-Ajax实现上面相同的需求:Ajax Ajax 是什么 AJAX 即"Async…...

排序算法——关于快速排序的详解

目录 1.基本思想 2.基本原理 2.1划分思想 2.2排序过程 &#xff08;1&#xff09;选择基准值 &#xff08;2&#xff09;分割过程&#xff08;Partition&#xff09; &#xff08;3&#xff09;递归排序 &#xff08;4&#xff09;合并过程 2.3具体实例 2.4实现代码 2.5关键要…...

序言:《未来已来》

尊敬的读者&#xff0c; 你是否曾经在面对冗长的报告、繁琐的工作、沉重的生活压力时感到困扰&#xff0c;渴望找到一种方式来提升效率&#xff0c;释放压力&#xff1f;你是否曾经在自我创业的道路上&#xff0c;苦于找不到有效的市场营销方式&#xff0c;寻求突破&#xff1f…...

【Spring实战】22 Spring Actuator 入门

文章目录 1. 定义2. 功能3. 依赖4. 配置5. 常用的应用场景1&#xff09;环境监控2&#xff09;运维管理3&#xff09;性能优化 结论 Spring Actuator 是 Spring 框架的一个模块&#xff0c;为开发人员提供了一套强大的监控和管理功能。本文将深入探讨 Spring Actuator 的定义、…...

JSON安全性

确保JSON处理的安全性是现代Web开发中重要的一环。以下是一些关键的安全实践&#xff0c;用于防止JSON注入攻击以及确保数据在传输过程中的安全性&#xff1a; 1. **验证和清洗输入&#xff1a;** - 在将任何数据写入数据库之前&#xff0c;请确保验证用户输入。对于期望的JSON…...

spring-boot-maven插件repackage(goal)的那些事

前言&#xff1a;在打包Springboot项目成jar包时需要在pom.xml使用spring-boot-maven-plugin来增加Maven功能&#xff0c;在我的上一篇博客<<Maven生命周期和插件的那些事&#xff08;2021版&#xff09;>>中已经介绍过Maven和插件的关系&#xff0c;在此不再赘述&…...

ubuntu的boot分区被删除恢复

在鼓捣黑苹果的时候&#xff0c;误删了ubuntu的boot分区&#xff0c;进系统的时候出现emergency mode&#xff0c;那么现在来讲讲怎么恢复 首先做一个ubuntu的启动盘&#xff0c;然后进入启动盘的系统选择试用 呼出命令行&#xff0c;然后添加一个源 sudo add-apt-repository…...

【userfaultfd 条件竞争】starCTF2019 - hackme

前言 呜呜呜&#xff0c;这题不难&#xff0c;但是差不多一个多月没碰我的女朋友 kernel pwn 了&#xff0c;对我的 root 宝宝也是非常想念&#xff0c;可惜这题没有找到我的 root 宝宝&#xff0c;就偷了她的 flag。 哎有点生疏了&#xff0c;这题没看出来堆溢出&#xff0c…...

深度学习中的自动化标签转换:对数据集所有标签做映射转换

在机器学习中&#xff0c;特别是在涉及图像识别或分类的项目中&#xff0c;标签数据的组织和准确性至关重要。本文探讨了一个旨在高效转换标签数据的 Python 脚本。该脚本在需要更新或更改类标签的场景中特别有用&#xff0c;这是正在进行的机器学习项目中的常见任务。我们将逐…...

c语言-函数指针

目录 前言一、函数指针1.1 函数指针定义1.2 函数指针调用函数1.3 函数指针代码分析 总结 前言 本篇文章介绍c语言中的函数指针以及函数指针的应用。 一、函数指针 函数指针&#xff1a;指向函数的指针。 函数在编译时分配地址。 &函数名 和 函数名代表的意义相同&#xf…...

conda

一、安装 推荐清华源 https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/?CN&OD选择版本 Miniconda3-py39_4.12.0-MacOSX-arm64.pkg测试命令 conda help二、更换仓库 配置加速 https://mirrors.tuna.tsinghua.edu.cn/help/anaconda/没有 .condarc 文件则执行…...

视觉设计网站/友链申请

[Error]集成第三方API时Other Linker Flags项添加-all_load引起的冲突 问题描述&#xff1a; 在XCode9.1新建一个项目&#xff0c;先集成了极光推送&#xff0c;再集成微信支付时出现的问题。 集成微信后运行时&#xff0c;报错&#xff08;如图&#xff09;&#xff1a; …...

推广目标包括什么/seo建站工具

神州数码客户端常见故障自查一、 客户端认证成功前故障1. 接上网线后网卡灯不亮。(确定自己电脑网卡带灯。注&#xff1a;测试期间最好是不要接交换机&#xff0c;直接接墙上端口)参考方案&#xff1a;A、更换网线&#xff1b;B、如确认是端口故障&#xff0c;则请致电网络中心…...

湖南省住房和城乡建设厅网站/南宁seo排名首页

本文价值与收获 看完本文后,您将能够作出下面的界面 看完本文您将掌握的技能 绘制虚线设置虚线宽度和颜色实战需求 我需要创建一条虚线。我尝试通过创建带有虚线笔触的Rectangle视图来解决这个问题。但是,将矩形的高度设置为1时,会导致出现一条双线,因为它同时显示了视图…...

海南专业做网站的公司/域名注册需要多久

献给所有得到过所爱却又失去所爱的人&#xff0c;给从未得到所爱的人&#xff0c;给因为仍旧爱着&#xff0c;于是选择自欺欺人的人。这&#xff0c;是一面镜子&#xff0c;勇敢面对&#xff0c;勇敢放弃&#xff0c;勇敢重新开始。 当她不爱你的时候&#xff0c;无论过去她是…...

文章 wordpress/seoyoon

我这个人走得很慢&#xff0c;但是我从不后退。----亚伯拉罕林肯前言&#xff1a; 本周我们主要了解Java中与面向对象的程序设计&#xff08;OOP&#xff09;有关的关键字。后面会逐一详细说明各个关键字的用法。其中特别注意的是this关键字&#xff0c;是Java中最常用的关…...

网站开发技术协议怎么写/seo搜索引擎优化平台

图解CSS padding、margin、border属性 W3C组织建议把所有网页上的对像都放在一个盒(box)中&#xff0c;设计师可以通过创建定义来控制这个盒的属性&#xff0c;这些对像包括段落、列表、标题、图片以及层。盒模型主要定义四个区域&#xff1a;内容(content)、内边距(padding)、…...