关于K8s中Pod调度[选择器,指定节点,主机亲和性]方式和节点[coedon,drain,taint]标记的Demo
今天要和大家聊聊 Kubernetes 的“灵魂人物”——Scheduler!这个小可爱在 Kubernetes 世界里可是个“老中医”,专门给 Pod “把脉问诊”,然后 decides 把它们分配到最适合的节点上。听起来好像很简单对吧?别急,它可有一套“十八般武艺”呢!
先来一个灵魂拷问:你是否经历过 Pod 一出生就“无家可归”的尴尬?这背后很可能就是调度问题在作怪!Scheduler 的职责就是确保每一个 Pod 都能找到一个温馨的“家”,而且还得是最优的“家”!
---
为什么 Scheduler 这么重要?
想象一下,假如 Kubernetes 是一个豪华的酒店,Pod 就是客人,节点就是酒店的客房。Scheduler 的任务就是确保每一位客人(Pod)都能住进最适合的客房(节点)。如果分配不当,轻则资源浪费,重则酒店(集群)崩溃!Scheduler 的能力直接决定了 Kubernetes 的“服务水平”!
---
Scheduler 的调度流程是啥?
简单概括,调度分为两步:
1. 预选阶段:先筛选出满足基本条件的节点。这有点像“海选”,但 Scheduler 有一套严格的“考核指标”,比如节点资源是否够用、标签是否匹配等等。
2. 优先级阶段:从“海选”出来的候选节点中,按照优先级打分,选出得分最高的那个。这一步就像选“最佳拍档”,Scheduler 会综合考虑资源利用效率、节点负载等因素。
---
如何手动指定 Pod 的运行位置?
有时候,我们可能想“指哪打哪”,这时候就得靠“节点选择器”和“亲和性”策略了!比如:
- 如果你想让 Pod 只运行在特定的节点上,可以在节点上打标签,然后在 Pod 的 YAML 文件中指定nodeSelector。
- 如果你想让 Pod 尽量避免某些节点,可以通过nodeAffinity 设置“反亲和性”。
---
节点的污点与 Pod 的容忍
节点有“污点”,Pod 有“容忍度”。简单概括,如果你的节点上有某些特殊标记(比如不支持 GPU 的节点打了个taint=NoGPU),那么只有那些明确表示“能容忍”这个污点的 Pod 才能运行在这个节点上。这就像相亲一样,有些 Pod 只会选择特定的“对象”。
---
整体而言:Scheduler 是 Kubernetes 的灵魂!
Scheduler 的作用不仅仅是为了分配资源,更是为了确保 Kubernetes 集群的高效和稳定运行。掌握调度机制,你就能更好地管理和优化自己的集群!
所以,下次当你看到 Pod 飘在空中找不到家的时候,不妨先看看 Scheduler 的表现如何哦!
写在前面
- 嗯,整理K8s中pod调度相关笔记,这里分享给小伙伴
- 博文内容涉及:
kube-scheduler
组件的简述Pod
的调度(选择器、指定节点、主机亲和性)方式- 节点的
coedon
与drain
标记 - 节点的
taint
(污点)标记及pod的容忍污点(tolerations
)定义
- 食用方式:
- 需要了解
K8s
基础知识 - 熟悉资源对象
pod,deploy
的创建,了解资源对象定义yaml
文件 - 了解
kubectl
常用命令
- 需要了解
- 理解不足小伙伴帮忙指正
所谓成功就是用自己的方式度过人生。--------《明朝那些事》
Scheduler 调度组件简述
Kubernetes Scheduler是什么
众多周知,Kubernetes Scheduler
是 Kubernetes
中负责Pod调度
的重要功能模块,运行在k8s 集群中的master节点。
作用 : Kubernetes Scheduler
的作用是将待调度的Pod (API新创建
的Pod, Controller Manager为补足副本而创建
的Pod等)按照特定的调度算法
和调度策略
绑定(Binding)到集群中某个合适的Node上,并将绑定信息写入etcd中。
在整个调度过程中涉及三个对象,分别是
待调度Pod列表
可用Node列表
以及调度算法和策略
整体流程 :通过调度算法调度,为待调度Pod列表
中的每个Pod从Node列表
中选择一个最适合的Node
随后, 目标node节点上的kubelet
通过APIServer监听到Kubernetes Scheduler
产生的Pod绑定事件
,然后获取对应的Pod清单
,下载Image镜像并启动容器
。
kubelet
进程通过与API Server
的交互,每隔一个时间周期,就会调用一次API Server的REST接口报告自身状态, API Server接收到这些信息后,将节点状态信息更新到etcd中。 同时kubelet也通过API Server的Watch接口监听Pod信息
,
- 如果监听到新的Pod副本被调度绑定到本节点,则执行Pod对应的容器的创建和启动逻辑;
- 如果监听到Pod对象被删除,则删除本节点上的相应的Pod容器;
- 如果监听到修改Pod信息,则kubelet监听到变化后,会相应地修改本节点的Pod容器。
所以说,kubernetes Schedule
在整个系统中承担了承上启下的
重要功能,对上负责接收声明式API或者控制器创建新pod的消息,并且为其安排一个合适的Node,对下,选择好node之后,把工作交接给node上的kubelet,由kubectl负责pod的剩余生命周期。
Kubernetes Scheduler调度流程
Kubernetes Scheduler
当前提供的默认调度流程分为以下两步。这部分随版本一直变化,小伙伴以官网为主
流程 | 描述 |
---|---|
预选调度过程 | 即遍历所有目标Node,筛选出符合要求的候选节点。为此, Kubernetes内置了多种预选策略(xxx Predicates)供用户选择 |
确定最优节点 | 在第1步的基础上,采用优选策略(xxxPriority)计算出每个候选节点的积分,积分最高者胜出 |
Kubernetes Scheduler的调度流程是通过插件方式加载的"调度算法提供者” (AlgorithmProvider)
具体实现的。一个AlgorithmProvider
其实就是包括了一组预选策略
与一组优先选择策略
的结构体.
Scheduler中可用的预选策略包含:NoDiskConflict、PodFitsResources、PodSelectorMatches、PodFitsHost、CheckNodeLabelPresence、CheckServiceAffinity 和PodFitsPorts
策略等。
其默认的AlgorithmProvider
加载的预选策略返回布尔值包括:
- PodFitsPorts(PodFitsPorts):判断端口是否冲突
- PodFitsResources(PodFitsResources):判断备选节点的资源是否满足备选Pod的需求
- NoDiskConflict(NoDiskConflict):判断备选节点和已有节点是否磁盘冲突
- MatchNodeSelector(PodSelectorMatches):判断备选节点是否包含备选Pod的标签选择器指定的标签。
- HostName(PodFitsHost):判断备选Pod的spec.nodeName域所指定的节点名称和备选节点的名称是否一致
即每个节点只有通过前面提及的5个默认预选策略后
,才能初步被选中,进入到确认最优节点(优选策略)流程。
Scheduler中的优选策略包含(不限于下面3个):
LeastRequestedPriority
:从备选节点列表中选出资源消耗最小的节点,对各个节点公式打分CalculateNodeLabelPriority
:判断策略列出的标签在备选节点中存在时,是否选择该备选节,这不太懂,打分BalancedResourceAllocation
:从备选节点列表中选出各项资源使用率最均衡的节点。对各个节点公式打分
每个节点通过优先选择策略时都会算出一个得分,计算各项得分,最终选出得分值最大的节点作为优选的结果
(也是调度算法的结果)。
Pod的调度
手动指定pod的运行位置:
通过给node节点设置指定的标签,然后我们可以在创建pod里指定通过选择器选择node标签,类似前端里面DOM操作元素定位,或者直接指定节点名
节点标签常用命令
标签设置 | – |
---|---|
查看 | kubectl get nodes --show-labels |
设置 | kubectl label node node2 disktype=ssd |
取消 | kubectl label node node2 disktype |
所有节点设置 | kubectl label node all key=vale |
给节点设置标签
┌──[root@vms81.liruilongs.github.io]-[~/ansible]└─$kubectl label node vms82.liruilongs.github.io disktype=node1node/vms82.liruilongs.github.io labeled┌──[root@vms81.liruilongs.github.io]-[~/ansible]└─$kubectl label node vms83.liruilongs.github.io disktype=node2node/vms83.liruilongs.github.io labeled
查看节点标签
┌──[root@vms81.liruilongs.github.io]-[~/ansible]└─$kubectl get node --show-labelsNAME STATUS ROLES AGE VERSION LABELSvms81.liruilongs.github.io Ready control-plane,master 45d v1.22.2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=vms81.liruilongs.github.io,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=,node.kubernetes.io/exclude-from-external-load-balancers=vms82.liruilongs.github.io Ready <none> 45d v1.22.2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=node1,kubernetes.io/arch=amd64,kubernetes.io/hostname=vms82.liruilongs.github.io,kubernetes.io/os=linuxvms83.liruilongs.github.io Ready <none> 45d v1.22.2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=node2,kubernetes.io/arch=amd64,kubernetes.io/hostname=vms83.liruilongs.github.io,kubernetes.io/os=linux┌──[root@vms81.liruilongs.github.io]-[