K8s中Node亲和反亲和

本文详细介绍了Kubernetes中的亲和性和反亲和性调度策略,包括nodeSelector、硬亲和性(required)、软亲和性(preferred)及其matchExpressions的使用方法,以及如何通过affinity配置让Pod在特定节点上运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

k8s中亲和性与反亲和性
Kubernetes的默认调度器以预选、优选、选定机制完成将每个新的Pod资源绑定至为其选出的目标节点上,不过,它只是Pod对象的默认调度器,默认情况下调度器考虑的是资源足够,并且负载尽量平均。
在使用中,用户还可以自定义调度器插件,并在定义Pod资源配置清单时通过spec.schedulerName指定即可使

一、node亲和性
NodeAffinity意为Node节点亲和性的调度策略,是用于替换NodeSelector的全新调度策略。

定义节点亲和性规则时有两种类型的节点亲和性规则 :硬亲和性required和软亲和性preferred。 硬亲和性实现的是强制性规则,它是Pod调度时必须要满足的规则,而在不存在满足规则的节点时 , Pod对象会被置为Pending状态。 而软亲和性规则实现的是一种柔性调度限制,它倾向于将Pod对象运行于某类特定的节点之上,而调度器也将尽量满足此需求,但在无法满足调度需求时它将退而求其次地选择一个不匹配规则的节点

1.1、nodeSelector
对于最初的k8s实现pod指定node调度时使用nodeSelector来实现的,主要是通过定义node以及pod标签进行选择,具体实现如下:

为节点添加label标签
 

[root@node1 ~]# kubectl label node node2 app=web
node/node2 labeled
######
定义deployment启动pod,如下:
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy
  labels:
    app: web
spec:
  replicas: 13
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      nodeSelector:
        app: web             ###选择标签
      containers:
      - name: nginx-deploy
        image: nginx:latest
        imagePullPolicy: IfNotPresent
            
[root@node1 ~]# kubectl apply -f deploy-pod.yaml 
deployment.apps/deploy created
[root@node1 ~]# 
########
查看pod启动所在的节点,如下:
[root@node1 ~]# kubectl get pod -o wide
NAME                            READY   STATUS    RESTARTS   AGE     IP              NODE    NOMINATED NODE   READINESS GATES
deploy-6cb97b569b-292kw         1/1     Running   0          11s     172.25.104.62   node2   <none>           <none>
deploy-6cb97b569b-2qbfm         1/1     Running   0          11s     172.25.104.52   node2   <none>           <none>
deploy-6cb97b569b-58px4         1/1     Running   0          11s     172.25.104.54   node2   <none>           <none>
deploy-6cb97b569b-7cmqv         1/1     Running   0          11s     172.25.104.56   node2   <none>           <none>
deploy-6cb97b569b-cmq74         1/1     Running   0          11s     172.25.104.57   node2   <none>           <none>
deploy-6cb97b569b-cpv8x         1/1     Running   0          11s     172.25.104.59   node2   <none>           <none>
deploy-6cb97b569b-d9hwz         1/1     Running   0          11s     172.25.104.63   node2   <none>           <none>
deploy-6cb97b569b-f2zwf         1/1     Running   0          11s     172.25.104.60   node2   <none>           <none>
deploy-6cb97b569b-f6hbl         1/1     Running   0          11s     172.25.104.61   node2   <none>           <none>
deploy-6cb97b569b-kz46f         1/1     Running   0          11s     172.25.104.58   node2   <none>           <none>
deploy-6cb97b569b-mjmnv         1/1     Running   0          11s     172.25.104.55   node2   <none>           <none>
deploy-6cb97b569b-nkdwm         1/1     Running   0          11s     172.25.104.51   node2   <none>           <none>
deploy-6cb97b569b-tg7qc         1/1     Running   0          11s     172.25.104.53   node2   <none>           <none>


1.2、node硬亲和性
为Pod对象使用nodeSelector属性可以基于节点标签匹配的方式将Pod对象强制调度至某一类特定的节点之上 ,不过它仅能基于简单的等值关系定义标签选择器,而nodeAffinity中支持使用 matchExpressions属性构建更为复杂的标签选择机制。

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy
  labels:
    app: web
spec:
  replicas: 6
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: nginx-deploy
        image: nginx:latest
        imagePullPolicy: IfNotPresent
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:  # 硬策略
            nodeSelectorTerms:
            - matchExpressions:
              - key: app
                operator: In
                values:
                - web
######
为node添加标签,如下:
[root@node1 ~]# kubectl label node node2 app=web
node/node2 labeled

######
启动pod,如下pod都起在node上:
[root@node1 ~]# kubectl apply -f deploy-pod.yaml 
deployment.apps/deploy created
[root@node1 ~]# kubectl get pod -o wide
NAME                            READY   STATUS    RESTARTS   AGE     IP              NODE    NOMINATED NODE   READINESS GATES
deploy-66747445f7-25pwb         1/1     Running   0          14s     172.25.104.5    node2   <none>           <none>
deploy-66747445f7-4qdf7         1/1     Running   0          14s     172.25.104.10   node2   <none>           <none>
deploy-66747445f7-f24bq         1/1     Running   0          14s     172.25.104.20   node2   <none>           <none>
deploy-66747445f7-f9vbq         1/1     Running   0          14s     172.25.104.34   node2   <none>           <none>
deploy-66747445f7-gx4mq         1/1     Running   0          14s     172.25.104.28   node2   <none>           <none>
deploy-66747445f7-zwtc8         1/1     Running   0          14s     172.25.104.33   node2   <none>           <none>


在定义节点亲和性时,requiredDuringSchedulinglgnoredDuringExecution字段的值是一个对象列表,用于定义节点硬亲和性,它可由一到多个nodeSelectorTerm定义的对象组成, 彼此间为“逻辑或”的关系,进行匹配度检查时,在多个nodeSelectorTerm之间只要满足其中之一 即可。

preferredDuringSchedulingIgnoredDuringExecution和requiredDuringSchedulingIgnoredDuringExecution名字中的后半段符串IgnoredDuringExecution隐含的意义所指,在Pod资源基于节点亲和性规则调度至某节点之后,节点标签发生了改变而不再符合此节点亲和性规则时 ,调度器不会将Pod对象从此节点上移出,因为,它仅对新建的Pod对象生效。

nodeSelectorTerm用于定义节点选择器条目,其值为对象列表,它可由一个或多个matchExpressions对象定义的匹配规则组成,多个规则彼此之间为“逻辑与”的关系, 这就意味着某节点的标签需要完全匹配同一个nodeSelectorTerm下所有的matchExpression对象定义的规则才算成功通过节点选择器条目的检查。而matchExmpressions又可由 一到多 个标签选择器组成,多个标签选择器彼此间为“逻辑与”的关系 。

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy
  labels:
    app: web
spec:
  replicas: 6
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: nginx-deploy
        image: nginx:latest
        imagePullPolicy: IfNotPresent
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:  # 硬策略
            nodeSelectorTerms:
            - matchExpressions:
              - key: app
                operator: In
                values:
                - server
                - web
#######为node2和node3打标签
[root@node1 ~]# kubectl label node node2 app=web
node/node2 labeled
[root@node1 ~]# kubectl label node node3 app=server
node/node3 labeled
########启动pod,如下会在node2和node3上调度
[root@node1 ~]# kubectl get pod -o wide
NAME                            READY   STATUS    RESTARTS   AGE     IP              NODE    NOMINATED NODE   READINESS GATES
deploy-d78b4d4d9-5hb4k          1/1     Running   0          2m17s   172.25.104.47   node2   <none>           <none>
deploy-d78b4d4d9-l8tjk          1/1     Running   0          2m17s   172.25.135.61   node3   <none>           <none>
deploy-d78b4d4d9-mcvsk          1/1     Running   0          2m17s   172.25.135.60   node3   <none>           <none>
deploy-d78b4d4d9-mj7gk          1/1     Running   0          2m17s   172.25.104.43   node2   <none>           <none>
deploy-d78b4d4d9-r5xqn          1/1     Running   0          2m17s   172.25.104.45   node2   <none>           <none>
deploy-d78b4d4d9-zl684          1/1     Running   0          2m17s   172.25.104.46   node2   <none>           <none>


构建标签选择器表达式中支持使用操作符有In、Notln、Exists、DoesNotExist、Lt和Gt等

In:label的值在某个列表中
NotIn:label的值不在某个列表中
Gt:label的值大于某个值
Lt:label的值小于某个值
Exists:某个label存在 #####values为任意值。
DoesNotExist:某个label不存在
1.3、node软亲和性
节点软亲和性为节点选择机制提供了一种柔性控制逻辑,被调度的Pod对象不再是“必须”而是“应该”放置于某些特定节点之上,当条件不满足时它也能够接受被编排于其他不符合条件的节点之上。另外,它还为每种倾向性提供了weight属性以便用户定义其优先级,取值范围是1 ~ 100,数字越大优先级越高 。

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy
  labels:
    app: web
spec:
  replicas: 6
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: nginx-deploy
        image: nginx:latest
        imagePullPolicy: IfNotPresent
      affinity:
        nodeAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 60      ###设置app=web的权重为60
              preference:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                    - web

            - weight: 40   ###设置app=server的权重为40
              preference:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                    - server

#####启动pod如下,会发现大部分pod在app=web的node上
[root@node1 ~]# kubectl get pod -o wide  
NAME                            READY   STATUS    RESTARTS   AGE     IP              NODE    NOMINATED NODE   READINESS GATES
deploy-55bf777f76-5466z         1/1     Running   0          9m9s    172.25.104.50   node2   <none>           <none>
deploy-55bf777f76-62rrz         1/1     Running   0          9m9s    172.25.104.49   node2   <none>           <none>
deploy-55bf777f76-bf9bn         1/1     Running   0          9m9s    172.25.104.48   node2   <none>           <none>
deploy-55bf777f76-lx5pz         1/1     Running   0          9m9s    172.25.104.53   node2   <none>           <none>
deploy-55bf777f76-s78v5         1/1     Running   0          9m9s    172.25.135.62   node3   <none>           <none>
deploy-55bf777f76-t9cw9         1/1     Running   0          9m9s    172.25.104.63   node2   <none>           <none>

<think>好的,用户想要了解如何在Kubernetes中设置节点亲和性,特别是如何同时亲和多个节点。我需要先回忆一下节点亲和性的基本概念和相关配置方法。 首先,节点亲和性Node Affinity)是Kubernetes中用来将Pod调度到特定节点上的机制,主要通过标签选择器来实现。用户可能已经知道基础用法,但这里的问题是关于设置多个节点的亲和性,可能需要同时满足多个条件或者选择多个节点中的一个。 接下来,我需要考虑用户可能的场景。比如用户可能有多个节点带有不同的标签,比如区域、硬件类型等,希望Pod能优先调度到这些节点上。或者用户希望Pod能够分布在多个节点上,但满足某些条件。这时候就需要配置多个匹配表达式。 然后,要区分requiredDuringSchedulingIgnoredDuringExecution和preferredDuringSchedulingIgnoredDuringExecution两种类型。前者是硬性要求,必须满足,后者是偏好,尽量满足。用户的问题里提到“亲和多个node”,可能需要同时指定多个节点标签的条件,或者在多个标签中选择。 例如,用户可能希望Pod只能运行在带有“disk=ssd”或者“gpu=true”的节点上。这时候就需要在nodeAffinity的required中使用多个matchExpressions,或者使用多个matchExpressions的组合。需要注意的是,如果使用同一个operator,比如In,并且不同的key,那么这会被视为“与”的关系,即需要同时满足多个条件。但用户可能需要的是“或”的关系,这时候可能需要将条件分开放在不同的matchExpressions中,或者使用不同的拓扑域。 或者,用户可能想在一个规则中指定多个节点标签,比如同时考虑区域和实例类型。这时候需要确认如何组织这些条件。例如,使用多个matchExpressions,每个对应不同的key,这样多个条件会被视为“与”的关系,即节点必须满足所有条件。而如果希望是“或”的关系,可能需要将这些条件放在不同的term中,或者在同一个matchExpressions中使用多个值。 另外,用户可能混淆了节点亲和性和Pod亲和性,但这里明确提到的是节点亲和性,所以不需要考虑Pod之间的亲和性。 接下来,我需要考虑如何编写具体的配置示例。比如,在required情况下,如何同时要求多个标签,或者在preferred中设置多个偏好。同时,可能需要解释如何组合不同的运算符,如In、Exists等。 可能的误区是用户可能认为在同一个matchExpressions中添加多个值就是“或”的条件,但实际上在同一个matchExpressions中,多个值使用In运算符时,是“或”的关系,即满足其中一个值即可。而不同的matchExpressions之间是“与”的关系,即必须同时满足所有matchExpressions的条件。 例如,如果配置如下: matchExpressions: - key: disk operator: In values: - ssd - hdd 这表示节点的disk标签必须是ssd或hdd。而如果另一个matchExpressions是: - key: gpu operator: Exists 那么节点必须同时满足disk是ssd或hdd,并且存在gpu标签。 如果用户想要同时亲和多个不同的标签,比如希望节点有disk=ssd或者env=prod,这时候可能需要将它们放在不同的matchExpressions中,但这样会因为“与”的关系而无法满足。因此,正确的做法可能是将它们放在同一个matchExpressions中,但不同的key可能需要不同的处理方式,这时候可能需要使用多个nodeSelectorTerms,每个term中可以有不同的matchExpressions,这样terms之间是“或”的关系。 例如,在required规则中,可以这样写: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: disk operator: In values: [ssd] - matchExpressions: - key: env operator: In values: [prod] 这样,节点只需要满足其中一个nodeSelectorTerm即可,即disk=ssd或者env=prod。这就是“或”的条件。 这可能正是用户需要的,即同时亲和多个不同的节点标签,每个标签对应不同的节点。这时候,多个nodeSelectorTerms之间是“或”的关系,而每个term内的matchExpressions是“与”的关系。 因此,在配置多个节点亲和时,关键在于如何组织nodeSelectorTerms和matchExpressions的结构。用户可能需要将不同的条件放在不同的terms中来实现“或”的逻辑,而同一个term中的多个条件则是“与”的关系。 总结步骤: 1. 确定亲和性是必须满足还是优先满足(required或preferred)。 2. 根据需求组织matchExpressions和nodeSelectorTerms。 3. 使用多个nodeSelectorTerms来实现“或”的条件。 4. 测试配置是否符合预期。 最后,需要提醒用户正确添加节点标签,以及验证配置的方法,比如使用kubectl describe节点查看标签,使用kubectl apply部署Pod后检查调度情况。</think>在Kubernetes中,**节点亲和性(Node Affinity)** 用于控制Pod调度到特定节点的策略。当需要同时亲和多个节点时,可通过组合多种匹配条件或标签选择器实现。以下是详细配置方法和场景解析: --- ### 一、核心概念 1. **节点亲和性类型**: - `requiredDuringSchedulingIgnoredDuringExecution`:硬性规则,**必须满足**条件才会调度。 - `preferredDuringSchedulingIgnoredDuringExecution`:软性规则,**优先尝试**满足条件,但不保证。 2. **匹配逻辑**: - **同一`nodeSelectorTerm`内的多个条件**:使用逻辑 **AND**(需全部满足)。 - **多个`nodeSelectorTerm`**:使用逻辑 **OR**(满足任意一个即可)。 --- ### 二、配置多节点亲和的示例 假设集群中有以下标签的节点: - 节点A:`env=prod, disk=ssd` - 节点B:`env=test, gpu=true` - 节点C:`env=prod, gpu=true` #### 场景1:Pod必须运行在**满足多个标签**的节点上 要求节点**同时具有** `env=prod` 和 `disk=ssd`(仅节点A符合): ```yaml affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: env operator: In values: [prod] - key: disk operator: In values: [ssd] ``` #### 场景2:Pod可运行在**多个标签满足其一**的节点上 要求节点具有 `env=prod` **或** `gpu=true`(节点A、B、C均符合): ```yaml affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: env operator: In values: [prod] - matchExpressions: - key: gpu operator: In values: [true] ``` #### 场景3:优先选择多个标签中的节点(软亲和) **优先**选择 `disk=ssd` 的节点,**次优**选择 `gpu=true` 的节点: ```yaml affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 60 # 权重越高优先级越高 preference: matchExpressions: - key: disk operator: In values: [ssd] - weight: 40 preference: matchExpressions: - key: gpu operator: In values: [true] ``` --- ### 三、操作步骤 1. **为节点打标签**: ```bash kubectl label nodes <node-name> env=prod kubectl label nodes <node-name> disk=ssd ``` 2. **验证节点标签**: ```bash kubectl describe node <node-name> ``` 3. **应用Pod配置**: ```bash kubectl apply -f pod-with-affinity.yaml ``` 4. **检查调度结果**: ```bash kubectl get pods -o wide ``` --- ### 四、关键注意事项 1. **运算符选择**: - `In`:标签值在列表中。 - `NotIn`:标签值不在列表中。 - `Exists`:标签键存在。 - `DoesNotExist`:标签键不存在。 2. **权重范围**:软亲和性中,`weight` 范围为 `1-100`,决定优先级。 3. **冲突处理**:硬亲和性规则若无法满足,Pod将处于`Pending`状态。 --- 通过合理组合`nodeSelectorTerms`和`matchExpressions`,可灵活实现Pod对多节点的亲和性调度需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值