写在前面

我们在使用k8s过程中经常有这样的需求:我的k8s集群有多台服务器,配置不尽相同。我想把数据库部署到CPU、内存比较好的这几台机;我想把静态承载服务部署到有固态硬盘的机器等;而这些需求,就是我们今天要讲的k8s的调度:

在Kubernetes 中,调度 是指将 Pod 部署到合适的节点(node)上。

k8s的默认调度器kube-scheduler,它执行的是一个类似平均分配的原则,让同一个service管控下的pod尽量分散在不同的节点。

那接下来分别说说k8s几种不同的调度策略。

节点标签

在介绍调度策略之前,我们先提一句节点标签;节点标签关联的指令是kubectl label ,标签是一种键值对,可以用来标识和选择资源。例如,你需要给某个节点打个标记以便后面用得上,这个标记就叫标签。

增加标签

kubectl label node docker-desktop restype=strong-cpu

这里增加了一个restype=strong-cpu的标签,表示这个节点cpu很强;

查看标签

kubectl get nodes --show-labels
NAME STATUS ROLES AGE VERSION LABELS
docker-desktop Ready <none> 328d v1.22.5 disktype=ssd

删除标签

kubectl label node docker-desktop restype-

nodeSelector-简单的节点选择器

nodeSelector:在部署pod的时候告诉集群,我要部署到符合我要求的节点;

前面已经看到我k8s的节点 docker-desktop,已经打了disktype=ssd的标签,那我们来部署一个测试的pod看看

创建文件:test-netcore6-dep.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
name: demoapi-net6
namespace: aspnetcore
labels:
name: demoapi-net6
spec:
replicas: 1
selector:
matchLabels:
name: demoapi-net6
template:
metadata:
labels:
name: demoapi-net6
spec:
containers:
- name: demoapi-net6
image: gebiwangshushu/demoapi-net6 #这是个kong的webapi
nodeSelector:
restype: strong-cpu #我这里要求节点要有资源类型restype=strong-cpu的标签

部署

kubectl apply -f .\test-netcore6-dep.yaml

查看pod状态

确实处于pending状态

 kubectl get pods
NAME READY STATUS RESTARTS AGE
demoapi-net6-c9c5cb85-rwqn2 0/1 Pending 0 52m

describe一下

可以清楚看到pending原因是affinity/selector不匹配

 kubectl describe pod demoapi-net6-c9c5cb85-rwqn2

 ...
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 32s default-scheduler 0/1 nodes are available: 1 node(s) didn't match Pod's node affinity/selector.

给node加上strong-cpn加上label看看

kubectl label node docker-desktop restype=strong-cpu

再看看

...
Normal Scheduled 46s default-scheduler Successfully assigned aspnetcore/demoapi-net6-c9c5cb85-l7sdb to docker-desktop
Normal Pulling 45s kubelet Pulling image "gebiwangshushu/demoapi-net6" #可以清楚看到已分配好node了,pod run起来了

nodeName-更粗暴的节点选择器

前面的nodeSelector是“我要部署到符合我要求的节点”;见名思意,nodeName是更粗暴的节点选择器,意思是:我就要部署到这个节点!

写法示例:

apiVersion: apps/v1
kind: Deployment
metadata:
name: demoapi-net6
namespace: aspnetcore
labels:
name: demoapi-net6
spec:
replicas: 1
selector:
matchLabels:
name: demoapi-net6
template:
metadata:
labels:
name: demoapi-net6
spec:
containers:
nodeName: docker-desktop #就要部署到这个

这种写法简单粗暴,一般用来测试和测试用途,一般不这么写,因为存在比较多的局限性

  1. 比如节点不存在或者节点名字写错了,部署失败;
  2. 指定的节点硬件资源不够,比如cpu或者内存不够了,部署失败;
  3. 在云服务环境中,节点名字总是变化的,指定节点名没什么意义;

affinity-节点亲和性和pod反亲和性

节点亲和性功能类似于 nodeSelector 字段,但它的选择表达能力更强,有各种各样的规则,还有软规则。甚至还可以有反亲和性,拒绝/排斥部署到哪些节点;

nodeAffinity--节点亲和性

节点亲和性(nodeAffinity)分成两种:

  • requiredDuringSchedulingIgnoredDuringExecution: 硬策略。就是node你一定要满足我的要求,才能执行调度,不然pod就一直pending
  • preferredDuringSchedulingIgnoredDuringExecution: 软策略。就是我更倾向于满足我要去的node,如果没有那就按默认规则调度。

示例

apiVersion: apps/v1
kind: Deployment
metadata:
name: demoapi-net6
namespace: aspnetcore
labels:
name: demoapi-net6
spec:
replicas: 1
selector:
matchLabels:
name: demoapi-net6
template:
metadata:
labels:
name: demoapi-net6
spec:
containers:
- name: demoapi-net6
image: gebiwangshushu/demoapi-net6
affinity:
nodeAffinity: #亲和性
requiredDuringSchedulingIgnoredDuringExecution: #硬策略
nodeSelectorTerms:
- matchExpressions: #这里意思一定要restype=strong-cpu的节点
- key: restype
operator: In
values:
- strong-cpu
preferredDuringSchedulingIgnoredDuringExecution: #软策略
- weight: 1
preference:
matchExpressions: #这里意思倾向于部署到有ssd硬盘的节点
- key: disktype
operator: In
values:
- ssd

affinity: 亲和性

requiredDuringSchedulingIgnoredDuringExecution:硬策略

preferredDuringSchedulingIgnoredDuringExecution:软策略

nodeSelectorTerms:节点选择项,数组

matchExpressions:匹配表达式,数组

weightpreferredDuringSchedulingIgnoredDuringExecution 可设置的权重字段,值范围是 1 到 100。 会计算到调度打分算法上,分数高的优先级高;

operator:逻辑操作符,比如这里的in表示包含,一共有以下逻辑运算符;

  - In:label 的值在某个列表中
- NotIn:label 的值不在某个列表中
- Gt:label 的值大于某个值
- Lt:label 的值小于某个值
- Exists:某个 label 存在
- DoesNotExist:某个 label 不存在 #可用NotIn和DoesNotExist实现反亲和性;

匹配规则:

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

如果你在与 nodeAffinity 类型关联的 nodeSelectorTerms 中指定多个条件, 只要其中一个 nodeSelectorTerms 满足,Pod 就可以被调度到节点上。

如果你在与 nodeSelectorTerms的一个 matchExpressions 中写个表达式, 则只有当所有表达式都满足,Pod 才能被调度到节点上。

pod间的亲和反亲和性

前面的节点亲和性是通过pod和节点之间的标签进行匹配,选择的;

pod的亲和性和反亲和性调度指:通过已在运行中的pod标签进行选择调度部署的节点;

pod的亲和性调度:一个典型的使用场景就是在集群环境是有多数据中心的,那一个服务部署已经部署到广东了,那我跟他相关的需要大量通信的其他服务也尽量部署到广东,降低彼此间的通信延迟;

pod的反亲和性调度:一个典型的使用场景就是我的服务要尽可能分散到各个数据中心、区域,比如广东、西安、上海、北京,都要有我的服务,避免某个数据中心故障服务全部宕机;

示例

apiVersion: apps/v1
kind: Deployment
metadata:
name: demoapi-net6
namespace: aspnetcore
labels:
name: demoapi-net6
spec:
replicas: 1
selector:
matchLabels:
name: demoapi-net6
template:
metadata:
labels:
name: demoapi-net6
spec:
containers:
- name: demoapi-net6
image: gebiwangshushu/demoapi-net6
affinity:
podAffinity: #pod亲和性
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: restype
operator: In
values:
- strong-cpu
topologyKey: topology.kubernetes.io/zone #topology.kubernetes.io/hostname 表示同一节点
podAntiAffinity: #pod间反亲和性
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: disktype
operator: In
values:
- ssd
topologyKey: topology.kubernetes.io/zone

亲和性规则表示:当且仅当至少一个已运行且有 restype=strong-cpu 的标签的 Pod 处于同一区域时(topology.kubernetes.io/zone=GuangDong),才可以将该 Pod 调度到节点上。

反亲和性规则表示:如果节点处于 Pod 所在的同一可用区(也是看topology.kubernetes.io/zone)且至少一个 Pod 具有 disktype=ssd 标签,则该 Pod 不应被调度到该节点上。

PS:Pod 间亲和性和反亲和性都需要一定的计算量,因此会在大规模集群中显著降低调度速度(比如上百个节点上千上万的pod),影响性能;

这块我也用的不多,就写到这里;

taint + tolerations -污点与容忍度调度

nodeSelector/nodeName和节点亲和性都是pod的一种属性,它可以主动选择某些节点。但如果Node想排他性地部署呢?答案就是污点+容忍的调度;

名称理解

taint-污点:污点是节点用来排斥pod的一组标签,比如设置一个weak-cpu的污点;当然你也可以设置strong-cpu这种“污点”;

toleration-容忍:容忍是pod用来容忍,接收节点污点的,比如给pod一个weak-cpu的容忍,这样它就可以被调度到weak-cpu的节点上了;

taint-污点

新增污点

语法

kubectl taint NODE NAME key1=value1:EFFECT(容忍的效果)

示例

kubectl taint nodes docker-desktop restype=strong-cpu:NoSchedule

EFFECT取值

  • PreferNoSchedule: 尽量不要调度。
  • NoSchedule: 一定不能被调度。
  • NoExecute: 不仅不会调度, 还会驱逐 Node 上已有的 Pod。

我们这时候再看看可以明显看到pod是pending状态

Warning  FailedScheduling  12s   default-scheduler  0/1 nodes are available: 1 node(s) had taint {restype: strong-cpu}, that the pod didn't tolerate.

查看污点

kubectl describe  node docker-desktop|grep Taints

删除污点

kubectl taint node restype-

tolerations-容忍

apiVersion: apps/v1
kind: Deployment
metadata:
name: demoapi-net6
namespace: aspnetcore
labels:
name: demoapi-net6
spec:
spec:
containers:
- name: demoapi-net6
image: gebiwangshushu/demoapi-net6
tolerations: #添加容忍
- key: "restype"
operator: "Equal"
value: "strong-cpu"
effect: "NoSchedule"

这里表示容忍restype=strong-cpu

tolerations有两种写法

写法1、operator="Equal"

tolerations:
- key: "restype"
operator: "Equal"
value: "strong-cpu"
effect: "NoSchedule"

这种写法时,key、value跟effect都要跟taint的一致;

写法2、operator="Exists"

tolerations:
- key: "restype"
operator: "Exists"
effect: "NoSchedule"

这种写法时,key、effect 跟taint的要一致,且不能写value的值;

tolerationSeconds-容忍时间

容忍时间是指:以指定当节点失效时, Pod 依旧不被驱逐的时间。

示例

tolerations:
- key: "node.kubernetes.io/unreachable"
operator: "Exists"
effect: "NoExecute"
tolerationSeconds: 6000 #单位(秒)

node.kubernetes.io/unreachable是k8s内置的污点,功能是让节点网络不可用时pod自动驱逐;这里tolerationSeconds: 6000,意思是网络不可用6000秒后,才开始驱逐;

说明

Kubernetes 会自动给 Pod 添加针对 node.kubernetes.io/not-readynode.kubernetes.io/unreachable 的容忍度,且配置 tolerationSeconds=300, 除非用户自身或者某控制器显式设置此容忍度。

这些自动添加的容忍度意味着 Pod 可以在检测到对应的问题之一时,在 5 分钟内保持绑定在该节点上。

其他规则

DaemonSet 中的 Pod 被创建时, 针对以下污点自动添加的 NoExecute 的容忍度将不会指定 tolerationSeconds

  • node.kubernetes.io/unreachable
  • node.kubernetes.io/not-ready

容忍规则

1、operator="Exists"且key为空,表示这个容忍度与任意的 key、value 和 effect 都匹配,即这个容忍度能容忍任何污点。

tolerations:
- operator: "Exists"

2、如果 effect 为空,,那么将匹配所有与 key 相同的 effect。

tolerations:
- key: "key"
operator: "Exists"

3、一个 node 可以有多个污点,一个 pod 可以有多个容忍。

4、pod如果需要调度到某个node,需要容忍该node的所有污点;

5、pod如果需要调度到某个node,但没有容忍该node的所有污点,且剩下的污点effect 均为 PreferNoSchedule,那存在调度的可能;

6、如果 Node 上带有污点 effect 为 NoExecute,这个已经在 Node 上运行的 、不容忍该污点的Pod 会从 Node 上驱逐掉(调度到其他node);

7、当集群只有一个 node 节点时,无法做到 Pod 迁移(主要是驱逐),因为 Pod 已经无路可退了。

总结

总的来说k8s中Node&Pod的调度策略还是比较实用,常用的需求,学学防身没毛病;

[参考]

https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/kube-scheduler/

https://www.cnblogs.com/hukey/p/15724506.html

Kubernetes 的亲和性污点与容忍的更多相关文章

  1. Kubernetes之Taints与Tolerations 污点和容忍

    NodeAffinity节点亲和性,是Pod上定义的一种属性,使Pod能够按我们的要求调度到某个Node上,而Taints则恰恰相反,它可以让Node拒绝运行Pod,甚至驱逐Pod. Taints(污 ...

  2. 七、kubernetes污点和容忍

    Kubernetes污点和容忍 一.Taint 和 Toleration介绍 节点亲和性,是 pod 的一种属性(偏好或硬性要求),它使 pod 被吸引到一类特定的节点.Taint 则相反,它使节点能 ...

  3. 【云原生 · Kubernetes】Taint和Toleration(污点和容忍)

    个人名片: 因为云计算成为了监控工程师‍ 个人博客:念舒_C.ying CSDN主页️:念舒_C.ying Taint和Toleration(污点和容忍) 概念 添加多个tainit(污点) 使用例子 ...

  4. Kubernetes的污点和容忍(下篇)

    背景 继上一篇<Kubernetes的污点和容忍(上篇)>,这是https://kubernetes.io/docs/concepts/configuration/taint-and-to ...

  5. Kubernetes的污点和容忍(上篇)

    背景 搭建了一个k8s(Kubernetes)的事件监听服务,监听事件之后对数据做处理.有天报了一个问题经调查是新版本的k8s集群添加会把unschedule等信息通过污点的方式反映.而这些污点是只有 ...

  6. kubernetes(k8s)Pod污点与容忍

    污点(taints)与容忍(tolerations) 对于nodeAffinity无论是硬策略还是软策略方式,都是调度 pod 到预期节点上,而Taints恰好与之相反,如果一个节点标记为 Taint ...

  7. Kubernetes使用节点污点和pod容忍度阻止节点调度到特定节点

    Kubernetes允许你去影响pod被调度到哪个节点.起初,只能通过在pod规范里指定节点选择器来实现,后面其他的机制逐渐加入来扩容这项功能,本章将包括这些内容. 现在要介绍的高级调度的两个特性是节 ...

  8. Kubernetes 调度 - 污点和容忍度详解

    当我们使用节点亲和力(Pod 的一个属性)时,它会将Pod吸引到一组节点(作为偏好或硬性要求).污点的行为完全相反,它们允许一个节点排斥一组 Pod. 在 Kubernetes 中,您可以标记(污染) ...

  9. 009.kubernets的调度系统之污点和容忍

    Taints和Tolerations(污点和容忍) Taint需要与Toleration配合使用,让pod避开那些不合适的node.在node上设置一个或多个Taint后,除非pod明确声明能够容忍这 ...

  10. k8s-Pod污点与容忍

    目录 Pod污点与容忍 大白话先解释一下污点与容忍 为什么要用污点和容忍? 官方解释 Taints参数 标记污点 容忍污点 取消所有节点污点 Pod污点与容忍 大白话先解释一下污点与容忍 污点:被打上 ...

随机推荐

  1. [2007年NOIP普及组] 奖学金

    某小学最近得到了一笔赞助,打算拿出其中一部分为学习成绩优秀的前5名学生发奖学金.期末,每个学生都有3门课的成绩:语文.数学.英语.先按总分从高到低排序,如果两个同学总分相同,再按语文成绩从高到低排序, ...

  2. 解决:pytesseract.pytesseract.TesseractNotFoundError: tesseract is not installed or it‘s not in your PATH. See README file for more information.

    问题:使用pytesseract库识别图片中文字时出现报错 代码: import pytesseract from PIL import Image,ImageEnhance img=Image.op ...

  3. jp@gc - PerfMon Metrics Collector:服务器性能监测控件

    1.下载客户端及服务器端插件: 参考如下地址:https://blog.csdn.net/qq_36643889/article/details/119142106 JMeterPlugins-Sta ...

  4. c++ thread, 模板类,锁的调用实例

    #include<thread> #include<condition_variable> #include<mutex> #include<queue> ...

  5. curl下载远程图片到服务器

    <?php //curl下载远程图片到服务器 方法 function download($url, $path = 'images/'){ $ch = curl_init(); $names = ...

  6. 【APT】Bitter APT组织针对巴基斯坦航空综合部门攻击活动分析

    前言 蔓灵花(Bitter)是一个被广泛认为来自印度的APT组织,该组织长期针对我国及巴基斯坦的政府.军工.电力.核等部门发动网络攻击,窃取敏感数据,具有较强的政治背景.本次分享一个蔓灵花组织针对巴基 ...

  7. [jmeter的使用]jmeter上传文件接口的写法

    1.类型和参数名称,依据接口/抓的包决定 2.必须选择java否则报错 3.http header也要写

  8. 第11章 配置ASP.NET Core应用程序(ASP.NET Core in Action, 2nd Edition)

    本章包括 从多个配置提供程序加载设置 安全存储敏感设置 使用强类型设置对象 在不同的宿主环境中使用不同的设置 在本书的第1部分中,您学习了ASP.NET Core应用程序启动和运行的基础知识,以及如何 ...

  9. BGP反射器

    路由反射器是一种减少自治系统内IBGP对等体连接数量的方法. 根据BGP路由通告原则,要求一个AS内的所有BGP Speaker将建立全连接关系(BGP Speaker两两建立邻接关系).当AS内的B ...

  10. 关于ADB命令工具

    android提供了不少命令行工具,方便我们调试和查看信息.下面是frameworks/base/cmds(android 6.0.1)中的命令. $ tree cmds -L 1 cmds am├─ ...