博客 kubernetes调度策略(一)

kubernetes调度策略(一)

   数栈君   发表于 2024-03-08 09:56  91  0

1、背景

在 Kubernetes 中,调度 (scheduling) 指的是确保 Pod 匹配到合适的节点,以便 kubelet 能够运行它们。调度的工作由调度器和控制器协调完成。

调度器通过 Kubernetes 的监测(Watch)机制来发现集群中新创建且尚未被调度到节点上的 Pod。调度器会将所发现的每一个未调度的 Pod 调度到一个合适的节点上来运行。调度器会依据下文的调度原则来做出调度选择。控制器则会将调度写入 Kubernetes 的 API Server 中。

一般而言是基于最大资源空闲率的均衡调度来实现,我们还可以基于自己的调度行为、调度标识影响预选和优选的调度结果,进而来完成高级调度行为。

2、操作前了解相关配置和要求

Pod 调度流程:

当用户向 APIServer 请求创建 Pod 时,APIServer 检查相关权限没问题后,将请求交给 Scheduler,由 Scheduler 在众多节点当中,选择一个匹配的节点做为运行此 Pod 的工作节点。Scheduler 的选择结果并不直接反映到节点之上,而是会告诉 APIServer ,并将相关信息保存到 etcd 当中。APIServer 指挥着被选定节点的 kubelet,或者说 kubelet 始终 Watch 着 APIServer 当中与当前节点相关联的事件变动,进而根据配置模版运行 Pod。

Pod 调度步骤:

  1. Predicate(预选)
    先排除完全不符合 Pod 运行法则的节点(最低资源需求、最大资源限额 limit)

  1. Priority(优选)
    基于一系列的算法函数,计算节点的优先级,找出最佳匹配节点

  1. Select(选定)
    将 Pod 绑定在优选后的节点之上

Pod 高级调度:

一般而言是基于最大资源空闲率的均衡调度来实现,我们还可以基于自己的调度行为、调度标识影响预选和优选的调度结果,进而来完成高级调度行为。

  • 偶尔有特殊偏好的 Pod 要运行在特定节点(SSD 节点、GPU 节点)之上,可以对节点使用标签进行分类

$ kubectl explain pods.spec
......
   nodeName     
   nodeSelector    # 预选
......[string]string>
  • 节点亲和性/反亲和性调度

  • Pod 亲和性/反亲和性调度(某一组 Pod 运行在同一节点或相邻节点)

  • 污点、污点容忍调度(Taints-nodes,Tolerations-pod)

常见的预选策略:

  • CheckNodeCondition
    检查节点是否可以在磁盘、网络不可用或未准备好的前提下把 Pod 调度到此节点

  • GeneralPredicates(通用预选策略)

    • HostName:检查 Pod 对象是否定义 pod.spec.hostname

    • PodFitsHostPort:检查 Pod 对象是否定义 pod.spec.containers.ports.hostPort

    • MatchNodeSelector:检查节点标签是否适配 pods.spec.nodeSelector

    • PodFitsResources:检查 Pod 的资源需求是否能被节点所满足

  • NoDiskConflict(默认没有启用)
    检查 Pod 依赖的存储卷能否能满足需求

  • PodToleratesNodeTaints
    检查 Pod 上的 spec.tolerations  可容忍的污点是否完全包含节点上的污点

  • PodToleratesNodeNoExecuteTaints(默认没有启用)
    默认节点污点变动后,容忍之前调度在该节点之上的 Pod 存在。而该项则不容忍 Pod,会驱离 Pod

  • CheckNodeLabelPresence(默认没有启用)
    检查节点标签存在性

  • CheckserviceAffinity(默认没有启用)
    检查服务亲和性,将相同 Service 的 Pod 对象尽可能放在一块

  • MaxEBSVolumeCount
    亚马逊弹性存储卷最大数量,默认 39

  • MaxGCEPDVolumeCount
    谷歌容器引擎最大存储卷数量,默认 16

  • MaxAzureDiskVolumeCount
    Azure 最大磁盘数量,默认 16

  • CheckVolumeBinding
    检查节点上已绑定和未绑定的 PVC

  • NoVolumeZoneConflict
    没有数据卷空间冲突(逻辑限制)

  • CheckNodeMemoryPressure
    检查节点是否存在内存压力

  • CheckNodePIDPressure
    检查节点是否存在进程压力

  • CheckNodeDiskPressure
    检查节点是否存在磁盘压力

  • MatchInterPodAffinity
    检查节点是否能满足 Pod 亲和性或反亲和性条件

常见的优选函数:

  • LeastRequested

# 节点空闲资源/节点总容量: 根据空闲比例评估
(cpu(capacity-sum(requested))*10/capacity)+(memory(capacity-sum(requested))*10/capacity)/2

capacity-sum(requested) # (总容量-已经被pod拿走的总容量)*10/总容量。*10是因为每一个优选函数的得分是10分,最后计算得分。
  • BalancedResourceAllocation
    CPU 和内存资源的被占用率相近的胜出,目的是平衡节点资源的使用率。

  • NodePreferAvoidPods
    节点亲向不要运行这个 Pod(优先级高),根据节点注解信息 "scheduler.alpha.kubernetes.io/preferAvoidPods" 判定,没有注解信息得分为 10,权重为 10000,存在此注解信息时,由控制器管控的 Pod 得分为 0。

  • TaintToleration
    将 Pod 对象的 spec.tolerations 与节点的 taints 列表项进行匹配度检查,匹配的条目越多得分越低。

  • SelectorSpreading: 调度器将 pod 分散调度。

  • InterPodAffinity: 根据 Pod 间的亲和性。

  • NodeAffinity: 根据节点亲和性。

  • MostRequested: 根据最多被请求的节点。

  • NodeLabel: 根据节点标签。

  • ImageLocality: 根据满足当前 Pod 对象需求的已有镜像的体积大小之和。

  • 3.操作步骤

    高级调度设计机制:

    • 节点选择器:nodeSelector

    • 节点亲和器:nodeAnffinity

    • 污点容忍:taints / tolerations

    3.1 nodeSelector

    "新增节点标签"
    $ kubectl label nodes worker2 disk=ssd
    node/worker2 labeled

    "创建测试Pod"
    $ cat demo-pod.yaml 
    apiVersion: v1
    kind: Pod
    metadata:
      name: demo-pod
      namespace: qingyun
    spec:
      containers:
      - name: myapp
        image: zhangyyhub/myapp:v1.0
        imagePullPolicy: IfNotPresent
      nodeSelector:  # 节点选择
        disk: ssd

    $ kubectl apply -f demo-pod.yaml 
    pod/demo-pod created

    "验证测试Pod: 在节点标签所在节点之上"
    $ kubectl get pods -n qingyun -o wide
    NAME       READY   STATUS    RESTARTS   AGE   IP              NODE      NOMINATED NODE   READINESS GATES
    demo-pod   1/1     Running   0          14s   10.244.189.98   worker2   <none>           <none>

    3.2 nodeAnffinity

    "nodeAnffinity"
    $ kubectl explain pods.spec.affinity
       nodeAffinity <Object>
          preferredDuringSchedulingIgnoredDuringExecution      <[]Object>  # 软亲和性,尽量满足
             preference   <Object> -required-
                matchExpressions     <[]Object>      # 匹配表达式
                matchFields  <[]Object>              # 匹配字段
                   key  <string> -required-          # key
                   operator     <string> -required-  # 操作符(In, NotIn, Exists, DoesNotExist, Gt, and Lt.)
                   values       <[]string>           # value
             weight       <integer> -required-
          requiredDuringSchedulingIgnoredDuringExecution       <Object>    # 硬亲和性,必须满足
             nodeSelectorTerms    <[]Object> -required-
                matchExpressions     <[]Object>      # 匹配表达式
                matchFields  <[]Object>              # 匹配字段
                   key  <string> -required-          # key
                   operator     <string> -required-  # 操作符(In, NotIn, Exists, DoesNotExist, Gt, and Lt.)
                   values       <[]string>           # value
       podAffinity  <Object>
       podAntiAffinity      <Object>

    实例:

    "创建测试Pod"
    cat demo-pod-nodeAffinity.yaml 
    apiVersion: v1
    kind: Pod
    metadata:
      name: demo-pod-affinity
      namespace: qingyun
    spec:
      containers:
      - name: myapp
        image: zhangyyhub/myapp:v1.0
        imagePullPolicy: IfNotPresent
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:  # 硬亲和性,必须满足
            nodeSelectorTerms:
            - matchExpressions:    # 匹配表达式
              - key: disk          # key
                operator: In       # 操作符
                values:            # value
                - ssd
                - essd

    $ kubectl apply -f demo-pod-nodeAffinity.yaml
    pod/demo-pod-affinity created

    "验证测试Pod"
    $ kubectl get pods -n qingyun -o wide
    NAME                READY   STATUS    RESTARTS   AGE   IP               NODE      NOMINATED NODE   READINESS GATES
    demo-pod            1/1     Running   0          41m   10.244.189.98    worker2   <none>           <none>
    demo-pod-affinity   1/1     Running   0          19s   10.244.189.123   worker2   <none>           <none>
    "部署测试Pod"
    $ cat demo-pod-nodeAffinity2.yaml 
    apiVersion: v1
    kind: Pod
    metadata:
      name: demo-pod-affinity2
      namespace: qingyun
    spec:
      containers:
      - name: myapp
        image: zhangyyhub/myapp:v1.0
        imagePullPolicy: IfNotPresent
      affinity:
        nodeAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:  # 软亲和性,尽量满足
          - preference:
              matchExpressions:    # 匹配表达式
              - key: disk          # key
                operator: In       # 操作符
                values:            # value
                - hssd
                - essd
            weight: 60
            
    $ kubectl apply -f demo-pod-nodeAffinity2.yaml
    pod/demo-pod-affinity2 created

    "验证测试Pod"
    $ kubectl get nodes --show-labels | grep hssd
    $ kubectl get nodes --show-labels | grep essd

    $ kubectl get pods -n qingyun -o wide
    NAME                 READY   STATUS    RESTARTS   AGE   IP               NODE      NOMINATED NODE   READINESS GATES
    demo-pod             1/1     Running   0          52m   10.244.189.98    worker2      <none>           <none>
    demo-pod-affinity    1/1     Running   0          10m   10.244.189.123   worker2      <none>           <none>
    demo-pod-affinity2   1/1     Running   0          12s   10.244.235.255   k8s-master   <none>           <none>

    (后续见下一篇)


《数据治理行业实践白皮书》下载地址:
https://fs80.cn/4w2atu

《数栈V6.0产品白皮书》下载地址:https://fs80.cn/cw0iw1

想了解或咨询更多有关袋鼠云大数据产品、行业解决方案、客户案例的朋友,浏览袋鼠云官网:https://www.dtstack.com/?src=bbs

同时,欢迎对大数据开源项目有兴趣的同学加入「袋鼠云开源框架钉钉技术群」,交流最新开源技术信息,群号码:30537511,项目地址:https://github.com/DTStack  

0条评论
社区公告
  • 大数据领域最专业的产品&技术交流社区,专注于探讨与分享大数据领域有趣又火热的信息,专业又专注的数据人园地

最新活动更多
微信扫码获取数字化转型资料
钉钉扫码加入技术交流群