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

目录
相关文章
|
3月前
|
运维 Kubernetes NoSQL
【k8s-1.34.2安装部署】九.k8s管理平台xkube安装部署
xkube是一款永久免费、无功能限制的云原生Kubernetes多集群管理工具,支持PC端与APP端,提供集群管理、运维监控、CI/CD发布等功能,助力企业实现跨集群统一管理与自动化运维。
315 2
【k8s-1.34.2安装部署】九.k8s管理平台xkube安装部署
|
2月前
|
Kubernetes Cloud Native 安全
一文掌握k8s容器的生命周期
容器生命周期钩子是Kubernetes核心机制,支持在容器启动后(postStart)和终止前(preStop)执行自定义逻辑,实现服务注册、优雅停机等操作。结合启动命令,可精细控制应用生命周期,提升云原生应用稳定性与可靠性。
244 4
一文掌握k8s容器的生命周期
|
2月前
|
安全 C语言 Docker
从零开始学构建Docker镜像:4种实用方法+生产级实践规范
本文系统讲解Docker镜像构建四大方法,聚焦生产实践,涵盖环境搭建、Dockerfile规范、多阶段构建、安全管控与CI/CD集成,强调非root运行、镜像瘦身及可追溯Tag规范,助力开发者掌握从开发到生产的全链路容器化技能。
740 5
|
26天前
|
Kubernetes 应用服务中间件 nginx
最全的kubectl命令用法
本文系统讲解kubectl命令行工具:详解所有子命令(创建、查询、部署、调试等)、API资源列表、自动补全配置,并通过大量实操示例(如创建/查看/编辑/删除资源、扩缩容、回滚、标签管理等)助你快速掌握Kubernetes集群管理核心技能。(239字)
403 143
|
23天前
|
应用服务中间件 Shell nginx
最全的docker命令参数解释及命令用法
本文系统详解Docker核心命令,涵盖容器(run/exec/ps/start/stop等)、镜像(pull/build/push/rmi等)、网络、数据卷及全局参数,并配实操示例与可直接执行的命令,助初学者快速掌握Docker日常运维与开发应用。
699 129
|
2月前
|
Kubernetes Go API
xkube v4.0发布,完全开发源代码并新增k8s网关、亲和性很多k8s实用功能
xkubе v4.0 是开源K8s可视化管理平台(Gitee:https://gitee.com/eeenet/xkube),全面开放Go后端源码。新增Gateway API全系支持(Gateway/HTTPRoute/GRPCRoute等)、增强Deployment/STS/Job配置能力、Pod资源Top监控、节点资源统计及审计日志,界面与依赖全面升级。
298 115
|
1月前
|
运维 Kubernetes 应用服务中间件
一文讲解kubernetes的gateway Api的功能、架构、部署、管理及使用
Gateway API是Kubernetes官方推出的下一代L4/L7网络网关标准,面向角色(基础设施商、运维、开发)、可移植、表达力强且高度可扩展。它通过GatewayClass、Gateway、HTTPRoute等资源实现权限分离与策略即代码,替代Ingress短板,已获Istio、Envoy、ASM等主流支持。
489 119
|
2月前
|
Kubernetes 应用服务中间件 API
应对 Nginx Ingress 退役,是时候理清这些易混淆的概念了
本文希望提供一种更简单的方式,来理解这些容易混淆的技术概念:Nginx、Ingress、Ingress Controller、Ingress API、Nginx Ingress、Higress、Gateway API。
983 84
|
3月前
|
Kubernetes 容器 Perl
kubernetes-1.34.2 二级制快速安装部署
kubenetes-1.34.2 二进制安装包,其他版本同样可以使用,包含etcd,kube-apiserver,kube-controller-manager,kube-scheduler,kubelet,containerd,coredns,metric-server的证书、配置文件,启动脚本。其中还包括证书的生成脚本、kubeconfig的生成脚本,同时包含了二进制可执行文件,本安装包已经包含了二进制文件,制作好的证书和安装包,可以直接拷贝到安装目录进行安装,也可以重新执行:make_install_package.sh 重新生成。该项目是为了配合k8s-1.34.2二进制的安装。
833 1
|
3月前
|
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的部署流程,包括文件准备、服务启动、状态验证及权限授权,为构建高可用集群奠定基础。
259 0