一文掌握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

目录
相关文章
|
2月前
|
运维 Kubernetes NoSQL
【k8s-1.34.2安装部署】九.k8s管理平台xkube安装部署
xkube是一款永久免费、无功能限制的云原生Kubernetes多集群管理工具,支持PC端与APP端,提供集群管理、运维监控、CI/CD发布等功能,助力企业实现跨集群统一管理与自动化运维。
239 2
【k8s-1.34.2安装部署】九.k8s管理平台xkube安装部署
|
21天前
|
安全 C语言 Docker
从零开始学构建Docker镜像:4种实用方法+生产级实践规范
本文系统讲解Docker镜像构建四大方法,聚焦生产实践,涵盖环境搭建、Dockerfile规范、多阶段构建、安全管控与CI/CD集成,强调非root运行、镜像瘦身及可追溯Tag规范,助力开发者掌握从开发到生产的全链路容器化技能。
381 5
|
1月前
|
存储 缓存 调度
阿里云Tair KVCache仿真分析:高精度的计算和缓存模拟设计与实现
在大模型推理迈向“智能体时代”的今天,KVCache 已从性能优化手段升级为系统级基础设施,“显存内缓存”模式在长上下文、多轮交互等场景下难以为继,而“以存代算”的多级 KVCache 架构虽突破了容量瓶颈,却引入了一个由模型结构、硬件平台、推理引擎与缓存策略等因素交织而成的高维配置空间。如何在满足 SLO(如延迟、吞吐等服务等级目标)的前提下,找到“时延–吞吐–成本”的最优平衡点,成为规模化部署的核心挑战。
491 38
阿里云Tair KVCache仿真分析:高精度的计算和缓存模拟设计与实现
|
21天前
|
Kubernetes Cloud Native 安全
一文掌握k8s容器的生命周期
容器生命周期钩子是Kubernetes核心机制,支持在容器启动后(postStart)和终止前(preStop)执行自定义逻辑,实现服务注册、优雅停机等操作。结合启动命令,可精细控制应用生命周期,提升云原生应用稳定性与可靠性。
147 4
一文掌握k8s容器的生命周期
|
2月前
|
Kubernetes 容器 API
【k8s-1.34.2安装部署】四.kubernets master组件kube-apiserver,kube-controller-manager,kube-scheduler安装
本章介绍k8s-1.34.2中master组件的安装,涵盖kube-apiserver、kube-controller-manager、kube-scheduler的部署流程,包括文件准备、服务启动、状态验证及权限授权,为构建高可用集群奠定基础。
193 1
|
2月前
|
Kubernetes 数据可视化 Perl
【k8s-1.34.2安装部署】八.metric-server-0.8.0安装
本章介绍metrics-server的安装与配置,用于采集K8s集群中节点和Pod的CPU、内存指标,支撑Dashboard及xkub等工具的资源使用可视化。通过修改配置启用 insecure-tls 并替换为阿里云镜像,快速完成部署,安装后可通过`kubectl top`命令验证。
280 1
|
2月前
|
Kubernetes 数据库 容器
【k8s-1.34.2安装部署】三.etcd-v3.6.6 TLS版集群安装
本章节主要讲解etcd-v3.6.6集群的安装过程,并通过脚本etcd.sh来查看etcd的集群状态以及etcd的数据库中存放数据的情况,也可以通过etcd.sh脚本来进行etcd的备份和还原。上一章中我们准备了etcd安装所需要的证书、配置、启动脚步、检测脚本。
227 0
|
1月前
|
Kubernetes 应用服务中间件 API
应对 Nginx Ingress 退役,是时候理清这些易混淆的概念了
本文希望提供一种更简单的方式,来理解这些容易混淆的技术概念:Nginx、Ingress、Ingress Controller、Ingress API、Nginx Ingress、Higress、Gateway API。
787 71
|
12天前
|
XML 前端开发 Serverless
自建一个 Agent 很难吗?一语道破,万语难明
本文分享了在奥德赛TQL研发平台中集成BFF Agent的完整实践:基于LangGraph构建状态图,采用Iframe嵌入、Faas托管与Next.js+React框架;通过XML提示词优化、结构化知识库(RAG+DeepWiki)、工具链白名单及上下文压缩(保留近3轮对话)等策略,显著提升TQL脚本生成质量与稳定性。
257 34
自建一个 Agent 很难吗?一语道破,万语难明
|
20天前
|
监控 Linux 网络安全
阿里云轻量应用服务器宝塔Linux面板搭建参考:详解操作流程
本文介绍了通过阿里云轻量应用服务器搭建宝塔Linux面板并获取专享特权的完整流程。宝塔面板支持一键配置LAMP/LNMP等环境,阿里云用户部署阿里云专享版9.2.0后可享两大特权:免费使用异常监控推送、堡塔APP等付费功能,以及购买宝塔官方软件享额外折扣。
464 10