持续集成部署-k8s-高级调度-亲和力

持续集成部署-k8s-高级调度-亲和力

  • 1. 亲和力的基本概念
  • 2. 亲和性和非亲和性
  • 3. 节点亲和力的使用
  • 4. 节点亲和性权重
  • 5. 验证节点亲和性
  • 6. Pod 间亲和性与反亲和性
  • 7. Pod 间亲和性与反亲和性的类型
  • 8. 调度一组具有 Pod 间亲和性的 Pod
  • 9. 验证 Pod 亲和性

1. 亲和力的基本概念

Kubernetes中,亲和力(Affinity)是一种高级调度机制,用于指定Pod如何与节点进行亲和匹配。通过亲和力规则,你可以控制Pod被调度到特定节点的方式,以便更好地满足应用程序的需求和约束条件。

亲和力规则分为两种类型:node亲和性pod亲和性

  • Node亲和性:

    • Node亲和性规则允许你指定Pod应该被调度到具有特定标签的节点上。这种标签可以是节点的特性、硬件配置或者地理位置等。通过使用Node亲和性,你可以确保某些Pod只被调度到符合特定要求的节点上。
  • Pod亲和性:

    • Pod亲和性规则允许你指定Pod应该与其他Pod共同部署在同一个节点上。这种规则可以确保某些相关的Pod被调度到相同的节点上,以减少网络延迟或提高局部性能。

相较于污点和容忍而言,污点和容忍更倾向于一个排除的效果,你能容忍我的污点,你就来,你不能容忍我的污点,那你就走。

接着来看下一种新的调度效果叫做亲和力。亲和力刚好跟污点容忍相反,就是配置 Pod 尽可能的到某个地方,而反亲和力刚好跟亲和力相反,就是尽可能的不到某个地方,跟污点一个效果。

污点是使用的是污点和容忍,而亲和力匹配使用的标签 Label。亲和度越高,越有可能被调度选中。

污点配合亲和力,就能够实现更细致、更复杂、更智能的调度功能。

2. 亲和性和非亲和性

nodeSelector 提供了一种最简单的方法来将 Pod 约束到具有特定标签的节点上。 亲和性和反亲和性扩展了你可以定义的约束类型。使用亲和性与反亲和性的一些好处有:

  • 亲和性、反亲和性语言的表达能力更强。nodeSelector 只能选择拥有所有指定标签的节点。 亲和性、反亲和性为你提供对选择逻辑的更强控制能力。
  • 你可以标明某规则是“软需求”或者“偏好”,这样调度器在无法找到匹配节点时仍然调度该 Pod。
  • 你可以使用节点上(或其他拓扑域中)运行的其他 Pod 的标签来实施调度约束, 而不是只能使用节点本身的标签。这个能力让你能够定义规则允许哪些 Pod 可以被放置在一起。

亲和性功能由两种类型的亲和性组成:

  • 节点亲和性功能类似于 nodeSelector 字段,但它的表达能力更强,并且允许你指定软规则。
  • Pod 间亲和性/反亲和性允许你根据其他 Pod 的标签来约束 Pod。

节点亲和性概念上类似于 nodeSelector, 它使你可以根据节点上的标签来约束 Pod 可以调度到哪些节点上。 节点亲和性有两种:

  • requiredDuringSchedulingIgnoredDuringExecution: 调度器只有在规则被满足的时候才能执行调度。此功能类似于 nodeSelector, 但其语法表达能力更强。
  • preferredDuringSchedulingIgnoredDuringExecution: 调度器会尝试寻找满足对应规则的节点。如果找不到匹配的节点,调度器仍然会调度该 Pod。

说明:
在上述类型中,IgnoredDuringExecution 意味着如果节点标签在 Kubernetes 调度 Pod 后发生了变更,Pod 仍将继续运行。

3. 节点亲和力的使用

看下官方文档里面的 Demo:pods/pod-with-node-affinity.yaml

apiVersion: v1
kind: Pod
metadata:name: with-node-affinity
spec:affinity:  # 定义亲和性规则nodeAffinity:  # 定义节点亲和性规则requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:  # 定义选择节点的条件- matchExpressions: # 定义匹配表达式- key: topology.kubernetes.io/zone  # 指定匹配的标签键operator: In  # 指定匹配操作符为In,表示节点的标签键值在指定的values中values:   # 指定匹配的标签值列表,包括"antarctica-east1"和"antarctica-west1"- antarctica-east1- antarctica-west1preferredDuringSchedulingIgnoredDuringExecution:   # 定义优选的节点亲和性规则,即首选但不是必需的- weight: 1   # 定义优选规则的权重为1preference: matchExpressions:   # 定义首选规则的匹配表达式- key: another-node-label-key # 指定匹配的标签键operator: In values:- another-node-label-valuecontainers:- name: with-node-affinityimage: registry.k8s.io/pause:2.0

所应用的规则如下:

  • 节点必须包含一个键名为 topology.kubernetes.io/zone 的标签, 并且该标签的取值必须为 antarctica-east1antarctica-west1
  • 节点最好具有一个键名为 another-node-label-key 且取值为 another-node-label-value 的标签。

可以使用 operator 字段来为 Kubernetes 设置在解释规则时要使用的逻辑操作符。 你可以使用 InNotInExistsDoesNotExistGtLt 之一作为操作符。

  • In:满足一个就行;
  • NotIn:一个都不能满足,反亲和性;
  • Exists:只要存在,就满足;
  • DoesNotExist:只有不存在,才满足;
  • Gt:必须要大于节点上的数值才满足;
  • Lt:必须要小于节点上的数值才满足;

在要求该Pod被调度到拥有特定标签的节点上(拓扑域为"antarctica-east1"或"antarctica-west1")。同时也定义了一个首选规则,希望该Pod被调度到带有特定标签的节点上(标签键为"another-node-label-key",标签值为"another-node-label-value")。

通过这样的配置,Kubernetes调度器将会优先考虑满足必需的节点亲和性规则,如果没有满足的节点,则会考虑首选的节点亲和性规则。

NotInDoesNotExist 可用来实现节点反亲和性行为。 你也可以使用节点污点 将 Pod 从特定节点上驱逐。

说明:
如果你同时指定了 nodeSelectornodeAffinity,两者 必须都要满足, 才能将 Pod 调度到候选节点上。
如果你在与 nodeAffinity 类型关联的 nodeSelectorTerms 中指定多个条件, 只要其中一个 nodeSelectorTerms 满足(各个条件按逻辑或操作组合)的话,Pod 就可以被调度到节点上。
如果你在与 nodeSelectorTerms 中的条件相关联的单个 matchExpressions 字段中指定多个表达式, 则只有当所有表达式都满足(各表达式按逻辑与操作组合)时,Pod 才能被调度到节点上。

4. 节点亲和性权重

可以为 preferredDuringSchedulingIgnoredDuringExecution 亲和性类型的每个实例设置 weight 字段,其取值范围是 1100。 当调度器找到能够满足 Pod 的其他调度请求的节点时,调度器会遍历节点满足的所有的偏好性规则, 并将对应表达式的 weight 值加和。

最终的加和值会添加到该节点的其他优先级函数的评分之上。 在调度器为 Pod 作出调度决定时,总分最高的节点的优先级也最高。

配置文件:pods/pod-with-affinity-anti-affinity.yaml

apiVersion: v1
kind: Pod
metadata:name: with-affinity-anti-affinity
spec:affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:- matchExpressions:- key: kubernetes.io/osoperator: Invalues:- linuxpreferredDuringSchedulingIgnoredDuringExecution:- weight: 1preference:matchExpressions:- key: label-1operator: Invalues:- key-1- weight: 50preference:matchExpressions:- key: label-2operator: Invalues:- key-2containers:- name: with-node-affinityimage: registry.k8s.io/pause:2.0

如果存在两个候选节点,都满足 preferredDuringSchedulingIgnoredDuringExecution 规则, 其中一个节点具有标签 label-1:key-1,另一个节点具有标签 label-2:key-2, 调度器会考察各个节点的 weight 取值,并将该权重值添加到节点的其他得分值之上,

说明:
如果你希望 Kubernetes 能够成功地调度此例中的 Pod,你必须拥有打了 kubernetes.io/os=linux 标签的节点。

5. 验证节点亲和性

看下当前 k8s 环境节点的标签:

[root@docker-54 ~]# kubectl get no --show-labels
NAME        STATUS   ROLES                  AGE    VERSION   LABELS
docker-54   Ready    control-plane,master   201d   v1.22.6   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,ingress=true,kubernetes.io/arch=amd64,kubernetes.io/hostname=docker-54,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=,node.kubernetes.io/exclude-from-external-load-balancers=
docker-55   Ready    <none>                 201d   v1.22.6   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,ingress=true,kubernetes.io/arch=amd64,kubernetes.io/hostname=docker-55,kubernetes.io/os=linux,type=microservice
docker-56   Ready    <none>                 201d   v1.22.6   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=docker-56,kubernetes.io/os=linux,type=microservice
[root@docker-54 ~]# 

可以看到,上面节点都已经具备标签kubernetes.io/os=linux了。

为了验证上面的节点亲和力配置,我这里将对两个从节点,分别添加标签:

[root@docker-54 ~]# kubectl label no docker-55 label-1=key-1
node/docker-55 labeled
[root@docker-54 ~]# 
[root@docker-54 ~]# kubectl label no docker-56 label-2=key-2
node/docker-56 labeled
[root@docker-54 ~]# 
[root@docker-54 ~]# kubectl get no --show-labels            
NAME        STATUS   ROLES                  AGE    VERSION   LABELS
docker-54   Ready    control-plane,master   202d   v1.22.6   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,ingress=true,kubernetes.io/arch=amd64,kubernetes.io/hostname=docker-54,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=,node.kubernetes.io/exclude-from-external-load-balancers=
docker-55   Ready    <none>                 201d   v1.22.6   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,ingress=true,kubernetes.io/arch=amd64,kubernetes.io/hostname=docker-55,kubernetes.io/os=linux,label-1=key-1,type=microservice
docker-56   Ready    <none>                 201d   v1.22.6   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=docker-56,kubernetes.io/os=linux,label-2=key-2,type=microservice
[root@docker-54 ~]# 

上面我对 docker-55 节点添加了 标签 label-1=key-1,对 docker-56 节点添加了 标签 label-2=key-2

这里我直接使用上面配置文件的亲和性的内容,来修改我这边当前环境里面的一个 deploy ,直接编辑 deploy:kubectl edit deploy nginx-deploy

  template:metadata:labels:app: nginx-deployspec:affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:- matchExpressions:- key: kubernetes.io/osoperator: Invalues:- linuxpreferredDuringSchedulingIgnoredDuringExecution:- weight: 1preference:matchExpressions:- key: label-1operator: Invalues:- key-1- weight: 50preference:matchExpressions:- key: label-2operator: Invalues:- key-2

注意这里亲和力的配置也是跟 containers 是平级的。

保存之后,看下 Pod 的调度情况:

[root@docker-54 ~]# kubectl get po -o wide
NAME                           READY   STATUS        RESTARTS      AGE    IP             NODE        NOMINATED NODE   READINESS GATES
nginx-deploy-b8976d7b5-b86q4   1/1     Terminating   0             55m    10.244.1.78    docker-55   <none>           <none>
nginx-deploy-b8976d7b5-fvqn8   1/1     Terminating   1 (55m ago)   115m   10.244.2.119   docker-56   <none>           <none>
nginx-deploy-c7f9688fd-mqfmf   1/1     Running       0             27s    10.244.2.123   docker-56   <none>           <none>
nginx-deploy-c7f9688fd-w6vhk   1/1     Running       0             29s    10.244.2.122   docker-56   <none>           <none>
[root@docker-54 ~]# 
[root@docker-54 ~]# kubectl get po -o wide
NAME                           READY   STATUS    RESTARTS   AGE   IP             NODE        NOMINATED NODE   READINESS GATES
nginx-deploy-c7f9688fd-mqfmf   1/1     Running   0          54s   10.244.2.123   docker-56   <none>           <none>
nginx-deploy-c7f9688fd-w6vhk   1/1     Running   0          56s   10.244.2.122   docker-56   <none>           <none>
[root@docker-54 ~]# 

可以看到,原来这两个 Pod 是分散在 两个从节点上的,在添加了上面的亲和力配置之后,Pod 都调度到了 docker-56 节点。

看下上面的节点亲和力配置,虽然两个从节点都满足了第一个要求,具有标签kubernetes.io/os=linux,但是具有标签 label-2=key-2的节点权重高,所以 Pod 会优先调度到具体此标签的节点上。

接着再次修改亲和力的配置,将标签 label-2=key-2的判断条件由 In 改为 NotIn,猜测下,这时候两个 Pod 都不能调度到带有标签 label-2=key-2的节点上了。

验证看下:

[root@docker-54 ~]# kubectl get po -o wide
NAME                            READY   STATUS              RESTARTS   AGE     IP             NODE        NOMINATED NODE   READINESS GATES
nginx-deploy-75578bc7f7-47cqt   0/1     ContainerCreating   0          2s      <none>         docker-55   <none>           <none>
nginx-deploy-75578bc7f7-78j75   1/1     Running             0          4s      10.244.1.79    docker-55   <none>           <none>
nginx-deploy-c7f9688fd-mqfmf    1/1     Running             0          7m52s   10.244.2.123   docker-56   <none>           <none>
nginx-deploy-c7f9688fd-w6vhk    1/1     Terminating         0          7m54s   10.244.2.122   docker-56   <none>           <none>
[root@docker-54 ~]# kubectl get po -o wide
NAME                            READY   STATUS        RESTARTS   AGE     IP             NODE        NOMINATED NODE   READINESS GATES
nginx-deploy-75578bc7f7-47cqt   1/1     Running       0          4s      10.244.1.80    docker-55   <none>           <none>
nginx-deploy-75578bc7f7-78j75   1/1     Running       0          6s      10.244.1.79    docker-55   <none>           <none>
nginx-deploy-c7f9688fd-mqfmf    1/1     Terminating   0          7m54s   10.244.2.123   docker-56   <none>           <none>
nginx-deploy-c7f9688fd-w6vhk    1/1     Terminating   0          7m56s   10.244.2.122   docker-56   <none>           <none>
[root@docker-54 ~]# 
[root@docker-54 ~]# kubectl get po -o wide
nginx-deploy-75578bc7f7-47cqt   1/1     Running       0          52s      10.244.1.80    docker-55   <none>           <none>
nginx-deploy-75578bc7f7-78j75   1/1     Running       0          56s      10.244.1.79    docker-55   <none>           <none>

可以看到确实符合上面的亲和力配置。

这里 Master 节点 docker-54 虽然符合带有标签kubernetes.io/os=linux,但是不会被调度到它上面,是因为 Master 节点带有污点。

[root@docker-54 ~]# kubectl describe no docker-54 |grep Taints
Taints:             node-role.kubernetes.io/master:NoSchedule
[root@docker-54 ~]#

如果把这个污点删除掉,则上面的 Pod 还是有可能被调度到 Master 节点上的,接着试下看看:

[root@docker-54 ~]# kubectl get po -o wide
NAME                            READY   STATUS    RESTARTS   AGE   IP            NODE        NOMINATED NODE   READINESS GATES
nginx-deploy-75578bc7f7-47cqt   1/1     Running   0          52s   10.244.1.80   docker-55   <none>           <none>
nginx-deploy-75578bc7f7-78j75   1/1     Running   0          54s   10.244.1.79   docker-55   <none>           <none>
[root@docker-54 ~]# 
[root@docker-54 ~]# kubectl taint no docker-54 node-role.kubernetes.io/master:NoSchedule-
node/docker-54 untainted
[root@docker-54 ~]# 
[root@docker-54 ~]# kubectl describe no docker-54 |grep Taints                           
Taints:             <none>
[root@docker-54 ~]# 
[root@docker-54 ~]# 
[root@docker-54 ~]# kubectl delete po nginx-deploy-75578bc7f7-47cqt nginx-deploy-75578bc7f7-78j75
pod "nginx-deploy-75578bc7f7-47cqt" deleted
pod "nginx-deploy-75578bc7f7-78j75" deleted
[root@docker-54 ~]# 
[root@docker-54 ~]# kubectl get po -o wide
NAME                            READY   STATUS    RESTARTS   AGE   IP            NODE        NOMINATED NODE   READINESS GATES
nginx-deploy-75578bc7f7-8zz8h   1/1     Running   0          33s   10.244.0.11   docker-54   <none>           <none>
nginx-deploy-75578bc7f7-xvnfm   1/1     Running   0          33s   10.244.1.81   docker-55   <none>           <none>
[root@docker-54 ~]# 

可以看到,确实在 Master 节点去掉污点之后,删除 Pod 重新调度,发现可以调度到 Master 节点上。

在没有删除 Master 节点的污点的时候,由于 该 Pod 没有配置容忍,即使带有亲和力的标签,也不会被调度到 Master 节点上,然而在删除 Master 节点的污点之后,由于符合亲和力的必备标签,所以有可能会被调度选中。

6. Pod 间亲和性与反亲和性

Pod 间亲和性与反亲和性使你可以基于已经在节点上运行的 Pod 的标签来约束 Pod 可以调度到的节点,而不是基于节点上的标签。

Pod 间亲和性与反亲和性的规则格式为“如果 X 上已经运行了一个或多个满足规则 Y 的 Pod, 则这个 Pod 应该(或者在反亲和性的情况下不应该)运行在 X 上”。 这里的 X 可以是节点、机架、云提供商可用区或地理区域或类似的拓扑域, Y 则是 Kubernetes 尝试满足的规则。

你通过标签选择算符 的形式来表达规则(Y),并可根据需要指定选关联的名字空间列表。 PodKubernetes 中是名字空间作用域的对象,因此 Pod标签也隐式地具有名字空间属性。 针对 Pod 标签的所有标签选择算符都要指定名字空间,Kubernetes 会在指定的名字空间内寻找标签。

你会通过 topologyKey 来表达拓扑域(X)的概念,其取值是系统用来标示域的节点标签键。 相关示例可参见常用标签、注解和污点。

说明:
Pod 间亲和性和反亲和性都需要相当的计算量,因此会在大规模集群中显著降低调度速度。 我们不建议在包含数百个节点的集群中使用这类设置。

说明:
Pod 反亲和性需要节点上存在一致性的标签。换言之, 集群中每个节点都必须拥有与 topologyKey 匹配的标签。 如果某些或者所有节点上不存在所指定的 topologyKey 标签,调度行为可能与预期的不同。

7. Pod 间亲和性与反亲和性的类型

与节点亲和性类似,Pod 的亲和性与反亲和性也有两种类型:

  • requiredDuringSchedulingIgnoredDuringExecution
  • preferredDuringSchedulingIgnoredDuringExecution

可以使用 requiredDuringSchedulingIgnoredDuringExecution 亲和性来告诉调度器, 将两个服务的 Pod 放到同一个云提供商可用区内,因为它们彼此之间通信非常频繁。

类似地,可以使用 preferredDuringSchedulingIgnoredDuringExecution 反亲和性来将同一服务的多个 Pod 分布到多个云提供商可用区中。

要使用 Pod 间亲和性,可以使用 Pod 规约中的 .affinity.podAffinity 字段。 对于 Pod 间反亲和性,可以使用 Pod 规约中的 .affinity.podAntiAffinity 字段。

8. 调度一组具有 Pod 间亲和性的 Pod

如果当前正被调度的 Pod 在具有自我亲和性的 Pod 序列中排在第一个, 那么只要它满足其他所有的亲和性规则,它就可以被成功调度。 这是通过以下方式确定的:确保集群中没有其他 Pod 与此 Pod 的名字空间和标签选择算符匹配; 该 Pod 满足其自身定义的条件,并且选定的节点满足所指定的所有拓扑要求。 这确保即使所有的 Pod 都配置了 Pod 间亲和性,也不会出现调度死锁的情况。

Pod 亲和性示例
考虑下面的 Pod 规约:pods/pod-with-pod-affinity.yaml

apiVersion: v1
kind: Pod
metadata:name: with-pod-affinity
spec:affinity:     # 定义亲和性规则podAffinity:    # 定义Pod亲和性规则requiredDuringSchedulingIgnoredDuringExecution:  # 定义在调度时必须满足的Pod亲和性规则- labelSelector:matchExpressions:- key: securityoperator: Invalues:- S1topologyKey: topology.kubernetes.io/zone  # 指定拓扑域的标签键 也就是 依赖的 Pod 所在的节点必须要有这个标签才行podAntiAffinity:  # 定义Pod反亲和性规则preferredDuringSchedulingIgnoredDuringExecution:   # 定义优选的Pod反亲和性规则,即首选但不是必需的- weight: 100  # 定义优选规则的权重为100podAffinityTerm:labelSelector:matchExpressions:- key: securityoperator: Invalues:- S2topologyKey: topology.kubernetes.io/zonecontainers:- name: with-pod-affinityimage: registry.k8s.io/pause:2.0

上面示例定义了一条 Pod 亲和性规则和一条 Pod 反亲和性规则。Pod 亲和性规则配置为 requiredDuringSchedulingIgnoredDuringExecution,而 Pod 反亲和性配置为 preferredDuringSchedulingIgnoredDuringExecution

亲和性规则规定,只有节点属于特定的 区域 且该区域中的其他 Pod 已打上 security=S1 标签时,调度器才可以将示例 Pod 调度到此节点上。 例如,如果我们有一个具有指定区域(称之为 “Zone V”)的集群,此区域由带有 topology.kubernetes.io/zone=V 标签的节点组成,那么只要 Zone V 内已经至少有一个 Pod 打了 security=S1 标签, 调度器就可以将此 Pod 调度到 Zone V 内的任何节点。相反,如果 Zone V 中没有带有 security=S1 标签的 Pod, 则调度器不会将示例 Pod 调度给该区域中的任何节点

反亲和性规则规定,如果节点属于特定的 区域 且该区域中的其他 Pod 已打上 security=S2 标签,则调度器应尝试避免将 Pod 调度到此节点上。 例如,如果我们有一个具有指定区域(我们称之为 “Zone R”)的集群,此区域由带有 topology.kubernetes.io/zone=R 标签的节点组成,只要 Zone R 内已经至少有一个 Pod 打了 security=S2 标签, 调度器应避免将 Pod 分配给 Zone R 内的任何节点。相反,如果 Zone R 中没有带有 security=S2 标签的 Pod, 则反亲和性规则不会影响将 Pod 调度到 Zone R。

通过这样的配置,Kubernetes调度器将会优先考虑满足必需的Pod亲和性规则,如果没有满足的节点,则会考虑首选的Pod反亲和性规则。

可以针对 Pod 间亲和性与反亲和性为其 operator 字段使用 InNotInExistsDoesNotExist 等值。

原则上,topologyKey 可以是任何合法的标签键。出于性能和安全原因,topologyKey 有一些限制:

对于 Pod 亲和性而言,在 requiredDuringSchedulingIgnoredDuringExecutionpreferredDuringSchedulingIgnoredDuringExecution 中,topologyKey 不允许为空。
对于 requiredDuringSchedulingIgnoredDuringExecution 要求的 Pod 反亲和性, 准入控制器 LimitPodHardAntiAffinityTopology 要求 topologyKey 只能是 kubernetes.io/hostname。如果你希望使用其他定制拓扑逻辑, 你可以更改准入控制器或者禁用之。
除了 labelSelectortopologyKey,你也可以指定 labelSelector 要匹配的名字空间列表,方法是在 labelSelectortopologyKey 所在层同一层次上设置 namespaces。 如果 namespaces 被忽略或者为空,则默认为 Pod 亲和性/反亲和性的定义所在的名字空间。

9. 验证 Pod 亲和性

按照上面的配置文件,这里先将 Master节点打上topology.kubernetes.io/zone=R 标签,给从节点打上topology.kubernetes.io/zone=V 标签。

[root@docker-54 ~]# kubectl label no docker-54 topology.kubernetes.io/zone=R  
node/docker-54 labeled
[root@docker-54 ~]# 
[root@docker-54 ~]# kubectl label no docker-55 docker-56 topology.kubernetes.io/zone=V
node/docker-55 labeled
node/docker-56 labeled
[root@docker-54 ~]# 
[root@docker-54 ~]# kubectl get no --show-labels                                      
NAME        STATUS   ROLES                  AGE    VERSION   LABELS
docker-54   Ready    control-plane,master   202d   v1.22.6   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,ingress=true,kubernetes.io/arch=amd64,kubernetes.io/hostname=docker-54,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=,node.kubernetes.io/exclude-from-external-load-balancers=,topology.kubernetes.io/zone=R
docker-55   Ready    <none>                 202d   v1.22.6   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,ingress=true,kubernetes.io/arch=amd64,kubernetes.io/hostname=docker-55,kubernetes.io/os=linux,label-1=key-1,topology.kubernetes.io/zone=V,type=microservice
docker-56   Ready    <none>                 202d   v1.22.6   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=docker-56,kubernetes.io/os=linux,label-2=key-2,topology.kubernetes.io/zone=V,type=microservice
[root@docker-54 ~]#

接着新建 s2 标签的配置文件:s2-nginx-deploy-affinity.yaml

apiVersion: apps/v1 # deployment api 版本
kind: Deployment # 资源类型为 deployment
metadata: # 元信息labels: # 标签app: nginx-deploy # 具体的 key: value 配置形式name: nginx-deploy-s2 # deployment 的名字namespace: default # 所在的命名空间
spec:replicas: 1 # 期望副本数revisionHistoryLimit: 10 # 进行滚动更新后,保留的历史版本数selector: # 选择器,用于找到匹配的 RSmatchLabels: # 按照标签匹配app: nginx-deploy # 匹配的标签key/valuestrategy: # 更新策略rollingUpdate: # 滚动更新配置maxSurge: 25% # 进行滚动更新时,更新的个数最多可以超过期望副本数的个数/比例maxUnavailable: 25% # 进行滚动更新时,最大不可用比例更新比例,表示在所有副本数中,最多可以有多少个不更新成功type: RollingUpdate # 更新类型,采用滚动更新template: # pod 模板metadata: # pod 的元信息labels: # pod 的标签app: nginx-deploytopology.kubernetes.io/zone: Vsecurity: S2spec: # pod 期望信息nodeSelector:kubernetes.io/hostname: docker-54containers: # pod 的容器- image: nginx:1.7.9 # 镜像imagePullPolicy: IfNotPresent # 拉取策略name: nginx # 容器名称resources:limits:cpu: 200mmemory: 128Mirequests:cpu: 100mmemory: 128MirestartPolicy: Always # 重启策略terminationGracePeriodSeconds: 30 # 删除操作最多宽限多长时间

这里上面配置的意思是部署一个 Nginx 的 Pod,使用标签选择器,部署到 docker-54 节点上,并且这个 Pod 带有两个后面测试 Pod 亲和力用到的标签:topology.kubernetes.io/zone: Vsecurity: S2

直接创建这个 deployment 看下,使用节点选择器直接调度到 Master 节点上,应该不会成功,因为我这里还没有处理 Master 节点上的污点,看下效果:

[root@docker-54 deployments]# kubectl create -f s2-nginx-deploy-affinity.yaml 
deployment.apps/nginx-deploy-s2 created
[root@docker-54 deployments]# 
[root@docker-54 ~]# kubectl get po -o wide
NAME                               READY   STATUS    RESTARTS       AGE   IP            NODE        NOMINATED NODE   READINESS GATES
nginx-deploy-75578bc7f7-8zz8h      1/1     Running   11 (46m ago)   11h   10.244.0.11   docker-54   <none>           <none>
nginx-deploy-75578bc7f7-xvnfm      1/1     Running   11 (46m ago)   11h   10.244.1.81   docker-55   <none>           <none>
nginx-deploy-s2-5fd5bf9d5c-52d2k   0/1     Pending   0              19s   <none>        <none>      <none>           <none>
[root@docker-54 ~]# 
[root@docker-54 deployments]# kubectl get po -o wide --show-labels
NAME                               READY   STATUS    RESTARTS       AGE    IP            NODE        NOMINATED NODE   READINESS GATES   LABELS
nginx-deploy-75578bc7f7-8zz8h      1/1     Running   11 (50m ago)   11h    10.244.0.11   docker-54   <none>           <none>            app=nginx-deploy,pod-template-hash=75578bc7f7
nginx-deploy-75578bc7f7-xvnfm      1/1     Running   11 (50m ago)   11h    10.244.1.81   docker-55   <none>           <none>            app=nginx-deploy,pod-template-hash=75578bc7f7
nginx-deploy-s2-5fd5bf9d5c-52d2k   0/1     Pending   0              5m2s   <none>        <none>      <none>           <none>            app=nginx-deploy,pod-template-hash=5fd5bf9d5c,security=S2,topology.kubernetes.io/zone=V
[root@docker-54 deployments]# 

可以看到 Pod 的状态为 Pending,接着看下事件:

[root@docker-54 ~]# kubectl describe po nginx-deploy-s2-5fd5bf9d5c-52d2k 
Name:           nginx-deploy-s2-5fd5bf9d5c-52d2k
Namespace:      default
// 省略中间内容
Events:Type     Reason            Age   From               Message----     ------            ----  ----               -------Warning  FailedScheduling  31s   default-scheduler  0/3 nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate, 2 node(s) didn't match Pod's node affinity/selector.
[root@docker-54 ~]# 

可以看到,上面显示了默认调度 3 个节点,没有一个可用,其中一个节点带有污点{node-role.kubernetes.io/master: },并且这个 Pod 没有配置容忍,所以不能调度到它上面,然后另外两个节点不包含 Pod 的节点亲和力标签。

接着来暂时去掉 Master 节点的污点,看下 Pod 能不能正常调度到 Master 节点上:

[root@docker-54 ~]# kubectl describe no docker-54 | grep Taint
Taints:             node-role.kubernetes.io/master:NoSchedule
[root@docker-54 ~]# 
[root@docker-54 ~]# kubectl taint no docker-54 node-role.kubernetes.io/master:NoSchedule-
node/docker-54 untainted
[root@docker-54 ~]# 
[root@docker-54 ~]# kubectl describe no docker-54 | grep Taint                           
Taints:             <none>
[root@docker-54 ~]# 

接着再次看下 Pod 状态:

[root@docker-54 deployments]# kubectl get po -o wide --show-labels
NAME                               READY   STATUS    RESTARTS       AGE     IP            NODE        NOMINATED NODE   READINESS GATES   LABELS
nginx-deploy-75578bc7f7-8zz8h      1/1     Running   11 (55m ago)   11h     10.244.0.11   docker-54   <none>           <none>            app=nginx-deploy,pod-template-hash=75578bc7f7
nginx-deploy-75578bc7f7-xvnfm      1/1     Running   11 (55m ago)   11h     10.244.1.81   docker-55   <none>           <none>            app=nginx-deploy,pod-template-hash=75578bc7f7
nginx-deploy-s2-5fd5bf9d5c-52d2k   1/1     Running   0              9m46s   10.244.0.12   docker-54   <none>           <none>            app=nginx-deploy,pod-template-hash=5fd5bf9d5c,security=S2,topology.kubernetes.io/zone=V
[root@docker-54 deployments]# 

可以看到 nginx-deploy-s2 的 Pod 被调度到 Maser 节点上了。这里不知道是不是 K8s 的bug,明明对节点 docker-54 打了 topology.kubernetes.io/zone=R 的标签,这个 Pod 竟然能调度到这个节点上。

然后我试了下将配置文件中 Pod 模板的标签选择器,配置成topology.kubernetes.io/zone=R 发现还是可以正常调度到 docker-54 节点。那是不是意味着 k8s 在调度时,如果仅仅配置了标签选择器,就会存在一个 BUG,就是仅比对了标签的key,没有比对标签的 value,也就是污点里面判断时用到的 Exists 的功能。这三个节点上都包含 topology.kubernetes.io/zone 的标签,虽然值不一样。

接着新建一个deploy,配置 Pod 带有 S1 的标签:s1-nginx-deploy-affinity.yaml

apiVersion: apps/v1 # deployment api 版本
kind: Deployment # 资源类型为 deployment
metadata: # 元信息labels: # 标签app: nginx-deploy # 具体的 key: value 配置形式name: nginx-deploy-s1 # deployment 的名字namespace: default # 所在的命名空间
spec:replicas: 2 # 期望副本数revisionHistoryLimit: 10 # 进行滚动更新后,保留的历史版本数selector: # 选择器,用于找到匹配的 RSmatchLabels: # 按照标签匹配app: nginx-deploy # 匹配的标签key/valuestrategy: # 更新策略rollingUpdate: # 滚动更新配置maxSurge: 25% # 进行滚动更新时,更新的个数最多可以超过期望副本数的个数/比例maxUnavailable: 25% # 进行滚动更新时,最大不可用比例更新比例,表示在所有副本数中,最多可以有多少个不更新成功type: RollingUpdate # 更新类型,采用滚动更新template: # pod 模板metadata: # pod 的元信息labels: # pod 的标签app: nginx-deploytopology.kubernetes.io/zone: Vsecurity: S1spec: # pod 期望信息containers: # pod 的容器- image: nginx:1.7.9 # 镜像imagePullPolicy: IfNotPresent # 拉取策略name: nginx # 容器名称resources:limits:cpu: 200mmemory: 128Mirequests:cpu: 100mmemory: 128MirestartPolicy: Always # 重启策略terminationGracePeriodSeconds: 30 # 删除操作最多宽限多长时间

可以看到这个配置的 Pod 的标签是 topology.kubernetes.io/zone: Vsecurity: S1 ,刚好对应我们的两个从节点的标签,启动看下是否会调度到两个从节点上:

[root@docker-54 deployments]# kubectl create -f s1-nginx-deploy-affinity.yaml 
deployment.apps/nginx-deploy-s1 created
[root@docker-54 deployments]# 
[root@docker-54 deployments]# kubectl get po -o wide --show-labels            
NAME                               READY   STATUS    RESTARTS   AGE   IP             NODE        NOMINATED NODE   READINESS GATES   LABELS
nginx-deploy-s1-7bbd9fbdb7-25627   1/1     Running   0          2s    10.244.0.19    docker-54   <none>           <none>            app=nginx-deploy,pod-template-hash=7bbd9fbdb7,security=S1,topology.kubernetes.io/zone=V
nginx-deploy-s1-7bbd9fbdb7-bqwm4   1/1     Running   0          2s    10.244.2.127   docker-56   <none>           <none>            app=nginx-deploy,pod-template-hash=7bbd9fbdb7,security=S1,topology.kubernetes.io/zone=V
nginx-deploy-s2-df8df55b9-f8cb6    1/1     Running   0          79s   10.244.0.18    docker-54   <none>           <none>            app=nginx-deploy,pod-template-hash=df8df55b9,security=S2,topology.kubernetes.io/zone=R
[root@docker-54 deployments]# 

理想情况下,s1 的 deploy 的两个 Pod 应该被调度到两个带有 topology.kubernetes.io/zone=V 的标签的从节点上,但是!!!事实情况却不是这样:

[root@docker-54 deployments]# kubectl get po -o wide --show-labels            
NAME                               READY   STATUS    RESTARTS   AGE   IP             NODE        NOMINATED NODE   READINESS GATES   LABELS
nginx-deploy-s1-7bbd9fbdb7-25627   1/1     Running   0          2s    10.244.0.19    docker-54   <none>           <none>            app=nginx-deploy,pod-template-hash=7bbd9fbdb7,security=S1,topology.kubernetes.io/zone=V
nginx-deploy-s1-7bbd9fbdb7-bqwm4   1/1     Running   0          2s    10.244.2.127   docker-56   <none>           <none>            app=nginx-deploy,pod-template-hash=7bbd9fbdb7,security=S1,topology.kubernetes.io/zone=V
nginx-deploy-s2-df8df55b9-f8cb6    1/1     Running   0          79s   10.244.0.18    docker-54   <none>           <none>            app=nginx-deploy,pod-template-hash=df8df55b9,security=S2,topology.kubernetes.io/zone=R
[root@docker-54 deployments]# 

其中一个节点死活就是不去 docker-55 节点上,就非得赖上 docker-54 节点了。

我还特意检查了下 docker-55 节点上是不是配置了污点什么的:

[root@docker-54 ~]# kubectl describe no docker-55 | grep Taints
Taints:             <none>
[root@docker-54 ~]# 
[root@docker-54 ~]# kubectl describe no docker-54 | grep Taints 
Taints:             <none>
[root@docker-54 ~]# 
[root@docker-54 ~]# kubectl describe no docker-56 | grep Taints 
Taints:             <none>
[root@docker-54 ~]# 

多次删除 deploy ,还是这样,玩不下去了。。。。。。。

就这吧,辣鸡标签选择器,果然仅用他来控制调度不靠谱,怪不得有污点和亲和力的功能的出现,不争气的东西。。。。。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/194852.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

prometheus基础,结合node_exporter监控节点

文章目录 一、Prometheus是什么二、exporters是什么三、node_exporter四、安装 Prometheus 和 node_exporter下载运行 prometheus运行 node_exporter 五、配置 Prometheus 收集监控数据总结 一、Prometheus是什么 Prometheus 是一个开源的监控和警报工具&#xff0c;它记录任何…

Centos7安装docker、java、python环境

文章目录 前言一、docker的安装二、docker-compose的安装三、安装python3和配置pip3配置python软链接&#xff08;关键&#xff09; 四、Centos 7.6操作系统安装JAVA环境 前言 每次vps安装docker都要看网上的文章&#xff0c;而且都非常坑&#xff0c;方法千奇百怪&#xff0c…

c++ 构造

#include <iostream> using namespace std; class Coordinate { public: // 无参构造函数 // 如果创建一个类你没有写任何构造函数&#xff0c;则系统自动生成默认的构造函数&#xff0c;函数为空&#xff0c;什么都不干 // 如果自己显示定义了一…

go elasticsearch 测试实例

// 查询列表数据 func QueryOperateList(ctx context.Context, esClient *elastic.Client, index string, pageNum, pageSize int, start, end int64, execSql string, list []interface{}, operateAccount string, operateAddr string, maxRows, minRows int, dbAddr, namespa…

对象转成json后转成byte[]后在转成string会提示序列化失败,第一个字符是问号

问题复现 一个对象需要转成json 后转成byte[]后经过网络传输&#xff0c;后再次反序列化为对象&#xff0c;但是最后反序列的时候会报错&#xff0c;打印json发现开头是一个问号 省流 使用这个进行反序列化 /// <summary>/// 反序列化方法/// </summary>/// <…

Java 中如何正确的将 float 转换成 double?

为什么 double 转 float 不会出现数据误差&#xff0c;而 float 转 double 却误差如此之大&#xff1f; double d 3.14; float f (float)d; System.out.println(f);输出结果是:3.14; float f 127.1f; double d f; System.out.println(d);输出结果是&#xff1a;127.09999…

【USRP】5G / 6G 原型系统 5g / 6G prototype system

面向5G/6G科研应用 USRP专门用于5G/6G产品的原型开发与验证。该系统可以在实验室搭建一个真实的5G 网络&#xff0c;基于开源的代码&#xff0c;专为科研用户设计。 软件无线电架构&#xff0c;构建真实5G移动通信系统 X410 采用了目前流行的异构式系统&#xff0c;融合了FP…

【毕业设计】基于雷达与深度学习的摔倒检测——微多普勒效应

运动物体的微多普勒效应为人体动作识别提供了可能&#xff0c;基于雷达的居家检测具有良好的隐私保护性&#xff0c;且不易受环境因素影响&#xff08;如光照、温度等&#xff09;&#xff0c;近年来已受到国内外学者的广泛关注。由于雷达信号的非平稳特性&#xff0c;通过短时…

Oracle-CDB容器数据库修改service_names踩坑

前言: 最近在对一套Oracle容器数据库进行迁移测试时&#xff0c;为了保持新环境与旧环境的服务名一致&#xff0c;需要在新环境添加旧环境的服务名&#xff0c;在CDB的根容器通过service_name参数添加旧环境的服务名之后&#xff0c;发现数据库PDB的服务名全部被注销&#xff0…

自动驾驶学习笔记(十四)——感知算法

#Apollo开发者# 学习课程的传送门如下&#xff0c;当您也准备学习自动驾驶时&#xff0c;可以和我一同前往&#xff1a; 《自动驾驶新人之旅》免费课程—> 传送门 《Apollo Beta宣讲和线下沙龙》免费报名—>传送门 文章目录 前言 感知算法 开发过程 测试和评价 前言…

[leetcode 哈希表] 模版

文章目录 1.有效字母的异位词 E2. 两个数组的交集 E3.快乐数 E4. 两数之和 E5. **topk(前k个高频元素) M** 1.有效字母的异位词 E :::details 给定两个字符串 s 和 t &#xff0c;编写一个函数来判断 t 是否是 s 的字母异位词。 注意&#xff1a;若 s 和 t 中每个字符出现的次…

一致性哈希算法,hash(key)是负值时,会出现异常吗?

一致性哈希算法,hash(key)是负值时,会出现异常吗? 一致性哈希算法中&#xff0c;哈希函数hash(key)的返回值通常是一个非负整数。如果hash(key)返回负值&#xff0c;则可能会出现一些问题&#xff0c;例如无法正确地映射对象到哈希环上的位置&#xff0c;或者无法正确地找到…

【PTA-C语言】编程练习3 - 循环结构Ⅱ

如果代码存在问题&#xff0c;麻烦大家指正 ~ ~有帮助麻烦点个赞 ~ ~ 编程练习3 - 循环结构&#xff08;9~15&#xff09; 7-9 特殊a串数列求和&#xff08;分数 15&#xff09;7-10 穷举法搬运砖块问题&#xff08;分数 15&#xff09;7-11 数字金字塔&#xff08;分数 15&…

鸿蒙4.0开发笔记之ArkTS装饰器语法基础@Prop@Link@State状态装饰器(十二)

文章目录 一、哪些是状态装饰器二、StatePropLink状态传递的核心规则三、状态装饰器练习 一、哪些是状态装饰器 1、State&#xff1a;被装饰拥有其所属组件的状态&#xff0c;可以作为其子组件单向和双向同步的数据源。当其数值改变时&#xff0c;会引起相关组件的渲染刷新。 …

思维模型 赫洛克效应

本系列文章 主要是 分享 思维模型&#xff0c;涉及各个领域&#xff0c;重在提升认知。及时反馈&#xff0c;激发动力。 1 赫洛克效应的应用 1.1 赫洛克效应在管理中的应用 美国惠普公司是一家全球知名的科技公司&#xff0c;该公司非常注重员工的激励和认可。在惠普公司&…

网络和Linux网络_9(应用层和传输层_笔试选择题)

目录 一. 常见应用协议等等 1. 以下不是合法HTTP请求方法的是( ) 2. 文件传输使用的协议是&#xff08;&#xff09; 3. HTTP1.1的请求方法不包括&#xff1f;() 4. http状态码中&#xff0c;( )表示访问成功&#xff0c;( )表示坏请求&#xff0c;( )表示服务不可用。() …

mysql的几种索引

mysql可以在表的一列、或者多列上创建索引&#xff0c;索引的类型可以选择&#xff0c;如下&#xff1a; 普通索引&#xff08;KEY&#xff09; 普通索引可以提高查询效率。在表的一列、或者多列上创建索引。 每个表可以创建多个普通索引。 例如&#xff0c;下面示例&#…

智能优化算法应用:基于海洋捕食者算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于海洋捕食者算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于海洋捕食者算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.海洋捕食者算法4.实验参数设定5.算法结果…

KWin、libdrm、DRM从上到下全过程 —— drmModeAddFBxxx(21)

接前一篇文章:KWin、libdrm、DRM从上到下全过程 —— drmModeAddFBxxx(20) 距离本系列上一篇文章发布的时间已经过去了十多天,虽然这样算下来时间不算长,但笔者感觉上都快过了一个月没更新了。这可能是在我心里一直把Linux图形、尤其是DRM、libdrm这块看得很重,总想尽快往…

实现一个简单的网络通信下(udp)

时间过去好久了&#xff0c;先回忆一下上一篇博客的代码&#xff01;&#xff01; 目前来看&#xff0c;我们客户端发一条消息&#xff0c;我服务器收到这一条消息之后呢&#xff0c;服务器也知道了是谁给我发来的消息&#xff0c;紧接这就把这条消息放进buffer当中&#xff0c…