K8s 的5 种 Pod 调度策略

Pod 的调度策略主要有:

  • nodeSelector

  • 亲和性与反亲和性

  • nodeName

  • Pod 拓扑分布约束

  • 污点与容忍性

1. Pod调度概述

调度器通过 Kubernetes 的监测(Watch)机制来发现集群中新创建且尚未被调度到节点上的 Pod。调度的主要任务是将Pod分配到集群中的合适的节点上。调度器根据Pod的需求(如CPU、内存、存储等)和节点的资源状况(如可用CPU、内存、节点标签等)来决定Pod部署在哪个节点上。

2. 五种调度策略详解

2.1 nodeSelector

nodeSelector 是 Kubernetes 中最简单、最直观的调度机制,它基于节点标签进行 Pod 调度。节点标签是 Kubernetes 用于标识节点属性的键值对,调度器会根据这些标签来决定将 Pod 调度到哪个节点。

工作原理:

每个 Kubernetes 节点可以具有多个标签(labels)。标签是 key: value 的形式,通常表示节点的特征,如硬件类型、地区、环境等。

Pod 的 nodeSelector 字段指定一组标签,调度器会筛选出具有这些标签的节点,然后将 Pod 调度到这些节点。

使用场景:

  • 环境隔离:比如,你有一些节点专门用于生产环境,其他节点用于测试环境,使用 nodeSelector 来确保 Pod 只在生产节点上运行。

  • 硬件要求:例如,某些应用需要 SSD 磁盘或特定的 CPU 类型,你可以使用 nodeSelector 来确保 Pod 调度到符合这些硬件要求的节点。

实战操作:

1、给节点打上标签

# 给k8s-node2节点打上ssd标签
kubectl label node  k8s-node2 disktype=ssd

# 查看
kubectl get node k8s-node1 --show-labels

2、编写pod的yaml文件

【温馨提示】生产环境不要直接运行pod,这里只是为了演示效果

vim nodeSelector_pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  nodeSelector:
    disktype: ssd
  containers:
  - name: nginx
    image: docker.m.daocloud.io/nginx:1.25

运行pod

kubectl apply -f nodeSelector_pod.yaml

3、查看pod调度情况

[root@k8s-master data]# kubectl get pod -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP               NODE        NOMINATED NODE   READINESS GATES
nginx   1/1     Running   0          60s   10.224.169.149   k8s-node2   <none>           <none>

已经根据节点标签将pod调度到node2节点。

nodeSelector的优缺点:

  • 优点:简单高效。

  • 缺点:灵活性差,无法处理复杂的调度需求。

2.2 亲和性与反亲和性

亲和性(Affinity)和反亲和性(Anti-Affinity)是比 nodeSelector 更强大、更灵活的调度策略。它们允许用户根据更多的条件进行节点选择,比如节点的标签、Pod 的存在与否等。

亲和性(Affinity)用于指定 Pod 需要尽量调度到某些节点上,基于节点标签、Pod 与节点的关系等。 反亲和性(Anti-Affinity)用于指定 Pod 不应该调度到某些节点,或者应该尽量避免和其他 Pod 调度到同一个节点上。

Kubernetes 中有两种亲和性:

  • 节点亲和性(Node Affinity)

  • Pod 亲和性与反亲和性(Pod Affinity & Anti-Affinity)。

节点亲和性(Node Affinity)

实战操作

1、编写yaml文件

vim nodeAffinity.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx2
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: disktype
            operator: In
            values:
            - ssd
  containers:
  - name: nginx2
    image: docker.m.daocloud.io/nginx:1.25

确保 Pod 只会调度到具有 disktype=ssd标签的节点。

2、运行pod

kubectl apply -f nodeAffinity.yaml

3、查看pod调度情况

[root@k8s-master data]# kubectl get pod -o wide
NAME     READY   STATUS    RESTARTS   AGE     IP               NODE        NOMINATED NODE   READINESS GATES
nginx    1/1     Running   0          27m     10.224.169.149   k8s-node2   <none>           <none>
nginx2   1/1     Running   0          3m16s   10.224.169.154   k8s-node2   <none>           <none>

已经将pod调度到预期的node上

字段解释:

  • nodeAffinity 是定义节点选择规则的字段。通过 requiredDuringSchedulingIgnoredDuringExecution(必须满足调度时条件)和 preferredDuringSchedulingIgnoredDuringExecution(调度时首选,但不强制)来定义硬性和软性约束。

  • matchExpressions 支持使用 In、NotIn、Exists 等操作符,这些操作符使得你可以做更复杂的条件匹配。

operator 字段操作符说明:

操作符

说明

In

指定值必须在给定的列表中

NotIn

指定值不在给定的列表中

Exists

指定键存在,不关心值

DoesNotExist

指定键不存在

Pod 亲和性

Pod 亲和性允许你指定 Pod 希望与其他 Pod 一起调度的偏好,而反亲和性则表示 Pod 希望避免与某些 Pod 一起调度。

1、给前面创建的pod打上app=nginx1的标签

# 给使用nodeSelector创建的nginx打上标签
kubectl label pod nginx app=nginx1

2、编写yaml文件

vim podAffinity.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx3
spec:
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:   # 满足条件才调度
      - labelSelector:
          matchExpressions:
            - key: app
              operator: In
              values:
                - nginx1
        topologyKey: "kubernetes.io/hostname"
  containers:
  - name: nginx3
    image: docker.m.daocloud.io/nginx:1.25

3、运行pod

kubectl apply -f podAffinity.yaml

4、查看调度情况

[root@k8s-master data]# kubectl get pod  -o wide
NAME     READY   STATUS    RESTARTS   AGE     IP               NODE        NOMINATED NODE   READINESS GATES
nginx    1/1     Running   0          4h32m   10.224.169.149   k8s-node2   <none>           <none>
nginx2   1/1     Running   0          4h8m    10.224.169.154   k8s-node2   <none>           <none>
nginx3   1/1     Running   0          14s     10.224.169.153   k8s-node2   <none>           <none>

可见pod已经调度到node2上,现在3个都运行在node2上,接下来测试一下反亲和性

Pod 反亲和性

要求 Pod 不与特定的 Pod 调度到同一节点上,通常用于防止某些类型的 Pod 集中到同一节点上,避免单点故障。

1、编写yaml文件

vim podAntiAffinity.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx4
spec:
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
            - key: app
              operator: In
              values:
                - nginx1
        topologyKey: "kubernetes.io/hostname"
  containers:
  - name: app
    image: docker.m.daocloud.io/nginx:1.25

2、运行pod

kubectl apply -f podAntiAffinity.yaml

3、查看调度情况

[root@k8s-master data]# kubectl get pod -o wide
NAME     READY   STATUS    RESTARTS   AGE     IP               NODE        NOMINATED NODE   READINESS GATES
nginx    1/1     Running   0          4h37m   10.224.169.149   k8s-node2   <none>           <none>
nginx2   1/1     Running   0          4h13m   10.224.169.154   k8s-node2   <none>           <none>
nginx3   1/1     Running   0          5m26s   10.224.169.153   k8s-node2   <none>           <none>
nginx4   1/1     Running   0          10s     10.224.36.69     k8s-node1   <none>           <none>

可以看到新建的nginx4避免与标签为 app=nginx1的 Pod 调度到同一节点上,所以被调度到node1上,验证了pod的反亲和性

亲和性和反亲和性优缺点:

优点:

  • 灵活性强:支持多条件、复杂的调度规则,可以基于节点标签、Pod 标签、拓扑结构等进行细粒度控制。

  • 支持跨节点调度:可以控制 Pod 在集群中的分布,增强应用的可用性和容错性。

缺点:

  • 配置复杂:调度规则更加复杂,理解和配置起来需要更多的时间。

  • 可能影响调度效率:当使用大量的亲和性和反亲和性规则时,调度器需要更多时间来评估每个节点的匹配情况。

2.3 nodeName:直接指定节点

nodeName 是 Kubernetes 中一种最简单且强制性的调度方式,它允许你直接指定一个节点来运行 Pod,而无需依赖调度器的调度决策。nodeName 适用于一些特殊场景,比如需要将 Pod 调度到特定的节点(例如硬件节点,或特定的节点上有特定设备,如 GPU)。

实战操作:

1、编写yaml

vim nodeName.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx5
spec:
  nodeName: k8s-node1
  containers:
  - name: nginx5
    image: docker.m.daocloud.io/nginx:1.25

2、运行pod

kubectl apply -f nodeName.yaml

3、查看调度情况

[root@k8s-master data]# kubectl get pod nginx5 -o wide
NAME     READY   STATUS    RESTARTS   AGE   IP             NODE        NOMINATED NODE   READINESS GATES
nginx5   1/1     Running   0          47s   10.224.36.70   k8s-node1   <none>           <none>

可以看到Pod nginx5 会被直接调度到 node1节点上。

nodeName优缺点:

  • 优点:简单、直观,适用于需要特定硬件或设备的场景。

  • 缺点:失去调度器的灵活性,不适用于动态环境。

2.4 Pod 拓扑分布约束

Pod 拓扑分布约束用于保证 Pod 在多个节点、区域或故障域中的均衡分布。通过设置 topologySpreadConstraints,可以确保 Pod 在集群中分布更加均衡,避免 Pod 集中到某个节点或某个区域,从而增强集群的高可用性和容灾能力。

apiVersion: v1
kind: Pod
metadata:
  name: nginx6
spec:
  topologySpreadConstraints:
  - maxSkew: 1
    topologyKey: kubernetes.io/hostname
    whenUnsatisfiable: DoNotSchedule
    labelSelector:
      matchLabels:
        app: nginx
  containers:
  - name: nginx6
    image: docker.m.daocloud.io/nginx:1.25
[root@k8s-master data]# kubectl get pod nginx6 -o wide
NAME     READY   STATUS    RESTARTS   AGE   IP             NODE        NOMINATED NODE   READINESS GATES
nginx6   1/1     Running   0          37s   10.224.36.71   k8s-node1   <none>           <none>

使用deployment来演示可能效果更明显

topologySpreadConstraints 保证 nginx Pod 在不同的主机上均匀分布。maxSkew 控制 Pod 在各个节点之间的最大不平衡度,而 topologyKey 是表示分布维度的关键字段,kubernetes.io/hostname 表示按主机名进行分布。

优缺点:

  • 优点:保证 Pod 在多个节点、区域的均衡分布,提高高可用性。

  • 缺点:配置较复杂,可能对调度性能产生影响。

2.5 污点与容忍性

污点(Taints)和容忍性(Tolerations)是 Kubernetes 的一对调度机制,用于控制 Pod 是否能调度到带有某些特定条件的节点。节点可以加上污点,只有设置了相应容忍性的 Pod 才能调度到这些节点。

污点(Taints) 是对节点的标记,表示该节点不希望接受不符合条件的 Pod。容忍(Tolerations) 是 Pod 上的标记,表示 Pod 能够“容忍”某些污点。

实战操作:

1、给节点加污点:

# 在节点1上添加污点
kubectl taint nodes k8s-node1 key=value:NoSchedule

【温馨提示】设置污点后,新建的pod如果没有设置容忍,都无法调度到该节点,已存在的pod不受影响。

2、Pod 上设置容忍性:

vim tolerations.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx7
spec:
  tolerations:
  - key: "key"
    operator: "Equal"
    value: "value"
    effect: "NoSchedule"
  containers:
  - name: nginx7
    image: docker.m.daocloud.io/nginx:1.25

3、查看调度情况

[root@k8s-master data]# kubectl get pod nginx7 -o wide
NAME     READY   STATUS    RESTARTS   AGE   IP             NODE        NOMINATED NODE   READINESS GATES
nginx7   1/1     Running   0          32s   10.224.36.72   k8s-node1   <none>           <none>

nginx7被调度到设置了污点的节点,说明tolerations生效了,容忍了污点。

4、去除污点

kubectl taint node k8s-node1 key-

优缺点:

  • 优点:提供了灵活的节点隔离和调度控制,适用于隔离特定类型的工作负载或维护节点。

  • 缺点:配置复杂,滥用污点可能导致资源浪费或 Pod 调度错误。

总结

Kubernetes 提供了多种调度策略,可以根据不同的需求灵活选择:

  • nodeSelector:简单的节点标签匹配调度。

  • 亲和性与反亲和性:更灵活的调度控制,基于节点和 Pod 之间的关系进行调度。

  • nodeName:直接指定节点进行调度。

  • Pod 拓扑分布约束:确保 Pod 在集群中的均衡分布,增强高可用性。

  • 污点与容忍性:通过污点和容忍性控制哪些 Pod 可以调度到哪些节点。

通过合理组合这些调度策略,你可以优化 Pod 的资源分配、提升集群的可靠性和性能。

<think>我们正在讨论KubernetesPod的调度机制和流程。根据引用内容,Kubernetes提供了多种调度方式,包括自动调度、定向调度、亲和性调度和污点(容忍)调度。调度过程主要由Scheduler组件完成,它根据一系列算法决定Pod运行在哪个节点上。 调度过程详解: 1. 自动调度:完全由Scheduler根据节点资源、负载均衡策略、数据局部性等算法自动选择节点。用户无法干预(引用[1]和引用[3])。 2. 定向调度:通过NodeName或NodeSelector指定节点(引用[1]和引用[3])。 - NodeName:直接在Pod配置中指定节点名称,Pod将被调度到该节点(如果该节点存在且满足资源要求)。 - NodeSelector:通过标签选择器(labels)匹配节点。例如,给节点打上标签,然后在Pod的spec中指定nodeSelector字段。 3. 亲和性调度(NodeAffinity, PodAffinity, PodAntiAffinity):更灵活的调度规则(引用[1])。 - NodeAffinity:节点亲和性,根据节点标签决定Pod调度位置(类似于NodeSelector,但更强大,支持硬性要求和软性要求)。 - PodAffinity:Pod亲和性,将Pod调度到与某些Pod在同一节点(或同一拓扑域)的节点上。 - PodAntiAffinity:Pod反亲和性,避免将Pod调度到与某些Pod在同一节点(或同一拓扑域)的节点上(用于避免单点故障等)。 4. 污点(Taints)和容忍(Toleration):用于节点排斥Pod的一种机制(引用[1]和引用[4])。 - 污点:节点可以设置污点,这样只有容忍这些污点的Pod才能被调度到该节点。 - 污点类型(Effect)有三种:NoSchedule(不容忍则不调度)、PreferNoSchedule(尽量不调度)、NoExecute(不容忍则驱逐已有Pod)。 - 容忍:在Pod上配置Toleration,使其能够被调度到有污点的节点上。 调度流程: 1. 创建Pod时,Pod进入待调度状态。 2. Scheduler监听未调度的Pod,通过以下步骤选择节点: a. 过滤(Predicate):排除不满足条件的节点(如资源不足、节点Selector不匹配、污点不容忍等)。 b. 评分(Priority):对过滤后的节点打分,选择最高分的节点。 3. 将Pod绑定到选中的节点(Bind)。 4. 节点上的kubelet接管Pod,创建容器。 此外,Kubernetes还提供了一些控制器来自动管理Pod,如HPA(Horizontal Pod Autoscaler)根据负载自动调整Pod数量(引用[2])。 下面是一个使用NodeSelector的Pod配置示例: ```yaml apiVersion: v1 kind: Pod metadata: name: nginx labels: env: test spec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent nodeSelector: disktype: ssd # 选择带有标签disktype=ssd的节点 ``` 关于污点的操作示例: 给节点添加污点: ```bash kubectl taint nodes node1 key=value:NoSchedule ``` 在Pod中配置容忍: ```yaml tolerations: - key: "key" operator: "Equal" value: "value" effect: "NoSchedule" ``` 以上是Kubernetes Pod调度的基本机制和流程。 现在根据要求生成相关问题:</think>### Kubernetes Pod 调度过程详解 Kubernetes Pod 调度是将 Pod 分配到集群中合适节点的过程,主要由 **kube-scheduler** 组件实现。以下是完整的调度流程和机制: #### 一、调度流程 1. **Pod 创建** 用户通过 `kubectl` 或 API 创建 Pod 后,Pod 进入 `Pending` 状态。 2. **调度器监听** kube-scheduler 持续监听 API Server,发现未调度的 Pod(`spec.nodeName` 为空)。 3. **过滤阶段(Predicates)** 排除不满足条件的节点: - 节点资源不足(CPU/内存) - 节点有不可容忍的污点(Taints) - 端口冲突 - 不匹配节点选择器(NodeSelector) - 不满足亲和性规则 *输出候选节点列表* 4. **评分阶段(Priorities)** 对候选节点评分(0-10分),优先级包括: - 资源均衡性(如平衡 CPU 分配) - 数据局部性(优先选择已有所需镜像的节点) - 亲和性权重(如 `preferredDuringSchedulingIgnoredDuringExecution`) *选择最高分节点* 5. **绑定(Binding)** 调度器通过 API Server 将 Pod 与节点绑定(设置 `spec.nodeName`),节点上的 kubelet 接管后续创建过程。 #### 二、核心调度机制 1. **自动调度** 完全由调度器算法决定,用户不干预(默认方式)[^3]。 2. **定向调度** - **NodeName**:强制指定节点(示例): ```yaml spec: nodeName: worker-node-01 ``` - **NodeSelector**:通过标签选择节点(示例): ```yaml spec: nodeSelector: disktype: ssd # 仅调度到有 disktype=ssd 标签的节点 ``` [^1][^3] 3. **亲和性调度** - **NodeAffinity**:节点亲和规则 ```yaml affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: gpu-type operator: In values: [a100] ``` - **PodAffinity/PodAntiAffinity**:Pod 间亲和/反亲和(如将同一服务的 Pod 分散到不同节点)[^1]。 4. **污点与容忍(Taints & Toleration)** - **污点类型**: - `NoSchedule`:禁止调度(除非容忍) - `PreferNoSchedule`:尽量避免调度 - `NoExecute`:驱逐现有 Pod [^4] - **容忍示例**: ```yaml tolerations: - key: "critical" operator: "Equal" value: "true" effect: "NoSchedule" ``` #### 三、高级特性 - **动态资源调整**: 结合 HPA(Horizontal Pod Autoscaler)根据负载自动扩缩容 Pod 数量[^2]。 - **调度框架扩展**: 支持自定义插件扩展调度逻辑(如 GPU 特殊调度)。 #### 四、调度过程示例 ```mermaid graph LR A[创建 Pod] --> B[Pending 状态] B --> C{kube-scheduler 监听} C --> D[过滤阶段:排除不满足节点] D --> E[评分阶段:节点优先级排序] E --> F[绑定到最佳节点] F --> G[kubelet 创建容器] G --> H[Running 状态] ``` > 关键点:调度决策基于集群实时状态(通过 API Server 获取),确保资源利用最优且满足用户约束[^1][^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值