一文掌握pod亲和性及调度策略

简介: Kubernetes中,Pod是调度的基本单位。通过nodeName、nodeSelector、亲和性等策略,可精细控制Pod部署位置,实现资源优化、低延迟通信与故障隔离。支持硬约束与软约束,结合标签选择器灵活配置。

简介

在Kubernetes中,工作负载调度的基本单位是Pod。创建工作负载时,调度器会自动对工作负载中的Pod进行合理分配,例如将Pod分散到资源充足的节点上。

虽然调度器的默认行为已经能够满足许多基本需求,但在一些特定场景下,用户可能需要更精细地控制Pod的部署位置。为了实现这一点,Kubernetes允许用户在工作负载定义中配置调度策略。例如:

  • 将前端应用和后端应用部署在一起,有助于减少延迟,因为这两种类型的Pod可以共享相同的物理资源。
  • 某类应用部署到某些特定的节点,确保关键应用总是运行在最优的硬件或配置上。
  • 不同应用部署到不同的节点,有助于隔离应用,防止一个应用的问题影响到其他应用。

2.调度策略

Kubernetes对Pod的调度策略方式如下表:

调度策略 Yaml定义 说明
节点名称 nodeName 指定节点的主机名来实现pod调度到指定节点上
节点选择 nodeSelector 通过选择节点的标签来希望调度到目标节点,然后Pod被调度到拥有指定标签的节点上。
节点亲和 nodeAffinity 节点亲和可以实现nodeSelector的能力,但其表达能力更强,您可以根据节点上的标签,使用标签选择器来筛选需要亲和的节点,支持必须满足和尽量满足的亲和性规则

注:如果同时指定nodeSelector和nodeAffinity,则两者必须都要满足,才能将Pod调度到候选节点上
pod亲和/反亲和 podAffinity/podAntiAffinity 根据工作负载标签,使用标签选择器来筛选需要 亲和/反亲和 的Pod,并将新建的pod 调度/不调度 至目标Pod所在的节点(或节点组),也支持必须满足和尽量满足的亲和性规则

注:pod的亲和性和反亲和性需要一定的计算时间,因此在大规模集群中会显著降低调度的速度。在包含数百个节点的集群中,不建议使用这类设置。

3.亲和性规则

基于节点亲和或pod亲和/反亲和的调度策略还可以设置必须满足的硬约束和尽量满足的软约束,以满足更复杂的调度情况。

在下表亲和规则中,YAML字段前半段requiredDuringScheduling或preferredDuringScheduling表示在调度时需要强制满足(require)或尽量满足(prefer)定义的标签规则。而后半段IgnoredDuringExecution表示如果节点标签在Kubernetes调度Pod后发生了变更,Pod仍将继续运行不会重新调度。但是如果该节点上的kubelet重启,kubelet会重新对节点亲和性规则进行校验,Pod仍会被调度至其他节点。

规则类型 YAML字段定义 说明
必须满足 requiredDuringSchedulingIgnoredDuringExecution 硬约束,即调度器只有在规则被满足的时候才能执行调度。
尽量满足 preferredDuringSchedulingIgnoredDuringExecution 软约束,即调度器会尝试寻找满足对应规则的目标对象。即使找不到匹配的目标,调度器仍然会调度该Pod。

在使用尽量满足的亲和性类型时,您可以为每个实例设置weight字段,其取值范围是1到100。 权重越高,调度的优先级越高。

4.标签选择器

在创建调度策略时,您需要使用标签选择器的逻辑运算符来筛选标签值,最终确定需要亲和/反亲和的对象。

参数 说明
key 标签键名,满足筛选条件的对象需包含该键名的标签,且标签的取值满足标签值列表(values字段)和逻辑运算符的运算关系。
operator 您可以使用逻辑运算符来确定标签值的筛选规则,所有逻辑运算符如下:

In:亲和/反亲和对象的标签包含在标签值列表(values字段)中。
NotIn:亲和/反亲和对象的标签不包含在标签值列表(values字段)中。
Exists:亲和/反亲和对象存在指定标签名,此时无需填写values字段。
DoesNotExist:亲和/反亲和对象不存在指定标签名,此时无需填写values字段。
Gt:仅在节点亲和性中设置,调度节点的标签值大于列表值 (字符串比较)。
Lt:仅在节点亲和性中设置,调度节点的标签值小于列表值 (字符串比较)。
values 标签值的数组

5.yaml配置示例

5.1.nodeName yaml示例

本示例中会将pod调度到通过nodeName指定的节点:gt5-node-test-vm10-188 上

    spec:
      containers:
      - image: crpi-44hgz4440mgo9lnt.cn-guangzhou.xxx.com/eeenet/nginx:stable-alpine3.17-slim
        imagePullPolicy: Always
        name: test-one
        ports:
        - containerPort: 80
          protocol: TCP
      dnsPolicy: ClusterFirst
      nodeName: gt5-node-test-vm10-188
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30

5.2.nodeSelector yaml示例

本示例表明该Pod将被调度到有deploy_qa=true标签的节点。示例如下

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      nodeSelector: 
        deploy_qa: "true"
      containers:
      - image: nginx:latest
        imagePullPolicy: IfNotPresent
        name: nginx
      imagePullSecrets:
      - name: default-secret

5.3.nodeAffinity yaml示例

本示例中,必须满足的规则表示调度的节点必须包含一个键名为gpu的标签,且标签值为true。而尽量满足规则表示根据节点可用区的标签topology.kubernetes.io/zone进行优先级排序,尽量将Pod调度至可用区az1的节点上:

apiVersion: apps/v1
kind: Deployment
metadata:
  name:  gpu
  labels:
    app:  gpu
spec:
  selector:
    matchLabels:
      app: gpu
  replicas: 3
  template:
    metadata:
      labels:
        app:  gpu
    spec:
      containers:
      - image:  nginx:alpine
        name:  gpu
        resources:
          requests:
            cpu: 100m
            memory: 200Mi
          limits:
            cpu: 100m
            memory: 200Mi
      imagePullSecrets:
      - name: default-secret
      affinity:  # 设置调度策略
        nodeAffinity:  # 表示节点亲和性调度
          requiredDuringSchedulingIgnoredDuringExecution:  # 表示必须满足的调度策略
            nodeSelectorTerms:     # 根据节点标签选择满足条件的节点
              - matchExpressions:    # 节点标签匹配规则
                - key: gpu   # 节点标签的键为gpu
                  operator: In  # 表示存在values列表中的值即满足规则
                  values:   # 节点标签的值为true
                  - "true"
          preferredDuringSchedulingIgnoredDuringExecution:  # 表示尽量满足的调度策略
            - weight: 100  # 使用尽量满足策略时可设置优先级,取值为1-100,数值越大优先级越高
              preference:  # 使用尽量满足策略时,设置优先选择的节点标签匹配规则
                matchExpressions:   # 节点标签匹配规则
                  - key: topology.kubernetes.io/zone   # 节点可用区的标签
                    operator: In  # 表示存在values列表中的值即满足规则
                    values:   # 节点标签的值为az1
                    - "az1"

5.4.podAffinity亲和性yaml示例

Kubernetes支持Pod和Pod之间的亲和,例如将应用的前端和后端部署在一起,从而减少访问延迟。
假设有个应用的后端已经创建,且带有app=backend的标签。您可以使用.spec.affinity.podAffinity字段来设置工作负载亲和性,将前端Pod(标签为app=frontend)和后端Pod(标签为app=backend)部署在一起。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
  labels:
    app: frontend
spec:
  selector:
    matchLabels:
      app: frontend
  replicas: 3
  template:
    metadata:
      labels:
        app: frontend
    spec:
      containers:
      - image: nginx:alpine
        name: frontend
        resources:
          requests:
            cpu: 100m
            memory: 200Mi
          limits:
            cpu: 100m
            memory: 200Mi
      imagePullSecrets:
      - name: default-secret
      affinity:  # 设置调度策略
        podAffinity:  # 工作负载亲和性调度规则
          requiredDuringSchedulingIgnoredDuringExecution:   # 表示必须满足的调度策略
          - topologyKey: prefer    # 根据节点标签划分拓扑域,示例中prefer为自定义标签
            labelSelector:  # 根据工作负载标签选择满足条件的工作负载
              matchExpressions: # 工作负载标签匹配规则
              - key: app # 工作负载标签的键为app
                operator: In # 表示存在values列表中的值即满足规则
                values: # 工作负载标签的值列表
                - backend
          preferredDuringSchedulingIgnoredDuringExecution:    # 表示尽量满足的调度策略
          - weight: 100  # 使用尽量满足策略时可设置优先级,取值为1-100,数值越大优先级越高
            podAffinityTerm:  # 使用尽量满足策略时的亲和项
              topologyKey: topology.kubernetes.io/zone   # 根据节点标签划分拓扑域,以节点的可用区为粒度
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - backend

上述示例中的pod调度时,必须满足规则会根据prefer标签划分节点拓扑域,如果当拓扑域中某个节点运行着后端Pod(标签为app=backend),即使该拓扑域中并非所有节点均运行了后端Pod,前端Pod(标签为app=frontend)同样会部署在此拓扑域中。而尽量满足规则根据topology.kubernetes.io/zone划分拓扑域,以节点的可用区为粒度进行调度,表示尽量将前后端部署至同一可用区的节点。

注意:
对于工作负载亲和来说,使用requiredDuringSchedulingIgnoredDuringExecution和preferredDuringSchedulingIgnoredDuringExecution规则时, topologyKey字段不允许为空。

topologyKey字段用于划分拓扑域,当节点上存在topologyKey字段指定的标签,且键、值均相同时,这些节点会被认为属于同一拓扑域,然后调度器会根据工作负载的标签选择需要调度的拓扑域。一个拓扑域中可能包含多个节点,当拓扑域中的一个节点上运行了满足标签选择规则的工作负载时,则该拓扑域中的节点均可以被调度。

例如,当topologyKey的标签为topology.kubernetes.io/zone时,表示以节点的可用区作为拓扑域,工作负载在部署时会以可用区为粒度进行调度。

5.5.podAntiAffinity yaml示例

工作负载反亲和性
在某些情况下,需要将Pod分开部署,例如Pod之间部署在一起会影响性能的情况。
假设有个应用的前端已经创建,且带有app=frontend的标签。您可以使用.spec.affinity.podAntiAffinity字段来设置工作负载反亲和性,将各个Pod部署在不同的节点,且优先多可用区。

apiVersion: apps/v1
kind: Deployment
metadata:
  name:   frontend
  labels:
    app:  frontend
spec:
  selector:
    matchLabels:
      app: frontend
  replicas: 5
  template:
    metadata:
      labels:
        app:  frontend
    spec:
      containers:
      - image:  nginx:alpine
        name:  frontend
        resources:
          requests:
            cpu:  100m
            memory:  200Mi
          limits:
            cpu:  100m
            memory:  200Mi
      imagePullSecrets:
      - name: default-secret
      affinity:
        podAntiAffinity:  # 工作负载反亲和性调度规则
          requiredDuringSchedulingIgnoredDuringExecution:   # 表示必须满足的调度策略
          - topologyKey: kubernetes.io/hostname    # 根据节点标签划分拓扑域
            labelSelector:    # Pod标签匹配规则
              matchExpressions:  # 工作负载标签的键为app
              - key: app  # 工作负载标签的键为app
                operator: In  # 表示存在values列表中的值即满足规则
                values:  # 工作负载标签的值列表
                - frontend
          preferredDuringSchedulingIgnoredDuringExecution:    # 表示尽量满足的调度策略
          - weight: 100  # 使用尽量满足策略时可设置优先级,取值为1-100,数值越大优先级越高
            podAffinityTerm:  # 使用尽量满足策略时的亲和项
              topologyKey: topology.kubernetes.io/zone   # 根据节点标签划分拓扑域,以节点的可用区为粒度
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - frontend

以上示例中定义了反亲和规则,必须满足的规则表示根据kubernetes.io/hostname标签划分节点拓扑域。由于拥有kubernetes.io/hostname标签的节点中,每个节点的标签值均不同,因此一个拓扑域中只有一个节点。当一个拓扑域中(此处为一个节点)已经存在frontend标签的Pod时,该拓扑域不会被继续调度具有相同标签的Pod。而尽量满足规则根据topology.kubernetes.io/zone划分拓扑域,以节点的可用区为粒度进行调度,表示尽量将Pod分布至不同可用区的节点。

注意:
对于工作负载反亲和来说,使用requiredDuringSchedulingIgnoredDuringExecution规则时, Kubernetes默认的准入控制器 LimitPodHardAntiAffinityTopology要求topologyKey字段只能是kubernetes.io/hostname。如果您希望使用其他定制拓扑逻辑,可以更改或者禁用该准入控制器。

通过xkube进行设置

通过多集群k8s管理平台xkube的功能进行亲和性设置,xkube安装部署参考:https://developer.aliyun.com/article/1696994

功能参考下图:
5f2d26e1e9e140f58943dffb49297b64.png
692ec2b3c5fd43028e5844b9a27b7809.png

相关文章
|
7天前
|
人工智能 JavaScript Linux
【Claude Code 全攻略】终端AI编程助手从入门到进阶(2026最新版)
Claude Code是Anthropic推出的终端原生AI编程助手,支持40+语言、200k超长上下文,无需切换IDE即可实现代码生成、调试、项目导航与自动化任务。本文详解其安装配置、四大核心功能及进阶技巧,助你全面提升开发效率,搭配GitHub Copilot使用更佳。
|
1天前
|
JSON API 数据格式
OpenCode入门使用教程
本教程介绍如何通过安装OpenCode并配置Canopy Wave API来使用开源模型。首先全局安装OpenCode,然后设置API密钥并创建配置文件,最后在控制台中连接模型并开始交互。
|
9天前
|
存储 人工智能 自然语言处理
OpenSpec技术规范+实例应用
OpenSpec 是面向 AI 智能体的轻量级规范驱动开发框架,通过“提案-审查-实施-归档”工作流,解决 AI 编程中的需求偏移与不可预测性问题。它以机器可读的规范为“单一真相源”,将模糊提示转化为可落地的工程实践,助力开发者高效构建稳定、可审计的生产级系统,实现从“凭感觉聊天”到“按规范开发”的跃迁。
1409 15
|
8天前
|
人工智能 JavaScript 前端开发
【2026最新最全】一篇文章带你学会Cursor编程工具
本文介绍了Cursor的下载安装、账号注册、汉化设置、核心模式(Agent、Plan、Debug、Ask)及高阶功能,如@引用、@Doc文档库、@Browser自动化和Rules规则配置,助力开发者高效使用AI编程工具。
1165 5
|
6天前
|
云安全 安全
免费+限量+领云小宝周边!「阿里云2026云上安全健康体检」火热进行中!
诚邀您进行年度自检,发现潜在风险,守护云上业务连续稳健运行
1177 2
|
9天前
|
消息中间件 人工智能 Kubernetes
阿里云云原生应用平台岗位急招,加入我们,打造 AI 最强基础设施
云原生应用平台作为中国最大云计算公司的基石,现全面转向 AI,打造 AI 时代最强基础设施。寻找热爱技术、具备工程极致追求的架构师、极客与算法专家,共同重构计算、定义未来。杭州、北京、深圳、上海热招中,让我们一起在云端,重构 AI 的未来。
|
11天前
|
IDE 开发工具 C语言
【2026最新】VS2026下载安装使用保姆级教程(附安装包+图文步骤)
Visual Studio 2026是微软推出的最新Windows专属IDE,启动更快、内存占用更低,支持C++、Python等开发。推荐免费的Community版,安装简便,适合初学者与个人开发者使用。
1213 11