十八、K8S-亲和性和反亲和性

目录

k8s中亲和性和反亲和性

一、固定节点调度 

1、nodeSelector(通过标签选择方式调度)

2、nodeName调度(通过指定节点名称的方式)

二、node亲和性

1、node 硬亲和性

2、node软亲和性

三、pod亲和性

1、pod硬亲和性

2、pod软亲和性

3、pod反亲和性

四、亲和性和反亲和性详细yaml文件

五、topology拓扑域的概念

 1、服务拓扑


k8s中亲和性和反亲和性

        kubernetes的默认调度以预选、优选、选定机制完成将每个新的Pod资源绑定至为其选出的目标节点上,不过,它只是pod对象的默认调度器,默认情况下调度器考虑的是资源足够,并且负载尽量平均。

        在使用中,可以自定义调度器插件,并在定义pod资源配置清单时通过spec.schedulerName指定即可

Affinity:

  1. nodeAffinity: 节点亲和力
    1. requiredDuringSchedulingIgnoredDuringExecution:硬亲和性,强制的,即支持必须部署在指定的节点上,也支持必须不部署在指定节点上,
    2. preferredDuringSchedulingIgnoredDuringExecution:软亲和性,尽量部署在满足条件的节点上,或者尽量不部署在满足条件的节点上
  2. podAffinity:pod亲和力
    1. requiredDuringSchedulingIgnoredDuringExecution:硬亲和性,强制的,将A应用和B 应用部署在一起
    2. preferredDuringSchedulingIgnoredDuringExecution:软亲和性,尽量将A应用和B 应用部署在一起
  3. podAntiAffinity:pod反亲和力
    1. requiredDuringSchedulingIgnoredDuringExecution:不要将A和B部署在一起
    2. preferredDuringSchedulingIgnoredDuringExecution:尽量不要将A和B部署在一起

一、固定节点调度 

1、nodeSelector(通过标签选择方式调度)

        对于最初k8s实现pod指定node调度时使用nodeSelector来实现的,主要是通过定义node以及pod标签进行选择,具体实现如下

1、给节点添加label标签
[root@k8s-master-1 diaodu]# kubectl label node k8s-node-2 ds=true
[root@k8s-master-1 diaodu]# vim deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: taint-test
  labels:
    ds: "true"
spec:
  replicas: 5
  selector:
    matchLabels:
      ds: "true"
  template:
    metadata:
      labels:
        ds: "true"
    spec:
      nodeSelector: #选择标签
        ds: "true"
      containers:
      - image: nginx:1.17.1
        name: nginx
[root@k8s-master-1 diaodu]# kubectl apply -f deployment.yaml 
deployment.apps/taint-test created
[root@k8s-master-1 diaodu]# 
[root@k8s-master-1 diaodu]# 
[root@k8s-master-1 diaodu]# kubectl get pod -owide
NAME                         READY   STATUS    RESTARTS   AGE   IP            NODE         NOMINATED NODE   READINESS GATES
taint-test-cbf7b4fdd-jf2rc   1/1     Running   0          4s    10.244.1.69   k8s-node-2              
taint-test-cbf7b4fdd-k6fmg   1/1     Running   0          4s    10.244.1.70   k8s-node-2              
taint-test-cbf7b4fdd-r9pvn   1/1     Running   0          4s    10.244.1.73   k8s-node-2              
taint-test-cbf7b4fdd-t8p56   1/1     Running   0          4s    10.244.1.71   k8s-node-2              
taint-test-cbf7b4fdd-zcdsz   1/1     Running   0          4s    10.244.1.72   k8s-node-2              

2、nodeName调度(通过指定节点名称的方式)


[root@k8s-master-1 diaodu]# vim test2.yaml 
 apiVersion: apps/v1
kind: Deployment
metadata:
  name: test2
  labels:
    test: "server"
spec:
  replicas: 3
  selector:
    matchLabels:
      test: "server"
  template:
    metadata:
      labels:
        test: "server"
    spec:
      nodeName: k8s-node-2        

      containers:
      - image: nginx:1.17.1
        name: nginx
        imagePullPolicy: IfNotPresent  
[root@k8s-master-1 diaodu]# kubectl get pod -owide
NAME                     READY   STATUS    RESTARTS   AGE   IP             NODE         NOMINATED NODE   READINESS GATES
test2-68d7b6dc48-4bn9q   1/1     Running   0          6s    10.244.1.128   k8s-node-2              
test2-68d7b6dc48-5t9lg   1/1     Running   0          6s    10.244.1.129   k8s-node-2              
test2-68d7b6dc48-6stqv   1/1     Running   0          6s    10.244.1.130   k8s-node-2              
             

二、node亲和性

        NodeAffinity 意为Node节点亲和性的调度策略,是用于替换NodeSelector的全新调度策略

        定义节点亲和性规则时有两种类型的节点亲和性规则:硬亲和性required和软亲和性perferred,硬亲和性实现的是强制性规则,它是Pod调度时必须要满足的规则,而在不存在满足规则的节点时,Pod对象会被置为Pending状态。而软亲和性规则实现的是一种柔性调度限制,它倾向于将pod对象运行与某类特定的节点上,而调度器也将尽量满足此需求,但在无法满足调度需求时它将退而求其次地选择一个不匹配规则的节点。

1、node 硬亲和性

        为pod对象使用nodeSelector属性可以基于节点标签匹配的方式将pod对象强制调度到某一类特定的节点上,不过它仅能基于简单的等值关系定义标签选择器,而nodeAffinity中支持使用matchExpressions属性构建更为复杂的标签选择机制.

        节点的亲和性是通过Pod.spec的affinity字段下的nodeAffinity字段进行指定的。

[root@k8s-master-1 diaodu]# vim deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: taint-test
  labels:
    ds: "true"
spec:
  replicas: 3
  selector:
    matchLabels:
      ds: "true"
  template:
    metadata:
      labels:
        ds: "true"
    spec:

      containers:
      - image: nginx:1.17.1
        name: nginx
        imagePullPolicy: IfNotPresent
      affinity:
        nodeAffinity:#作用域,Pod和Node之间
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: ds
                operator: In
                values:
                - "true"
[root@k8s-master-1 diaodu]# kubectl apply -f deployment.yaml 
deployment.apps/taint-test created
[root@k8s-master-1 diaodu]# 

[root@k8s-master-1 diaodu]# kubectl get pod -owide
NAME                          READY   STATUS    RESTARTS   AGE   IP            NODE         NOMINATED NODE   READINESS GATES
taint-test-6ffb5f4cc4-6wv4x   1/1     Running   0          5s    10.244.1.75   k8s-node-2              
taint-test-6ffb5f4cc4-9mcjk   1/1     Running   0          5s    10.244.1.77   k8s-node-2              
taint-test-6ffb5f4cc4-jjrkd   1/1     Running   0          5s    10.244.1.76   k8s-node-2              

        在定义节点亲和性时,requiredDuringSchedulingIgnoredDuringExecution字段的值是一个对象列表,用于定义节点硬亲和性,它可由一个或者多个nodeSelectorTerm定义的对象组成,彼此间为“逻辑或”的关系,进行匹配度检查时,在多个nodeSelectorTerm之间只要满足其中之一即可。

        preferredDuringSchedulingIgnoredDuringExecution和requiredDuringSchedulingIgnoredDuringExecution名字中的后半段符串IgnoredDuringExecution隐含的意义所指,在Pod资源基于节点亲和性规则调度至某节点之后,节点标签发生了改变而不再符合此节点亲和性规则时 ,调度器不会将Pod对象从此节点上移出,因为,它仅对新建的Pod对象生效。

        nodeSelectorTerm用于定义节点选择器条目,其值为对象列表,它可由一个或多个matchExpressions对象定义的匹配规则组成,多个规则彼此之间为“逻辑与”的关系, 这就意味着某节点的标签需要完全匹配同一个nodeSelectorTerm下所有的matchExpression对象定义的规则才算成功通过节点选择器条目的检查。而matchExmpressions又可由 一到多 个标签选择器组成,多个标签选择器彼此间为“逻辑与”的关系 。

        注意事项

  • 如果同时指定了nodeSelector和nodeAffinity,两者必须都要满足,才能将Pod调度到候选节点上;
  • 如果指定了多个与nodeAffinity类型关联的nodeSelectorTerms,只要其中有一个nodeSelectorTerms满足的话,Pod就可以调度到指定节点上;
  • 如果指定了多个与nodeSelectorTerms关联的matchExpressions,则只有当所有的matchExpressions满足要求,Pod才会调度到指定节点上;
  • 如果我们修改或删除了Pod所调度到的节点的标签,Pod不会被删除;
  • 软策略中的weight属性是权重的意思,取值范围是1-100。如果存在多个软策略的话,对于亲和性规则而言,权重越大越亲和;对于反亲和性规则而言,权重越大越不亲和。
给node1打一个标签
[root@k8s-master-1 diaodu]# kubectl label node k8s-node-1 ds=server
node/k8s-node-1 labeled
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:    # 硬策略
            nodeSelectorTerms:
            - matchExpressions:
              - key: ds
                operator: In
                values:
                - "true"
                - "server"
- - - 或者- - -
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:#逻辑或的关系,满足其一即可
            - matchExpressions:
              - key: ds
                operator: In
                values:
                - "true"

            - matchExpressions:
              - key: ds
                operator: In
                values:
                - "server"

########启动pod,都会在node2和node1上调度
[root@k8s-master-1 diaodu]# kubectl get pod -owide
NAME                          READY   STATUS    RESTARTS   AGE   IP            NODE         NOMINATED NODE   READINESS GATES
taint-test-68485fdf87-5fvz5   1/1     Running   0          4s    10.244.0.44   k8s-node-1              
taint-test-68485fdf87-b644w   1/1     Running   0          4s    10.244.1.79   k8s-node-2              
taint-test-68485fdf87-f4cfx   1/1     Running   0          4s    10.244.0.45   k8s-node-1              
taint-test-68485fdf87-h7kp9   1/1     Running   0          4s    10.244.1.81   k8s-node-2              
taint-test-68485fdf87-j2m8z   1/1     Running   0          4s    10.244.1.80   k8s-node-2              

- - -或者- - -
node1上原来标签删除,重新添加一个新的标签
[root@k8s-master-1 diaodu]# kubectl label node k8s-node-1 test=server
node/k8s-node-1 labeled
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: ds #逻辑与的关系,必须同时满足,此时创建pod状态为:Pending,
                operator: In
                values:
                - "true"
              - key: test
                operator: In
                values:
                - "server"

[root@k8s-master-1 diaodu]# kubectl get pod -owide
NAME                          READY   STATUS    RESTARTS   AGE   IP       NODE     NOMINATED NODE   READINESS GATES
taint-test-57f98dd8c8-59kb7   0/1     Pending   0          4s                     
taint-test-57f98dd8c8-7sh6w   0/1     Pending   0          4s                     
taint-test-57f98dd8c8-8cxxr   0/1     Pending   0          4s                     
taint-test-57f98dd8c8-dwm9r   0/1     Pending   0          4s                     
taint-test-57f98dd8c8-mshmd   0/1     Pending   0          4s                     

此时创建pod状态为:Pending,因为他是逻辑与的关系,两个条件必须同时满足 才能创建成功,我们在node1上添加标签

[root@k8s-master-1 diaodu]# kubectl label node k8s-node-1 ds=true
node/k8s-node-1 labeled

此时pod状态为:Running,因为只有node1满足条件,所以都被调度到node1上了。
[root@k8s-master-1 diaodu]# kubectl get pod -owide
NAME                          READY   STATUS    RESTARTS   AGE    IP            NODE         NOMINATED NODE   READINESS GATES
taint-test-57f98dd8c8-59kb7   1/1     Running   0          104s   10.244.0.52   k8s-node-1              
taint-test-57f98dd8c8-7sh6w   1/1     Running   0          104s   10.244.0.50   k8s-node-1              
taint-test-57f98dd8c8-8cxxr   1/1     Running   0          104s   10.244.0.51   k8s-node-1              
taint-test-57f98dd8c8-dwm9r   1/1     Running   0          104s   10.244.0.48   k8s-node-1              
taint-test-57f98dd8c8-mshmd   1/1     Running   0          104s   10.244.0.49   k8s-node-1              

构建标签选择器表达式中支持使用操作符有In、NotIn、Exists、DoesNotExist、Lt、和Gt等

  • In:label的值在某个列表中
  • NotIn:label的值不在某个列表中
  • Gt:label的值大于某个值
  • Lt:label的值小于某个值
  • Exists:某个label存在####value为任意值
  • DoesNoExist:某个label

2、node软亲和性

        节点软亲和性为节点选择机制提供了一种柔性控制逻辑,被调度的pod对象不再试“必须”而是“应该”,放置于某些特定的节点上,当条件不满足时它也能够接受被编排于其他不符合条件的节点之上,另外,它还为每种倾向性提供了weight属性便于用户定义其优先级,取值范围是1-100,数字越大优先级越高。

[root@k8s-master-1 diaodu]# vim deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: taint-test
  labels:
    ds: "true"
spec:
  replicas: 5
  selector:
    matchLabels:
      ds: "true"
  template:
    metadata:
      labels:
        ds: "true"
    spec:
#      nodeSelector:
#        ds: "true"
      containers:
      - image: nginx:1.17.1
        name: nginx
        imagePullPolicy: IfNotPresent
      affinity:
        nodeAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:  # 软策略
          - weight: 80    ###设置ds=true的权重为80
            preference:
              matchExpressions:
              - key: ds
                operator: In
                values:
                - "true"
          - weight: 20    ###设置test=server的权重为20
            preference:
              matchExpressions:
              - key: test
                operator: In
                values:
                - "server"
[root@k8s-master-1 diaodu]# kubectl get pod -owide
NAME                          READY   STATUS    RESTARTS   AGE   IP            NODE         NOMINATED NODE   READINESS GATES
taint-test-7bf8b98c9d-492h2   1/1     Running   0          6s    10.244.1.91   k8s-node-2              
taint-test-7bf8b98c9d-ff42s   1/1     Running   0          6s    10.244.1.90   k8s-node-2              
taint-test-7bf8b98c9d-g9wqb   1/1     Running   0          6s    10.244.1.89   k8s-node-2              
taint-test-7bf8b98c9d-grbqv   1/1     Running   0          6s    10.244.1.88   k8s-node-2              
taint-test-7bf8b98c9d-hpbxr   1/1     Running   0          6s    10.244.0.55   k8s-node-1              
#####启动pod如下,会发现大部分pod在ds=true的node上

三、pod亲和性

        Pod亲和性指的是满足特定条件的pod对象运行在同一个node上,而反亲和性调度则要求它们不能运行在同一个node上

1、pod硬亲和性

        Pod强制约束的亲和性调度也是用requiredDuringSchedulinglgnoredDuringExecution属性进行定义

查看有标签为ds=true的pod
[root@k8s-master-1 diaodu]# kubectl get pod -l ds=true -owide
NAME                          READY   STATUS    RESTARTS   AGE    IP             NODE         NOMINATED NODE   READINESS GATES
test-848f897788-vjlbv   1/1     Running   0          107s   10.244.1.105   k8s-node-2              

[root@k8s-master-1 diaodu]# vim deployment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: taint-test
  labels:
    ds: "true"
spec:
  replicas: 5
  selector:
    matchLabels:
      ds: "true"
  template:
    metadata:
      labels:
        ds: "true"
    spec:

      containers:
      - image: nginx:1.17.1
        name: nginx
        imagePullPolicy: IfNotPresent
      affinity:
        podAffinity:#作用域,Pod和Pod之间
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: ds
                operator: In
                values:
                - "true"
            namespaces:
            - kube-system                    
            topologyKey: kubernetes.io/hostname
[root@k8s-master-1 diaodu]# kubectl apply -f deployment.yaml 
deployment.apps/taint-test created
[root@k8s-master-1 diaodu]# 

[root@k8s-master-1 diaodu]# kubectl get pod -owide
NAME                          READY   STATUS    RESTARTS   AGE     IP             NODE         NOMINATED NODE   READINESS GATES
taint-test-7c4f9995f6-4sj82   1/1     Running   0          8m54s   10.244.1.111   k8s-node-2              
taint-test-7c4f9995f6-6crp6   1/1     Running   0          8m54s   10.244.1.113   k8s-node-2              
taint-test-7c4f9995f6-skxk5   1/1     Running   0          8m54s   10.244.1.112   k8s-node-2              
taint-test-7c4f9995f6-x6vp9   1/1     Running   0          8m54s   10.244.1.114   k8s-node-2              
taint-test-7c4f9995f6-xkv5j   1/1     Running   0          8m54s   10.244.1.115   k8s-node-2              
test-848f897788-tt6kj         1/1     Running   0          9m30s   10.244.1.110   k8s-node-2              

在调度示例中的Deployment控制器创建的Pod资源时,调度器首先会基于标签选择器 查询拥有标签ds=true的所有Pod资源,
接着获取到它们分别所属 的节点的zone标签值,接下来再查询拥有匹配这些标签值的所有节点,从而完成节点预选。
而后根据优选函数计算这些节点的优先级,从而挑选出运行新建Pod对象的节点。

上面这个例子中的 pod 需要调度到某个指定的主机上,至少有一个节点上运行了这样的 pod:这个 pod 有一个ds=true的 label。
加入对应ds=true的label的pod在node2上,我们部署的5个 pod 副本也应该运行在 node02 节点

namespaces:如果写了namespaces字段,但是值为空的话,它是匹配所有namespaces下指定label的Pod
如果写了namespaces,并且指定了该值,那么他就会筛选指定namespaces下的指定label的Pod.
如果没有写namespaces,就会匹配当前的namespaces
topologyKey: kubernetes.io/hostname  拓扑域,意思就是我们当前调度的 pod 要和目标的 pod 处于同一个主机上面,因为要处于同一个拓扑域下面,
为了说明这个问题,我们把拓扑域改成beta.kubernetes.io/os,同样的我们当前调度的 pod 要和目标的 pod 处于同一个拓扑域中,
目标的 pod 是不是拥有beta.kubernetes.io/os=linux的标签,而我们这里3个节点都有这样的标签,这也就意味着我们3个节点都在同一个拓扑域中,
所以我们这里的 pod 可能会被调度到任何一个节点:

2、pod软亲和性

        类似于节点亲和机制,Pod也支持使用preferredDuringSchedulinglgnoredDuringExecution属性定义柔性亲和机制,调度器会尽力确保满足亲和约束的调度逻辑,然而在约束条件不能得到满足时,他也允许将Pod对象调度值其他节点运行。下面是使用了Pod软亲和性调度机制的资源配置清单示例:

#Pod软亲和性
[root@k8s-master-1 diaodu]# kubectl get pod --show-labels
NAME                          READY   STATUS    RESTARTS   AGE     LABELS

test-848f897788-tt6kj         1/1     Running   0          19m     ds=true,pod-template-hash=848f897788
test2-5897dbc444-8wdth        1/1     Running   0          6m37s   pod-template-hash=5897dbc444,test=server
[root@k8s-master-1 diaodu]# vim deployment.yaml 
    spec:
      containers:
      - image: nginx:1.17.1
        name: nginx
        imagePullPolicy: IfNotPresent
#Pod软亲和性
      affinity:
        podAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 90
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: test
                  operator: In
                  values:
                  - "server"
              topologyKey: kubernetes.io/hostname
          - weight: 5
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: ds
                  operator: In
                  values:
                  - "true"
              topologyKey: kubernetes.io/hostname
创建成功之后
pod软硬亲和性时针对pod而言的,是先判断该节点上存在不存在有标签为test=server的pod或者标签为ds=true的pod,
如果有则有90的权重会调度到test=server节点,5的权重会调度到ds=true节点
[root@k8s-master-1 diaodu]# kubectl get pod -owide
NAME                          READY   STATUS    RESTARTS   AGE     IP             NODE         NOMINATED NODE   READINESS GATES
taint-test-77c94446f7-5scz7   1/1     Running   0          4s      10.244.0.74    k8s-node-1              
taint-test-77c94446f7-gxzzz   1/1     Running   0          4s      10.244.1.122   k8s-node-2              
taint-test-77c94446f7-n4kbx   1/1     Running   0          4s      10.244.0.75    k8s-node-1              
taint-test-77c94446f7-n8qk2   1/1     Running   0          4s      10.244.0.76    k8s-node-1              
taint-test-77c94446f7-vdsjj   1/1     Running   0          4s      10.244.0.77    k8s-node-1              
test-848f897788-tt6kj         1/1     Running   0          18m     10.244.1.110   k8s-node-2              
test2-5897dbc444-8wdth        1/1     Running   0          5m53s   10.244.0.64    k8s-node-1              

3、pod反亲和性

        podAffinity用于定义Pod对象的亲和性约束,对应的,将其替换为podAntiAffinity即可用于定义Pod的反亲和约束。不过,反亲和性调度一般用于分散同一类应用的Pod对象等,也包括将不同安全级别的Pod对象调整至不同 的区域,机架或节点等,下面的资源配置清单中定义了由同一Deployment创建但彼此基于节点位置互斥的Pod对象:

[root@k8s-master-1 diaodu]# kubectl get pod -owide --show-labels
NAME                          READY   STATUS    RESTARTS   AGE    IP             NODE         NOMINATED NODE   READINESS GATES   LABELS

test-848f897788-28qwn         1/1     Running   0          2m7s   10.244.1.125   k8s-node-2                          ds=true,pod-template-hash=848f897788
test2-5897dbc444-2tp2g        1/1     Running   0          25s    10.244.0.80    k8s-node-1                          pod-template-hash=5897dbc444,test=server
[root@k8s-master-1 diaodu]# vim deployment.yaml
    spec:
      containers:
      - image: nginx:1.17.1
        name: nginx
        imagePullPolicy: IfNotPresent
#Pod反亲和性
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: test
                operator: In
                values:
                - "server"
            topologyKey: kubernetes.io/hostname
[root@k8s-master-1 diaodu]# kubectl apply -f deployment.yaml 
deployment.apps/taint-test created
从上面的标签就可以看出来,pod标签为test=server的pod 在node1上,根据pod反亲和性的规则,创建的deploy声明了不让他调度到test=server的pod
所在的节点上。
[root@k8s-master-1 diaodu]# kubectl get pod -owide
NAME                          READY   STATUS    RESTARTS   AGE    IP             NODE         NOMINATED NODE   READINESS GATES
taint-test-78f8c5f9c6-7n7m2   1/1     Running   0          4s     10.244.1.126   k8s-node-2              
taint-test-78f8c5f9c6-w24bj   1/1     Running   0          4s     10.244.1.127   k8s-node-2              
test-848f897788-28qwn         1/1     Running   0          111s   10.244.1.125   k8s-node-2              
test2-5897dbc444-2tp2g        1/1     Running   0          9s     10.244.0.80    k8s-node-1              

四、亲和性和反亲和性详细yaml文件

[root@k8s-master-1 diaodu]# cat deployment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: taint-test
  labels:
    ds: "true"
spec:
  replicas: 2
  selector:
    matchLabels:
      ds: "true"
  template:
    metadata:
      labels:
        ds: "true"
    spec:
      containers:
      - image: nginx:1.17.1
        name: nginx
        imagePullPolicy: IfNotPresent
#Pod反亲和性
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: test
                operator: In
                values:
                - "server"
            topologyKey: kubernetes.io/hostname


#Pod软亲和性
#      affinity:
#        podAffinity:
#          preferredDuringSchedulingIgnoredDuringExecution:
#          - weight: 90
#            podAffinityTerm:
#              labelSelector:
#                matchExpressions:
#                - key: test
#                  operator: In
#                  values:
#                  - "server"
#              topologyKey: kubernetes.io/hostname
#          - weight: 5
#            podAffinityTerm:
#              labelSelector:
#                matchExpressions:
#                - key: ds
#                  operator: In
#                  values:
#                  - "true"
#              topologyKey: kubernetes.io/hostname


#Pod 硬亲和性
#      affinity:
#        podAffinity:
#          requiredDuringSchedulingIgnoredDuringExecution:
#          - labelSelector:
#              matchExpressions:
#              - key: ds
#                operator: In
#                values:
#                - "true"
#            topologyKey: kubernetes.io/hostname

#            
#node 软亲和性
#      affinity:
#        nodeAffinity:
#          preferredDuringSchedulingIgnoredDuringExecution:
#          - weight: 80
#            preference:
#              matchExpressions:
#              - key: ds
#                operator: In
#                values:
#                - "true"
#          - weight: 20
#            preference:
#              matchExpressions:
#              - key: test
#                operator: In
#                values:
#                - "server"

#- - - - -               
# node硬亲和性
#      affinity:
#        nodeAffinity:
#          requiredDuringSchedulingIgnoredDuringExecution:
#            nodeSelectorTerms:
#            - matchExpressions:
#              - key: ds
#                operator: In
#                values:
#                - "true"
#              - key: test
#                operator: In
#                values:
#                - "server"

五、topology拓扑域的概念

如图所示:

北京是一个拓扑域

        朝阳是一个拓扑域

                大兴是一个拓扑域

上海是一个拓扑域

        上海机房是一个拓扑域

                机房中机柜A是一个拓扑域

                        机柜中主机A是一个拓扑域

                机房中机柜B是一个拓扑域

十八、K8S-亲和性和反亲和性_第1张图片

关于topologyKey属性的解释说明:

  • topologyKey:属性是用于表示一个拓扑域的,并不是表示一个节点,一个拓扑域可以包含多个节点;
  • topologyKey:后跟的是节点标签的key值,假设k8s集群中有A、B、C三个节点,它们都拥有名为env这个相同的key值的节点标签,但是标签的value值分别是dev、test、prod,那么这时候拓扑域和集群中的节点就是一对一的关系,这时候将Pod调度到拓扑域上就是指将Pod调度到k8s集群的某一节点上。如果A、B两个节点的标签的value值都是dev,而C节点的标签的value值是test的话,拓扑域和节点就是一对多的关系了,这时候A、B节点处于同一拓扑域,C节点处于另一个拓扑域;
  • Pod间的亲和性规则并不是说两个Pod一定会处于同一个节点上,只有当拓扑域和节点时一对一的关系的时候,才会被调度到同一个节点上,如果拓扑域中包含多个节点的haunt,配置了Pod间亲和性规则后,k8s只会该Pod调度到另一个Pod相同拓扑域中的某一个节点上,并不一定就和另一个Pod是同一个节点,但一定和这个Pod处于同一拓扑域;

 1、服务拓扑

        是实现基于Node 拓扑的流量路由,例如,将发送到某个服务的流量优先路由到与客户端相同的Node的Endpoint上,或者路由到与客户端相同点Zone的那些node的Endpoint上。

        服务括扑机制需要通过设置 kube-apiserver 和 kube-proxy 服务的启动参制--feature-gates="ServiceTopology=true,EndpointSlice=true"进行启用 (需要周时启mipointsSlice 功能),然后就可以在 Service 源对象上通过定义 topoloyKeys 字段来转制到Service 的流量路由了。

        topologyKeys 字段设置的是一组 Node 标签列表,按顺序匹配 Node完成流量的路由转发,流量会被转发到标签匹配成功的 Node 上。如果第 1 个标签找不到匹配的 Node.尝试匹配第 2 个标签,以此类推。如果全部标签都没有匹配的 Node,则请求将被拒绝。

        将 topologyKeys 配置为“*”表示任意拓扑,它只能作为配置列表中的最后一个才有效,如果完全不设置 topologyKeys 字段,或者将其值设置为空,就相当于没有启用服务拓扑功能。

        对于需要使用服务拓扑机制的集群,管理员需要为 Node 设置相应的拓扑标签,包括kubernetes.io/hostname、topology.kubernetes.io/zone 和 topology.kubernetes.io/region.

然后为 Service 设置 topologyKeys 的值,就可以实现如下流量路由策略:

  • 配置为["kubernetes.io/hostname”]:流量只会被路由到相同 Node 的 Endpoint 上,如果 Node 的 Endpoint 不存在,则将请求丢弃。
  • 配置为["kubernetes.io/hostname"、"topology.kubernetes.io/zone"、"topology.kubernetesio/region”]:流量优先被路由到相同 Node 的 Endpoint 上,如果 Node 没有 Endpoint,流量则被路由到相同 zone 的 Endpoint 上;如果在 one 中没有 Endpoint,流量则被路由到相同 region 的 Endpoint 上。
  • 配置为["topology.kubernetes.io/zone","*":流量优先被路由到同zone的Endpoint 上,如果zone中没有可用的Endpoint,流量则被路由到任意可用的Endpoint上

示例:

(1)只将流量路由到相同 Node 的 Endpoint 上,如果 Node 没有可用的 Endpoimt,将请求丢弃:
apiVersion: vl
kind: Service
metadata:
  name: webapp
spec:
  selector:
    app: webapp
  ports:
  - port:8080
  topologyKeys :
  - "kubernetes.io/hostname"
(2)优先将流量路由到相同 Node 的 Endpoint 上,如 Node 没有可用的 Endpoint,则将请求路由到任意可用的 Endpoint:
apiVersion: vl
kind: Service
metadata:
  name: webapp
spec:
  selector:
    app: webapp
  ports:
  - port:8080
  topologyKeys :
  - "kubernetes.io/hostname"
  - "*"
(3)只将流量路由到相同 zone或同 region 的 Endpoint 上,如没有可用的 Endpoint,将请求丢弃:
apiVersion: vl
kind: Service
metadata:
  name: webapp
spec:
  selector:
    app: webapp
  ports:
  - port:8080
  topologyKeys :
  - "topology.kubernetes.io/zone"
  - "topology.kubernetesio/region"
(4)按同Node 同zone 同 region 的优先级顺序路有流量,如果Node、zone、region都没有可用的Endpoint,则将请求路由到任意可用的 Endpoint:
apiVersion: vl
kind: Service
metadata:
  name: webapp
spec:
  selector:
    app: webapp
  ports:
  - port:8080
  topologyKeys :
  - "kubernetes.io/hostname"
  - "topology.kubernetes.io/zone"
  - "topology.kubernetesio/region"
  - "*"

你可能感兴趣的:(k8s,kubernetes,容器,云原生)