深入理解pod对象调度
1696字约6分钟
2024-09-29
创建一个Pod的工作流程
Kubernetes基于list-watch机制的控制器架构,实现组件间交 互的解耦。 其他组件监控自己负责的资源,当这些资源发生变化时,kubeapiserver会通知这些组件,这个过程类似于发布与订阅。
Pod中影响调度的主要属性
资源限制对Pod调度的影响
容器资源限制:
resources.limits.cpu
resources.limits.memory
容器使用的最小资源需求,作为容器调度时资 源分配的依据:
resources.requests.cpu
resources.requests.memory
CPU单位:可以写m也可以写浮点数,例如0.5=500m,1=1000m
K8s会根据Request的值去查找有足够资源的Node来调度此Pod
vim pod-resources.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-resources
spec:
containers:
- name: web
image: nginx
resources:
requests: #容器最小资源配额
memory: "64Mi"
cpu: "250m"
limits: #容器最大资源上限
memory: "128Mi"
cpu: "500m"
kubectl apply -f pod-resources.yaml
kubectl describe pod pod-resources
kubectl describe nodes k8s-node1
kubectl get pod -o wide
nodeSelector & nodeAffinity
nodeSelector:用于将Pod调度到匹配Label的Node上,如果没有匹配的标签会调度失败。
作用:
约束Pod到特定的节点运行
完全匹配节点标签
应用场景:
专用节点:根据业务线将Node分组管理
配备特殊硬件:部分Node配有SSD硬盘、GPU
示例:确保Pod分配到具有SSD硬盘的节点上
第一步:给节点添加标签
格式:kubectl label nodes <node-name> <label-key>=<label-value>
例如:kubectl label nodes k8s-node1 disktype=ssd
验证:kubectl get nodes --show-labels
第二步:添加nodeSelector字段到Pod配置中
vim pod-selector.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-selector
spec:
nodeSelector:
disktype: "ssd"
containers:
- name: nginx
image: nginx
最后,验证:
kubectl apply -f pod-selector.yaml
kubectl get pods -o wide
示例:使Pod分配到gpu是NVIDIA的节点上,k8s节点中并没有这个标签的节点
vim pod-selector2.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-selector2
spec:
nodeSelector:
gpu: "NVIDIA"
containers:
- name: nginx
image: nginx
验证:
kubectl apply -f pod-selector2.yaml
kubectl get pod
kubectl describe pod pod-selector2
nodeAffinity:节点亲和性,与nodeSelector作用一样,但相比 更灵活,满足更多条件,诸如:
匹配有更多的逻辑组合,不只是字符串的完全相等
调度分为软策略和硬策略,而不是硬性要求
硬(required):必须满足
软(preferred):尝试满足,但不保证
操作符:In、NotIn、Exists、DoesNotExist、Gt、Lt
示例:在pod满足硬性标签要求的前提下,如果没有满足其他的标签,则在满足硬性标签要求的机器上随机调度分配一台
vim pod-affinity.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-node-affinity
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: gpu
operator: In
values:
- nvidia-tesla
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: group
operator: In
values:
- ai
containers:
- name: web
image: nginx
kubectl apply -f pod-affinity.yaml
kubectl get pod
kubectl describe pod pod-node-affinity
验证:
1.如果两个节点都满足硬性标签要求,其中一个节点也满足软性标签要求,那么会优先分配到这个节点。
2.如果两个节点都满足硬性标签要求,都没有满足软性标签要求,那么会随机调度到其中的一个节点。
#给节点添加标签的命令
kubectl label nodes <node-name> <label-key>=<label-value>
例如:kubectl label node 192.168.1.205 mem=large
#给节点删除标签的命令
kubectl label nodes <node-name> <label-key>-
例如:kubectl label node 192.168.1.205 mem-
Taint(污点)与Tolerations(污点容忍)
Taints:避免Pod调度到特定Node上
Tolerations:允许Pod调度到持有Taints的Node上
应用场景:
专用节点:根据业务线将Node分组管理,希望在默认情况下不调度该节点,只有配置了污点容忍才允许分配
配备特殊硬件:部分Node配有SSD硬盘、GPU,希望在默认情况下不调度该节点,只有配置了污点容忍才允许分配
基于Taint的驱逐
第一步:给节点添加污点
格式:kubectl taint node [node] key=value:[effect]
例如:kubectl taint node k8s-node1 gpu=yes:NoSchedule
验证:kubectl describe node k8s-node1 |grep Taint
其中[effect] 可取值:
NoSchedule :一定不能被调度
PreferNoSchedule:尽量不要调度,非必须配置容忍
NoExecute:不仅不会调度,还会驱逐Node上已有的Pod
第二步:添加污点容忍(tolrations)字段到Pod配置中
去掉污点:
kubectl taint node [node] key:[effect]-
示例一
1.给node节点添加标签
kubectl label nodes k8s-node1 gpu=iniaid
kubectl label nodes k8s-node2 disktype=ssd
kubectl get nodes --show-labels
kubectl taint node |grep Taint
2.给node1节点配置污点
kubectl taint node k8s-node1 gpu=iniaid:NoSchedule
3.新建pod2.yaml文件并启动pod
vim pod2.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod2
spec:
containers:
- name: web
image: nginx
4.验证
kubectl apply -f pod2.yaml
kubectl get pod -o wide #观察pod2是否被调度到node2节点上
示例二
1.基于示例一,给node2节点配置污点
kubectl taint node k8s-node2 disktype=ssd:NoSchedule
2.新建pod3.yaml文件并启动pod
vim pod3.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod3
spec:
containers:
- name: web
image: nginx
3.验证
kubectl apply -f pod3.yaml
kubectl get pod #查看pod3是否处于pending状态
kubectl describe pod pod3 #查看pod3的状态
上面的意思是默认计划程序0/3个节点可用:1个节点有污点{disktype:ssd},pod不能容忍,1个节点有污点{gpu:iniaid},pod不能容忍,1个节点有污点{node}-role.kubernetes.io/主。
示例三
1.基于示例二,添加污点容忍使pod能够分配到node1节点上
vim pod4.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod4
spec:
tolerations: #意思是分配到标签gpu=iniaid的这个节点上
- key: "gpu"
operator: "Equal" #操作符等于的意思
value: "iniaid"
effect: "NoSchedule"
containers:
- name: web
image: nginx
加上effect: "NoSchedule"的意思:更精确一点,如果不加的话,比如两个节点都有gpu=iniaid这个标签,但它们的effect的调度策略不同,那么pod可能会分配到这两个节点上。
2.验证
kubectl apply -f pod4.yaml
kubectl get pod -o wide #验证是否被分配到node1节点上
最后去掉污点
kubectl describe nodes |grep Taint #查看当前有污点的节点
kubectl taint node k8s-nod2 disktype- #去掉node1节点的污点
kubectl taint node k8s-node2 disktype- #去掉node2节点的污点
kubectl describe nodes |grep Taint #验证是否去掉了污点
验证pod3是否被调度成功
nodeName
nodeName:指定节点名称,用于将Pod调度到指定的Node上,不经过调度器
示例:将pod指定到有污点的节点上
vim pod5.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod5
spec:
nodeName: k8s-node2
containers:
- name: web
image: nginx
验证:
kubectl apply -f pod5.yaml
kubectl get pod #可以看到pod成功运行,因为它不经过调度器
适用于调度器故障的时候,可以手动指定分配pod到某个节点上,很少使用。