默认的情况下,一个pod在哪个node节点上运行,是由scheduler组件采取对应的算法计算出来的,这个过程是不受人工控制的,在实际的使用过程中,这不能够满足客观的场景,针对这样的情况,k8s 提供了四大类调度方式:

  1. 自动调度: 运行在哪个node节点上完全由scheduler 经过一些里的算法计算出来
  2. 定向调度:NodeName、NodeSelector
  3. 亲和性调度:NodeAffinity、PodAffinity、PodAntiAffinity
  4. 污点(容忍)调度:taints、Toleration
  • 定向调度

定向调度,指的是利用在 Pod 上声明的 nodeName 或 nodeSelector ,以此将 Pod 调度到期望的 Node 节点上。这里的调度是强制的,这就意味着即使要调度的目标 Node 不存在,也会向上面进行调度,只不过 Pod 运行失败而已。

NodeName方式调度

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  namespace: default
  labels:
    app: nginx
spec:
  nodeName: k8s-node1 # 指定调度到k8s-node1节点上
  containers:
  - name: nginx
    image: nginx:1.20.2
    resources:
      limits:
        cpu: 200m
        memory: 500Mi
      requests:
        cpu: 100m
        memory: 200Mi
    ports:
    - containerPort:  80
      name:  http
    volumeMounts:
    - name: localtime
      mountPath: /etc/localtime
  volumes:
    - name: localtime
      hostPath:
        path: /usr/share/zoneinfo/Asia/Shanghai
  restartPolicy: Always

NodeSelector方式调度

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  namespace: default
  labels:
    app: nginx
spec:
  nodeSelector:
    nodeevn: pro # 指定调度到 nodeevn = pro 标签的 Node 节点上
  containers:
  - name: nginx
    image: nginx:1.20.2
    resources:
      limits:
        cpu: 200m
        memory: 500Mi
      requests:
        cpu: 100m
        memory: 200Mi
    ports:
    - containerPort: 80
      name:  http
    volumeMounts:
    - name: localtime
      mountPath: /etc/localtime
  volumes:
    - name: localtime
      hostPath:
        path: /usr/share/zoneinfo/Asia/Shanghai
  restartPolicy: Always
  • 亲和性调度

虽然定向调度的两种方式,使用起来非常方便,但是也有一定的问题,那就是如果没有满足条件的 Node,那么 Pod 将不会被运行,即使在集群中还有可用的 Node 列表也不行,这就限制了它的使用场景。基于上面的问题,Kubernetes 还提供了一种亲和性调度(Affinity)。它在 nodeSelector 的基础之上进行了扩展,可以通过配置的形式,实现优先选择满足条件的 Node 进行调度,如果没有,也可以调度到不满足条件的节点上,使得调度更加灵活。

● Affinity 主要分为三类:
○ nodeAffinity(node亲和性):以 Node 为目标,解决 Pod可 以调度到那些 Node 的问题。
○ podAffinity(pod亲和性):以 Pod 为目标,解决 Pod 可以和那些已存在的 Pod 部署在同一个拓扑域中的问题。
○ podAntiAffinity(pod反亲和性):以 Pod 为目标,解决 Pod 不能和那些已经存在的 Pod 部署在同一拓扑域中的问题。

关于亲和性和反亲和性的使用场景的说明:
● 亲和性:如果两个应用频繁交互,那么就有必要利用亲和性让两个应用尽可能的靠近,这样可以较少因网络通信而带来的性能损耗。
● 反亲和性:当应用采用多副本部署的时候,那么就有必要利用反亲和性让各个应用实例打散分布在各个 Node 上,这样可以提高服务的高可用性。

pod.spec.affinity.nodeAffinity
  requiredDuringSchedulingIgnoredDuringExecution  # Node节点必须满足指定的所有规则才可以,硬性过滤
    nodeSelectorTerms  # 节点选择列表
      matchFields   # 按节点字段列出的节点选择器要求列表  
      matchExpressions   # 按节点标签列出的节点选择器要求列表(推荐)
        key    # 键
        values # 值
        operator # 关系符 支持Exists, DoesNotExist, In, NotIn, Gt, Lt
  preferredDuringSchedulingIgnoredDuringExecution # 优先调度到满足指定的规则的Node,软性评分 (倾向)   
    preference   # 一个节点选择器项,与相应的权重相关联
      matchFields # 按节点字段列出的节点选择器要求列表
      matchExpressions   # 按节点标签列出的节点选择器要求列表(推荐)
        key # 键
        values # 值
        operator # 关系符 支持In, NotIn, Exists, DoesNotExist, Gt, Lt  
    weight # 倾向权重,在范围1-100。

● podAffinity 主要实现以运行的 Pod 为参照,实现让新创建的 Pod 和参照的 Pod 在一个区域的功能。
● podAntiAffinity 主要实现以运行的 Pod 为参照,让新创建的 Pod 和参照的 Pod 不在一个区域的功能。
● PodAffinity 的可选配置项:

pod.spec.affinity.podAffinity
  requiredDuringSchedulingIgnoredDuringExecution  硬限制
    namespaces 指定参照pod的namespace
    topologyKey 指定调度作用域
    labelSelector 标签选择器
      matchExpressions  按节点标签列出的节点选择器要求列表(推荐)
        key    键
        values 值
        operator 关系符 支持In, NotIn, Exists, DoesNotExist.
      matchLabels    指多个matchExpressions映射的内容  
  preferredDuringSchedulingIgnoredDuringExecution 软限制    
    podAffinityTerm  选项
      namespaces
      topologyKey
      labelSelector
         matchExpressions 
            key    键  
            values 值  
            operator
         matchLabels 
    weight 倾向权重,在范围1-1
  • 污点和容忍

● 前面的调度方式都是站在 Pod 的角度上,通过在 Pod 上添加属性,来确定 Pod 是否要调度到指定的 Node 上,其实我们也可以站在 Node 的角度上,通过在 Node 上添加污点属性,来决定是否运行 Pod 调度过来。
● Node 被设置了污点之后就和 Pod 之间存在了一种相斥的关系,进而拒绝 Pod 调度进来,甚至可以将已经存在的 Pod 驱逐出去。

污点的格式为:

key=value:effect

key 和 value 是污点的标签及对应的值

effect 描述污点的作用

● effect 支持如下的三个选项:
○ PreferNoSchedule:Kubernetes 将尽量避免把 Pod 调度到具有该污点的 Node 上,除非没有其他节点可以调度;换言之,尽量不要来,除非没办法。
○ NoSchedule:Kubernets 将不会把 Pod 调度到具有该污点的 Node 上,但是不会影响当前 Node 上已经存在的 Pod ;换言之,新的不要来,在这的就不要动。
○ NoExecute:Kubernets 将不会将 Pod 调度到具有该污点的 Node 上,同时会将 Node 上已经存在的 Pod 驱逐;换言之,新的不要来,这这里的赶紧走。

  1. 新增污点

kubectl taint node xxx key=value:effect

  1. 去除污点

kubectl taint node xxx key:effect-

  1. 去除所有污点

kubectl taint node xxx key-

  1. 查看污点

kubectl describe node xxx | grep -i taints


容忍:

● 上面介绍了污点的作用,我们可以在 Node上 添加污点用来拒绝 Pod 调度上来,但是如果就是想让一个 Pod 调度到一个有污点的 Node 上去,这时候应该怎么做?这就需要使用到容忍。

污点就是拒绝,容忍就是忽略,Node 通过污点拒绝 Pod 调度上去,Pod 通过容忍忽略拒绝。

kubectl explain pod.spec.tolerations

FIELDS:
key # 对应着要容忍的污点的键,空意味着匹配所有的键
value # 对应着要容忍的污点的值
operator # key-value的运算符,支持Equal和Exists(默认)
effect # 对应污点的effect,空意味着匹配所有影响
tolerationSeconds # 容忍时间, 当effect为NoExecute时生效,表示pod在Node上的停留时间

● 污点和容忍的匹配:
○ 当满足如下条件的时候,Kubernetes 认为污点和容忍匹配:
■ 键(key)相同。
■ 效果(effect)相同。
■ 污点的 operator 为:
● Exists ,此时污点中不应该指定 value 。
● Equal,此时容忍的 value 应该和污点的 value 相同。
○ 如果不指定 operator ,默认为 Equal 。
● 特殊情况:
○ 容忍中没有定义 key ,但是定义了 operator 为 Exists ,Kubernetes 则认为此容忍匹配所有的污点,如:

tolerations:
- operator: Exists
# 最终,所有有污点的机器我们都能容忍,Pod 都可以调度。
  tolerations: # 容忍
    - key: "tag" # 要容忍的污点的key
      operator: Exists # 操作符
# 最终,有这个污点的机器我们可以容忍,Pod 都可以调度。
Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐