Kubernetes 的亲和性污点与容忍
写在前面
我们在使用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 #就要部署到这个
这种写法简单粗暴,一般用来测试和测试用途,一般不这么写,因为存在比较多的局限性:
- 比如节点不存在或者节点名字写错了,部署失败;
- 指定的节点硬件资源不够,比如cpu或者内存不够了,部署失败;
- 在云服务环境中,节点名字总是变化的,指定节点名没什么意义;
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:匹配表达式,数组
weight: preferredDuringSchedulingIgnoredDuringExecution
可设置的权重字段,值范围是 1 到 100。 会计算到调度打分算法上,分数高的优先级高;
operator:逻辑操作符,比如这里的in表示包含,一共有以下逻辑运算符;
- In:label 的值在某个列表中
- NotIn:label 的值不在某个列表中
- Gt:label 的值大于某个值
- Lt:label 的值小于某个值
- Exists:某个 label 存在
- DoesNotExist:某个 label 不存在
#可用NotIn和DoesNotExist实现反亲和性;
匹配规则:
如果你同时指定了 nodeSelector
和 nodeAffinity
,两者 必须都要满足, 才能将 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-ready
和 node.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 的亲和性污点与容忍的更多相关文章
- Kubernetes之Taints与Tolerations 污点和容忍
NodeAffinity节点亲和性,是Pod上定义的一种属性,使Pod能够按我们的要求调度到某个Node上,而Taints则恰恰相反,它可以让Node拒绝运行Pod,甚至驱逐Pod. Taints(污 ...
- 七、kubernetes污点和容忍
Kubernetes污点和容忍 一.Taint 和 Toleration介绍 节点亲和性,是 pod 的一种属性(偏好或硬性要求),它使 pod 被吸引到一类特定的节点.Taint 则相反,它使节点能 ...
- 【云原生 · Kubernetes】Taint和Toleration(污点和容忍)
个人名片: 因为云计算成为了监控工程师 个人博客:念舒_C.ying CSDN主页️:念舒_C.ying Taint和Toleration(污点和容忍) 概念 添加多个tainit(污点) 使用例子 ...
- Kubernetes的污点和容忍(下篇)
背景 继上一篇<Kubernetes的污点和容忍(上篇)>,这是https://kubernetes.io/docs/concepts/configuration/taint-and-to ...
- Kubernetes的污点和容忍(上篇)
背景 搭建了一个k8s(Kubernetes)的事件监听服务,监听事件之后对数据做处理.有天报了一个问题经调查是新版本的k8s集群添加会把unschedule等信息通过污点的方式反映.而这些污点是只有 ...
- kubernetes(k8s)Pod污点与容忍
污点(taints)与容忍(tolerations) 对于nodeAffinity无论是硬策略还是软策略方式,都是调度 pod 到预期节点上,而Taints恰好与之相反,如果一个节点标记为 Taint ...
- Kubernetes使用节点污点和pod容忍度阻止节点调度到特定节点
Kubernetes允许你去影响pod被调度到哪个节点.起初,只能通过在pod规范里指定节点选择器来实现,后面其他的机制逐渐加入来扩容这项功能,本章将包括这些内容. 现在要介绍的高级调度的两个特性是节 ...
- Kubernetes 调度 - 污点和容忍度详解
当我们使用节点亲和力(Pod 的一个属性)时,它会将Pod吸引到一组节点(作为偏好或硬性要求).污点的行为完全相反,它们允许一个节点排斥一组 Pod. 在 Kubernetes 中,您可以标记(污染) ...
- 009.kubernets的调度系统之污点和容忍
Taints和Tolerations(污点和容忍) Taint需要与Toleration配合使用,让pod避开那些不合适的node.在node上设置一个或多个Taint后,除非pod明确声明能够容忍这 ...
- k8s-Pod污点与容忍
目录 Pod污点与容忍 大白话先解释一下污点与容忍 为什么要用污点和容忍? 官方解释 Taints参数 标记污点 容忍污点 取消所有节点污点 Pod污点与容忍 大白话先解释一下污点与容忍 污点:被打上 ...
随机推荐
- 【RTOS】《多任务抢占式调度器》笔记
<多任务抢占式调度器>读书笔记 1.多任务系统 在多任务调度器的作用下,多个任务轮流使用cpu,实现多任务相互独立并发运行的效果,能够充分利用硬件资源,提高cpu效率 2.任务特性 a.动 ...
- SQL优化:distribute by 小数据场景处理数据倾斜
distribute by rand() distribute by :用来控制map输出结果的分发,即map端如何拆分数据给reduce端. 会根据distribute by 后边定义的列,根据re ...
- sql 错误问题
message: ### Error querying database. Cause: java.sql.SQLSyntaxErrorException: SELECT command denie ...
- uniapp调起微信支付查询订单状态逻辑处理
首先看页面效果: <template> <view class="page"> <view class="page-bd"> ...
- Java8中Stream的用法
Java8中Stream的用法 1.概述 Stream APl ( java.util.stream)把真正的函数式编程风格引入到Java中.这是目前为止对Java类库最好的补充,因为Stream A ...
- 记一次因为关键字OUT 导致的后台"sql injection violation" 报错的问题
在navicat和mssm中执行用字段别名'out'均没有问题,但是在mybatis里使用就会报 "sql injection violation, syntax error: ERROR. ...
- springMVC的定时器
大家好,本人从事软件行业已有8年,大部分时间从事软件开发编写工作.好了废话少说了哈哈哈,直接干货. 在Java开发过程中有很多业务需求里面需要我们实时处理一些动态的业务比如库存的数据动态更新,实时数据 ...
- 如果遇到This QueryDict instance is immutable错误
添加数据的时候,大家遇到"This QueryDict instance is immutable". 唯一的解决方法是request.data.copy()即可成功实现添加功能
- hdu:"红色病毒"问题(指数型母函数用e^x指数函数来计算)
Problem Description医学界发现的新病毒因其蔓延速度和Internet上传播的"红色病毒"不相上下,被称为"红色病毒",经研究发现,该病毒及其变 ...
- Okhttp请求
theme: juejin highlight: a11y-dark 同步请求 OkHttpClient httpClient = new OkHttpClient(); String url = & ...