目录
软亲和性策略(preferredDuringSchedulingIgnoredDuringExecution):
硬亲和性策略(requiredDuringSchedulingIgnoredDuringExecution):
自动调度
调度器组件
Kubernetes的调度器(kube-scheduler)是一个独立的控制面组件,负责将Pod调度到合适的节点上。当Pod被创建时,如果Pod的spec.nodeName
字段为空,则表明该Pod需要被调度。此时,kube-scheduler会根据一系列的调度算法和策略来选择一个最佳的节点。
调度流程
Pod的自动调度流程大致可以分为以下几个步骤:
1.监听Pod创建:
kube-scheduler通过监听API Server来发现新创建的且尚未被调度的Pod。
2.过滤(Predicates):
在这个阶段,kube-scheduler会应用一系列的过滤规则来排除不满足Pod调度需求的节点。这些规则包括但不限于:
节点资源是否满足Pod的资源请求(如CPU、内存等)。
节点上是否已存在与Pod端口冲突的Pod。
节点是否设置了Pod无法容忍的污点(Taints)。
节点是否满足Pod的亲和性(Affinity)和反亲和性(Anti-Affinity)要求。
节点是否处于可调度状态(Schedulable)。
3.打分(Priorities):
经过过滤阶段后,会得到一个包含所有可调度节点的列表。在打分阶段,kube-scheduler会根据一系列优先级函数来为这些节点打分。这些优先级函数包括但不限于:
LeastRequestedPriority:优先选择资源利用率最低的节点。
BalancedResourceAllocation:在CPU和内存资源利用率之间寻求平衡。
SelectorSpreadPriority:尽量将Pod分散到不同的节点上,以实现负载均衡。
NodeAffinityPriority:根据Pod的NodeAffinity/NodeSelector要求给节点打分。
TaintTolerationPriority:根据Pod是否能够容忍节点的Taint来给节点打分。
4.选择最优节点:
kube-scheduler会将所有节点的分数进行加权求和,得到每个节点的最终得分。然后,选择得分最高的节点作为Pod的调度目标。如果存在多个得分最高的节点,kube-scheduler会从中随机选取一个。
5.绑定(Binding):
一旦选定了节点,kube-scheduler就会将Pod与选定的节点进行绑定,并将这个调度决定告知API Server。API Server随后会更新Pod的状态,并将其调度到指定的节点上。
定向调度
Pod的定向调度主要有以下几种方式:
NodeName:
通过直接在Pod的YAML文件中指定nodeName字段,将Pod调度到具有该名称的节点上。这种方式跳过了kube-scheduler的调度逻辑,是强制性的。
NodeSelector:
通过为节点和Pod设置标签(Labels),并在Pod的YAML文件中指定nodeSelector字段,选择具有特定标签的节点进行调度。这种方式也是强制性的,如果找不到匹配的节点,Pod将处于Pending状态。
示例:
以下是一个使用nodeName
进行定向调度的Pod YAML文件示例:
apiVersion: v1
kind: Pod
metadata:
name: nginx-1
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
nodeName: k8s-node-1 # 指定Pod运行的节点名称
在这个示例中,nodeName
字段被设置为 k8s-node-1
这意味着Pod将被调度到名为 k8s-node-1
的节点上。如果集群中不存在名为 k8s-node-1
的节点,Pod将无法成功调度。
---
使用nodeSelector
进行定向调度的Pod YAML文件示例:
apiVersion: v1
kind: Pod
metadata:
name: nginx-2
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
nodeSelector:
disktype: ssd # 选择具有disktype=ssd标签的节点
environment: production # 选择具有environment=production 标签的节点
在这个示例中,nodeSelector
字段被设置为disktype: ssd 和environment: production
,这意味着Pod将被调度到同时具有disktype=ssd
和environment=production
标签的节点上。在调度之前,需要确保集群中有节点被打上了disktype=ssd
和environment=production
的标签。
实例:
nodeName:
[root@k8s-master-1 ~]# mkdir test1
[root@k8s-master-1 ~]# cd test1/
[root@k8s-master-1 test1]# vim namePod.yaml
[root@k8s-master-1 configmap]# kubectl get pod -o wide
nodeSelector:
先给node节点打上标签:
[root@k8s-master-1 test1]# kubectl label nodes k8s-node-3 disktype=ssd environment=production
node/k8s-node-3 labeled
这里给k8s-node-3节点打了disktype=ssd environment=production的标签
[root@k8s-master-1 test1]# vim selector_pod.yaml
[root@k8s-master-1 test1]# kubectl apply -f selector_pod.yaml
pod/nginx-2 created
[root@k8s-master-1 test1]# kubectl get pod -o wide
亲和调度和反亲和调度
亲和调度(Affinity Scheduling)和反亲和调度(Anti-Affinity Scheduling)是两种高级的Pod调度策略,用于控制Pod在集群内的节点分布。这两种调度方式通过定义亲和性和反亲和性规则,使得Pod能够基于节点的标签、拓扑属性或其他Pod的存在状态等因素被调度到合适的节点上。
亲和调度
亲和调度可以分为软亲和策略和硬亲和策略
软亲和性策略(preferredDuringSchedulingIgnoredDuringExecution):
非强制性:如果现在没有满足调度要求的节点,Pod就会忽略这条规则,继续完成调度的过程。
灵活性高:适用于那些对调度有一定偏好,但不是必须满足的场景。
硬亲和性策略(requiredDuringSchedulingIgnoredDuringExecution):
强制性:如果没有满足条件的节点,就会不断重试直到满足条件为止。
确保调度:适用于那些必须满足特定条件才能调度的场景。
亲和调度类型
在Kubernetes中,亲和调度主要包括Node亲和性和Pod亲和性两种类型:
Node亲和性:
用于控制Pod应该被调度到哪些节点上。
可以通过nodeSelector、nodeAffinity(包括requiredDuringSchedulingIgnoredDuringExecution和preferredDuringSchedulingIgnoredDuringExecution)来实现。
Pod亲和性:
用于控制Pod之间的相对位置,例如将关联性较强的Pod调度到同一个节点上,或将需要避免相互干扰的Pod调度到不同的节点上。
使用podAffinity(亲和性)和podAntiAffinity(反亲和性)字段配置。
示例:
apiVersion: v1
kind: Pod
metadata:
name: my-pod-1
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- backend
topologyKey: kubernetes.io/hostname
containers:
- name: my-container
image: nginx
apiVersion: v1:指定Kubernetes API的版本。
kind: Pod:指定对象的类型为Pod。
metadata:包含Pod的元数据,如名称。
spec:定义Pod的规格。
affinity:定义亲和性规则。
podAffinity:定义Pod亲和性规则。
requiredDuringSchedulingIgnoredDuringExecution:指定在调度时是必须的,但在
执行过程中被忽略。
labelSelector:用于选择具有特定标签的Pod。
matchExpressions:定义标签选择器中的表达式。
key、operator、values:分别指定匹配键、匹配操作符和匹配值。
topologyKey:定义拓扑约束,这里是kubernetes.io/hostname,表示使用节点
主机名进行调度。
containers:定义Pod中的容器,包括容器名称和使用的镜像。
反亲和调度
Pod反亲和调度的基本概念
在Pod的YAML配置文件中,可以通过affinity
字段下的podAntiAffinity
子字段来定义Pod反亲和性规则。这些规则可以指定Pod不应该与具有特定标签或属性的其他Pod部署在同一节点上。
Pod反亲和调度的类型
pod的反亲和调度的类型同样具有
软亲和性策略(preferredDuringSchedulingIgnoredDuringExecution) 和
硬亲和性策略(requiredDuringSchedulingIgnoredDuringExecution)
示例:
apiVersion: v1
kind: Pod
metadata:
name: my-pod-2
spec:
containers:
- name: my-container
image: nginx:latest
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- backend
topologyKey: kubernetes.io/hostname
在这个示例中,podAntiAffinity
字段定义了一个必需的Pod反亲和性规则。这个规则指定了Pod不应该与具有app=backend
标签的Pod部署在同一节点上。topologyKey
字段设置为kubernetes.io/hostname
,表示反亲和性是基于节点主机名来匹配的。
注意事项
topologyKey是必需的,它定义了Pod之间反亲和性匹配的范围。常见的值包括kubernetes.io/hostname(表示节点级别)和beta.kubernetes.io/os(表示操作系统级别,但请注意,beta.kubernetes.io/os可能不是所有Kubernetes版本都支持)。
你可以使用不同的操作符(如NotIn、Exists、DoesNotExist等)和多个匹配表达式来定义更复杂的反亲和性规则。
在实际部署时,请确保你的Kubernetes集群版本支持Pod反亲和性特性,并且你的Pod标签和选择器配置正确无误。
污点和容忍度调度
污点(Taints)和容忍度(Tolerations)是Kubernetes(K8S)中用于Pod调度的两种重要机制,它们允许集群管理员通过给节点(Node)添加污点来拒绝或限制Pod的调度,同时Pod可以通过配置容忍度来忽略这些污点,从而实现更灵活的调度策略。
污点(Taints)
定义与作用:
污点是定义在节点上的键值对类型的数据,用于让节点有能力拒绝调度器将一些Pod运行到该节点上。污点并不表示节点故障或不可用,而是用于表达节点对Pod的某种排斥关系。
污点的格式为key=value:effect,其中key和value是污点的标签,effect描述污点的作用,主要有三种:
NoSchedule:不能容忍此污点的Pod对象不可调度至当前节点,但不会影响节点上已存在的Pod。
PreferNoSchedule:调度器尽量确保不能容忍此污点的Pod不会被调度至当前节点,但如果没有其他节点可选,仍然会调度。
NoExecute:不能容忍此污点的Pod对象不可调度至当前节点,并且会将节点上已存在的、不能容忍此污点的Pod驱离。
管理污点:
使用kubectl taint命令可以管理节点的污点。例如,为节点添加污点:kubectl taint nodes <node-name> <key>=<value>:<effect>。
删除污点可以使用相同的命令,但将<effect>部分替换为-,如:kubectl taint nodes <node-name> <key>:<effect>-。
容忍度(Tolerations)
定义与作用:
容忍度是定义在Pod上的,用于配置该Pod可容忍的节点污点。如果Pod能够容忍某个节点上的污点,那么Pod就可以被调度到该节点上。
容忍度在Pod的spec.tolerations字段中定义,可以指定key、value、effect和operator(操作符)。操作符主要有两种:Equal(等值比较)和Exists(存在性判断)。