Kuberneres Pod亲和度与反亲和度,强制亲和与首选亲和_kubernetes

Pod亲和调度

在生产上有一些相应的多个pod之间有一定的依赖关系,比如运行应用程序和某一个数据库之间和某一个redis之间可能有依赖,我这个程序本身要依赖别的pod,就是这个pod要依赖另外一个pod来运行,两个pod相互之间有依赖关系,就尽量让他俩pod之间离得更近,离得更近意味着网络延迟更小

pod亲和度

pod亲和度和反亲和度

pod亲和度:想让两个pod离得更近

pod反亲和度:想让两个pod离得更远,同一个调度器运行的pod,运行在不同的机器上,这叫反亲和度

亲和度和反亲和度里面也有强制亲和度,强制反亲和度

和node节点亲和度类似

位置拓扑

这个会使用的更频繁,必须要用的,位置拓扑就是:在运行对应的应用程序的时候,基于位置想让他运行在不同的机架上面去,服务器是运行在数据中心里面的,数据中心每一个机柜可能有10台20台服务器,可能公司有很多台机柜,不同的机柜我们就认为在不同的位置,不同的位置的意思:如果你运行在相同的机柜(位置)里面他的可抗风险性就差,因为所有机器都靠电源的,如果这个机柜电源坏了,网线坏了 ,进水了,那么整个机器就不可用了,一旦哪有就意味着坏了不能提供服务了,如果你有一个服务,这个服务运行10个pod,刚好都运行在同一个机柜里面,那如果这个机柜出问题,那么整个服务都不可用了,如果是运行在不同的机柜,那么一个机柜宕机了还有其他机柜在工作,这样就不会让服务中断,虽然说k8s有个自动修复,你宕机了能给你创建出来,但是他是需要时间的。那这个时间意味着你的服务是无法使用的

因为我们用的是虚拟机,模拟不了机柜,我们可以在机柜的机器上打个标签,比如相同标签的意味着在同一个机柜,如果不同在不同的机柜那就是不同的标签

pod亲和度的参数

[root@k8s-master1 9-6]# kubectl explain pod.spec.affinity.podAffinity
KIND:     Pod
VERSION:  v1

RESOURCE: podAffinity <Object>

DESCRIPTION:
     Describes pod affinity scheduling rules (e.g. co-locate this pod in the
     same node, zone, etc. as some other pod(s)).

     Pod affinity is a group of inter pod affinity scheduling rules.

FIELDS:
   preferredDuringSchedulingIgnoredDuringExecution  <[]Object>
   #首选亲和度 
     The scheduler will prefer to schedule pods to nodes that satisfy the
     affinity expressions specified by this field, but it may choose a node that
     violates one or more of the expressions. The node that is most preferred is
     the one with the greatest sum of weights, i.e. for each node that meets all
     of the scheduling requirements (resource request, requiredDuringScheduling
     affinity expressions, etc.), compute a sum by iterating through the
     elements of this field and adding "weight" to the sum if the node has pods
     which matches the corresponding podAffinityTerm; the node(s) with the
     highest sum are the most preferred.

   requiredDuringSchedulingIgnoredDuringExecution   <[]Object>
   #强制亲和
     If the affinity requirements specified by this field are not met at
     scheduling time, the pod will not be scheduled onto the node. If the
     affinity requirements specified by this field cease to be met at some point
     during pod execution (e.g. due to a pod label update), the system may or
     may not try to eventually evict the pod from its node. When there are
     multiple elements, the lists of nodes corresponding to each podAffinityTerm
     are intersected, i.e. all terms must be satisfied.

看下强制亲和

[root@k8s-master1 9-6]# kubectl explain pod.spec.affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution
KIND:     Pod
VERSION:  v1

RESOURCE: requiredDuringSchedulingIgnoredDuringExecution <[]Object>

DESCRIPTION:
     If the affinity requirements specified by this field are not met at
     scheduling time, the pod will not be scheduled onto the node. If the
     affinity requirements specified by this field cease to be met at some point
     during pod execution (e.g. due to a pod label update), the system may or
     may not try to eventually evict the pod from its node. When there are
     multiple elements, the lists of nodes corresponding to each podAffinityTerm
     are intersected, i.e. all terms must be satisfied.

     Defines a set of pods (namely those matching the labelSelector relative to
     the given namespace(s)) that this pod should be co-located (affinity) or
     not co-located (anti-affinity) with, where co-located is defined as running
     on a node whose value of the label with key <topologyKey> matches that of
     any node on which a pod of the set of pods is running

FIELDS:
   labelSelector    <Object>
   #pod标签选择器
   #定义标签选择器,用于选择目标Pod集合
     A label query over a set of resources, in this case pods.

   namespaceSelector    <Object>
   #通过标签选择器指定namespace
   #通过标签选择器指定namespace
     A label query over the set of namespaces that the term applies to. The term
     is applied to the union of the namespaces selected by this field and the
     ones listed in the namespaces field. null selector and null or empty
     namespaces list means "this pod's namespace". An empty selector ({})
     matches all namespaces.

   namespaces   <[]string>
      #名称空间  这些都是名称空间级别的概念 跨名称空间是识别不了的
      #指定labelSelector适用的namespace列表
     namespaces specifies a static list of namespace names that the term applies
     to. The term is applied to the union of the namespaces listed in this field
     and the ones selected by namespaceSelector. null or empty namespaces list
     and null namespaceSelector means "this pod's namespace".

   topologyKey  <string> -required-
   #位置拓扑,定义位置拓扑的值,位置相同不相同就是靠他
   #定调度所基于的拓扑域(例如节点、Rack、Zone等)
     This pod should be co-located (affinity) or not co-located (anti-affinity)
     with the pods matching the labelSelector in the specified namespaces, where
     co-located is defined as running on a node whose value of the label with
     key topologyKey matches that of any node on which any of the selected pods
     is running. Empty topologyKey is not allowed.

写一个pod节点强制亲和

首先给node节点加不同的标签,当作来区分不同机架 rock标签我们引用

[root@k8s-master1 9-6]# kubectl label nodes k8s-node1.guoguo.com rack=rack001
node/k8s-node1.guoguo.com labeled
[root@k8s-master1 9-6]# kubectl label nodes k8s-node2.guoguo.com rack=rack002
node/k8s-node2.guoguo.com labeled
[root@k8s-master1 9-6]# kubectl label nodes k8s-node3.guoguo.com rack=rack003
node/k8s-node3.guoguo.com labeled
[root@k8s-master1 9-6]# cat pod-affinity-pod-required-1.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis
spec: 
  replicas: 1
  selector:
    matchLabels:
      app: redis
      version: v6
      env: test
      port: p6379
  template:
    metadata:
      labels:
        app: redis
        version: v6
        env: test
        port: p6379
    spec:
      containers:
      - name: redis
        image: images.guoguo.com/apps/redis:6
        ports:
        - containerPort: 6379
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-pod-required
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
      version: v3
  template:
    metadata:
      labels:
        app: nginx
        version: v3
    spec:
      containers:
      - name: nginx
        image: images.guoguo.com/apps/nginx:1.22.1
        ports:
        - containerPort: 80
      affinity:
        podAffinity: #pod亲和
          requiredDuringSchedulingIgnoredDuringExecution: #强制亲和  就是将与某的pod运行在同一个node节点
          - labelSelector: #标签选择器
              matchExpressions:  #匹配表达式
              - {key: app,operator: In,values: ["redis"]}  #第一种写法
              - key: version   #第二种写法
                operator: In #in 包含
                values:  #key的值
                - "v6"
              - key: env  #第三种写法
                operator: In  
                values: ["test"]
              - key: port  #第四种写法
                operator: In
                values:
                  - "p6379"
            topologyKey: rack  #位置拓扑,定义位置拓扑的值,位置相同不相同就是靠他 我们一开始就给每个node加了标签来区分
[root@k8s-master1 9-6]# kubectl get pods -owide
NAME                                READY   STATUS    RESTARTS   AGE   IP               NODE                
redis-6b4fd9d856-mrzzw              1/1     Running   0          57s   192.26.131.163   k8s-node1.guoguo.com
web-pod-required-6dbb479946-2nwq6   1/1     Running   0          57s   192.26.131.164   k8s-node1.guoguo.com

上面先写了一个redis的 并定义了标签 下面写nginx 的时候 引用redis的标签 用podAffinity pod强制亲和 强制与redis 调度在同一个node节点并且 最后使用了topologykey 使用了位置拓扑

以上就是强制亲和

不光要符合pod亲和本身,还得符合你的强制亲和拓扑位置!

pod首选亲和

写一个

[root@k8s-master1 9-6]# cat pod-preferred-1.yaml 
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis
      version: v6
  template:
    metadata:
      labels:
        app: redis
        version: v6
    spec:
      containers:
      - name: redis
        image: images.guoguo.com/apps/redis:6
        ports:
        - containerPort: 6379
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pod-preferred
spec:
  replicas: 6
  selector:
    matchLabels:
      app: nginx
      env: test
  template:
    metadata:
      labels:
        app: nginx
        env: test
    spec:
      containers:
      - name: nginx
        image: images.guoguo.com/apps/nginx:1.22.1
        ports:
        - containerPort: 80
        resources:
          limits:
            cpu: "1500m"
            memory: "1Gi"
      affinity:
        podAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions: 
                - {key: app,operator: In,values: ["redis"]}
                - {key: version, operator: In,values: ["v6"]}
              topologyKey: rack
          - weight: 50
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - {key: app,operator: In,values: ["redis"]}
                - {key: version, operator: In,values: ["v6"]}
              topologyKey: kubernetes.io/hostname

说一下思路,上面是先创建了个redis的pod,然后下面用的首选亲和(柔性)去和reids一个node,因为我们做的资源限制是1.5核心,要启动4个pod,我们node核心现在分别是node1 4核心 node2 2核心 node3 2核心 没有一台机器能够放下6台1.5核心的pod,这需要一台9核心以上的机器,因为我们使用的首选亲和,咋也得给我们匹配到node里面

[root@k8s-master1 9-6]# kubectl get pods -o wide
NAME                             READY   STATUS    RESTARTS   AGE   IP               NODE                
pod-preferred-5fcd77c845-b4lgz   1/1     Running   0          31s   192.26.131.175   k8s-node1.guoguo.com
pod-preferred-5fcd77c845-dph2m   1/1     Running   0          31s   192.26.131.174   k8s-node1.guoguo.com
pod-preferred-5fcd77c845-gdgdl   0/1     Pending   0          31s   <none>           <none>              
pod-preferred-5fcd77c845-tx94q   1/1     Running   0          31s   192.28.252.227   k8s-node2.guoguo.com
pod-preferred-5fcd77c845-v8m8f   0/1     Pending   0          31s   <none>           <none>              
pod-preferred-5fcd77c845-vjwxs   1/1     Running   0          31s   192.17.65.206    k8s-node3.guoguo.com
redis-7449cd45c9-cth9c           1/1     Running   0          31s   192.26.131.173   k8s-node1.guoguo.com

他在123 节点都运行了 有几台调度失败了 因为 没有资源了

这就是pod的首选亲和度

pod本身有个亲和度还有个反亲和度概念

pod反亲和

pod亲和是为了让多个pod运行在一个node节点里面,反亲和是为了不让运行在一起

在生产上有一些工作负载pod不能运行在一个node上的情况来用,这叫反亲和度,

[root@k8s-master1 9-6]# kubectl explain pod.spec.affinity
KIND:     Pod
VERSION:  v1

RESOURCE: affinity <Object>

DESCRIPTION:
     If specified, the pod's scheduling constraints

     Affinity is a group of affinity scheduling rules.

FIELDS:
   nodeAffinity	<Object>
   #node亲和度
     Describes node affinity scheduling rules for the pod.

   podAffinity	<Object>
   #pod亲和度
     Describes pod affinity scheduling rules (e.g. co-locate this pod in the
     same node, zone, etc. as some other pod(s)).

   podAntiAffinity	<Object>
   #pod反亲和度
     Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod
     in the same node, zone, etc. as some other pod(s)).
[root@k8s-master1 9-6]# kubectl explain pod.spec.affinity.podAntiAffinity
KIND:     Pod
VERSION:  v1

RESOURCE: podAntiAffinity <Object>

DESCRIPTION:
     Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod
     in the same node, zone, etc. as some other pod(s)).

     Pod anti affinity is a group of inter pod anti affinity scheduling rules.

FIELDS:
   preferredDuringSchedulingIgnoredDuringExecution	<[]Object>
   #首选反亲和
     The scheduler will prefer to schedule pods to nodes that satisfy the
     anti-affinity expressions specified by this field, but it may choose a node
     that violates one or more of the expressions. The node that is most
     preferred is the one with the greatest sum of weights, i.e. for each node
     that meets all of the scheduling requirements (resource request,
     requiredDuringScheduling anti-affinity expressions, etc.), compute a sum by
     iterating through the elements of this field and adding "weight" to the sum
     if the node has pods which matches the corresponding podAffinityTerm; the
     node(s) with the highest sum are the most preferred.

   requiredDuringSchedulingIgnoredDuringExecution	<[]Object>
   #强制反亲和
     If the anti-affinity requirements specified by this field are not met at
     scheduling time, the pod will not be scheduled onto the node. If the
     anti-affinity requirements specified by this field cease to be met at some
     point during pod execution (e.g. due to a pod label update), the system may
     or may not try to eventually evict the pod from its node. When there are
     multiple elements, the lists of nodes corresponding to each podAffinityTerm
     are intersected, i.e. all terms must be satisfied.

写一个pod强制反亲和

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pod-antiaffinity
spec:
  replicas: 4
  selector:
    matchLabels:
      app: nginx
      env: test
  template:
    metadata:
      labels:
        app: nginx
        env: test
    spec:
      containers:
      - name: nginx
        image: images.guoguo.com/apps/nginx:1.22.1
        ports:
        - containerPort: 80
      affinity:
        podAntiAffinity: #pod反亲和
          requiredDuringSchedulingIgnoredDuringExecution: #强制反亲和
          - labelSelector:
              matchExpressions:
              - {key: app,operator: In,values: ["nginx"]}
              - {key: env,operator: In,values: ["test"]}  #意思是有着两个标签的 不能调度到一个节点上去
            topologyKey: kubernetes.io/hostname    #位置拓扑,定义位置拓扑的值,位置相同不相同就是靠他
[root@k8s-master1 9-6]# kubectl get pods
NAME                                READY   STATUS    RESTARTS   AGE
pod-antiaffinity-6b58c95666-6wqdm   0/1     Pending   0          34s
pod-antiaffinity-6b58c95666-kgm28   1/1     Running   0          34s
pod-antiaffinity-6b58c95666-vgkfs   1/1     Running   0          34s
pod-antiaffinity-6b58c95666-xgghg   1/1     Running   0          34s

4个要求强制反亲和,也就是四个pod要求调度到不同node上去,但是一共就三个node节点 所以有一个无法创建

在生产上很少说创建deployment 弄到不同node节点上,因为生产上node机器很多,不需要这样搞,一般都是两个或者多个deployment同时创建 然后 互相不在同一个node节点上,写一个

[root@k8s-master1 9-6]# cat pod-antiaffinity-2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pod-redis-antiaffinity
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis
      version: v6
  template:
    metadata:
      labels:
        app: redis
        version: v6
    spec:
      containers:
      - name: redis
        image: images.guoguo.com/apps/redis:6
        ports:
        - containerPort: 6379
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pod-nginx-antiaffinity
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
      version: v1
  template:
    metadata:
      labels:
        app: nginx
        version: v1
    spec:
      containers:
      - name: nginx
        image: images.guoguo.com/apps/nginx:1.22.1
        ports: 
        - containerPort: 80
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - {key: app,operator: In,values: ["redis"]}
              - {key: version,operator: In,values: ["v6"]}
            topologyKey: kubernetes.io/hostname

上面的意思是,让俩个pod不创建在一个node节点上,使用了强制反亲和度

[root@k8s-master1 9-6]# kubectl get pods -owide
NAME                                      READY   STATUS    RESTARTS   AGE   IP               NODE                 
pod-nginx-antiaffinity-877484984-gwpv9    1/1     Running   0          83s   192.17.65.210    k8s-node3.guoguo.com 
pod-redis-antiaffinity-7449cd45c9-jqvt5   1/1     Running   0          12m   192.26.131.180   k8s-node1.guoguo.com

两个pod 不在同一个节点