创建一个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到某个节点上,很少使用。