在K8S中,Pod常见调度方式有哪些?

好的,这是一个非常核心的Kubernetes话题。Kubernetes提供了非常丰富和灵活的调度方式,从最简单到最复杂,可以满足各种部署需求。

Pod的调度方式主要可以分为以下几大类:


1. 自动调度:最基本的调度

这是最常见的方式。您只需定义一个Pod(通常通过Deployment、StatefulSet等控制器来管理),不指定任何节点相关的约束。那么调度器(kube-scheduler)会自动为您选择一个最合适的Node来运行Pod。

调度器基于其调度算法和策略进行决策,主要考虑两大因素:

  • 资源需求与限制(Resources Requests/Limits):确保Node有足够的CPU和内存资源来运行Pod。
  • 硬件/软件约束(Hardware/Software Constraints):Pod是否要求特定的操作系统、架构(如amd64/arm64)等。

这是默认且最常用的方式,体现了Kubernetes的声明式API和自动化运维的优势。


2. 定向调度:将Pod分配到特定节点

这种方式允许您显式地告诉Kubernetes将Pod调度到某一个或某一类Node上。

a) nodeName

最直接的方式,直接在Pod Spec中指定节点的名称。这会绕过调度器,直接强制将Pod部署到指定节点。

  • 缺点:如果该节点不存在或不资源不足,Pod会运行失败。
  • 适用场景:调试或非常特殊的静态环境,一般不推荐生产使用。
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
  nodeName: k8s-node-01 # 直接指定节点主机名

b) nodeSelector

通过为Node打上标签(Label),并为Pod指定对应的标签选择器(Selector),来实现简单的定向调度。

  • 步骤
    1. 给Node打标签:kubectl label nodes <node-name> disktype=ssd
    2. 在Pod Spec中定义 nodeSelector
apiVersion: v1
kind: Pod
metadata:
  name: nginx-ssd
spec:
  containers:
  - name: nginx
    image: nginx
  nodeSelector:
    disktype: ssd # 只会调度到带有 disktype=ssd 标签的节点上

3. 亲和性与反亲和性 (Affinity/Anti-affinity):更高级的定向调度

这是nodeSelector的升级版,提供了更强大、更灵活的表达能力。它通过 affinity 字段来定义。

a) 节点亲和性 (Node Affinity)

类似于 nodeSelector,但语法更强大,支持软偏好(soft/preferred)硬要求(hard/required) 规则,以及更丰富的操作符(In, NotIn, Exists, Gt, Lt等)。

  • requiredDuringSchedulingIgnoredDuringExecution(硬策略):必须满足的条件,不满足则不调度。
  • preferredDuringSchedulingIgnoredDuringExecution(软策略):偏好满足的条件,不满足也会调度。
apiVersion: v1
kind: Pod
metadata:
  name: with-node-affinity
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: topology.kubernetes.io/zone
            operator: In
            values:
            - ap-southeast-1a
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: another-node-label
            operator: In
            values:
            - another-node-label-value
  containers:
  - name: nginx
    image: nginx

b) Pod间亲和性与反亲和性 (Inter-Pod Affinity/Anti-affinity)

这是最强大的调度策略之一,它根据已经在节点上运行的Pod的标签来调度新Pod,而不是根据Node的标签。

  • Pod亲和性 (Pod Affinity):将Pod调度到已经有某类Pod运行的节点上(例如,将Web服务部署到已经有Redis缓存的节点上,减少网络延迟)。
  • Pod反亲和性 (Pod Anti-affinity):让Pod远离某类Pod,避免部署到同一个节点、机架或可用区(例如,保证同一应用的两个实例不在同一个节点或可用区,实现高可用)。
# 使用反亲和性实现高可用:确保同一个应用的Pod不被调度到同一个节点
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-server
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web-store
  template:
    metadata:
      labels:
        app: web-store
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - web-store
            topologyKey: kubernetes.io/hostname # 拓扑域为“主机名”,即不能在同一台机器
      containers:
      - name: web-app
        image: nginx:latest

4. 污点和容忍度 (Taints and Tolerations):让节点排斥Pod

这与亲和性的作用相反。亲和性是“Pod吸引Pod”,而污点和容忍度是“Node排斥Pod”

  • 污点 (Taint):应用于Node上,表示该节点拒绝不能“容忍”这个污点的Pod。
  • 容忍度 (Toleration):应用于Pod上,允许(但非强制)Pod调度到带有对应污点的Node上。

常见应用场景:

  • 专用节点:将某些节点专用于特定团队或特定类型的任务(如GPU机器学习)。
  • 边缘节点/有问题的节点:给即将维护或资源耗尽的节点打上污点 (NoSchedule),阻止新Pod调度上来。
  • Master节点:Kubernetes默认给Master节点打上了 node-role.kubernetes.io/control-plane:NoSchedule 污点,以防止普通业务Pod调度到Master上。

给Node打污点:

kubectl taint nodes node01 key=value:NoSchedule

在Pod上配置容忍度:

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: nginx
    image: nginx
  tolerations:
  - key: "key"
    operator: "Equal"
    value: "value"
    effect: "NoSchedule"

5. 其他调度方式

DaemonSet:在每个节点上运行一个Pod副本

这是一种特殊的控制器,它确保所有(或匹配的)节点上都运行一个且只有一个指定的Pod副本。常用于运行系统级别的守护进程,如:

  • 日志收集器(Fluentd, Filebeat)
  • 节点监控代理(Prometheus Node Exporter)
  • 网络插件(Calico, Cilium)

静态Pod (Static Pod)

由特定节点上的 kubelet 守护进程直接管理,不需要通过API服务器进行调度。Pod定义文件放在节点的特定目录(如 /etc/kubernetes/manifests)下。kubelet 会定期扫描该目录并创建/删除Pod。

  • 主要用途:用于部署Kubernetes自身的核心组件,如 kube-apiserver, kube-scheduler, kube-controller-manager 等(常用在kubeadm搭建的集群中)。

总结

调度方式 核心思想 适用场景
自动调度 由调度器全权决定 最通用的场景,无特殊需求的应用
nodeSelector 简单标签匹配 需要调度到具有特定硬件(如SSD、GPU)的节点
节点亲和性 更丰富的节点标签匹配规则(软/硬策略) 复杂的节点选择需求,如优先选择某个可用区
Pod间亲和/反亲和 根据已有Pod来调度新Pod 高可用(分散部署)、低延迟(集中部署)
污点和容忍度 让节点排斥Pod 专用节点、隔离故障节点、保护Master节点
DaemonSet 每个节点运行一个Pod 系统级守护进程(日志、监控、网络)
静态Pod 由kubelet直接管理 部署Kubernetes自身系统组件

在实际生产环境中,通常会组合使用多种策略。例如,先使用污点隔离出专用GPU节点,然后使用节点亲和性nodeSelector将机器学习任务Pod调度到这些节点上,同时使用Pod反亲和性确保这些任务自身不会堆积在同一个节点上。

posted @ 2025-08-23 09:01  天道酬勤zjh  阅读(10)  评论(0)    收藏  举报