k8s调度之初探nodeSelector和nodeAffinity

news2025/8/7 17:02:04
在k8s的调度中,有强制性的nodeSelector,节点亲和性nodeAffinity、Pod亲和性podAffinity、pod反亲和性podAntiAffinity。本篇先对nodeSelector和nodeAffinity做个初探。

进入主题之前,先看看创建pod的大概过程

  1. kubectl向apiserver发起创建pod请求,apiserver将创建pod配置写入etcd

  1. scheduler收到apiserver有新pod的事件,scheduler根据自身调度算法选择一个合适的节点,并打标记pod=test-b-k8s-node01

  1. kubelet收到分配到自己节点的pod,调用docker api创建容器,并获取容器状态汇报给apiserver

  1. 执行kubectl get查看,apiserver会再次从etcd查询pod信息

k8s的各个组件是基于list-watch机制进行交互的,了解了list-watch机制,以及结合上述pod的创建流程,就可以很好的理解各个组件之间的交互。

关于list-watch机制概念(参考):

list-watch机制是一种比较常用的分布式协调机制,它使得系统中的多个节点能够相互通信并且同步更新状态。list-watch机制的基本原理是:一个节点A将发布一个列表存储到共享内存,然后另一个节点B可以访问该存储列表,当A对该存储列表进行任何变更时,系统会自动通知B节点同步数据。list-watch是一种轻量级的架构,用于在分布式环境中支持和管理系统name-value对模型。首先,它构建一个包含所有name-value对的结构,当name-value发生变化时更新这个结构,然后将其提供给特定的节点。对于每个节点,可以创建一条监视链条,以便检测名称-值的变化,以便节点能够保持最新的数据。如果name-value发生变化,list-watch机制将通知特定节点同步新的name-value。list-watch机制的工作方式非常简单,它不需要复杂的分布式框架。list-watch机制非常适合用于高可用系统,因为它可以自动地进行数据共享和同步,使各个节点能够及时获取最新的信息,从而提升系统的可用性和可靠性。此外,list-watch还可以帮助系统在各个节点上实现一致,这有助于提高系统的可扩展性,改进其可靠性和稳定性。

何为调度

说白了就是将Pod指派到合适的节点上,以便对应节点上的Kubelet能够运行这些Pod。在k8s中,承担调度工作的组件是kube-scheduler,它也是k8s集群的默认调度器,它在设计上就允许编写一个自定义的调度组件并替换原有的kube-scheduler。所以,如果你足够牛逼,就可以自己开发一个调度器来替换默认的了。调度器通过K8S的监测(Watch)机制来发现集群中新创建且尚未被调度到节点上的Pod,调度器会将所发现的每一个未调度的Pod调度到一个合适的节点上来运行。
  • 调度程序会过滤掉任何不满足Pod特定调度需求的节点

  • 创建Pod时也可以手动指定一个节点

  • 如果没有任何一个节点能满足Pod的资源请求, 那么这个Pod将一直停留在未调度状态直到调度器能够找到合适的Node

调度流程

kube-scheduler给一个Pod做调度选择时包含了两个步骤:过滤、打分。
  1. pod开始创建,通知apiserver

  1. kube-scheduler在集群中找出所有满足需求的可调度节点(过滤阶段)

  1. kube-scheduler根据当前打分规则给这些可调度节点打分(打分阶段)

  1. kube-scheduler选择得分最高的节点运行Pod(存在多个得分最高的节点则随机选取)

  1. kube-scheduler通知kube-apiserver

nodeSelector和nodeAffinity

实际工作中,可能会有这样的情况,需要进一步控制Pod被部署到哪个节点。例如,确保某些Pod最终落在具有SSD硬盘的主机上,又需要确保某些pod落在具体部门的主机上运行,这时就可以使用标签选择器来进行选择。
  • nodeSelector:通过它可以将pod指派到具有特定标签的节点上,nodeSelector只能选择指定标签的节点,它属于强制性的,如果标签不小心写错则无法调度

  • nodeAffinity:节点亲和性有以下两种,它的表达能力更强,允许指定软规则,提供了对选择逻辑更强的控制能力,operator字段支持In、NotIn、Exists、DoesNotExist、Gt和Lt,

  • requiredDuringSchedulingIgnoredDuringExecution:调度器只有在规则被满足的时候才能执行调度(硬策略)

  • preferredDuringSchedulingIgnoredDuringExecution:调度器会尝试寻找满足对应规则的节点。如果找不到匹配的节点,调度器仍然会调度该Pod(软策略)

进一步对nodeAffinity的理解:我对亲和性和反亲和性的理解是这样的,亲和性就是希望某些pod在同一个node上,反亲和性是希望某些pod不要在同一个node上。nodeAffinity是亲和性的,它的NotIn和DoesNotExist可用来实现节点反亲和性行为(当然也可以使用节点污点将Pod从特定节点上驱逐,后面专门分享),通过逻辑组合可以控制pod要部署在哪些节点上,以及不能部署在哪些节点上。

注意:

  • 如果同时指定了 nodeSelector 和 nodeAffinity,两者必须都要满足, 才能将Pod调度到候选节点上

  • 如果在与 nodeAffinity 类型关联的 nodeSelectorTerms 中指定多个条件, 只要其中一个 nodeSelectorTerms 满足(各个条件按逻辑或操作组合)的话,Pod 就可以被调度到节点上

  • 如果在与 nodeSelectorTerms 中的条件相关联的单个 matchExpressions 字段中指定多个表达式,则只有当所有表达式都满足(各表达式按逻辑与操作组合)时,Pod才能被调度到节点上

实战案例

1. 节点亲和性案例(nodeAffinity)

pod.yaml

apiVersion: v1kind: Podmetadata:  name: goweb-demospec:  affinity:    nodeAffinity:      requiredDuringSchedulingIgnoredDuringExecution: # 调度器只有在规则被满足的时候才执行调度        nodeSelectorTerms:        - matchExpressions:          - key: team            operator: In            values:            - team-a            - team-b      preferredDuringSchedulingIgnoredDuringExecution: # 调度器会尝试寻找满足对应规则的节点(如果找不到匹配的节点,调度器仍然会调度该Pod)      - weight: 1        preference:          matchExpressions:          - key: hostbrand            operator: In            values:            - ibm  containers:  - name: container-goweb-demo    image: 192.168.11.247/web-demo/goweb-demo:20221229v3

配置node的标签

# 设置标签kubectl label node test-b-k8s-node01 team=team-akubectl label node test-b-k8s-node02 team=team-bkubectl label node test-b-k8s-node01 hostbrand=ibm# 查看kubectl get node --show-labels# 创建kubectl create -f pod.yaml # 查看Podtantianran@test-b-k8s-master:~/goweb-demo$ kubectl get pod -o wideNAME         READY   STATUS    RESTARTS   AGE   IP              NODE                NOMINATED NODE   READINESS GATESgoweb-demo   1/1     Running   0          17s   10.244.240.58   test-b-k8s-node01   <none>           <none>tantianran@test-b-k8s-master:~/goweb-demo$ 

在上面的案例中,所应用的规则如下:

  • 节点必须包含一个键名为 team 的标签, 并且该标签的取值必须为 team-a 或 team-b

  • 节点最好具有一个键名为 hostbrand 且取值为 ibm 的标签

关于节点亲和性权重的weight字段:

  • preferredDuringSchedulingIgnoredDuringExecution 亲和性类型可以设置 weight 字段,其取值范围是 1 到 100。 当调度器找到能够满足 Pod 的其他调度请求的节点时,调度器会遍历节点满足的所有的偏好性规则, 并将对应表达式的 weight 值加和。

  • 最终的加和值会添加到该节点的其他优先级函数的评分之上。 在调度器为 Pod 作出调度决定时,总分最高的节点的优先级也最高。

2. 节点亲和性+带有权重的例子

pod.yaml

apiVersion: v1kind: Podmetadata:  name: goweb-demospec:  affinity:    nodeAffinity:      requiredDuringSchedulingIgnoredDuringExecution:        nodeSelectorTerms:        - matchExpressions:          - key: team            operator: In            values:            - team-a      preferredDuringSchedulingIgnoredDuringExecution:      - weight: 1        preference:          matchExpressions:          - key: disktype            operator: In            values:            - ssd      - weight: 50        preference:          matchExpressions:          - key: disktype            operator: In            values:            - sas  containers:  - name: container-goweb-demo    image: 192.168.11.247/web-demo/goweb-demo:20221229v3
# 创建tantianran@test-b-k8s-master:~/goweb-demo$ kubectl create -f pod.yaml pod/goweb-demo created# 查看tantianran@test-b-k8s-master:~/goweb-demo$ kubectl get pods -o wideNAME         READY   STATUS    RESTARTS   AGE   IP              NODE                NOMINATED NODE   READINESS GATESgoweb-demo   1/1     Running   0          35s   10.244.240.18   test-b-k8s-node01   <none>           <none>tantianran@test-b-k8s-master:~/goweb-demo$ 
上面的例子,存在两个候选节点,都满足 preferredDuringSchedulingIgnoredDuringExecution 规则, 其中一个节点具有标签 disktype:ssd,另一个节点具有标签 disktype:sas,调度器会考察各个节点的weight取值,并将该权重值添加到节点的其他得分值之上。

3. nodeSelector案例

设置节点的标签

# 给节点打标签,key和value:gpu=truekubectl label node test-b-k8s-node02 gpu=truenode/test-b-k8s-node02 labeled# 查看指定节点标签kubectl get node test-b-k8s-node02 --show-labels# 不指定节点时,查看所有节点标签kubectl get node --show-labels

添加nodeSelector字段到pod配置

apiVersion: v1kind: Namespacemetadata:  name: test-a---apiVersion: apps/v1kind: Deploymentmetadata:  name: goweb-demo  namespace: test-aspec:  replicas: 10  selector:    matchLabels:      app: goweb-demo  template:    metadata:      labels:        app: goweb-demo    spec:      nodeSelector:        gpu: true      containers:      - name: goweb-demo        image: 192.168.11.247/web-demo/goweb-demo:20221229v3---apiVersion: v1kind: Servicemetadata:  name: goweb-demo  namespace: test-aspec:  ports:  - port: 80    protocol: TCP    targetPort: 8090  selector:    app: goweb-demo  type: NodePort
提示:刚测了一下,非要取这种标签的话gpu=true,在yaml定义时gpu: true ,true就要加双引号,它是字符串,不加的话,他认为是bool。所以,设置node的标签,value以后尽量不要是true/false,非要的话,指定时加上双引号即可。
tantianran@test-b-k8s-master:~/goweb-demo$ kubectl get pods -n test-a -o wideNAME                          READY   STATUS    RESTARTS   AGE   IP              NODE                NOMINATED NODE   READINESS GATESgoweb-demo-69d79997f7-24862   1/1     Running   0          16m   10.244.222.7    test-b-k8s-node02   <none>           <none>goweb-demo-69d79997f7-48c62   1/1     Running   0          16m   10.244.222.32   test-b-k8s-node02   <none>           <none>goweb-demo-69d79997f7-76jd9   1/1     Running   0          16m   10.244.222.51   test-b-k8s-node02   <none>           <none>goweb-demo-69d79997f7-dt7sf   1/1     Running   0          16m   10.244.222.21   test-b-k8s-node02   <none>           <none>goweb-demo-69d79997f7-fddpd   1/1     Running   0          16m   10.244.222.60   test-b-k8s-node02   <none>           <none>goweb-demo-69d79997f7-lw2t8   1/1     Running   0          16m   10.244.222.47   test-b-k8s-node02   <none>           <none>goweb-demo-69d79997f7-nwwkg   1/1     Running   0          16m   10.244.222.10   test-b-k8s-node02   <none>           <none>goweb-demo-69d79997f7-v768k   1/1     Running   0          16m   10.244.222.38   test-b-k8s-node02   <none>           <none>goweb-demo-69d79997f7-vgt5w   1/1     Running   0          16m   10.244.222.56   test-b-k8s-node02   <none>           <none>goweb-demo-69d79997f7-xqhxp   1/1     Running   0          16m   10.244.222.41   test-b-k8s-node02   <none>           <none>
如果创建pod,指派的标签是不存在任何1台节点时,pod会一直处于pending状态,直至进入Terminating状态,pod的重启策略是always(默认策略:当容器退出时,总是重启容器),则一直在pending和Terminating中徘徊,直到有符合条件的标签,就会立马分配节点,从而创建pod。

删除标签

tantianran@test-b-k8s-master:~/goweb-demo$ kubectl label node test-b-k8s-node02 gpu-node/test-b-k8s-node02 unlabeledtantianran@test-b-k8s-master:~/goweb-demo$ 
提示:key和小横杠之间不能有空格,否则删除失败。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/394007.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【UE4 RTS游戏】01-项目准备

步骤新建一个工程&#xff0c;选择俯视角游戏模板我命名工程如下&#xff1a;删除场景内的所有cube再删除Floor和Wall删除TopDownCharacter删除“NavgationMeshBoundVolume”删除“TamplateLabel”和“RecastNavMesh-Default”删除LightmassImportanceVolume、PostProcessVolum…

【java】java异常分类和异常处理以及面试中常见的问题

文章目录什么是异常&#xff1f;程序错误一般分为三种编译错误运行时错误逻辑错误两个子类区别java几种常见的异常&#xff1a;运行时异常&#xff1a;IOException异常的产生&#xff1a;异常的处理&#xff1a;消极的处理&#xff1a;积极的处理&#xff1a;(异常捕获)throw和…

Jenkins自动化部署入门

Jenkins自动化部署入门 一、简介 Jenkins是一个开源软件项目&#xff0c;是基于Java开发的一种持续集成工具&#xff0c;用于监控持续重复的工作&#xff0c;旨在提供一个开放易用的软件平台&#xff0c;使软件的持续集成变成可能。 Jenkins自动化部署实现原理 二、Jenkins部…

交互:可以执行命令行的框架才是好框架

上一节课&#xff0c;我们开始把框架向工业级迭代&#xff0c;重新规划了目录&#xff0c;这一节课将对框架做更大的改动&#xff0c;让框架支持命令行工具。 第三方命令行工具库 cobra obra 不仅仅能让我们快速构建一个命令行&#xff0c;它更大的优势是能更快地组织起有许多…

SpringBoot整合Mybatis详解

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言一、创建项目&#xff0c;导入依赖&#xff0c;完善项目结构二、编码1.yml配置2.编写实体类3.编写mapper.xml和接口4.编写业务层5.编写控制层6.启动类加上包扫描…

实践分享:Vue 项目如何迁移小程序

最近我们小组刚经历了将成熟的 HTML5 项目转换成小程序&#xff0c;并在app中运行的操作&#xff01;记录下来分享给各位。 项目&#xff1a;将已有的 Vue 项目转为小程序&#xff0c; 在集成了FinClip SDK 的 App 中运行。 技术&#xff1a;uni-app、FinClip 两个注意事项&…

多机器人集群网络通信协议分析

本文讨论的是多机器人网络通信各层的情况和协议。 每个机器人连接一个数据传输通信模块&#xff08;以下简称为数传&#xff0c;也泛指市面上的图传或图数一体的通信模块&#xff09;&#xff0c;数传之间进行组网来传递信息。 根据ISO的划分&#xff0c;网络通信的OSI模型分…

速看|快速软件开发框架突破信息孤岛,高效实现数字化发展!

在企业办公自动化发展的过程中&#xff0c;各部门之间的信息链接存在着链接不及时、信息孤岛的现象。伴随着日益激烈的市场竞争&#xff0c;这样单枪匹马的作战方式已经让不少企业吃尽了苦头&#xff0c;借助快速软件开发框架&#xff0c;可以有效打破信息孤岛&#xff0c;让各…

Jetpack Compose 中适配不同的屏幕尺寸

窗口大小分类 Compose 将 Android 设备的屏幕尺寸分为三类&#xff1a; Compact: 小屏幕&#xff0c;一般就是手机设备&#xff0c;屏幕宽度 < 600dpMedium&#xff1a;中等屏幕&#xff0c;大号的板砖手机如折叠屏或平板的竖屏&#xff0c;600dp < 屏幕宽度 < 840d…

swagger关闭/v2/api-docs仍然可以访问漏洞

今天接到安全团队的说swagger有未授权访问漏洞&#xff0c;即使在swagger关闭的情况下http://127.0.0.1:8086/agcloud/v2/api-docs?group%E7%94%A8%E6%88%B7%E5%85%B3%E8%81%94%E4%BF%A1%E6%81%AF%E6%A8%A1%E5%9D%97仍然还能访问。 看了下原来是有写一个拦截器 registry.addI…

图表控件TeeChart for .NET系列教程六:将数据添加到系列中(使用系列)

TeeChart for .NET是优秀的工业4.0 WinForm图表控件&#xff0c;官方独家授权汉化&#xff0c;集功能全面、性能稳定、价格实惠等优势于一体。TeeChart for .NET 中文版还可让您在使用和学习上没有任何语言障碍&#xff0c;至少可以节省30%的开发时间。 TeeChart for .NET最新…

BFD协议原理

BFD协议原理引入背景不使用BFD带来的问题OSPF感知慢VRRP产生次优路径BFD技术简介BFD会话建立方式和检测机制BFD会话建立过程BFD工作流程BFD的单臂回声BFD默认参数以及调整方法总结引入背景 随着网络应用的广泛部署&#xff0c;网络发生中断可能影响业务正常运行并造成重大损失…

Git开发常用指令及其使用场景

目录前言一、Git安装1.1 官网安装二、配置Git工具2.1 用户信息配置2.2 查看配置三、初始化仓库3.1 创建仓库四、常用命令4.1 git clone拉取远端仓库4.2 git分支操作4.2.1 查看分支4.2.2 分支操作4.3 撤回操作4.3.1 撤回删错的分支4.3.2 撤回提交4.3 拉取代码操作4.4 贮存操作五…

ChatGPT也有犯晕的时候

前面测试 ChatGPT 进行写代码、优化代码、解释代码、一般问答都表现的很好。偷个懒&#xff0c;用ChatGPT 帮我写段生物信息代码如果 ChatGPT 给出的的代码不太完善&#xff0c;如何请他一步步改好&#xff1f;代码看不懂&#xff1f;ChatGPT 帮你解释&#xff0c;详细到爆&…

详解Redis的主从同步原理

前言 Redis为了保证服务高可用&#xff0c;其中一种实现就是主从模式&#xff0c;即一个Redis服务端作为主节点&#xff0c;若干个Redis服务端作为主节点的从节点&#xff0c;从而实现即使某个服务端不可用时&#xff0c;也不会影响Redis服务的正常使用。本篇文章将对主从模式…

asp.net网站读取app.config配置内容

目录1、情况说明1.1 使用场景1.2 基本概念2、优化1、情况说明 1.1 使用场景 创建了一个网站&#xff08;项目A&#xff09;&#xff0c;又创建了一个访问数据的项目B。项目A因为是个网站&#xff0c;所有会有web.config文件。项目B是一个读取数据库的类库&#xff0c;会有一个…

小樽C++ 单章④ 字符数组与字符串

目录 一、字符与数组 1.求字符数组的长度 2.查找单词 二、字符串与数组 2.1 字符串倒序输出 2.2 字符串比较 2.3 大写字母输出 ​编辑 三、字符串常用函数 一、初始化字符串&#xff1a; 二、字符串操作&#xff1a;(增删改查) 三、截取与替换字符串 四、替换字符串…

从0开始学python -48

Python MySQL - mysql-connector 驱动 MySQL 是最流行的关系型数据库管理系统&#xff0c;如果你不熟悉 MySQL&#xff0c;可以先学习 MySQL 教程。 本章节我们为大家介绍使用 mysql-connector 来连接使用 MySQL&#xff0c; mysql-connector 是 MySQL 官方提供的驱动器。 我…

DoubleAccumulator 源码详解

DoubleAccumulator 简介 这个类是新增的并发统计工具&#xff0c;可以多线程安全计数。 他的构造方法有两个参数&#xff0c;分别是统计方法和初始值。所以具体的统计是加减乘除是由传入的操作方法决定的。 public DoubleAccumulator(DoubleBinaryOperator accumulatorFunct…

​力扣解法汇总1599. 经营摩天轮的最大利润

目录链接&#xff1a; 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目&#xff1a; https://github.com/September26/java-algorithms 原题链接&#xff1a;力扣 描述&#xff1a; 你正在经营一座摩天轮&#xff0c;该摩天轮共有 4 个座舱 &#xff0c;每个座舱…