概述
k8s节点调度
- 调度算法
- node标签
- node标签选择器
- nodeSelector
- Node亲和性调度affinity
- 亲和度示例yaml
- nodeName
- node污点与容忍
- 污点容忍yaml示例
- 容忍放大
- 基于污点的驱逐
- effect标记值
- 查看污点
- 添加污点
- 删除污点
- 设置master调度
- 设置master尽量不调度
- 允许master节点调度pod
- 恢复Master Only状态
- 将node标记为不可调度状态(节点警戒)
- 设置node不可用并驱逐节点上的所有pod(腾空节点)
- 设置node为可用
- node调度故障诊断排查
- 常见调度失败原因
- pod一直是pending
- 查看node资源是否足够
调度算法
node标签
# 查看节点标签
kubectl get node --show-labels=true
# 添加标签 key=value
kubectl label nodes node1 node=node1
# 去除标签 key-
kubectl label nodes node1 node-
node标签选择器
如果同时指定了 nodeSelector
和 nodeAffinity
,两者必须都要满足, 才能将 Pod 调度到候选节点上。
如果指定了多个与 nodeAffinity
类型关联的 nodeSelectorTerms
,满足一个 nodeSelectorTerms
,pod将可以调度到节点上。
指定了多个与 nodeSelectorTerms
关联的 matchExpressions
,满足所有 matchExpressions
,Pod 才会可以调度到节点上。
由于IgnoredDuringExecution
,改变labels不会影响
已运行的pod.
nodeSelector
参考: 将 Pod 分配给节点
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
# 选择node标签为disktype=ssd的node
nodeSelector:
disktype: ssd
Node亲和性调度affinity
理解 Kubernetes 的亲和性调度
官方doc-节点亲和性
K8S高级调度方式
requiredDuringSchedulingIgnoredDuringExecution
: 硬策略/硬需求–必须满足
preferredDuringSchedulingIgnoredDuringExecution
: 软策略/软需求–尽量满足
支持的操作符有:
In
, 包含
NotIn
, 不包含,一般用来做反亲和(Anti-Affinity)
Exists
, 存在
DoesNotExist
,不存在
Gt
, (greater than), label 的值大于某个值,int类型
Lt
, (less than),label 的值小于某个值,int类型
name in( redis-master, redis-salve)# 匹配所有带有标签name=master或者name=salve的资源
name not in ( php)#匹配所有不具有标签name=php的资源对象
亲和度示例yaml
pod 亲和性 的示例
apiVersion: v1
kind: Pod
metadata:
name: myapp
labels:
name: myapp
spec:
# 亲和性
affinity:
# 节点亲和度
nodeAffinity:
# 硬策略/硬需求
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
# 匹配所有带有标签disktype=ssd或者disktype=shd的资源
- key: disktype
operator: In
values:
- ssd
- shd
# 软策略/软需求(尽量匹配标签的资源,不满足时会找其他的资源)
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1 # 权重值/(加分项,1-100,100是最高分),能提高匹配概率,不用太关注
preference: # 固定语法,意为偏爱
matchExpressions:
# 尽可能匹配标签为disktye=ssd2的资源
- key: disktype
operator: In
values:
- ssd2
containers:
- name: myapp
image: <Image>
resources:
limits:
memory: "128Mi"
cpu: "500m"
ports:
- containerPort: <Port>
nodeName
参考: pod 调度到一个指定节点
nodeName不会通过调度器,即使node有污点也能直接运行pod.一般用于测试.
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
nodeName: node1 # 让pod运行在指定node上,nodeName不会通过调度器
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
node污点与容忍
参考: 官方污点文档
三只兔子的故事来了解k8s污点与容忍
为什么Node要使用污点:
- 安全考虑
- Node职责角色分工不同
- 硬件不同
污点也类似于在node上打一个标签.例如专用节点
,比如GPU,SSD等,一般pod不会运行在这种专用节点,如果pod想运行在这种专用节点上,需要配置污点容忍
.
Taint
: 污点,避免pod调度到特定Node上,相当于排斥
Pod
Tolerations
: 污点容忍,允许pod调度到带有特定Taints
的Node上
污点容忍yaml示例
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
# 污点容忍
tolerations:
# 容忍key=example-key 等effect值存在NoSchedule
- key: "example-key"
operator: "Exists"
# value: "example-value" # 可不配置
effect: "NoSchedule"
容忍放大
k8s的一些基础静态pod,比如apiserver
,配置的就是容忍放大,下方是示例
容忍放大,只要key
或effect
存在即容忍.
apiVersion: v1
kind: Pod
metadata:
name: apiserver
labels:
env: test
spec:
containers:
- name: apiserver
image: apiserver
imagePullPolicy: IfNotPresent
# 污点容忍
tolerations:
# 容忍所有effect值为NoSchedule的污点
- effect: NoSchedule
operator: Exists
# 容忍污点key值CriticaAddonsOnly存在
- key: CriticaAddonsOnly
operator: Exists
# 容忍所有effect值为NoExecute的污点
- effect: NoExecute
operator: Exists
基于污点的驱逐
参考: 官方文档
kubelet 驱逐策略详解
污点的 effect 值 NoExecute
会影响(驱逐)已经在节点上运行的 Pod,如果Pod没有配置容忍
effect 值为 NoExecute 的污点,会被立即驱逐
.
Pod配置了容忍NoExecute
,但在容忍度定义中没有指定 tolerationSeconds(宽限期)
,则 Pod 还会一直在这个节点上运行。
Pod配置了容忍NoExecute
,,而且指定了 tolerationSeconds(宽限期)
, 则 Pod 还能在这个节点上继续运行这个指定的时间长度。
当节点故障
时,节点控制器会自动给节点添加一个(内置)污点
.如果异常状态恢复正常,kubelet 或节点控制器能够移除相关的污点。
effect标记值
effect标记值
NoSchedule
不会将 Pod 分配到该节点(不驱逐已运行pod)PreferNoSchedule
尽量不将 Pod 分配到该节点(不驱逐已运行pod)NoExecute
不会将 Pod 分配到该节点,还会将 已运行Pod从该节点驱逐
查看污点
对于k8s1.24+
,master节点将不再添加node-role.kubernetes.io/master
标签, 只会添加node-role.kubernetes.io/control-plane
标签。更多信息请参考 KEP-2067:重命名 kubeadm “master” 标签和污点。
https://kubernetes.io/zh-cn/blog/2022/04/07/upcoming-changes-in-kubernetes-1-24/
# 查看污点
kubectl describe nodes node名 |grep Taints
# Taints: node.kubernetes.io/unreachable:NoSchedule
添加污点
# 添加污点
kubectl taint nodes node名 key=value:effect值
## effect是标记值
kubectl taint nodes node1 key1=value1:NoSchedule
kubectl taint nodes node1 key1=value1:NoExecute
kubectl taint nodes node1 key2=value2:PreferNoSchedule
# 给master1机器加NoSchedule污点--k8s1.23
kubectl taint nodes m1 node-role.kubernetes.io/control-plane:NoSchedule
删除污点
# 去除污点
kubectl taint nodes node名 key:effec值-
## 或
kubectl taint nodes node名 key=value-
## 建议
kubectl taint nodes node名 key-
设置master调度
设置master尽量不调度
尽量不调度
的污点PreferNoSchedule
;
禁止调度并驱逐
的污点NoExecute
# master添加 尽量不调度 PreferNoSchedule
kubectl taint nodes k8s-master02 node-role.kubernetes.io/master:PreferNoSchedule
允许master节点调度pod
# 去除污点NoSchedule,最后一个"-"代表删除污点
# 允许所有master节点调度pod
kubectl taint nodes --all node-role.kubernetes.io/master-
# 允许master2节点调度pod;
kubectl taint nodes k8s-master02 node-role.kubernetes.io/master:NoSchedule-
恢复Master Only状态
参考: https://cloud.tencent.com/developer/article/1788356
# 指定master1为Only状态(加污点,不允许pod调度)
kubectl taint node maser1 node-role.kubernetes.io/master="":NoSchedule
将node标记为不可调度状态(节点警戒)
# 将node标记为不可调度状态(节点警戒)
kubectl cordon node名
设置node不可用并驱逐节点上的所有pod(腾空节点)
当节点磁盘空间不足时,Pod被驱逐的顺序为: BestEffort
先于 Burstable
# 切换到名为ek8s的集群
kubectl config use-context ek8s
# 查看node状态
kubectl get nodes
# 设置节点不可用并驱逐节点上的所有pod(腾空节点)
## 节点排水(驱逐节点上的所有pod)
## 忽略节点上不能杀死的特定系统Pod,例如:CNI插件,daemonSet
## --delete-local-data 清空本地数据
## --ignore-daemonsets 忽略daemonsets错误
## --force 强制执行
kubectl drain ek8s-node-1 --ignore-daemonsets --force # 考试执行
## 如果报错,加--delete-local-data 清空本地数据
kubectl drain ek8s-node-1 --delete-local-data --ignore-daemonsets --force # 练习执行
# 查看node状态
kubectl get nodes
# 查看污点
kubectl describe nodes node名 |grep Taints
# Taints: node.kubernetes.io/unreachable:NoSchedule
设置node为可用
# 标记my-node 节点为可以调度
kubectl uncordon node名
# 取消污点
## 如果已存在具有指定键和效果的污点,则替换其值为指定值。
kubectl taint nodes node名 dedicated=special-user:NoSchedule
# 去除污点NoSchedule,最后一个"-"代表删除
kubectl taint nodes node名 node-role.kubernetes.io/master:NoSchedule-
# 查看污点是否去除
kubectl describe nodes node名 |grep Taints
node调度故障诊断排查
# 显示给定节点的度量值
kubectl top node my-node
# 显示主控节点和服务的地址
kubectl cluster-info
# 将当前集群状态转储到标准输出
kubectl cluster-info dump
# 将当前集群状态输出到 /path/to/cluster-state
kubectl cluster-info dump --output-directory=/path/to/cluster-state
常见调度失败原因
- CPU不足
- 没有匹配到节点标签
- 所有的节点有污点,但你没有配置污点容忍
pod一直是pending
参考: https://cloud.tencent.com/document/product/457/42948
当Pod处在Pending的时候,可能是由于如下哪个问题造成的。
资源不足,造成无法调度;
Pod尚未进入调度阶段;
Pod正在拉取镜像;
看kubelet日志.
# 查看pod详情
kubectl describe po pod名
## 显示pod已经调度到node2,但一直是pending
查看node资源是否足够
# 查看node资源是否足够
kubectl describe node <node-name>
# 或kubectl top node
在返回信息中,请注意关注以下内容:
Allocatable
:表示此节点能够申请的资源总和。
Allocated resources
:表示此节点已分配的资源(Allocatable 减去节点上所有 Pod 总的 Request)。
最后
以上就是愤怒鸡为你收集整理的k8s节点调度的全部内容,希望文章能够帮你解决k8s节点调度所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复