继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Kubernetes Node Affinity

慕姐8265434
关注TA
已关注
手记 1147
粉丝 221
获赞 1064

Assigning Pods to Nodes

可以限制Pods在特定节点上运行,也可以优先调度到特定节点。有几种方式可以实现这个功能,它们都使用选择标签的方式完成。通常情况下这些限制是没必要的,k8s会自动实现合理的调度(例如,pods在集群中调度时,不会被调度到资源不足的节点上)。但是,有些场景下,希望对运行pod的节点进行限制,如需要将pod调度到磁盘为SSD的节点上,或将两个不同的服务但需要经常通信的pod调度到同一个zone。

1.nodeSelector

nodeSelector是最简单的一种实现方式,是podSpec的一个字段,它指定了一个key-value的键值对。为了使pods能够在该节点上运行,该节点必须有所有需要的键值对作为标签(节点也可以有其它的标签)。

第一步:节点打标签

#语法kubectl label nodes <node-name> <label-key>=<label-value>#示例,如果节点名称是harmonycloud,需要添加‘disktype=ssd’标签kubectl lable nodes harmonycloud disktype=ssd# 验证,使用如下命令查看是否成功给node添加标签kubectl get nodes --show-labels

第二步:配置文件中添加nodeSelector 字段

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: testspec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  nodeSelector:  #Add this field
    disktype: ssd

第三步:验证

#运行以下命令,创建podkubectl create -f pod.yaml#查看pod运行节点kubectl get pods -o wide

2. Affinity and anti-affinity

nodeSelector 提供了一种简单的方式将pods调度到具有特定标签的节点上。

Affinity and anti-affinity 现在是beta版,大大拓展了可以表达的约束类型。相对于nodeSelector主要有以下几个优点:

  1. 语法更具表现力(不仅仅支持“与(AND)”完全匹配)

  2. 可以指明规则是“soft/preference”而不是强制要求,所以如果不满足调度条件,pods依然可以被调度。

  3. 可以将规则限制在运行在一个节点上的pods(或其他拓扑域),而不仅仅是节点本身,这将允许pods是否可以调度到同一个节点。

Affinity特征有两种类型,“node affinit” 和 “inter-pod affinity/anti-affinity”。 Node affinity跟nodeSelector很像,但有以上两个优点。inter-pod affinity/anti-affinity是对pod的标签进行限制,具有以上三条特性。

nodeSelector可以正常工作,最终将会被弃用,因为node affinity可以表示它可以表示的所有内容。

2.1 Node affinity(beta)

Kubernetes 1.2中,node affinity是alpha版。 Node affinity概念上与nodeSelector相似,通过选择标签的方式,可以限制pod被调度到特定的节点上。

目前支持两种类型的node affinity,requiredDuringSchedulingIgnoredDuringExecutionpreferredDuringSchedulingIgnoredDuringExecution,可以他们看作“hard(强制)”和“soft(非强制)”。某种意义上,前者指定了要将pod调度到节点上必须满足的规则(像nodeSelector,但使用了更具表现力的语法),而后者试图调度到特定的节点但不能保证一定会调度到该节点。其中,“IgnoredDuringExecution”表示如果在pod运行时节点的标签发生改变导致无法满足pods创建时使用的调度规则,pod会继续在该节点上运行,这点与nodeSelector相似。将来会提供requiredDuringSchedulingRequiredDuringExecution,与requiredDuringSchedulingIgnoredDuringExecution一样,但是会迁移节点上的pod以满足其node affinity 的规则。

下面有一个使用node affinity的例子:

apiVersion: v1
kind: Pod
metadata:
  name: with-node-affinity
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/e2e-az-name            operator: In
            values:
            - e2e-az1
            - e2e-az2
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: another-node-label-key            operator: In
            values:
            - another-node-label-value
  containers:
  - name: with-node-affinity
    image: gcr.io/google_containers/pause:2.0

这条规则表示,pod可以被调度到key为“kubernetes.io/e2e-az-name”,值为“e2e-az1”或“e2e-az2”的节点。另外,在满足该条件的节点中,优先使用具有“another-node-label-key”标签,且至为“another-node-label-value”的节点。

上面的例子使用了“In”操作符,node affinity语法支持以下集中操作符:In, NotIn, Exists, DoesNotExist,Gt,Lt。没有明确的“node anti-affinity”概念,但是NotIn和DoesNotExist可以表示该含义。

如果同时指定了nodeSelectornodeAffinity,要调度的节点必须同时满足这两点规则。

如果指定了与多条与nodeSelector相关的表达式,pod将会被调度到同时满足这几条表达式的节点。

2.2 Inter-pod affinity and anti-affinity(beat)

Kubernetes 1.4中提出了inter-pod和anti-affinity的概念。inter-pod affinity和anti-affinity允许根据已在节点上运行的pod上的标签来限制pod可以调度到哪些节点,而不是基于节点上的标签。

规则的形式是,pod应该(anti-affinity表示不应该)运行在X中,如果X已经运行了一个或多个满足规则Y的pod。Y表示为LabelSelector具有相关namespace的列表(或所有namespace)。与节点不同,pod是属于不同namespace的(因此pod上的标签是隐含的namespace),pod 标签上的label selector必须制定该selector应用到哪个namespace。从概念上来说,X是一个拓扑域,如节点,机架,云提供商域等。

如node affinity,目前支持两种类型的pod affinity和anti-affinity:requiredDuringSchedulingIgnoredDuringExecutionpreferredDuringSchedulingIgnoredDuringExecutionrequiredDuringSchedulingIgnoredDuringExecution会将service A和service B的pod调度到同一个zone,因为他们彼此通信很多;preferredDuringSchedulingIgnoredDuringExecution,anti-affinity会把同一个service的pods调度到不同的zone(强制要求是没有意义的,因为pod的数量要大于zone)。

下面有一个使用pod affinity的例子:

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

这个例子中定义了affinity和anti-affinity规则。podAffinity是requiredDuringSchedulingIgnoredDuringExecution,podAntiaffinity是preferredDuringSchedulingIgnoredDuringExecution。pod affinity 规则表示,该pod只能运行在集群中的特定节点上,这些节点已经至少运行一个具有”security=S1“标签的pod,并且和这些节点在同一个zone(更确切的说,这个pod可以运行在节点N上,如果节点N有key为failure-domain.beta.kubernetes.io/zone和值为V的标签,同时该节点上运行着一个具有“security=S1”标签的pod)。pod anti-affinity规则表示,如果该节点已经运行着具有“security=S2”标签的pod,将不会优先调度到该节点。(如果topologyKeyfailure-domain.beta.kubernetes.io/zone,该pod也不会被优先调度到具有“security=S2”标签的节点所在的zone)。

和node affinity 一样,pod affinity 合法的操作符有In, NotIn, Exists, DoesNotExist, Gt, Lt。

原则上,topologyKey可以是任意标签,为了性能考虑只允许一些有限的topologyKey,默认情况下,有以下几个:

  • kubernetes.io/hostname

  • failure-domain.beta.kubernetes.io/zone

  • failure-domain.beta.kubernetes.io/region

除了labelSelectortopologyKey,也可以选择性的指定一些labelSelector需要匹配的namespace。如果忽略namespace,默认匹配affinity/anti-affinity定义的规则指定的namespace。如果定义了namespace,意味着所有namespace都可以。

必须满足所有与requiredDuringSchedulingIgnoredDuringExecution 相关的表达式才能将pod调度到某个节点。



作者:iCaptain
链接:https://www.jianshu.com/p/102c4df69af9


打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP