Kubernetes 集群调度
目录
一、Kubernetes 集群调度
1、Kubernetes 组件协作机制
关键组件关系:
2、Pod 创建与工作机制流程
典型创建过程(List-Watch 模型)
(1)三大组件启动监听(List-Watch)
3、调度流程
3.1 过滤阶段(Predicate)
3.2 优选阶段(Priorities)
指定调度节点方式
nodeName(强制绑定)
ymal文件
查看调度节点
nodeSelector(基于标签匹配)
当前的节点
给对应的 node 设置标签分别为 yjs=a 和 yjs=b
展示标签
修改label的值
删除标签
修改成 nodeSelector 调度方式
查看详细事件
节点亲和性与 Pod 亲和性
定义
类比举例子
硬策略
yaml文件
查看pod节点
删除所有的容器并不会被创建的命令
软策略
查看节点信息
软策略加硬策略
查看信息
Pod 亲和性与反亲和性
Pod 亲和性调度
创建一个标签为 app=myapp01 的 Pod
使用 Pod 亲和性调度,创建多个 Pod 资源
Pod 反亲和性调度
污点(Taint) 和 容忍(Tolerations)
命令示例
污点(Taint)
容忍 (Tolerations)
仍然能运行起来
一、Kubernetes 集群调度
1、Kubernetes 组件协作机制
Kubernetes 通过 List-Watch 机制使各个组件协作、数据同步,从而实现解耦与实时一致性。
关键组件关系:
组件 | 职责 |
---|---|
kubectl / API 客户端 | 向 APIServer 发起资源创建或管理请求 |
APIServer | 负责 API 调用、权限校验、存储交互,是集群控制的核心入口 |
etcd | 存储集群所有状态信息 |
Controller Manager | 维持副本数、执行自愈逻辑(扩容、重建等) |
Scheduler | 调度器,将未分配节点的 Pod 分配到合适的 Node |
kubelet | 节点代理,负责 Pod 生命周期管理和容器运行状态上报 |
用户是通过 kubectl 根据配置文件,向 APIServer 发送命令,在 Node 节点上面建立 Pod 和 Container。
APIServer 经过 API 调用,权限控制,调用资源和存储资源的过程,实际上还没有真正开始部署应用。这里 需要 Controller Manager、Scheduler 和 kubelet 的协助才能完成整个部署过程。
在 Kubernetes 中,所有部署的信息都会写到 etcd 中保存。实际上 etcd 在存储部署信息的时候,会发送 Create 事件给 APIServer,而 APIServer 会通过监听(Watch)etcd 发过来的事件。其他组件也会监听(Watch)APIServer 发出来的事件。
2、Pod 创建与工作机制流程
Pod 创建的整个生命周期由多组件配合完成:
典型创建过程(List-Watch 模型)
(1)三大组件启动监听(List-Watch)
-
Controller Manager、Scheduler、kubelet 启动后会分别通过 Watch API Server(HTTPS 6443 端口)监听集群资源事件变化。
-
Controller Manager:监听副本控制类对象(如 ReplicaSet、Deployment)
-
Scheduler:监听未调度的 Pod
-
kubelet:监听分配到本节点的 Pod
-
3、调度流程
3.1 过滤阶段(Predicate)
过滤掉不满足条件的节点。
常见过滤算法:
算法名 | 功能描述 |
---|---|
PodFitsResources | 检查节点剩余资源是否满足 Pod 需求 |
PodFitsHost | 检查 NodeName 是否匹配 |
PodFitsHostPorts | 检查端口冲突 |
PodSelectorMatches | label 匹配 |
NoDiskConflict | Volume 挂载冲突检测 |
若无节点满足条件,Pod 进入 Pending 状态,不断重试。
如果在 predicate 过程中没有合适的节点,pod 会一直在 pending 状态,不断重试调度,直到有节点满足条件。 经过这个步骤,如果有多个节点满足条件,就继续 priorities 过程:按照优先级大小对节点排序。
3.2 优选阶段(Priorities)
对可行节点进行打分排序。
常见算法:
优先级项 | 描述 |
---|---|
LeastRequestedPriority | 资源使用率越低,权重越高 |
BalancedResourceAllocation | CPU 与内存使用率越接近越好(这个一般和上面的一起使用,不单独使用。比如 node01 的 CPU 和 Memory 使用率 20:60,node02 的 CPU 和 Memory 使用率 50:50,虽然 node01 的总使用率比 node02 低,但 node02 的 CPU 和 Memory 使用率更接近,从而调度时会优选 node02。) |
ImageLocalityPriority | 优先节点上已有目标镜像的节点 |
指定调度节点方式
nodeName(强制绑定)
ymal文件
vim myapp.yamlapiVersion: apps/v1
kind: Deployment # pod
metadata:name: myapp
spec:replicas: 3selector:matchLabels:app: myapptemplate:metadata:labels:app: myappspec:nodeName: node01containers:- name: myappimage: soscscs/myapp:v1ports:- containerPort: 80kubectl apply -f myapp.yaml
查看调度节点
kubectl get pods -o wide
kubectl describe pod myapp-699655c7fd-5qrp2|tail -6
nodeSelector(基于标签匹配)
当前的节点
给对应的 node 设置标签分别为 yjs=a 和 yjs=b
kubectl label nodes node01 yjs=akubectl label nodes node02 yjs=b
展示标签
kubectl get node --show-labels
修改label的值
kubectl label node node02 yjs=c --overwrite
删除标签
kubectl label nodes node02 yjs-
修改成 nodeSelector 调度方式
vim myapp1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: myapp1
spec:replicas: 3selector:matchLabels:app: myapp1template:metadata:labels:app: myapp1spec:nodeSelector:yjs: acontainers:- name: myapp1image: soscscs/myapp:v1ports:- containerPort: 80 kubectl apply -f myapp1.yaml
获取pod信息
kubectl get pods -o wide
查看详细事件
kubectl describe pod myapp1-64c58784f9-42ctc|tail -10
节点亲和性与 Pod 亲和性
定义
affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution: # 硬策略preferredDuringSchedulingIgnoredDuringExecution: # 软策略
类比举例子
你更“想去”陈老师的班(软策略),还是“必须去”陈老师的班(硬策略)
运算符 | 含义 | 通俗理解 | 示例 |
---|---|---|---|
In | label 的值在列表中 | “只要它的值在我列的名单里,就选上它” | env In (dev, test) → 选出 env=dev 或 env=test 的 Pod |
NotIn | label 的值不在列表中 | “黑名单里的不要” | env NotIn (prod) → 除了生产环境都选上 |
Gt | label 的值大于某个数 | “比这个数字大的才要” | version Gt 3 → 选出 version=4,5,6… 的 Pod |
Lt | label 的值小于某个数 | “比这个数字小的才要” | version Lt 3 → 选出 version=1,2 的 Pod |
Exists | label 存在即可 | “只要有这个标签就算数,不管值是啥” | Exists zone → 只要有 zone 这个标签 |
DoesNotExist | label 不存在 | “没有这个标签的才要” | DoesNotExist debug → 没有 debug 标签的 Pod |
硬策略
kubectl get nodes --show-labels
yaml文件
vim pod1.yaml
apiVersion: v1
kind: Pod
metadata:name: affinitylabels:app: node-affinity-pod
spec:containers:- name: with-node-affinityimage: soscscs/myapp:v1affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:- matchExpressions:- key: kubernetes.io/hostname #指定node的标签operator: NotIn #设置Pod安装到kubernetes.io/hostname的标签值不在values列表中的node上values:- node02kubectl apply -f pod1.yaml
查看pod节点
删除所有的容器并不会被创建的命令
kubectl delete deployments --all
软策略
vim pod2.yaml
apiVersion: v1
kind: Pod
metadata:name: affinitylabels:app: node-affinity-pod
spec:containers:- name: with-node-affinityimage: soscscs/myapp:v1affinity:nodeAffinity:preferredDuringSchedulingIgnoredDuringExecution:- weight: 1 #如果有多个软策略选项的话,数值越小,权重越大,优先级越高preference:matchExpressions:- key: kubernetes.io/hostnameoperator: Invalues:- node03 # 这里没有node03这个节点kubectl apply -f pod2.yaml
查看节点信息
软策略加硬策略
vim demo2.yamlapiVersion: v1
kind: Pod
metadata:name: affinity1labels:app: node-affinity-pod
spec:containers:- name: with-node-affinityimage: soscscs/myapp:v1affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution: #先满足硬策略,排除有kubernetes.io/hostname=node02标签的节点nodeSelectorTerms:- matchExpressions:- key: kubernetes.io/hostnameoperator: NotInvalues:- node02preferredDuringSchedulingIgnoredDuringExecution: #再满足软策略,优先选择有yjsc=a标签的节点- weight: 1preference:matchExpressions:- key: yjsoperator: Invalues:- akubectl apply -f pod2.yaml
查看信息
Pod 亲和性与反亲和性
调度策略 | 匹配标签 | 操作符 | 拓扑域支持 | 调度目标 |
---|---|---|---|---|
nodeAffinity | 主机 | IIn, NotIn, Exists,DoesNotExist, Gt, Lt | ❌ | 指定主机 |
podAffinity | Pod | In, NotIn, Exists,DoesNotExist | ✅ | 与指定 Pod 同域 |
podAntiAffinity | Pod | In, NotIn, Exists,DoesNotExist | ✅ | 与指定 Pod 不同域 |
Pod 亲和性调度
创建一个标签为 app=myapp01 的 Pod
vim pod3.yamlapiVersion: v1
kind: Pod
metadata:name: myapp01labels:app: myapp01
spec:containers:- name: with-node-affinityimage: soscscs/myapp:v1kubectl apply -f pod3.yaml
使用 Pod 亲和性调度,创建多个 Pod 资源
apiVersion: v1
kind: Pod
metadata:name: myapp02labels:app: myapp02
spec:containers:- name: myapp02image: soscscs/myapp:v1affinity:podAffinity:requiredDuringSchedulingIgnoredDuringExecution:- labelSelector:matchExpressions:- key: appoperator: Invalues:- myapp01topologyKey: yjs
Pod 反亲和性调度
vim pod5.yamlapiVersion: v1
kind: Pod
metadata:name: myapp10labels:app: myapp10
spec:containers:- name: myapp10image: soscscs/myapp:v1affinity:podAntiAffinity:preferredDuringSchedulingIgnoredDuringExecution:- weight: 100podAffinityTerm:labelSelector:matchExpressions:- key: appoperator: Invalues:- myapp01topologyKey: kubernetes.io/hostname
反亲和调度
vim pod6.yamlapiVersion: v1
kind: Pod
metadata:name: myapp20labels:app: myapp20
spec:containers:- name: myapp20image: soscscs/myapp:v1affinity:podAntiAffinity:requiredDuringSchedulingIgnoredDuringExecution:- labelSelector:matchExpressions:- key: appoperator: Invalues:- myapp01topologyKey: yjskubectl apply -f pod6.yaml
污点(Taint) 和 容忍(Tolerations)
类型 | 描述 |
---|---|
NoSchedule | 不调度到此节点 |
PreferNoSchedule | 尽量避免调度具有该污点的 Node 上 |
NoExecute | 不调度 + 驱逐已存在 Pod(只是将pod放到其他的node上面) |
命令示例
# 主节点的污点
kubectl describe node master|grep Taint
Taints: node-role.kubernetes.io/master:NoSchedule# node01设置污点
kubectl taint node node01 key1=value1:NoSchedule
kubectl describe node node01|grep Taint
Taints: key1=value1:NoSchedule# 去除污点
kubectl taint node node01 key1:NoSchedule-
kubectl describe node node01|grep Taint
Taints: <none>
污点(Taint)
kubectl taint node node02 check=mycheck:NoExecute
容忍 (Tolerations)
# 先给两个节点设置污点
kubectl taint node node01 key1=value1:NoSchedule
kubectl taint node node02 key1=value1:NoSchedule
按常理来说,镜像运行不起来
但是我们在文件中加上toleration的参数
vim pod3.yaml
apiVersion: v1
kind: Pod
metadata:name: myapp01labels:app: myapp01
spec:containers:- name: with-node-affinityimage: soscscs/myapp:v1tolerations:- key: "check"operator: "Equal" #operator: "Equal" #Equal意味着这个值等于value,如果是Exists,则不需要填写value,只要有这个key就容忍value: "mycheck"effect: "NoExecute"tolerationSeconds: 3600
仍然能运行起来
kubectl get pod -owide