一、概念

 ​Sheduler 是作为单独的程序运行的(可以剥离),启动之后会一直监听 API Server,获取 PodSpec.NodeName为空的 pod,对每个 pod 都会创建一个 binding,表明该 pod 应该放到哪个节点上​

概念听起来是非常简单的,但有很多要考虑的问题:

◆ ​公平​:如何保证每个节点都能被分配资源

◆ ​资源高效利用​:集群所有资源最大化被使用

◆ ​效率​:调度的性能要好,能够尽快地对大批量的 pod 完成调度工作

◆ ​灵活​:允许用户根据自己的需求控制调度的逻辑 

二、自定义调度器

"除了 Kubernetes 自带的调度器,你也可以编写自己的调度器。通过 spec.schedulerName参数指定调度器的名字,可以为 Pod 选择某个调度器进行调度。比如下面的 Pod 选择 my-scheduler进行调度,而不是默认的 default-scheduler。"

  

Deployment控制器

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: myapp
  name: myapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      schedulerName: my-scheduler
      containers:
      - image: wangyanglinux/myapp:v1.0
        name: myapp

创建一个 调度器(逻辑演示)

kubectl proxy --port=8001

vi my-scheduler.sh
#!/bin/bash
SERVER='localhost:8001'
while true;
do
    for PODNAME in $(kubectl --server $SERVER get pods -o json | jq '.items[] | 
select(.spec.schedulerName =="my-scheduler") | select(.spec.nodeName == null) | 
.metadata.name' | tr -d '"')
    do
        NODES=($(kubectl --server $SERVER get nodes -o json | jq 
'.items[].metadata.name' | tr -d '"'))
        NUMNODES=${#NODES[@]}
        CHOSEN=${NODES[$[ $RANDOM % $NUMNODES]]}
        curl --header "Content-Type:application/json" --request POST --data 
'{"apiVersion":"v1","kind":"Binding","metadata": {"name":"'$PODNAME'"},"target": 
{"apiVersion":"v1","kind": "Node", "name": "'$CHOSEN'"}}' 
http://$SERVER/api/v1/namespaces/default/pods/$PODNAME/binding/
        echo "Assigned $PODNAME to $CHOSEN"
    done
    sleep 1
done

三、过程

调度分为几个部分:首先是过滤掉不满足条件的节点,这个过程称为"预选: 然后对通过的节
点按照优先级排序,这个是优选';最后从中选择优先级最高的节点。如果中间任何一步骤有
错误,就直接返回错误

1、预选

部分预选算法,每个版本不一样

1. ​PodFitsResources​

  • ​功能​:检查节点上剩余的资源是否大于 Pod 请求的资源

  • ​作用​:确保节点有足够的 CPU、内存等资源来运行 Pod

2. ​PodFitsHost​

  • ​功能​:如果 Pod 明确指定了 NodeName,检查节点名称是否匹配

  • ​作用​:确保 Pod 被调度到指定的节点上

3. ​PodFitsHostPorts​

  • ​功能​:检查节点上已经使用的端口是否与 Pod 申请的端口冲突

  • ​作用​:避免端口冲突,确保网络服务正常运行

4. ​PodSelectorMatches​

  • ​功能​:过滤掉与 Pod 指定的标签不匹配的节点

  • ​作用​:基于节点标签进行智能筛选和匹配

5. ​NoDiskConflict​

  • ​功能​:确保已挂载的卷与 Pod 指定的卷不冲突(除非它们都是只读)

  • ​作用​:防止存储卷的访问冲突,确保数据安全

2、优选

如果在预选过程中没有合适的节点,Pod 会一直处于 ​pending​ 状态,不断重试调度,直到有节点满足条件。经过这个步骤后,如果有多个节点满足条件,就继续优选过程:按照优先级大小对节点排序。

优先级配置原理

优先级由一系列键值对组成:

  • ​键​:优先级项的名称

  • ​值​:权重(表示该项的重要性)

优先级选项详解

➤ LeastRequestedPriority

  • ​机制​:通过计算 CPU 和 Memory 的使用率来决定权重

  • ​倾向​:使用率越低权重越高,即倾向于资源使用比例更低的节点

➤ BalancedResourceAllocation

  • ​机制​:节点上 CPU 和 Memory 使用率越接近,权重越高

  • ​建议​:应该与 LeastRequestedPriority 一起使用,不建议单独使用

➤ ImageLocalityPriority

  • ​机制​:倾向于已经存在所需镜像的节点

  • ​权重​:镜像总大小值越大,权重越高

四、亲和性

1、pod.spec.nodeAffinity

preferredDuringSchedulinglgnoredDuringExecution:软性策略
requiredDuringSchedulinglgnoredDuringExecution:硬性策略

2、软策略

有更好,没有也行

  • 这是一个使用节点亲和性​(Node Affinity)的 Pod 配置

  • 采用了 preferredDuringSchedulingIgnoredDuringExecution策略,表示"优选但不强制"

  • Pod 会优先调度到带有 domain=xinxianghf标签的节点上

  • 权重(weight)为 1,表示该偏好的相对重要性

apiVersion: v1
kind: Pod
metadata:
  name: node-affinity-preferred
  labels:
    app: node-affinity-preferred
spec:
  containers:
    - name: node-affinity-preferred-pod
      image: wangyanglinux/myapp:v1.0
  affinity:
    nodeAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
        - weight: 1
          preference:
            matchExpressions:
              - key: domain
                operator: In
                values:
                  - xinxianghf

3、硬策略

必须有,不然就不玩了

  1. ​Pod基本信息​:

    • 名称:node-affinity-required

    • 标签:app: node-affinity-required

  2. ​容器配置​:

    • 容器名称:node-affinity-required-pod

    • 使用镜像:wangyanglinux/myapp:v1.0

  3. ​节点亲和性配置​:

    • 使用requiredDuringSchedulingIgnoredDuringExecution策略(硬性要求)

    • 要求Pod必须调度到主机名为k8s-node04的节点上

    • 使用节点标签选择器:kubernetes.io/hostname

apiVersion: v1
kind: Pod
metadata:
  name: node-affinity-required
  labels:
    app: node-affinity-required
spec:
  containers:
    - name: node-affinity-required-pod
      image: wangyanglinux/myapp:v1.0
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
          - matchExpressions:
              - key: kubernetes.io/hostname
                operator: In
                values:
                  - k8s-node04

4、反亲和性pod.spec.podAffinity/podAntiAffinity

针对pod,

preferredDuringSchedulinglgnoredDuringExecution:软性策略
requiredDuringSchedulinglgnoredDuringExecution:硬性策略

亲和性-软策略

weight(权重)

​定义​:weight是一个介于 ​1 到 100​ 之间的整数值,用于在多个软性(preferred)亲和性/反亲和性规则同时存在时,表示该规则的相对重要性或偏好程度。

​作用机制​:

  • Kubernetes 调度器在通过预选阶段(找到所有满足硬性条件的节点)后,会进入优选阶段,为每个节点打分。

  • 对于每一条满足的软性规则,调度器会为该节点加上此规则对应的 weight分数。

  • ​分数越高,节点在最终排序中的优先级就越高,Pod 被调度到该节点的可能性就越大。

topologyKey(拓扑域键)

​定义​:topologyKey是一个节点标签的键(Key)​,用于定义什么是“同一个拓扑域”。它决定了亲和性/反亲和性规则的作用范围。

​作用机制​:

  • 调度器会检查节点的 topologyKey标签的值。​拥有相同标签值的节点被视为在同一个拓扑域中。

  • Pod 亲和性/反亲和性规则是在这个“拓扑域”的范围内生效的。

apiVersion: v1
kind: Pod
metadata:
  name: pod-aff-prefer
  labels:
    app: pod-aff
spec:
  containers:
  - name: myapp
    image: wangyanglinux/myapp:v1.0
  affinity:
    podAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: app
              operator: In
              values:
              - pod-1
          topologyKey: kubernetes.io/hostname

亲和性-硬策略

  1. ​容器配置​:

    • 容器名称:pod-aff-req-c

    • 使用镜像:wangyanglinux/myapp:v1.0

  2. ​Pod亲和性配置​:

    • 使用requiredDuringSchedulingIgnoredDuringExecution策略(硬性要求)

    • 要求Pod必须与标签为app: pod-1的其他Pod在同一主机上运行

    • 拓扑域键:kubernetes.io/hostname(基于节点主机名的拓扑域)

​功能说明:​​

此配置定义了一个具有强制Pod亲和性规则的Pod,它必须被调度到已经运行着带有app: pod-1标签的Pod的同一节点上。这种配置适用于需要确保某些Pod在同一节点上紧密协作的场景。

apiVersion: v1
kind: Pod
metadata:
  name: pod-aff-req
  labels:
    app: pod-aff-req
spec:
  containers:
  - name: pod-aff-req-c
    image: wangyanglinux/myapp:v1.0
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app
            operator: In
            values:
            - pod-1
        topologyKey: kubernetes.io/hostname

反亲和性-软策略

  • 此 Pod 配置使用了 Pod 反亲和性规则

  • 调度时会优先避免将本 Pod 部署到已经运行着 app: pod-2标签的 Pod 的同一节点上

  • 这是一个软性规则(优选规则),如果无法满足,Pod 仍可能被调度到其他节点

apiVersion: v1
kind: Pod
metadata:
  name: pod-antiaff-prefer
  labels:
    app: pod-aff
spec:
  containers:
  - name: myapp
    image: wangyanglinux/myapp:v1.0
  affinity:
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: app
              operator: In
              values:
              - pod-2
          topologyKey: kubernetes.io/hostname

反亲和性-硬策略

  • 此 Pod 配置使用了 ​Pod 反亲和性​ 规则,采用 requiredDuringSchedulingIgnoredDuringExecution策略(硬性要求)。

  • 它要求 Pod ​必须避免被调度到已经运行着带有 app: pod-1标签的 Pod 的同一节点上(基于 kubernetes.io/hostname拓扑域)。

  • 适用于需要确保 Pod 在不同节点上分散部署的场景,以提高可用性或避免资源冲突。

apiVersion: v1
kind: Pod
metadata:
  name: pod-aff-req
  labels:
    app: pod-aff-req
spec:
  containers:
  - name: pod-aff-req-c
    image: wangyanglinux/myapp:v1.0
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app
            operator: In
            values:
            - pod-1
        topologyKey: kubernetes.io/hostname

5、总结

更多推荐