7 Pod 调度

目录

1 创建Pod的工作流程

2 Pod中影响调度的主要属性

3 资源限制对Pod调度的影响

4 将Pod调度到指定节点

4.1 nodeSelector(强硬)

4.2 nodeAffinity(亲和)

5 污点及污点容忍

6 绕过调度器nodeName


1 创建Pod的工作流程

  • 用户发出创建pod的指令
  • APIServer接收到创建pod命令,生成包含Pod创建信息的yaml文件,将yaml文件写入ETCD
  • Scheduler被APIServer通知到有新的待创建Pod的请求,于是运用调度算法,找出待部署Pod的目标节点,将结果返回给APIServer
  • APIServer更新ETCD中的Pod创建信息,明确了具体要把这个Pod部署到哪个节点上
  • 目标节点上的Kubelet被APIServer通知到有创建容器的请求,于是Kubelet调用docker api 创建容器,将容器信息返回给APIServer
  • APIServer再将容器信息保存到ETCD,整体过程如下图所示:

2 Pod中影响调度的主要属性

在Deployment资源的yaml文件中:

  • 一些字段会间接的影响到Pod的调度策略(resources),比如预设好容器占用资源限制后(最低要求、最高限制),那些达不到容器最低要求的node就不会被选择。
  • 还有一些字段可以直接设置Pod的调度策略(schedulerName、nodeName、nodeSelector、affinity、tolerations)

如下的指令可以打开一个集群中现存的Deployment资源的yaml文件进行查看:

#查看集群中的deployment资源
kubectl get deploy

#查看deployment资源的yaml文件
 kubectl get deploy nginx -o yaml

3 资源限制对Pod调度的影响

通过编辑Pod的yaml文件中的resources字段来验证资源限制对Pod调度的影响。

#1、当对于容器的资源配置要求在合理范围内时,创建一个nginx容器是没有任何问题的
vi pod-resource.yaml

#2、nginx的yaml文件
apiVersion: v1
kind: Pod
metadata:
  name: pod-resource
spec:
  containers:
  - name: web
    image: nginx
    resources:
      #容器使用的最小资源需求
      requests:
        memory: "64Mi"
        cpu: "250m"
      #容器使用的最大资源限制,因此要大于等于request的值
      limits:
        memory: "64Mi"
        cpu: "250m"

#3、部署
kubectl apply -f pod-resource.yaml

#4、查看pod,发现一切正常
kubectl get pod

#5、然而此时,在Pod的yaml中设置nginx容器的最低内存和核心数都远远大于任意节点的的配置
vi pod-resources2

#yaml文件
apiVersion: v1
kind: Pod
metadata:
  name: pod-resource2
spec:
  containers:
  - name: web
    image: nginx
    resources:
      requests:
        memory: "4Gi"
        cpu: "2500m"

#6、部署
kubectl apply -f pod-resources2.yaml

#7、查看pod,发现pod-resource2处于pending状态
kubectl get pod

#8、继续查看pod的详细信息,发现显示资源不足
kubectl describe pod pod-resource2

 注意:资源配额中的"request"即容器所要求的最小配置才会影响到Pod的调度。

4 将Pod调度到指定节点

如果我们想把一些Pod调度到指定的节点上,有两种方式:nodeSelector 、nodeAffinity接下来分别介绍。

4.1 nodeSelector(强硬)

用于将Pod调度到匹配Label的Node上,如果没有匹配的标签会调度失败。

 作用

  • 约束Pod到特定的节点运行
  • 完全匹配节点标签

应用场景

  • 专用节点:根据业务线将Node分组管理
  • 配备特殊硬件:部分Node配有SSD硬盘、GPU

实践

#1、先查询一下集群中的所有节点,选择一个目标节点,准备让一些Pod都调度到该节点上
kubectl get node

#2、给目标节点打标签
#格式:kubectl label nodes <node-name> <label-key>=<label-value>
kubectl label nodes kubeadm-node1 disktype=ssd

#3、验证是否已经打上了标签
kubectl get nodes --show-labels

#4、添加nodeSelector字段到Pod配置文件中
vi pod-selector.yaml

#yaml文件
apiVersion: v1
kind: Pod
metadata:
  name: pod-node-selecter
spec:
  nodeSelector:
    disktype: "ssd"
  containers:
  - name: nginx
    image: nginx

5、部署pod
kubectl apply -f  pod-selector.yaml 

6、验证该Pod是否部署到了目标节点node1上
kubectl get pods -o wide

注意

  • 如果有多个node被打上了相同的标签,则Pod在调度时又会根据调度算法进行选择
  • 如果没有Pod的yaml中指定了一个nodeSelector,然而根本没有任何node被打上对应的标签,则Pod创建会一直处于pending状态。

4.2 nodeAffinity(亲和)

通过4.1的介绍,发现nodeselector对于Pod的调度过于强硬,因此nodeSelector出现了,它与nodeSelector作用类似(软硬结合),但是更加亲和、灵活,满足更多条件,如:

  • 匹配有更多的逻辑组合,不只是字符串的完全相等
  • 调度分为软策略和硬策略,而不是硬性要求
  • 硬(required):必须满足
  • 软(preferred):尝试满足,但不保证

操作符(operator):In、NotIn、Exists、DoesNotExist、Gt、Lt

如下操作,测试了nodeAffinity策略的验证过程:

#1、创建Pod的yaml文件(为了验证nodeSelector策略下label不匹配导致Pod创建不成功)
vi pod-selecter2.yaml

#2、编辑yaml,此时集群中所有节点都没有被打上 gpu: "nvidia"这个标签
apiVersion: v1
kind: Pod
metadata:
  name: pod-node-selecter2
spec:
  nodeSelector:
    gpu: "nvidia"
  containers:
  - name: nginx
    image: nginx

#3、部署Pod
kubectl apply -f pod-selecter2.yaml

#4、查看Pod部署情况
#目前Pod采用的是nodeSelector来控制Pod的调度,由于集群节点中没有匹配的标签,因此Pod部署失败,处于pending状态
kubectl get pod
kubectl describe pod pod-node-selecter2

#此时转而使用nodeAffinity,让Pod的调度更具有亲和性:我希望把Pod部署在某个node上,如果没有成功那么也没关系,也允许部署到其他node上

#5、创建Pod的yaml文件(为了验证nodeaffinity的软策略下即便lable不匹配也能成功创建Pod)
vi pod-nodeaffinity.yaml

#6、编辑yaml,此时集群中所有节点都没有被打上 gpu: "nvidia"这个标签
apiVersion: v1
kind: Pod
metadata:
  name: pod-node-affinity
spec:
  affinity:
    nodeAffinity:
      #软策略:如果有node的标签和“gpu-nvidia”能够对应,那就直接部署在该node上,对应不上也没关系,也会找个node来部署
      preferredDuringSchedulingIgnoredDuringExecution:
      #权重越大,越期望将Pod调度到label为"gpu: nvidia"的节点上
      - weight: 1
        preference:
          matchExpressions:
          - key: gpu
            operator: In
            values:
            - nvidia
  containers:
  - name: web
    image: nginx

#7、部署Pod
kubectl apply -f pod-nodeaffinity.yaml

#8、查看Pod部署情况,发现采用affinity软策略之后,即便label没有匹配,也能成功部署Pod
kubectl get pod

#9、创建Pod的yaml文件(为了验证nodeaffinity的硬策略下和nodeSelector策略达成相同的效果)
vi pod-selecter2.yaml

#10、编辑yaml,测试nodeaffinity的硬策略,功能和nodeSelector完全一致
apiVersion: v1
kind: Pod
metadata:
  name: pod-node-affinity2
spec:
  affinity:
    nodeAffinity:
      #此策略下,功能和nodeSelector完全一致
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: gpu
            operator: In
            values:
            - nvidia
  containers:
  - name: web
    image: nginx

#11、部署Pod
kubectl apply -f pod-nodeaffinity2.yaml

#12、查看Pod部署情况,发现采用affinity硬之后,发现功能和nodeSelector完全一致
kubectl get pod

5 污点及污点容忍

  • Taints(污点):避免Pod调度到特定Node上
  • Tolerations(污点容忍):允许Pod调度到持有Taints的Node上

应用场景

  • 专用节点:根据业务线将Node分组管理,希望在默认情况下不调度该节点,只有配置了污点容忍才允许分配
  • 配备特殊硬件:部分Node配有SSD硬盘、GPU,希望在默认情况下不调度该节点,只有配置了污点容忍才允许分配
  • 基于Taint的驱逐

步骤

  • step1:给节点添加污点

格式:kubectl taint node [node] key=value:[effect]
例如:kubectl taint node kubeadm-node1 gpu=yes:NoSchedule
验证:kubectl describe node kubeadm-node1 |grep Taint

其中[effect] 可取值:

NoSchedule :一定不能被调度
PreferNoSchedule:尽量不要调度,非必须配置容忍
NoExecute:不仅不会调度,还会驱逐Node上已有的Pod

  • step2:添加污点容忍(tolrations)字段到Pod配置中
  • 去掉污点:kubectl taint node [node] key:[effect]- 

实践

#1、给节点node1、node2 都添加污点
kubectl taint node kubeadm-node1 gpu=yes:NoSchedule
kubectl taint node kubeadm-node2 gpu=yes:NoSchedule

#2、查看节点是否已经被添加上了污点,此时该节点上一般不会部署Pod了,除非Pod设置了污点容忍
kubectl describe node  |grep Taint

#3、创建Pod
vi pod-taint.yaml

#4、编辑yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-taint
spec:
  containers:
  - name: nginx
    image: nginx

#5、部署pod
kubectl apply -f pod-taint.yaml

#6、查看pod,发现没法创建,因为3个node都被打上了污点,Pod文件中没有设置污点容忍
kubectl get pod
kubectl describe pod pod-taint

#接下来,添加污点容忍(tolrations)字段到Pod配置中

#7、创建另一个Pod,该Pod被设置了污点容忍
vi pod-taint2.yaml

#8、编辑yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-taint2
spec:
  tolerations:
  - key: "gpu"
    values: "yes"
  containers:
  - name: nginx
    image: nginx

#9、部署Pod
kubectl apply -f pod-taint2.yaml

#10、再次查看pod,发现设置污点容忍后又可以创建Pod了,验证完毕
kubectl get pod

#11、把node1、node2的污点去掉,去掉污点后,之前的pod-taint2状态已经不是pending了,而是创建完毕
kubectl taint node kubeadm-node1 gpu-
kubectl taint node kubeadm-node2 gpu-

 

6 绕过调度器nodeName

在Pod的yaml文件中指定节点名称,用于将Pod调度到指定的Node上,不经过调度器即便所有节点都被打上了污点也没有关系。在实际中,绕过调度器的应用场景很少。

实践

#1、创建Pod的yaml文件
vi pod-podname.yaml

#2、编辑yaml(直接指定了将该Pod调度到集群中的node2节点上)
apiVersion: v1
kind: Pod
metadata:
  name: pod-podname
spec:
  podName: kubeadm-node2
  containers:
  - name: nginx
    image: nginx

#3、部署Pod
kubectl apply -f pod-podname.yaml

#4、查看Pod,发现Pod被直接调度到node2节点上了
kubectl get pod
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值