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

本文介绍Kubernetes调度器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节点上。

Kubernetes 集群中,`kube-scheduler` 是一个关键的控制平面组件,负责将 Pod 调度到合适的节点上。如果 `kube-scheduler` 出现 IP 配置错误,可能会导致调度功能异常,进而影响整个集群的正常运行。 如果发现 `kube-system` 命名空间中的 `kube-scheduler-master` 出现 IP 配置问题,可以采取以下排查和解决措施: ### 检查 kube-scheduler 的 Pod 状态和事件信息 首先,使用以下命令查看 `kube-scheduler` Pod 的状态以及相关的事件信息,这有助于识别问题的根本原因: ```bash kubectl get pods -n kube-system | grep kube-scheduler kubectl describe pod kube-scheduler-master -n kube-system ``` 在输出中,重点关注 `Events` 部分,查看是否有与 IP 地址分配或网络配置相关的错误信息。 ### 检查 kube-scheduler 的配置文件 `kube-scheduler` 的配置文件通常位于主节点上的 `/etc/kubernetes/manifests/` 目录中。该文件定义了 `kube-scheduler` 的启动参数和配置选项。检查其中的 `--bind-address` 参数是否正确设置,确保其绑定的 IP 地址与集群中其他组件的配置一致。 ```yaml spec: containers: - name: kube-scheduler image: k8s.gcr.io/kube-scheduler:v1.22.0 command: - /bin/sh - -c - | exec kube-scheduler \ --bind-address=0.0.0.0 \ --leader-elect=true \ --config=/etc/kubernetes/config/kube-scheduler.yaml ``` 确保 `--bind-address` 设置为正确的 IP 地址或 `0.0.0.0` 以监听所有网络接口。 ### 检查节点的网络配置 如果 `kube-scheduler` 正确绑定了 IP 地址但仍无法正常通信,可能是由于节点的网络配置问题。检查主节点的网络接口配置,确保没有防火墙规则阻止了必要的端口通信(如 TCP 10251)。 使用 `ip addr` 和 `ip route` 命令检查网络接口的状态和路由表: ```bash ip addr show ip route show ``` 此外,检查 `kube-proxy` 的配置和状态,确保其能够正确地将流量转发到 `kube-scheduler` 所在的节点和端口。 ### 检查 kube-apiserver 的配置 `kube-scheduler` 需要与 `kube-apiserver` 进行通信。确保 `kube-apiserver` 的配置中包含了正确的 `--advertise-address` 参数,该参数应指向主节点的 IP 地址。 ```bash ps -ef | grep kube-apiserver ``` 从输出中查找 `--advertise-address` 参数的值,并确认其与实际的主节点 IP 地址匹配。 ### 检查集群的 DNS 配置 如果 `kube-scheduler` 通过服务名称进行通信,还需要确保集群的 DNS 配置正确。使用 `nslookup` 或 `dig` 命令检查 DNS 解析是否正常: ```bash nslookup kube-scheduler.kube-system.svc.cluster.local ``` 如果 DNS 解析失败,可能需要检查 CoreDNS 或 kube-dns 的配置和状态。 ### 日志分析 最后,查看 `kube-scheduler` 的日志以获取更多详细的错误信息: ```bash kubectl logs kube-scheduler-master -n kube-system ``` 日志中可能会包含具体的错误消息,帮助进一步定位问题。例如,日志中可能会显示无法绑定到指定的 IP 地址或端口,或者与其他组件通信时遇到的问题。 通过以上步骤,应该能够诊断并解决 `kube-scheduler-master` 的 IP 配置错误问题。如果问题仍然存在,建议检查 Kubernetes 官方文档或社区资源,寻找更多针对性的解决方案。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

taoli-qiao

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

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

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

打赏作者

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

抵扣说明:

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

余额充值