默认的情况下,一个pod在哪个node节点上运行,是由scheduler组件采取对应的算法计算出来的,这个过程是不受人工控制的,在实际的使用过程中,这不能够满足客观的场景,针对这样的情况,k8s 提供了四大类调度方式:
定向调度,指的是利用在 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
● effect 支持如下的三个选项:
○ PreferNoSchedule:Kubernetes 将尽量避免把 Pod 调度到具有该污点的 Node 上,除非没有其他节点可以调度;换言之,尽量不要来,除非没办法。
○ NoSchedule:Kubernets 将不会把 Pod 调度到具有该污点的 Node 上,但是不会影响当前 Node 上已经存在的 Pod ;换言之,新的不要来,在这的就不要动。
○ NoExecute:Kubernets 将不会将 Pod 调度到具有该污点的 Node 上,同时会将 Node 上已经存在的 Pod 驱逐;换言之,新的不要来,这这里的赶紧走。
kubectl taint node xxx key=value:effect
kubectl taint node xxx key:effect-
kubectl taint node xxx key-
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 都可以调度。