目录
前言
本文将探讨 Kubernetes 中关键的调度和资源管理概念,包括 nodeName、nodeSelector、Pod/Node 的亲和性与反亲和性、污点与污点容忍、服务质量(QoS)、Pod 优先级(PriorityClass)以及资源限制(limits 和 requests)。这些功能和策略共同构成了 Kubernetes 强大的调度机制,使得管理员能够基于各种条件和需求,灵活地管理 Pod 的调度和运行。通过具体的设置和应用场景,我们将初步理解这些概念如何共同作用于 Pod 的调度过程,以及它们如何帮助提高集群的效率和应用的可靠性。
nodeName
作用
指定节点名称,用于将Pod调度到指定的Node上,不经过调度器,优先级最高,如果节点挂了,也不会分配到其他节点
应用场景
- 调试、测试
使用方法
apiVersion: v1
kind: Pod
metadata:
name: example-pod
spec:
nodeName: node-1 #在此处设置想让pod调度到哪个node节点上
containers:
- name: example-container
image: example-image
ports:
- containerPort: 80
nodeSelect
作用
将 Pod 约束到具有特定标签的节点上运行。通过在 Pod 的配置文件中指定 nodeSelector
字段,可以确保 Pod 只在满足特定条件的节点上进行调度和运行
应用场景
- 调度Pod至专用节点:根据场景需求将Node分组管理,
nodeSelector
可以确保 Pod 只在为特定用途预留的节点上运行 - 把有特殊需求的Pod调度至特殊配置节点的Node:如对SSD磁盘或GPU有硬件要求的业务Pod则调度至具有相关标签的Node上
使用方法
1、给节点打上标签
kubectl label nodes node-1 disk=ssd
2、查看节点标签
kubectl get nodes --show-labels
3、在Pod的Yaml中添加nodeSelect字段,需要注意的是如果node上没有能够与yaml中nodeselector匹配的标签,则pod会一直处于pending状态
apiVersion: v1
kind: Pod
metadata:
name: ssd-pod
spec:
nodeSelector: #在此处配置nodeSelector相关信息
disk: ssd
containers:
- name: nginx-container
image: nginx
Pod/Node亲和反亲和
硬软亲和
硬亲和
requiredDuringSchedulingIgnoredDuringExecution 这个参数指定了调度期间必须满足的亲和性或反亲和性条件。一旦 Pod 被调度(即,在创建时),这些规则就会被评估并应用。如果满足条件,Pod 将被调度到符合规则的节点上。如果在调度过程中没有任何节点满足这些条件,那么Pod会处于Pending
软亲和
preferredDuringSchedulingIgnoredDuringExecution,与上述参数作用类似,不过它定义的是优先级而非硬性要求。调度器会尽量满足这些条件,但如果无法满足,Pod 仍然会被调度
Pod Affinity
作用
使得 Pod 倾向于或不倾向于被调度到与符合特定规则的 Pod 同一节点上。
应用场景
- 保证相关联的应用组件(如前端和后端服务,存在大量数据交互的服务)部署在相近的位置,以减少通信延迟。
使用方法
这个例子中,podAffinity
要求该 Pod 被调度到运行带有标签 app=frontend
的 Pod 的同一个节点上
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
spec:
replicas: 2
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- backend
topologyKey: "kubernetes.io/hostname"
containers:
- name: nginx-container
image: nginx
Pod AntiAffinity
作用
定义 Pod 间的排斥规则,确保 Pod 不会被调度到与符合特定规则的 Pod 同一节点上。
应用场景
- 分散相同类型的应用实例,如多个计算类型的Pod、多个需要GPU类型的Pod
- 高容灾能力,避免单点故障,如:ingress-controller pod、core-dns pod等
使用方法
在 Pod 的 affinity.podAntiAffinity字段中定义反亲和性规则,通常使用标签选择器来指定排斥的 Pod。这个例子中,podAntiAffinity 要求该 Pod 不能被调度到运行带有标签 app=database
的 Pod 的同一个节点上
apiVersion: apps/v1
kind: Deployment
metadata:
name: database
spec:
replicas: 3
selector:
matchLabels:
app: database
template:
metadata:
labels:
app: database
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- database
topologyKey: "kubernetes.io/hostname"
containers:
- name: db-container
image: postgres
Node Affinity
作用
根据节点的标签约束 Pod 被调度到特定节点或节点组。
应用场景
- 将 Pod 调度到具有特定硬件属性(如 GPU)的节点,或满足特定需求(如地理位置)的节点。如:需要GPU资源的Pod,则调度到安装了GPU显卡的Node上
使用方法
在 Pod 的 affinity.nodeAffinity
字段中设置节点选择规则,通过节点标签和表达式来指定所需的节点特性
这个例子中,NodeAffinity 要求该 Pod 必须调度到运行带有标签 hardware=gpu
的 Node节点上
apiVersion: apps/v1
kind: Deployment
metadata:
name: gpu-app
spec:
replicas: 2
selector:
matchLabels:
app: gpu-app
template:
metadata:
labels:
app: gpu-app
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: hardware
operator: In
values:
- gpu
containers:
- name: cuda-container
image: nvidia/cuda
Node AntiAffinity
作用
确保 Pod 不会被调度到具有特定标签或满足某些条件的节点上。
应用场景
- 避免将 Pod 调度到不适合的节点,如具有不兼容硬件的节点。
使用方法
使用 nodeAffinity
的 NotIn
和 DoesNotExist
操作符定义节点反亲和性规则,以排除不希望 Pod 调度的节点。
这个 Deployment 的 Pod 不会被调度到标签 hardware=high-performance
的节点上
apiVersion: apps/v1
kind: Deployment
metadata:
name: legacy-app
spec:
replicas: 2
selector:
matchLabels:
app: legacy-app
template:
metadata:
labels:
app: legacy-app
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: hardware
operator: NotIn
values:
- high-performance
containers:
- name: legacy-app-container
image: legacy-app
污点/污点容忍
作用
污点(Taints)
污点允许节点拒绝某些 Pod 除非该 Pod 具有相应的容忍度。污点通过键值对和效果进行定义,效果可以是 NoSchedule、PreferNoSchedule 或 NoExecute
污点容忍(Tolerations)
污点容忍允许 Pod 调度到带有特定污点的节点上。Pod 的容忍度需要与节点的污点匹配,这样 Pod 才能被调度到该节点
应用场景
污点
- 专用节点: 为特定类型的 Pod 保留节点,例如,只让数据库 Pod 运行在特定的节点上。
- 节点维护: 在节点维护期间,通过添加污点来阻止新的 Pod 调度到该节点上。
污点容忍
- 专用部署: 允许特定的 Pod 在有污点的专用节点上运行,比如,只允许有 GPU 容忍度的 Pod 在带有 GPU 的节点上运行。
使用方法
1、给节点添加污点
kubectl taint nodes node1 key1=value1:NoSchedule
#node1 是节点的名称。
#key1=value1是污点的键值对。
#NoSchedule 是污点的效果,可以是 NoSchedule、PreferNoSchedule 或 NoExecute
effect污点类型
- NoSchedule:当节点被打上此类污点时,Kubernetes 不会把新的 Pod 调度到这个节点上。
- PreferNoSchedule:此类污点告诉 Kubernetes 尽可能避免将新的 Pod 调度到带有该污点的节点上,但这不是一个强制性的限制。
- NoExecute:该污点不仅阻止新的 Pod 被调度到节点上,还会导致该节点上已运行的 Pod 被驱逐,除非这些 Pod 明确声明了对该污点的容忍。
2、Pod 配置中添加污点容忍
在 的 YAML 文件中定义容忍度,具有相应容忍度的 Pod 将能够调度到具有相匹配污点的节点上,而其他 Pod 则会被排除在外:
apiVersion: apps/v1
kind: Deployment
metadata:
name: tolerant-deployment
spec:
replicas: 2
selector:
matchLabels:
app: tolerant-app
template:
metadata:
labels:
app: tolerant-app
spec:
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoSchedule"
containers:
- name: tolerant-container
image: nginx
注意点
- 污点的灵活性: 污点可以只通过 key 来定义,不一定需要指定 value 。这样的污点影响所有没有相应容忍度的 Pod。
- 污点容忍非强制调度: 即使 Pod 配置了对某个污点的容忍,也不意味着它一定会被调度到带有该污点的节点上。污点容忍只是扩大了 Pod 的调度可能性。
- 容忍度增加调度灵活性: Pod 的污点容忍配置相当于增加了匹配条件,让 Pod 可以在更多节点上运行。条件越多,匹配越精确。
- 容忍度与污点效果的关系: 即使 Pod 没有配置对应的污点容忍,它仍可能被调度到带有 PreferNoSchedule 污点的节点上,因为 PreferNoSchedule 是软性限制。
- 容忍类型需要与节点污点的效果相对应: 如果节点的污点效果为 NoExecute 而 Pod 的容忍度效果为 NoSchedule ,则 Pod 只会在没有 NoExecute 污点的节点上调度,展示了效果匹配的重要性。
拓展
Qos服务质量
作用
服务质量 (QoS, Quality of Service) 是一种技术,在 Kubernetes 中,QoS 可以用于控制 Pod 的调度、 资源限制、自动重启等行为,以此保证应用程序的高可用性和性能
Qos类型
Guaranteed(保证型):Pod 有确定的 CPU 和内存资源,不受其他 Pod 影响,遇故障或重启时优先恢复。
Burstable(突发型):Pod 可超额使用资源应对高峰,可能与其他 Pod 竞争资源,资源紧张时可能被终止。
BestEffort(尽力型):Pod 需与所有节点进程竞争资源,性能受影响,资源不足时优先被终止。
优先级:Guaranteed > Burstable > BestEffort
使用方法
通过配置Pod的limit和request来实现
- Guaranteed: 所有容器(包括初始化容器)都设置了相等的
requests
和limits
。 - Burstable: 至少一个容器设置了不相等的
requests
和limits
,或者只设置了limits
。 - BestEffort: 所有容器均未设置
requests
或limits
。
Pod优先级(PriorityClass)
作用
- Pod 可配置优先级,表示其相对重要性。
- 调度器可驱逐低优先级 Pod 以调度高优先级 Pod
使用方法
PriorityClass
- 定义优先级的集群范围对象,内置 system-cluster-critical 和`system-node-critical
1、查看PriorityClass
kubectl get pc
2、定义 PriorityClass
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority
value: 1000000 #定义优先级值,范围 [0-1000000000]
globalDefault: false #若为 true,未指定 priorityClassName 的 Pod 使用此优先级
description: "用于 XYZ 服务的 Pod"
3、在 Pod 中指定优先级
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
priorityClassName: high-priority #指定pod对应的优先级
4、通过命令查看Pod优先级
kubectl describe pod/nginx # 优先级1000000解析并填充到 podSpec 的 priority 字段
资源限制(limit、request)
作用
Limits 和 Requests 是 Kubernetes 中用于管理 Pod 资源(如 CPU 和内存)的关键参数。Kubernetes 调度器会根据这些请求值将 Pod 调度到有足够资源的节点上
- Requests: 指定了 Pod 启动时最低需要的资源量。调度器使用这个值来决定将 Pod 放置在哪个节点上,以确保每个 Pod 有足够的资源来运行。
- Limits: 指定了 Pod 可以消耗的资源的最大量。它防止了 Pod 占用过多的节点资源,影响到其他 Pod
使用方法
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.19.0
ports:
- containerPort: 80
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
注意点
- requests 和 limits: requests 定义了 Pod 启动所需的最小资源量,而 limits 指定了 Pod 可使用的最大资源量。
- 设置建议: 通常建议将 requests 设置为 limits 的 20%-30%,以保证资源的有效利用;requests 应小于或等于 limits。
- 宿主机资源限制: limits 不应超过节点的物理资源,以避免无效的资源限制。
- 调度影响: requests 值影响 Pod 的调度,节点必须满足这些请求值,否则 Pod 将处于 pending 状态。
- 资源预留: requests 仅表示资源预留,并非宿主机的实际占用。
- 默认行为: 若仅设置 limits 未设置 requests,默认将 requests 与 limits 设置为相同值。
- 集群容量: 较大的 requests 值可能限制集群可容纳的 Pod 数量,而较小的值可能增加容纳数量。
- 资源不足处理: 如果 Pod 的 requests 大于节点资源,Pod 将一直处于 pending 状态。CPU 作为可压缩资源,超出 limits 时将限制 CPU 使用率而不会终止 Pod;内存是不可压缩资源,超出 limits 会导致 OOM kill。
Pod调度过程
调度分为几个部分:
- 首先是过滤掉不满足条件的节点,这个过程称为预选(predicate) ;
- 然后对通过的节点按照优先级排序,这个是优选(priority) ;
- 最后从中选择优先级最高的节点。如果中间任何一步骤有错误,就直接返回错误。
预选(predicate)有一系列的算法可以使用:
- PodFitsResources :节点上剩余的资源是否大于pod 请求的资源
- PodFitsHost :如果pod 指定了NodeName,检查节点名称是否和NodeName匹配
- PodFitsHostPorts :节点上已经使用的port是否和pod申请的port冲突
- PodselectorMatches :过滤掉和pod指定的 label 不匹配的节点
- NoDiskConflict :已经mount的volume和pod指定的volume不冲突,除非它们都 是只读
如果在predicate 过程中没有合适的节点,pod 会一直在 pending 状态,不断重试调度,直到有节点满足条件。经过这个步骤,如果有多个节点满足条件,就继续 priorities 过程:按照优先级大小对节点排序。
Pod调度策略
-
默认调度策略:此策略致力于在不满足Pod需求的情况下找到代价最小的节点。如果没有合适的节点,系统可能会考虑移除一些已部署的Pod以为新Pod腾出空间,从而确保资源分配的高效性。(预选阶段)
-
优先级调度策略:根据Pod的优先级进行节点排序,优先部署优先级高的Pod。这通过为Pod设置不同的
PriorityClass
来实现,以保证关键服务的高可用性。(优选阶段) -
节点亲和性调度策略:依据节点的标签或其他属性,选取与Pod需求相符的节点。此策略通过在Pod配置中设置
NodeAffinity
来指定,以确保Pod部署在最适合的节点上。(预选阶段) -
Pod亲和性调度策略:根据已部署Pod的标签和属性,选择与这些Pod相似或关联的节点。通过在Pod配置中使用
PodAffinity
设置,此策略有助于将相互关联的服务部署在邻近的位置,以提高整体的服务效率和响应速度。(预选阶段) -
Pod互斥性调度策略:选择与待部署Pod不同或无关的节点,避免在同一节点上运行过多相似的Pod。通过
PodAntiAffinity
配置实现,这有助于分散风险,提高系统的健壮性。(预选阶段) -
资源限制调度策略:优先选择资源充足的节点,满足Pod的资源要求。这通常通过设置Pod的
ResourceLimits
来实现,确保每个Pod都能获得必要的资源,从而保证服务的稳定性和性能。(预选阶段)