k8s亲和性和反亲和性

k8s中的亲和性主要是用来做pod的调度策略,可以使pod调度到满足指定条件的节点
通常我们还需要给node设置标签,pod通过设置的label标签相关的策略可以使pod关联到对应的label节点上
我们先来看下测试环境的node标签

kubectl get node --show-labels
NAME         STATUS   ROLES                  AGE   VERSION   LABELS
k8s-master   Ready    control-plane,master   14d   v1.23.5   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=,node.kubernetes.io/exclude-from-external-load-balancers=
k8s-node1    Ready    <none>                 14d   v1.23.5   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node1,kubernetes.io/os=linux
k8s-node2    Ready    <none>                 14d   v1.23.5   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node2,kubernetes.io/os=linux

给k8s-node1,k8s-node2添加标签

kubectl label node k8s-node1 nodetype=test_worker
kubectl label node k8s-node1 disktype=ssd
kubectl label node k8s-node2 nodetype=test_node
kubectl get node --show-labels
NAME         STATUS   ROLES                  AGE   VERSION   LABELS
k8s-master   Ready    control-plane,master   14d   v1.23.5   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=,node.kubernetes.io/exclude-from-external-load-balancers=
k8s-node1    Ready    <none>                 14d   v1.23.5   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=ssd,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node1,kubernetes.io/os=linux,nodetype=test_worker
k8s-node2    Ready    <none>                 14d   v1.23.5   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node2,kubernetes.io/os=linux,nodetype=test_node

如果删除标签=test_node换成-即可,如下代码

kubectl label node k8s-node2 nodetype-

1.node亲和性
一般我们需要pod调度到指定节点可以使用nodeSelector,这个方法可以很好的解决这种需求,当我们需要多个服务按需求调度到各个指定节点时,这种需求nodeSelector就满足不了了,这个时候我们就需要亲和性的相关策略来实现这种需求
我们先来讲讲节点亲和性nodeAffinity,nodeAffinity允许我们指定一些Pod在Node间调度的约束
nodeAffinity 支持两种形式:
requiredDuringSchedulingIgnoredDuringExecution  #硬限制, 同nodeSelector
preferredDuringSchedulingIgnoredDuringExecution #软限制)
可以认为前一种是必须满足,如果不满足则不进行调度,后一种是倾向满足,不满足的情况下会调度到不符合条件的Node节点上
IgnoreDuringExecution表示如果在Pod运行期间Node的标签发生变化,导致亲和性策略不能满足,则继续运行当前的Pod
我们接着来上个例子
nginx-affinity.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: nginx-affinity
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: nodetype
            operator: In
            values:
            - test_node
            - test_worker
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1  #取值范围1-100
        preference:
          matchExpressions:
          - key: disktype
            operator: In
            values:
            - ssd
  containers:
  - name: nginx
    image: nginx

创建pod并查看调度位置

kubectl apply -f nginx-affinity.yaml
kubectl get pod -o wide

微信截图_20220407174921.png
标签判断的操作符除了使用In之外,还可以使用NotIn、Exists、DoesNotExist、Gt、Lt 操作符, 也可以使用 NotIn 、 DoesNotExist 来实现反亲和性,也可以通过node taints来实现,上述例子pod调度节点必须满足nodetype是test_worker或者test_node,同时下面软性条件是disktype必须是ssd,所以最后调度到了k8s-node1这个节点上了。
1)如果同时指定 nodeSelector 和 nodeAffinity ,两者同时满足才会被调度。
2)如果指定多个nodeSelectorTerms,则只要满足其中一个条件,就会被调度到相应的节点上。
3)如果指定多个matchExpressions,则所有的条件都必须满足,才会调度到对应的节点。必须是ssd,所以最后调度到了k8s-node1这个节点上了。
2.pod亲和性
pod亲和性podAffinity、反亲和性podAntiAffinity,pod亲和性主要是通过在已经运行的pod上的标签来定制调度策略,注意这里说的是pod标签不是node标签
因为Node没有命名空间,Pod有命名空间,这样就允许管理员在配置的时候指定这个亲和性策略适用于哪个命名空间,可以通过topologyKey来指定,同时topologyKey不能为空,一般将其限制为kubernetes.io/hostname
同nodeAffinity,pod亲和性和反亲和性也有两种类型:
requiredDuringSchedulingIgnoredDuringExecution,硬性要求,必须精确匹配
preferredDuringSchedulingIgnoredDuringExecution,软性要求
pod亲和性和反亲和性需要大量的计算,会显著降低集群的调度速度,不建议在大于几百个节点的集群中使用。 pod反亲和性要求集群中的所有节点必须具有 topologyKey匹配的标签,否则可能会导致意外情况发生
我们接着来上个例子
pod-affinity.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: pod-affinity
spec:
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: remark
            operator: In
            values:
            - study
        topologyKey: failure-domain.beta.kubernetes.io/zone
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: remark
              operator: In
              values:
              - game
          topologyKey: kubernetes.io/hostname
  containers:
  - name: nginx
    image: nginx

podAffinity 和 podAntiAffinity 支持 In 、 NotIn 、 Exists 、 DoesNotExist 四种表达式,上述示例表示pod调度到标签是remark=study的pod所在的节点上,而podAntiAffinity反亲和性则说是不要调度到标签是remark=study的pod所在的节点上
上述两种情况的中topologyKey则是描述的更精准的说法也是node节点要满足failure-domain.beta.kubernetes.io/zone或者kubernetes.io/hostname这两个key

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://sulao.cn/post/827.html

我要评论

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。