Kubernetes基本概念之Affinity,Taints和T

2020-02-08  本文已影响0人  伊凡的一天

为了使Pods分配到特定的Nodes上运行,K8s提出了两种解决方案:nodeSelector和nodeAffinity。

nodeSelector

nodeSelector是一种最简单的指定Pod运行在哪一个Node上的方式。它的使用简单粗暴,直接给node打上一个label,然后在Pod的定义中添加一个nodeSelector即可。

  1. 为node-1打上一个"disktype=ssd"的label
kubectl label nodes node-1 disktype=ssd
  1. 在Pod的定义中添加一个nodeSelector
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: test
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  nodeSelector:
    disktype: ssd    # 对应node-1的label

通过label选择器的方式,这样这个名为nginx的Pod就会调度到拥有"disktype=ssd"的label的Node上运行。如果K8s集群找不到任何一个拥有"disktype=ssd"的label的Node,那么这个Pod就会处于Pending状态(即无法运行成功)。

nodeAffinity

nodeAffinity提供的功能与nodeSelector类似,都是用于指定Pod运行在哪些Node上。但是nodeAffinity拥有更加复杂的语法和更加强大的功能。下面是一个例子:

apiVersion: v1  
kind: Pod  
metadata:  
  name: database
spec:  
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
          - matchExpressions:
            - key: role
              operator: In
              values: [ "database-require" ]
      preferredDuringSchedulingIgnoredDuringExecution:
        - weight: 1
          preference:
            matchExpressions:
              - key: role
                operator: In
                values: [ "database-prefer" ]

目前nodeAffinity支持两种模式:requiredDuringSchedulingIgnoredDuringExecution 和 preferredDuringSchedulingIgnoredDuringExecution

podAffinity和podAntiAffinity

podAffinity用于根据已经在Node上运行的Pod的标签来限制Pod调度在哪个Node上。例如有些时候出于性能考虑,我们希望将某2个Pod分配在同一个Node上,此时我们就能够使用nodeAffinity。下面是一个例子:

apiVersion: v1
kind: Pod
metadata:
  name: with-pod-affinity
spec:
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: security
            operator: In
            values:
            - S1
        topologyKey: kubernetes.io/hostname
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: security
              operator: In
              values:
              - S2
          topologyKey: kubernetes.io/hostname
  containers:
  - name: with-pod-affinity
    image: k8s.gcr.io/pause:2.0

例如上面的例子中,requiredDuringSchedulingIgnoredDuringExecution中的定义表示,必须将这个Pod调度到一个运行着拥有label:security=S1的Pod的Node上。也就是说,当且仅当某个Node上运行着一个Pod,并且这个Pod拥有security=S1的label,那么这个例子中Pod才能分配到这个Node上。

podAntiAffinity则刚好相反,如果某个Node拥有了满足matchExpressions的Pod,那么久不会将这个Pod分配到这个Node上。

注意到podAffinity和podAntiAffinity还包含一个属性:topologyKey。topologyKey本身代表着一个label的key,它用于限定Node范围。因此nodeAffinity的规则是:如果 X 已经运行一个或多个符合规则 Y 的 pod,那么这个 pod 应该运行在 X 上。这里的Y就是matchExpressions定义的规则。而X则是这里的topologyKey,例如上面的kubernetes.io/hostname将Node的范围限定在拥有"kubernetes.io/hostname"这个label的Node中。通常情况下,"kubernetes.io/hostname" 是Node默认就拥有的Label,Node默认拥有的其他Label包括:failure-domain.beta.kubernetes.io/zonefailure-domain.beta.kubernetes.io/regiontopology.kubernetes.io/zonetopology.kubernetes.io/regionbeta.kubernetes.io/instance-typenode.kubernetes.io/instance-typekubernetes.io/oskubernetes.io/arch。(参考资料:https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#built-in-node-labels

Taints和Tolerations

如果说我们可以使用nodeSelector和nodeAffinity来表达Pod对于Node的亲和性,那么Taints和Tolerations就是用于表达Pod对于Node的反亲和性。换种方式说,nodeSelector/nodeAffinity是Pod的一个属性,将其吸引到一个特定的Node集合上;而Taint则刚好相反,它允许Node排斥Pod。

Taint中文译为污点,它作用于Node,当为Node打上污点后,任何没有显示声明能够容忍这个污点的Pod都不会被调度到这个Node上。Pod通过定义Tolerations来声明自己能够容忍某些污点(Taints)。下面是Taints的使用例子:

kubectl taint nodes node1 key=value:NoSchedule

一个Taint由三部分组成:key,value和effect。格式为 key=value:effect。key/value类似于label的使用,而effect包含三个可选值:

为Pod添加Toleration:

apiVersion: v1  
kind: Pod  
metadata:  
  name: database
spec:  
  tolerations:
    - key: <key>
      operator: "Equal"
      value: <value>
      effect: "NoSchedule"

声明了Toleration的Pod表示其可以容忍该污点,可以被调度到有该污点的Pod上。

可以添加多个 taint 到一个 node 上,也能添加多个 toleration 到一个 pod 上。 Kubernetes以过滤器的形式来处理多个taint和toleration的情况: 遍历 node 的所有 taint,如果 pod 拥有匹配的 toleration 则将 taint 忽略掉;最后剩下的没有被忽略的 taint 将作用于这个 pod。

我们提到了 NoExecute taint 的效果,它将对正在运行的 pod 产生如下影响:

参考文章

上一篇 下一篇

猜你喜欢

热点阅读