这应该是最全的Pod调度策略

首先说明,文章很长很长很长很长😊......建议先收藏

API Server接受客户端提交Pod对象创建请求后的操作过程中,有一个重要的步骤就是由调度器程序kube-scheduler从当前集群中选择一个可用的最佳节点来接收并运行它,通常是默认的调度器kube-scheduler负责执行此类任务。对于每个待创建的Pod对象来说,调度过程通常分为两个阶段—》过滤—》打分,过滤阶段用来过滤掉不符合调度规则的Node,打分阶段建立在过滤阶段之上,为每个符合调度的Node进行打分,分值越高则被调度到该Node的机率越大。

Pod调度策略除了系统默认的kube-scheduler调度器外还有以下几种实现方式:

  1. nodeName(直接指定Node主机名)
  2. nodeSelector (节点选择器,为Node打上标签,然后Pod中通过nodeSelector选择打上标签的Node)
  3. 污点taint与容忍度tolerations
  4. NodeAffinity 节点亲和性
  5. PodAffinity Pod亲和性
  6. PodAntAffinity Pod反亲和性

以下几章节内容主要讲解上面几种调度策略以及kube-scheduler调度器的调度原理。

Pod调度之kube-scheduler

官方文档:https://kubernetes.io/zh/docs/concepts/scheduling-eviction/kube-scheduler/

kube-scheduler调度介绍

kube-scheduler是Kubernetes 集群的默认调度器,并且是集群控制面(master)的一部分。 对每一个新创建的Pod或者是未被调度的Pod,kube-scheduler会选择一个最优的Node去运行这个Pod。然而,Pod内的每一个容器对资源都有不同的需求,而且Pod本身也有不同的资源需求。因此,Pod在被调度到Node上之前,根据这些特定的资源调度需求,需要对集群中的Node进行一次过滤。

在一个集群中,满足一个Pod调度请求的所有Node称之为可调度节点。如果没有任何一个Node能满足Pod的资源请求,那么这个Pod将一直停留在未调度状态直到调度器能够找到合适的Node。

调度器先在集群中找到一个Pod的所有可调度节点,然后根据一系列函数对这些可调度节点打分,然后选出其中得分最高的Node来运行Pod。之后,调度器将这个调度决定通知给kube-apiserver,这个过程叫做绑定。

在做调度决定时需要考虑的因素包括:单独和整体的资源请求、硬件/软件/策略限制、亲和以及反亲和要求、数据局域性、负载间的干扰等等。

kube-scheduler 调度流程

kube-scheduler 给一个 pod 做调度选择包含两个步骤:

  1. 过滤(Predicates 预选策略)
  2. 打分(Priorities 优选策略)

过滤阶段:过滤阶段会将所有满足 Pod 调度需求的 Node 选出来。例如,PodFitsResources 过滤函数会检查候选 Node 的可用资源能否满足 Pod 的资源请求。在过滤之后,得出一个 Node 列表,里面包含了所有可调度节点;通常情况下,这个 Node 列表包含不止一个 Node。如果这个列表是空的,代表这个 Pod 不可调度。

打分阶段:在过滤阶段后调度器会为 Pod 从所有可调度节点中选取一个最合适的 Node。根据当前启用的打分规则,调度器会给每一个可调度节点进行打分。最后,kube-scheduler 会将 Pod 调度到得分最高的 Node 上。如果存在多个得分最高的 Node,kube-scheduler 会从中随机选取一个。

过滤阶段

官方文档:https://kubernetes.io/docs/reference/scheduling/policies/

在调度时的过滤阶段到底时通过什么规则来对Node进行过滤的呢?就是通过以下规则!

  1. PodFitsHostPorts:检查Node上是否不存在当前被调度Pod的端口(如果被调度Pod用的端口已被占用,则此Node被Pass)。
  2. PodFitsHost:检查Pod是否通过主机名指定了特性的Node (是否在Pod中定义了nodeName)。
  3. PodFitsResources:检查Node是否有空闲资源(如CPU和内存)以满足Pod的需求。
  4. PodMatchNodeSelector:检查Pod是否通过节点选择器选择了特定的Node (是否在Pod中定义了nodeSelector)。
  5. NoVolumeZoneConflict:检查Pod请求的卷在Node上是否可用 (不可用的Node被Pass)。
  6. NoDiskConflict:根据Pod请求的卷和已挂载的卷,检查Pod是否合适于某个Node (例如Pod要挂载/data到容器中,Node上/data/已经被其它Pod挂载,那么此Pod则不适合此Node)
  7. MaxCSIVolumeCount::决定应该附加多少CSI卷,以及是否超过了配置的限制。
  8. CheckNodeMemoryPressure:对于内存有压力的Node,则不会被调度Pod。
  9. CheckNodePIDPressure:对于进程ID不足的Node,则不会调度Pod。
  10. CheckNodeDiskPressure:对于磁盘存储已满或者接近满的Node,则不会调度Pod。
  11. CheckNodeCondition:Node报告给API Server说自己文件系统不足,网络有写问题或者kubelet还没有准备好运行Pods等问题,则不会调度Pod。
  12. PodToleratesNodeTaints:检查Pod的容忍度是否能承受被打上污点的Node。
  13. CheckVolumeBinding:根据一个Pod并发流量来评估它是否合适(这适用于结合型和非结合型PVCs)。

打分阶段

官方文档:https://kubernetes.io/docs/reference/scheduling/policies/ 当过滤阶段执行后满足过滤条件的Node,将进行打分阶段。

  1. SelectorSpreadPriority:优先减少节点上属于同一个 Service 或 Replication Controller 的 Pod 数量
  2. InterPodAffinityPriority:优先将 Pod 调度到相同的拓扑上(如同一个节点、Rack、Zone 等)
  3. LeastRequestedPriority:节点上放置的Pod越多,这些Pod使用的资源越多,这个Node给出的打分就越低,所以优先调度到Pod少及资源使用少的节点上。
  4. MostRequestedPriority:尽量调度到已经使用过的 Node 上,将把计划的Pods放到运行整个工作负载所需的最小节点数量上。
  5. RequestedToCapacityRatioPriority:使用默认资源评分函数形状创建基于requestedToCapacityResourceAllocationPriority
  6. BalancedResourceAllocation:优先平衡各节点的资源使用。
  7. NodePreferAvoidPodsPriority:根据节点注释对节点进行优先级排序,以使用它来提示两个不同的 Pod 不应在同一节点上运行。scheduler.alpha.kubernetes.io/preferAvoidPods
  8. NodeAffinityPriority:优先调度到匹配 NodeAffinity (Node亲和性调度)的节点上。
  9. TaintTolerationPriority:优先调度到匹配 TaintToleration (污点) 的节点上
  10. ImageLocalityPriority:尽量将使用大镜像的容器调度到已经下拉了该镜像的节点上。
  11. ServiceSpreadingPriority:尽量将同一个 service 的 Pod 分布到不同节点上,服务对单个节点故障更具弹性。
  12. EqualPriority:将所有节点的权重设置为 1。
  13. EvenPodsSpreadPriority:实现首选pod拓扑扩展约束。

kube-scheduler 调度示例

默认配置使用的就是kube-scheduler调度组件,我们下面例子启动三个Pod,看分别被分配到哪个Node。 1.创建资源配置清单

cat scheduler-pod.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: scheduler-deploy
spec:
  replicas: 3
  selector:
    matchLabels:
      app: scheduler-pod
  template:
    metadata:
      labels:
        app: scheduler-pod
    spec:
      containers:
      - image: busybox:latest
        name: scheduler-pod
        command: [ "/bin/sh", "-c", "tail -f /etc/passwd" ]

2.使用kubectl创建资源对象

kubectl apply -f scheduler-pod.yaml

3.查看被kube-scheduler自动调度的Pod 两个Pod在Node03上,一个在Node02上

kubectl get pods -o wide | grep scheduler
scheduler-deploy-65d8f9c98-cqdm9    1/1     Running            0          111s    10.244.5.59   k8s-node03   <none>           <none>
scheduler-deploy-65d8f9c98-d4t9p    1/1     Running            0          111s    10.244.5.58   k8s-node03   <none>           <none>
scheduler-deploy-65d8f9c98-f8xxc    1/1     Running            0          111s    10.244.2.45   k8s-node02   <none>           <none>

4.我们查看一下Node资源的使用情况 Node01,可用内存2.7G

Node02,可用内存5.8G

Node03,可用内存5.6G

所以默认的kube-scheduler调度策略经过了过滤和打分后,将以上三个Pod分布在Node2和Node3上。

Pod调度之nodeName

nodeNamed这种调度方式比较简单,我们可以指定Pod在哪台Node上进行运行,通过spec.nodeName参数来指定Node主机名称即可。

创建资源配置清单

cat nodeName-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nodename-pod
spec:
#指定该Pod运行在k8s-node02节点上
  nodeName: k8s-node02
  containers:
  - image: busybox:latest
    name: nodename-containers
    command: [ "/bin/sh", "-c", "tail -f /etc/passwd" ]

创建Pod资源对象

kubectl apply -f nodeName-pod.yaml

查看Pod调度节点

如下,nodename-pod被绑定在了k8s-node02上

kubectl get pods -o wide | grep name
nodename-pod                        1/1     Running            0          25s     10.244.2.46   k8s-node02   <none>           <none>

Pod调度之nodeSelector

nodeSelector用于将Pod调度到匹配Label的Node上,所以要先给node打上标签,然后在Pod配置清单中选择指定Node的标签。 先给规划node用途,然后打标签,例如将两台node划分给不同团队使用:

为Node添加标签

k8s-node02给开发团队用,k8s-node03给大数据团队用

1.添加标签

kubectl label nodes k8s-node02 team=development
kubectl label nodes k8s-node03 team=bigdata

2.查看标签

kubectl get nodes -o wide --show-labels

创建资源配置清单

cat nodeSelector-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nodeselector-pod
spec:
  nodeSelector:                      #指定标签选择器
    team: development                #label指定开发团队的label
  containers:
  - image: busybox:latest
    name: nodeselector-containers
    command: [ "/bin/sh", "-c", "tail -f /etc/passwd" ]

创建Pod对象

kubectl apply -f nodeSelector-pod.yaml

查看pod被分配的Node

kubectl get pods -o wide | grep nodeselect
nodeselector-pod                    1/1     Running            0          49s     10.244.2.47   k8s-node02   <none>           <none>

删除标签

kubectl label nodes k8s-node02 team-
kubectl label nodes k8s-node03 team-

删除标签后pod还在正常运行

kubectl get pods -o wide | grep nodeselect
nodeselector-pod                    1/1     Running            0      
  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值