Kubernetes调度之Pod亲和性

news2024/11/25 3:43:33

Kubernetes调度中的Pod亲和性

abstract.png

Pod亲和性

节点亲和性,是基于节点的标签对Pod进行调度。而Pod亲和性则可以实现基于已经在节点上运行Pod的标签来约束新Pod可以调度到的节点。具体地,如果X上已经运行了一个或多个满足规则Y的Pod,则这个新Pod也应该运行在X上。其中,X可以是节点、机架、可用性区域、地理区域等。可通过topologyKey字段定义拓扑域X,其取值是节点标签的键名Key;而Y则是Kubernetes尝试满足的规则。可以通过标签选择器的形式来定义。此外,Pod亲和性使用podAffinity字段,其下支持两种亲和性:

  • 「requiredDuringSchedulingIgnoredDuringExecution」:requiredDuringScheduling表明其是一个强制性的调度,调度器只有在规则被满足的时候才能执行调度;而IgnoredDuringExecution则表明其不会影响已在节点上运行的Pod

  • 「preferredDuringSchedulingIgnoredDuringExecution」:preferredDuringScheduling表明其是一个偏好性的调度,调度器会根据偏好优先选择满足对应规则的节点来调度Pod。但如果找不到满足规则的节点,调度器则会选择其他节点来调度Pod。而IgnoredDuringExecution则表明其不会影响已在节点上运行的Pod

强制性调度

这里提供了一个存在5个工作节点的K8s集群,然后我们使用Deployment部署了应用的前端服务

# 应用的前端服务apiVersion: apps/v1kind: Deploymentmetadata:    name: my-app-frontendspec:    # Pod副本数量  replicas: 2  selector:    matchLabels:      app: frontend  # Pod模板  template:    metadata:      # 标签信息: 应用的前端服务      labels:        app: frontend    spec:      # 容器信息      containers:      - name: my-app-frontend        image: jocatalin/kubernetes-bootcamp:v1

效果如下所示,可以看到前端服务运行了2个Pod。分别在my-k8s-cluster-multi-node-worker2、my-k8s-cluster-multi-node-worker3节点上

figure 1.jpeg

现在我们来部署应用的后端服务,这里我们期望后端服务的Pod能够运行在前端服务的Pod所在的节点上。这时就可以通过节点亲和性实现。具体地:

  • 首先,使用podAffinity来定义Pod亲和性规则,使用requiredDuringSchedulingIgnoredDuringExecution定义强制性的调度规则

  • 然后,使用标签选择器来确定Pod的范围,这里我们显然选择的是前端服务的Pod

  • 最后,使用topologyKey来定义拓扑域信息,这里我们使用的是节点主机名。对于 此时即将被调度的新Pod 与 标签选择器所确定的Pod 来说,它们各自运行节点的主机名是相同的。即,后端服务的Pod 必须被调度到 与前端服务的Pod所在节点拥有相同主机名 的节点上

这样即可实现后端服务的Pod所在的节点上,一定存在前端服务的Pod

# 应用的后端服务apiVersion: apps/v1kind: Deploymentmetadata:    name: my-app-backendspec:    # Pod副本数量  replicas: 4  selector:    matchLabels:      app: backend  # Pod模板  template:    metadata:      # 标签信息: 应用的后端服务      labels:        app: backend    spec:    # 亲和性      affinity:        # Pod亲和性规则        podAffinity:          # 强制性的调度规则, 但不会影响已在节点上运行的Pod          requiredDuringSchedulingIgnoredDuringExecution:          - topologyKey: kubernetes.io/hostname            # 标签选择器            labelSelector:              matchLabels:                app: frontend      # 容器信息      containers:      - name: my-app-backend        image: tutum/dnsutils        command:        - sleep        - infinity

效果如下所示。后端服务的5个Pod均运行在my-k8s-cluster-multi-node-worker2、my-k8s-cluster-multi-node-worker3节点上

figure 2.jpeg

偏好性调度

这里提供了一个存在5个工作节点的K8s集群,然后我们使用Deployment部署了应用的前端服务

# 应用的后端服务apiVersion: apps/v1kind: Deploymentmetadata:    name: my-app-backendspec:    # Pod副本数量  replicas: 2  selector:    matchLabels:      app: backend  # Pod模板  template:    metadata:      # 标签信息: 应用的后端服务      labels:        app: backend    spec:      # 容器信息      containers:      - name: my-app-backend        image: tutum/dnsutils        command:        - sleep        - infinity

效果如下所示,可以看到后端服务运行了2个Pod。分别在my-k8s-cluster-multi-node-worker、my-k8s-cluster-multi-node-worker3节点上。而通过标签信息可知,这两个节点都位于上海

figure 3.jpeg

现在我们来部署应用的缓存服务,这里我们期望 缓存服务Pod所在的节点 能够尽可能与 前端服务Pod所在的节点 在通过一个地理区域,以减少网络通讯的延迟。

  • 首先,使用podAffinity来定义Pod亲和性规则,使用preferredDuringSchedulingIgnoredDuringExecution定义偏好性的调度规则。可通过权重值来定义对节点偏好,权重值越大优先级越高。其中,权重范围: 1~100

  • 然后,使用标签选择器来确定Pod的范围,这里我们显然选择的是前端服务的Pod

  • 最后,使用topologyKey来定义拓扑域信息,这里我们使用的是节点的Region标签地理位置。此时即将被调度的新Pod 将会更倾向于调度到 与标签选择器所确定的Pod的所在节点 具有相同Region标签值的节点当中。即,缓存服务的Pod的所在节点 与 后端服务的Pod的所在节点 将会尽可能得位于同一个地理区域(具有相同Region标签值)

# 应用的缓存服务apiVersion: apps/v1kind: Deploymentmetadata:    name: my-app-redisspec:    # Pod副本数量  replicas: 4  selector:    matchLabels:      app: redis  # Pod模板  template:    metadata:      # 标签信息: 应用的后端服务      labels:        app: redis    spec:    # 亲和性      affinity:        # Pod亲和性规则        podAffinity:          # 偏好性的调度规则, 但不会影响已在节点上运行的Pod          preferredDuringSchedulingIgnoredDuringExecution:          - weight: 70  # 权重范围: 1~100, 权重值越大, 优先级越高            podAffinityTerm:              topologyKey: Region              # 标签选择器              labelSelector:                matchLabels:                  app: backend                        # 容器信息      containers:      - name: my-app-redis        image: redis:3.2-alpine

效果如下所示。缓存服务的4个Pod均运行同样位于上海的节点上。需要注意的是,由于这里是偏好性调度。故如果当上海的节点由于某种原因导致无法调度Pod到其上运行,调度器选择其他地域的节点进行调度也是合法的、允许的。比如这里位于广州的节点

figure 4.jpeg

Pod反亲和性

而Pod反亲和性,同样也是基于已经在节点上运行Pod的标签来约束新Pod可以调度到的节点。只不过其与Pod亲和性恰恰相反。即,如果X上已经运行了一个或多个满足规则Y的Pod,则这个新Pod不应该运行在X上。此外,Pod反亲和性使用podAntiAffinity字段,其下同样支持两种反亲和性:requiredDuringSchedulingIgnoredDuringExecution 强制性调度、preferredDuringSchedulingIgnoredDuringExecution 偏好性调度

强制性调度

这里提供了一个存在5个工作节点的K8s集群,然后我们使用Deployment部署了应用的后端服务。这里为了便于后续演示,我们规定后端服务的Pod只允许运行在上海的节点上

# 应用的后端服务apiVersion: apps/v1kind: Deploymentmetadata:    name: my-app-backendspec:    # Pod副本数量  replicas: 5  selector:    matchLabels:      app: backend  # Pod模板  template:    metadata:      # 标签信息: 应用的后端服务      labels:        app: backend    spec:    # 配置节点选择器, 要求K8s只将该Pod部署到包含标签Region=ShangHai的节点上      nodeSelector:        Region: ShangHai      # 容器信息      containers:      - name: my-app-backend        image: tutum/dnsutils        command:        - sleep        - infinity

效果如下所示,可以看到后端服务运行了5个Pod。分别运行在位于上海的my-k8s-cluster-multi-node-worker、my-k8s-cluster-multi-node-worker3、my-k8s-cluster-multi-node-worker5节点上

figure 5.jpeg

现在我们来部署应用的前端服务,同时基于某种特殊原因的考量,我们期望该应用的前、后端服务的Pod分别运行在不同区域。即前端服务的Pod的运行在位于上海的节点,则我们希望后端服务的Pod运行在除上海之外的节点当中。这时就可以通过节点反亲和性实现。具体地:

  • 首先,使用podAntiAffinity来定义Pod反亲和性规则,使用requiredDuringSchedulingIgnoredDuringExecution定义强制性的调度规则

  • 然后,使用标签选择器来确定Pod的范围,这里我们显然选择的是后端服务的Pod

  • 最后,使用topologyKey来定义拓扑域信息,这里我们使用的是节点的Region标签地理位置。对于 此时即将被调度的新Pod 与 标签选择器所确定的Pod 来说,它们各自运行节点的地理位置是不同的。即,后端服务的Pod 必须被调度到 与前端服务的Pod所在节点拥有不同地理位置 的节点上

# 应用的前端服务apiVersion: apps/v1kind: Deploymentmetadata:    name: my-app-frontendspec:    # Pod副本数量  replicas: 5  selector:    matchLabels:      app: frontend  # Pod模板  template:    metadata:      # 标签信息: 应用的前端服务      labels:        app: frontend    spec:    # 亲和性      affinity:        # Pod反亲和性规则        podAntiAffinity:          # 强制性的调度规则, 但不会影响已在节点上运行的Pod          requiredDuringSchedulingIgnoredDuringExecution:          - topologyKey: Region            # 标签选择器            labelSelector:              matchLabels:                app: backend      # 容器信息      containers:      - name: my-app-frontend        image: jocatalin/kubernetes-bootcamp:v1

效果如下所示。前端服务的5个Pod均运行在位于广州的my-k8s-cluster-multi-node-worker2、my-k8s-cluster-multi-node-worker4节点上

figure 6.jpeg

偏好性调度

这里提供了一个存在5个工作节点的K8s集群,然后我们使用Deployment部署了应用的后端服务

# 应用的后端服务apiVersion: apps/v1kind: Deploymentmetadata:    name: my-app-backendspec:    # Pod副本数量  replicas: 2  selector:    matchLabels:      app: backend  # Pod模板  template:    metadata:      # 标签信息: 应用的后端服务      labels:        app: backend    spec:      # 容器信息      containers:      - name: my-app-backend        image: tutum/dnsutils        command:        - sleep        - infinity

效果如下所示,可以看到前端服务运行了2个Pod。分别在my-k8s-cluster-multi-node-worker、my-k8s-cluster-multi-node-worker4节点上

figure 7.jpeg

现在我们来部署应用的缓存服务,这里由于后端服务、缓存服务都非常占用资源。故我们提出下述调度要求

  1. 缓存服务Pod所在的节点 能够尽可能与 前端服务Pod所在的节点 不是同一个节点

  1. 缓存服务Pod所在的节点 能够尽可能与 前端服务Pod所在的节点 不在同一个地理区域

  1. 上诉2点均为偏好性要求,且第1点优先级是最高的

  • 首先,使用podAntiAffinity来定义Pod反亲和性规则,使用preferredDuringSchedulingIgnoredDuringExecution定义偏好性的调度规则。可通过权重值来定义偏好,权重值越大优先级越高。其中,权重范围: 1~100

  • 然后,使用标签选择器来确定Pod的范围,这里我们显然选择的是前端服务的Pod

  • 最后,使用topologyKey来定义拓扑域信息。这里我们分别使用了节点主机名、地理位置。以此实现即将被调度的新Pod 将会更倾向于调度到 与标签选择器所确定的Pod的所在节点 具有不同节点 或 不同地理区域的节点上

# 应用的缓存服务apiVersion: apps/v1kind: Deploymentmetadata:    name: my-app-redisspec:    # Pod副本数量  replicas: 4  selector:    matchLabels:      app: redis  # Pod模板  template:    metadata:      # 标签信息: 应用的后端服务      labels:        app: redis    spec:    # 亲和性      affinity:        # Pod反亲和性规则        podAntiAffinity:          # 偏好性的调度规则, 但不会影响已在节点上运行的Pod          preferredDuringSchedulingIgnoredDuringExecution:          - weight: 100  # 权重范围: 1~100, 权重值越大, 优先级越高            podAffinityTerm:              topologyKey: kubernetes.io/hostname              # 标签选择器              labelSelector:                matchLabels:                  app: backend          - weight: 1  # 权重范围: 1~100, 权重值越大, 优先级越高            podAffinityTerm:              topologyKey: Region              # 标签选择器              labelSelector:                matchLabels:                  app: backend                        # 容器信息      containers:      - name: my-app-redis        image: redis:3.2-alpine

效果如下所示。缓存服务的4个Pod均运行在与后端服务Pod所在节点不同的节点上。但这里由于是偏好性调度,当最终结果未满足两个服务运行在不同的地理位置时,即调度器选择相同地理位置的节点进行调度也是合法的、允许的

figure 8.jpeg

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

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

相关文章

在ubuntu上(docker虚拟环境)部署完laravel的环境后如何运行一个基础的laravel项目

先测试laravel有没有安装成功 laravel如果报laravel command not found,先测试是否安装成功 find / -name laravel出现结果: 说明已经安装成功只是没有配环境变量 要么进这些文件夹测试那个路径下有真的laravel可执行文件,要么每个分别配置…

MCP2515国产替代DP2515带有SPI 接口的独立CAN 控制器

DP2515是一款独立控制器局域网络(Controller AreaNetwork, CAN)协议控制器,完全支持CAN V2.0B 技术规范。该器件能发送和接收标准和扩展数据帧以及远程帧。DP2515自带的两个验收屏蔽寄存器和六个验收滤波寄存器可以过滤掉不想要的…

图像处理--基于像素层面

python 图像锐化 图像锐化可以使图像的边缘更加清晰,增强图像的细节。常见的图像锐化算法有拉普拉斯算子、Sobel算子、Prewitt算子等。下面是使用拉普拉斯算子实现图像锐化的Python代码: import cv2 import numpy as npdef laplacian_sharpen(img, ksi…

MySQL日志文件

文章目录1.MySQL中的日志文件2.bin log的作用3.redo log的作用4.bin log和redo log的区别(1)存储的内容(2)功能(3)写入时间(4)写入方式5.两阶段提交6.undo log的作用1.MySQL中的日志…

springcloud3 fegin实现服务调用1

一 Fegin的作用 1.1 fegin的作用 fegin是一个声明式的web服务客户端,让编写web服务器客户端变得非常容易,只需创建一个接口并在接口中添加FeginClients注解即可。 Fegin的使用方式:使用fegin的注解定义接口,调用这个接口&#…

BI软件工具也有ChatGPT

ChatGPT最近大火,朋友圈、聊天群啊到处都在分享它、讨论它。我也凑了个热闹,先和它聊了一下孩子学习上的困惑,然后用它给孩子出了一套易错题型的练习题,缓解了我做为熊孩子家长的压力。ChatGET能做的可不止这些,还能写…

MTK平台开发入门到精通(休眠唤醒篇)休眠唤醒LPM框架

文章目录 一、lpm驱动源码分析二、设备属性调试文件沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇文章将介绍 lpm 驱动源码分析。 mtk 平台下,其默认的 lpm 机制的源码位置:drivers/misc/mediatek/lpm/ 一、lpm驱动源码分析 目录:drivers/misc/mediatek/lpm/…

aardio 编程语言

今天看到一篇文章《独自坚持 17 年,aardio 作者:“因妻子患癌,再无精力维护项目”》,才知道有个这个项目,也算是很有情怀的一个开发者,对程序有着真挚的热忱,aardio 🔊 专注于桌面软…

Unity Avatar Cover System - 如何实现一个Avatar角色的智能掩体系统

文章目录简介变量说明实现动画准备动画状态机State 状态NoneStand To CoverIs CoveringCover To Stand高度适配高度检测脚部IK简介 本文介绍如何在Unity中实现一个Avatar角色的智能掩体系统,效果如图所示: 初版1.0.0代码已上传至SKFramework框架Package…

数据库系统-关系模式

二、DB的抽象与演变 2.1 DB的标准结构 DBMS管理数据的三个层次 ● (局部模式)Entrenal Level 外部层次 User Level 用户层次 ○ 用户能够看到雨处理的数据,全局数据中的某一部分 ● (全局模式)Conceptual Level 概念层次 Logic Level 逻辑层次 ○ 从全局角度理解…

【Linux】编译器gcc g++和调试器gdb的使用

文章目录1.编译器gcc/g1.1C语言程序的翻译过程1.预处理2.编译3.汇编4. 链接1.2 链接方式与函数库1.动态链接与静态链接2.动态库与静态库1.3 gcc与g的使用2.调试器gdb2.1debug和release2.2gdb的安装2.3gdb的使用2.4gdb的常用指令3.总结1.编译器gcc/g 1.1C语言程序的翻译过程 1…

一个ELF文件分析和逆向的过程

CrackMe1、2分析和逆向的过程 1. CrackMe1、2相关信息 CrackMe1 1、CrackMe1是一个ELF可执行文件,可在Android中独立执行 2、通过adb(Android SDK中默认带有adb工具)将CrackMe1 push到远程Android设备中,建议放在/data/local/tmp目录下 3、打开adb shel…

关于MSVCR100.dll、MSVCR100d.dll、Msvcp100.dll、abort()R6010等故障模块排查及解决方法

一、常见故障介绍  最近在开发相机项目(项目细节由于公司保密就不介绍了),程序运行5个来月以来首次出现msvcr100.dll故障等问题,于是乎开始了分析之路,按照度娘上的一顿操作,期间也是出现了各种不一样的问…

Lombok常见用法总结

目录一、下载和安装二、常见注释(一)Data(二)Getter和Setter(三)NonNull和NotNull(不常用)(四)ToString(不常用)(五&#…

一款丧心病狂的API测试工具:Apifox!

你好,我是测试开发工程师——凡哥。欢迎和我交流测试领域相关问题(测试入门、技术、python交流都可以) 我们平时在做接口测试的时候,对于一些常用的接口测试工具的使用应该都非常熟悉了: 接口文档:Swagge…

Databend 开源周报 第 83 期

Databend 是一款现代云数仓。专为弹性和高效设计,为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务:https://app.databend.com 。Whats New探索 Databend 本周新进展,遇到更贴近你心意的 Databend 。Support for WebHDFSHDFS 是大数…

ArrayList集合底层原理

ArrayList集合底层原理ArrayList集合底层原理1.介绍2.底层实现3.构造方法3.1集合的属性4.扩容机制5.其他方法6.总结ArrayList集合底层原理 1.介绍 ​ ArrayList是List接口的可变数组的实现。实现了所有可选列表操作,并允许包括 null 在 内的所有元素。 每个 Array…

静态库和动态库的打包与使用

静态库和动态库 静态库和动态库的打包 生成可执行程序时链接使用 运行可执行程序时加载使用 提前声明,笔者示例的文件有mian.c/child.c/child.h。OK,我们先了解一下,库文件是什么?它其实就是打包了一堆实现常用功能的代码文件. ⭐…

Python之re库用法细讲

文章目录前言一、使用 re 模块的前期准备工作二、使用 re 模块匹配字符串1. 使用 match() 方法进行匹配2. 使用 search() 方法进行匹配3. 使用 findall() 方法进行匹配三、使用 re 模块替换字符串四、使用 re 模块分割字符串总结前言 在之前的博客中我们学习了【正则表达式】的…

C++ typedef用法详解

typedef的4种常见用法:给已定义的变量类型起个别名定义函数指针类型定义数组指针类型为复杂的声明定义一个新的简单的别名总结一句话:“加不加typedef,类型是一样的",这句话可以这样理解:没加typedef之前如果是个…