透彻理解kube-scheduler是如何完成调度的

kube-scheduler负责分配调度pod到集群内的节点上,它监听kube-apiserver,查询还未分配Node的pod,根据调度策略为这些pod分配节点,调度器在给pod分配节点时需要充分考虑多方面信息,需要考虑的信息如下所示:
公平调度
资源高效利用
Qos
affinity和anti-affinity
数据本地化(data locality)
内部负载干扰(inter-workload interference)
deadlines等

kube-scheduler调度分为两个阶段,predicate和priority,predicate过滤不符合条件的节点,priority选择高优先级的节点。Predicate策略有多个,
内置的Predicate策略如下所示,除下面列举的部分策略外,还有其他策略,另外,还可以自定义Predicate策略。

  • PodFitsHostPorts:检查是否有Host Ports冲突
  • PodFitsResources:检查Node的资源是否充足,包括允许的Pod数、CPU、内存等
  • HostName:检查pod.Spec.NodeName是否与候选节点一致
  • MatchNodeSelector:检查候选节点的pod.Spec.NodeSelector是否匹配
  • PodTolerateNodeTaints:检查Pod是否容忍Node Taints
  • MatchInterPodAffinity:检查是否匹配Pod的亲和性要求

和Predicate一样,priority也内置了很多策略,如下所示,下面列举了部分priority策略。

  • InterPodAffinityPriority:优先将pod调度到相同拓扑上(如同一个节点、Rack、Zone等)
  • LeastRequestedPriority:优先调度到请求资源少的节点上
  • BalancedResourceAllocation:优先平衡各个节点的资源使用
  • NodeAffinityPriority:优先调度到匹配NodeAffinity的节点上
  • TaintTolerationPriority:优先调度到匹配TaintToleration的节点上

接着我们来看看实际例子,第一类例子是在定义pod的deployment文件时,可以设置pod请求的cpu/memory资源以及cpu/memory资源上限,这样kube-scheduler在调度的时候可以根据这些信息把pod分配到更合理的node节点上,具体的yaml文件如下所示:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          resources:
            limits:
              memory: 1Gi
              cpu: 1
            requests:
              memory: 256Mi
              cpu: 100m

通过上面的文件创建pod,查看pod的信息(kubectl describe podname)可以看到启动的pod的资源设置和yaml文件中设置一致。

除了对单个pod或者container进行资源限制设置外,还可以对namespace中所有pod或者所有container中所使用的资源进行限制。如下所示创建limitRange对象,namespace中创建的pod或者container总使用的cpu或者memory量不能大于max cpu和max memory。

接着看第二类例子,第二类例子是设置nodeSelector或者设置pod-anti-affinity,这样kube-scheduler在调度pod的时候会根据设置的信息将pod调度到合理的node节点上。

pod的Deployment yaml文件中设置的nodeSelector,如下所示

创建pod,会看到pod一直是pending状态,查看pod信息,可以看到因为没有找到match的node

给node打上label,pod从pending状态变成running状态。

查看node节点的标签命令:kubectl get node --show-labels

给node节点打上标签命令:kubectl label nodes nodename key=value

删除node节点上的标签命令:kubectl label nodes nodename key-

除了通过nodeSelector将pod分配到指定的node节点上外,还可以通过nodeAffinity来设置,下面是一个强node亲和性设置,如果集群中不存在如下标签的node节点,pod会处于pending状态

除了强亲和性,还可以设置弱亲和性,当有满足条件的pod时,就分配到满足的node上,如果不存在则分配到任意一个node上。

Node可以设置亲和性,pod间也可以设置亲和性和反亲和性,例如相同的一个服务,需要部署多个pod副本,为了高可用,这些pod期望分配到不同node节点上,那么可以设置pod的反亲和性达到这样的效果。下面的例子中podAffinity设置了pod部署到一个已经存在运行的pod的节点上,且这个允许的pod的label key=a,value=b。podAntiAffinity设置了pod不能部署到这样的node,node上存在了已经允许pod,pod的label的key=app,value=anti-nginx.

上述的deployment文件创建pod,pod使用处于pending状态,因为node节点上不存在允许的pod,且pod的label key=a,value=b.删除podAffinity,只保留podAntiAffinity,再次创建pod,可以看到pod创建成功,因为replicas=2,所以会创建两个pod,且两个pod分别被创建在不同的node节点上。

 接着再看看如何通过设置污点(Taints)和容忍度(Tolerations)来控制哪些pod被部署到期望的node节点上。例如大数据的项目非常耗费资源,可能想把大数据类的应用部署到独享的某些节点上,防止其他应用占用了这些节点资源,针对这种需求,那么可以把这些节点设置Taints,其他团队在不知道节点的Taints的情况下,所有的应用就不会部署到这些节点上。

给节点打上污点的命令:kubectl taint nodes nodename for-special-user=taintstest:NoSchedule

取消节点上的污点命令:kubectl taint nodes nodename for-special-user=taintstest:NoSchedule-

查看节点上的污点命令:kubectl describe nodes {Node名称}

pod的deployment yaml文件中如果设置了tolerations,那么这个pod就会被部署到指定的node节点上,具体内容如下所示:

以上介绍了如何设置资源limit/request,nodeSelector,podAffinity/podAntiAffinity,taints&&tolerations来影响kube-schedule,从而实现将某些pod部署到指定的node节点上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

taoli-qiao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值