> 文档中心 > 关于K8s中Pod调度[选择器,指定节点,主机亲和性]方式和节点[coedon,drain,taint]标记的Demo

关于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的调度(选择器、指定节点、主机亲和性)方式
    • 节点的coedondrain标记
    • 节点的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镜像并启动容器

关于K8s中Pod调度[选择器,指定节点,主机亲和性]方式和节点[coedon,drain,taint]标记的Demo

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]-[