k8s nodeSelector和affinity

全栈工程师开发手册 (作者:栾鹏)
架构系列文章


nodeSelector

1.分配pod到node的方法

通过node label selector实现约束pod运行到指定节点,有两种方法 nodeSelector 以及affinity

2.nodeSelector 是k8s早起提供的节点选择器实现

1)首先为nodes打对应的label
kubectl label nodes master disktype=ssd
2)创建yaml文件,nginx-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: test
spec:
  containers:
  - name: nginx
    image: nginx

创建pod

kubectl create -f nginx-pod.yaml
节点默认的label
kubectl get nodes -o yaml 可以看到默认节点的label,也可以使用这些label进行约束

alpha.kubernetes.io/fluentd-ds-ready: "true"
beta.kubernetes.io/arch: amd64
beta.kubernetes.io/os: linux
disktype: ssd
kubeadm.alpha.kubernetes.io/role: master
kubernetes.io/hostname: master

亲和性和反亲和性

根据类型有

nodeAffinity(主机亲和性),
podAffinity(POD亲和性)
podAntiAffinity(POD反亲和性)。

三种亲和性和反亲和性策略的比较如下表所示:

策略名称匹配目标支持的操作符支持拓扑域设计目标
nodeAffinity主机标签In,NotIn,Exists,DoesNotExist,Gt,Lt不支持决定Pod可以部署在哪些主机上
podAffinityPod标签In,NotIn,Exists,DoesNotExist支持决定Pod可以和哪些Pod部署在同一拓扑域
PodAntiAffinityPod标签In,NotIn,Exists,DoesNotExist支持决定Pod不可以和哪些Pod部署在同一拓扑域

对于亲和性和反亲和性,每种都有三种规则可以设置:

RequiredDuringSchedulingRequiredDuringExecution :在调度期间要求满足亲和性或者反亲和性规则,如果不能满足规则,则POD不能被调度到对应的主机上。在之后的运行过程中,如果因为某些原因(比如修改label)导致规则不能满足,系统会尝试把POD从主机上删除(现在版本还不支持)。

RequiredDuringSchedulingIgnoredDuringExecution :在调度期间要求满足亲和性或者反亲和性规则,如果不能满足规则,则POD不能被调度到对应的主机上。在之后的运行过程中,系统不会再检查这些规则是否满足。

PreferredDuringSchedulingIgnoredDuringExecution :在调度期间尽量满足亲和性或者反亲和性规则,如果不能满足规则,POD也有可能被调度到对应的主机上。在之后的运行过程中,系统不会再检查这些规则是否满足。

使用场景介绍

nodeAffinity使用场景 :

  • 将S1服务的所有Pod部署到指定的符合标签规则的主机上。
  • 将S1服务的所有Pod部署到除部分主机外的其他主机上。

podAffinity使用场景 :

  • 将某一特定服务的pod部署在同一拓扑域中,不用指定具体的拓扑域。
  • 如果S1服务使用S2服务,为了减少它们之间的网络延迟(或其它原因),把S1服务的POD和S2服务的pod部署在同一拓扑域中。

podAntiAffinity使用场 景:

  • 将一个服务的POD分散在不同的主机或者拓扑域中,提高服务本身的稳定性。
  • 给POD对于一个节点的独占访问权限来保证资源隔离,保证不会有其它pod来分享节点资源。
  • 把可能会相互影响的服务的POD分散在不同的主机上。

NodeAffinity

参考:https://k8smeetup.github.io/docs/concepts/configuration/assign-pod-node/#node-%E4%BA%B2%E5%92%8C%E6%80%A7beta-%E7%89%B9%E6%80%A7

requiredDuringSchedulingIgnoredDuringExecution的示例

下面这个例子使用nodeAffinity把POD部署到主机mesos-slave1和mesos-slave2上面

apiVersion: v1
kind: Pod
metadata:
  name: with-node-affinity
  annotations:
    scheduler.alpha.kubernetes.io/affinity: >
      {
        "nodeAffinity": {
          "requiredDuringSchedulingIgnoredDuringExecution": {
            "nodeSelectorTerms": [
              {
                "matchExpressions": [
                  {
                    "key": "kubernetes.io/hostname",
                    "operator": "In",
                    "values": [“mesos-slave1″,”mesos-slave2”]
                  }
                ]
              }
            ]
          }
        }
      }
    another-annotation-key: another-annotation-value
spec:
  containers:
  - name: with-node-affinity
    image: gcr.io/google_containers/pause:2.0

我们可以看到NodeSelectorTerms可以有多个,之间是或的关系,满足任意一个既满足,,MatchExpressions也可以有多个,他们之间是且的关系 必须都满足。

preferredDuringSchedulingIgnoredDuringExecution 例子
apiVersion: v1
kind: Pod
metadata:
  name: with-labels
  annotations:
    scheduler.alpha.kubernetes.io/affinity: >
    {
       "nodeAffinity": {
          "preferredDuringSchedulingIgnoredDuringExecution": [
                {
                    "weight" : 1,
                    "preference": {
                        "matchExpressions": [
                            {
                                "key": "disktype",
                                "operator": "In",
                                "values": ["ssd"]
                            }
                        ]
                    }
                }
            ]
        }
    }
    another-annotation-key: another-annotation-value
spec:
  containers:
  - name: test-affinity
    env:
      - name: MYSQL_ROOT_PASSWORD
        value: pass
    image: mysql

preferredDuringSchedulingIgnoredDuringExecution值为列表,根据权重决定顺序
MatchExpressions 值为列表 关系为且,必须都满足

Inter-pod affinity and anti-affinity

Inter-pod affinity 是根据通过已运行在节点上的pod的标签而不是node的标签来决定被调度pod的运行节点,因为pod运行在指定的namespace所以需要自己指定运行pod的namesapce

anti-affinity 和Inter-pod affinity相反

在下面这个例子中,定义了一个Pod亲和性和一个Pod反亲和性规则。其中Pod亲和性规则是一定要满足的,Pod反亲和性规则是参考满足的。

Pod亲和性规则的含义是:Pod必须部署在一个节点上,这个节点上至少有一个正在运行的Pod,这个Pod的security属性取值是“S1”,并且要求部署的节点同正在运行的Pod所在节点都在相同的云服务区域中,也就是“topologyKey:failure-domain.beta.kubernetes.io/zone”。换言之,一旦某个区域出了问题,我们希望这些 Pod 能够再次迁移到同一个区域。

Pod反亲和性规则的含义是,Pod不能部署在一个节点上,这个节点上正在运行的Pod中security属性取值是“S2”,并且新部署的Pod不能同security属性取值是“S2”的Pod在相同的主机上,也就是“topologyKey: kubernetes.io/hostname”。

matchExpressions中operator的取值包括In、NotIn、Exists、DoesNotExist、Gt和Lt。

DoesNotExist实现反亲密的示例

 affinity:
   nodeAffinity:
     requiredDuringSchedulingIgnoredDuringExecution:
       nodeSelectorTerms:
       - matchExpressions:
         - key: error
           operator: DoesNotExist

topologyKey的取值包括:

  1.   kubernetes.io/hostname       同一个主机
    
  2.   failure-domain.beta.kubernetes.io/zone      同一个云服务区
    
  3.   failure-domain.beta.kubernetes.io/region    同一个区域
    
apiVersion: v1
kind: Pod
metadata:
  name: with-pod-affinity
  annotations:
    scheduler.alpha.kubernetes.io/affinity: >
        {
          "podAffinity": {
            "requiredDuringSchedulingIgnoredDuringExecution": [
              {
                "labelSelector": {
                  "matchExpressions": [
                    {
                      "key": "security",
                      "operator": "In",
                      "values": ["S1"]
                    }
                  ]
                },
                "topologyKey": "failure-domain.beta.kubernetes.io/zone"
             }
            ]
           },
          "podAntiAffinity": {
            "requiredDuringSchedulingIgnoredDuringExecution": [
              {
                "labelSelector": {
                  "matchExpressions": [
                    {
                      "key": "security",
                      "operator": "In",
                      "values": ["S2"]
                    }
                  ]
                },
                "topologyKey": "kubernetes.io/hostname"
             }
            ]
           }
         }
spec:
  containers:
  - name: with-pod-affinity
    image: gcr.io/google_containers/pause:2.0
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值