Kubernetes基本概念之Affinity,Taints和Tolerations

为了使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

  • requiredDuringSchedulingIgnoredDuringExecution:可以分为两部分requiredDuringScheduling和IgnoredDuringExecution。requiredDuringScheduling意味着K8s调度器必须将这个Pod调度到目标Node(这个目标Node由matchExpressions决定)上,否则像nodeSelector一样,Pod的状态将处于Pending。IgnoredDuringExecution意味着这个node affinity的过程仅仅作用于Pod调度阶段,它不适用与已经处于运行中的Pod。也就是说,如果一个Pod被分配到node1之后,此时node1的label被修改了(修改后不满足这个Pod的nodeAffinity了),此时K8s并不会重新调度这个Pod。

  • preferredDuringSchedulingIgnoredDuringExecution:同样的,preferredDuringScheduling意味着一种倾向性,K8s调度器首先尝试将Pod分配到满足node affinity的目标Node上,如果找不到这样的Node,那么允许将其分配到其他Node上。

  • matchExpressions中的operator可选值包括:In, NotIn, Exists, DoesNotExist, Gt, Lt。可以使用NotIn和DoesNotExist实现node anti-affinity,或者使用taints(稍后会提到)来实现node anti-affinity。

  • 如果一个nodeAffinity中包含了多个nodeSelectorTerms,那么Pod可以被分配到任意一个满足了nodeSelectorTerms的Node上。

  • 如果一个nodeSelectorTerms包含了多个matchExpressions,那么Pod分配的Node必须完全满足所有的atchExpressions。

  • preferredDuringSchedulingIgnoredDuringExecution中的weight字段,其取值范围为1-100,用于定义每一个preference的权重。每满足一个preference,该Node的得分就会增加(增加的值即为这个weight)。最终K8s会统计每一个Node的得分,从而选择得分最高的Node作为目标Node。

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包含三个可选值:

  • NoSchedule:打上这种effect的taint的Node,一定不会被调度上没有声明对应Toleration的Pod
  • PreferNoSchedule:打上这种effect的taint的Node,尽可能不会被调度上没有声明对应Toleration的Pod
  • NoExecute:不仅不会调度,还会驱逐Node上已有的没有声明对应Toleration的Pod

为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 产生如下影响:

  • 不能容忍对应 taint 的 pod 将立即被驱逐
  • 能够容忍对应 taint 但是没有在toleration specification中指定tolerationSeconds则将继续保持在原节点上
  • 能够容忍对应 taint 并且指定 tolerationSeconds 则在原节点上保持指定的时间,指定时间到达后将被驱逐

参考文章

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容