Pod的亲和性和反亲和性

文章详细介绍了Kubernetes中pod的亲和性、反亲和性配置,以及如何使用拓扑域和污点容忍机制来优化资源调度。通过硬策略和软策略展示了pod的亲和性配置,同时探讨了污点和容忍在避免节点故障影响业务部署中的作用。

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

 如何部署pod是重要的集群的调度机制,合理的配置pod调度机制可以实现资源最大化利用。

调度策略匹配标签操作符拓扑域调度目标
node的亲和性主机标签In、NotIn、Exists、DoesNotExist、Gt、Lt不支持指定主机
pod的亲和性pod的标签In、NotIn、Exists、DoesNotExist支持pod和指定标签的pod部署在同一拓扑域中
pod的反亲和性pod的标签In、NotIn、Exists、DoesNotExist支持pod和指定标签的pod部署在不同的拓扑域中

 

拓扑域:k8s集群节点当中的一个组织结构,可以更具节点的物理关系或者逻辑关系进行划分。可以用来表示节点之间的空间关系。网络关系或者其他类型的关系。

这里的亲和性反亲和性都指的是标签。

node匹配的是主机的标签而pod匹配的是pod自己的标签

策略部署实验

 这里使用硬策略

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: nginx2
  name: nginx2
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx2
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx2
    spec:
      containers:
      - image: nginx:1.22
        name: nginx2
      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - nginx
            topologyKey: test1
#topologyKey:指定拓扑域的关键字段
#表示我正在使用test1作为拓扑域的关键字
#这个test1一般是节点标签。
#表示希望把pod调度到包含有app标签的pod。他的值为nginx在test1的拓扑域上的节点

使用Exists包含类型:

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: nginx2
  name: nginx2
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx2
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx2
    spec:
      containers:
      - image: nginx:1.22
        name: nginx2
      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: Exists
            topologyKey: test1
#topologyKey:指定拓扑域的关键字段
#表示我正在使用test1作为拓扑域的关键字
#这个test1一般是节点标签。
#表示希望把pod调度到包含有app标签的pod。他的值为nginx在test1的拓扑域上的节点

使用DoesNotExist不包含:

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    test: nginx
  name: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      test: nginx
  template:
    metadata:
      creationTimestamp: null
      labels:
        test: nginx
    spec:
      containers:
      - image: nginx:1.22
        name: nginx
      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: DoesNotExist
            topologyKey: test3
#topologyKey:指定拓扑域的关键字段
#表示我正在使用test1作为拓扑域的关键字
#这个test1一般是节点标签。
#表示希望把pod调度到包含有app标签的pod。他的值为nginx在test1的拓扑域上的节点
#这里DoesNotExists表示不包含key值为app还必须满足在包含test1的拓扑域中

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    test: nginx2
  name: nginx2
spec:
  replicas: 3
  selector:
    matchLabels:
      test: nginx2
  template:
    metadata:
      creationTimestamp: null
      labels:
        test: nginx2
    spec:
      containers:
      - image: nginx:1.22
        name: nginx2
      affinity:
        podAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 1
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                 - key: app
                   operator: DoesNotExist
              topologyKey: test1

pod的反亲和性

这里使用软策略:

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    test: nginx2
  name: nginx2
spec:
  replicas: 3
  selector:
    matchLabels:
      test: nginx2
  template:
    metadata:
      creationTimestamp: null
      labels:
        test: nginx2
    spec:
      containers:
      - image: nginx:1.22
        name: nginx2
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 1
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                 - key: app
                   operator: In
                   values:
                   - nginx1
              topologyKey: test1

这里使用硬策略:

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    test: nginx2
  name: nginx2
spec:
  replicas: 3
  selector:
    matchLabels:
      test: nginx2
  template:
    metadata:
      creationTimestamp: null
      labels:
        test: nginx2
    spec:
      containers:
      - image: nginx:1.22
        name: nginx2
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - nginx1
            topologyKey: test1

特点:

  1. pod的亲和性策略。在配置时,必须要加上拓扑域的关键字topologkey指向的是节点标签

  2. pod亲和性的策略也分为硬策略和软策略

  3. pod亲和性的notin可以替代反亲和性

  4. pod亲和性主要是为了把相关联的pod组件部署在同一节点上。例如:LNMP

污点和容忍

污点和容忍可以配合node的亲和性一起使用。

污点是node的调用机制。不是pod的

被设置为污点的节点不会部署pod

污点和亲和性相反。亲和性是尽量选择和一定选择。

污点的节点一定不被选择。

taint(污点)有三种策略:

  1. NoSchedule:k8s不会把pod调度到这个节点上。

  2. PreferNoSchedule:这个污点类型表示尽量避免把pod部署在该节点上。不是一定(master节点的污点就是这个类型在一定程度上提高资源利用率)

  3. NoExecute:这个污点类型表示k8s将会把该节点上的pod驱逐出去。也不会调度到这个节点。

基于控制器创建的pod虽然被驱逐,但是会在其他节点上重新部署。

如果是自主pod将会被直接杀死

过滤污点

kubectl describe nodes master01 | grep -i taints
#查看污点

kubectl taint nodes 主机名 node-role.kubernetes.io/master:NoSchedule-
#过滤并删除污点

设置污点

kubectl taint node node01 key=1:NoSchedule
#key=1设置标签的值
#:NoSchedule并将这个值与污点做映射

kubectl taint node node01 key:NoSchedule-
#删除污点

PreferNoSchedule

kubectl taint node node02 key=1:PreferNoSchedule

NoExecute(驱逐):

kubectl taint node node02 key=1:NoExecute

所有的pod都会被驱逐和命名空间无关。所有的pod都会被驱逐。只有组件pod还在。

不论创建方式是什么都会被驱逐。系统集群组件不会被驱逐。

所有的pod都会被驱逐和命名空间无关。所有的pod都会被驱逐。基于控制器创建的pod会驱逐到其他节点上重新部署。自主创建的将直接被杀死。系统集群组件不会被驱逐。

容忍

即使节点上设置了污点。有了容忍机制,依然可以在设置为污点的节点上部署pod

配置容忍

容忍NoSchedule举例:

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    test: nginx2
  name: nginx2
spec:
  replicas: 6
  selector:
    matchLabels:
      test: nginx2
  template:
    metadata:
      creationTimestamp: null
      labels:
        test: nginx2
    spec:
      containers:
      - image: nginx:1.22
        name: nginx2
      tolerations:
#tolerations:表示容忍
      - key: key
#这里的key是节点的标签名
        operator: Equal
        value: "1"
        effect: NoSchedule
#effect:表示对应的污点类型。必须要和节点的污点保持一致
#表示容忍节点上的标签是key。对应的标签值是1

容忍NoExecute举例:

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    test: nginx2
  name: nginx2
spec:
  replicas: 6
  selector:
    matchLabels:
      test: nginx2
  template:
    metadata:
      creationTimestamp: null
      labels:
        test: nginx2
    spec:
      containers:
      - image: nginx:1.22
        name: nginx2
      tolerations:
      - key: key
#tolerations:表示容忍
#这里的key是节点的标签名
        operator: Equal
        value: "1"
        effect: NoExecute
        tolerationSeconds: 36
#effect:表示对应的污点类型。必须要和节点的污点保持一致
#表示容忍节点上的标签是key。对应的标签值是1
#tplerationSeconds:设置节点可以容忍多长时间。

设置容忍策略36秒后

时间到期后将会销毁并且拉起新的容器

特殊情况:NoExecute依然可以部署pod但是有生命周期。时间一到pod将会被销毁。生命周期结束之后,会驱逐一部分pod到其他节点。

用于该节点维护完毕,测试以下节点的工作是否正常

不指定key实验举例:

 

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    test: nginx2
  name: nginx2
spec:
  replicas: 3
  selector:
    matchLabels:
      test: nginx2
  template:
    metadata:
      creationTimestamp: null
      labels:
        test: nginx2
    spec:
      containers:
      - image: nginx:1.22
        name: nginx2
      tolerations:
      - operator: Exists
        effect: NoSchedule
#如果没有声明key和value。将会容忍所有污点的key。
#key对应节点的污点类型是NoSchedule

没有key。他不会匹配节点的标签。他会容忍所有污点。但是类型是指定的类型。

指定key不指定effect实验举例:

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    test: nginx2
  name: nginx2
spec:
  replicas: 3
  selector:
    matchLabels:
      test: nginx2
  template:
    metadata:
      creationTimestamp: null
      labels:
        test: nginx2
    spec:
      containers:
      - image: nginx:1.22
        name: nginx2
      tolerations:
      - key: key
        operator: Exists
#指定key没有设置effect:容忍污点的类型
#他将会容忍所有节点的所有污点类型

指定节点的标签值。但是不指定污点类型。那么所有节点上只要包含了这个指定的标签名,那么它可以容忍所有的污点

pod的亲和性和反亲和性以及污点和容忍的作用就是通过判断条件选择node节点来部署pod。选择一个期望的节点来部署pod

多个master节点的情况:

,node-role.kubernetes.io/master=:PreferNoSchedule
#尽量不往master节点上部署pod。但是不是一定。这样可以防止资源浪费。同样也可也自定义一个标签。

业务维护的情况:

当node02需要维护两个小时,但是节点上还有业务pod在运行。

这个时候就需要把这个节点的污点设置为:NoExecute(驱逐)污点类型。

我们部署pod一般都是使用deployment部署,会在其他的节点重启杀死,并不是被杀死

但是自主式的pod会被删除

一旦节点恢复就把污点去除

cordon和drain

cordon

cordon:可以直接把节点标记为不可用状态

kubectl cordon 节点名称
#直接把节点标记为不可用状态

kubectl uncordon 节点名称
#取消标记为不可用状态

 

drain

drain:排水。把节点下的pod全部转移到其他的node节点上运行。

  1. 一旦执行了drain。被执行的节点会变成不可调度状态。

  2. 会驱逐该节点上的所有pod

kubectl drain 节点名称 --ignore-daemonsets --delete-local-data --force
#drain:开始标记node节点为不可调度。然后驱逐pod
#--ignore-daemonsets:表示忽视。会无视daemonsets部署的pod。他还会在原节点上。
#--delete-local-data:如果有本地挂载卷的pod将会被强制杀死
#--force:强制释放不是控制器管理的pod
#是控制器创建的将会被驱逐。不是控制器创建的将会被杀死
#daemonsets一般部署的都是重要的后台系统pod。所以会忽略

kubectl uncordon 节点名称
#取消标记驱逐节点

 

<think>我们正在讨论Kubernetes中的Pod亲和性(affinity)反亲和性(anti-affinity)规则及其配置方法。根据用户的问题,我们需要解释这两个概念,并展示如何配置它们。亲和性反亲和性Kubernetes调度机制的一部分,允许用户指定Pod如何被调度到节点上,例如将Pod调度到与某些其他Pod相同或不同的节点(或拓扑域)上。亲和性有两种类型:-nodeaffinity:类似于节点选择器,但功能更强大。-podaffinity/anti-affinity:根据其他Pod的标签来调度Pod。用户询问的是podaffinityanti-affinity。配置方法:在Pod的spec中,有一个`affinity`字段,其中包含`podAffinity``podAntiAffinity`两个子字段。关键概念:-拓扑域(topologyKey):用于定义拓扑域(例如节点、机架、云供应商区域等)的节点标签的键。调度器将根据这个键的值来划分拓扑域。-标签选择器(labelSelector):用于选择具有特定标签的Pod。规则类型:-requiredDuringSchedulingIgnoredDuringExecution:硬规则,必须满足。-preferredDuringSchedulingIgnoredDuringExecution:软规则,调度器会尽量满足,但不保证。配置示例:假设我们有两个应用:appAappB,我们希望appA的Pod尽量appB的Pod在同一个拓扑域(例如同一个节点)中运行(亲和性),而appA的Pod之间尽量分散在不同的拓扑域(反亲和性)。示例1:Pod亲和性podAffinity)要求将Pod调度到已经运行了标签为`app=appB`的Pod的节点上(同一个拓扑域)。示例2:Pod反亲和性podAntiAffinity)要求将Pod调度到没有运行标签为`app=appA`的Pod的节点上(避免同一个节点上有多个appA的Pod)。注意:反亲和性常用于避免单点故障(例如将同一应用的Pod分散到不同节点)。下面我们给出一个Pod的yaml配置示例,其中同时包含亲和性反亲和性规则。注意:在配置拓扑域时,需要确保节点上有相应的标签。例如,默认的拓扑域标签是`kubernetes.io/hostname`(节点级别),也可以使用其他标签如区域(zone)等。示例配置:```yamlapiVersion:v1kind:Podmetadata:name:appA-podlabels:app:appAspec:affinity:podAffinity:requiredDuringSchedulingIgnoredDuringExecution:-labelSelector:matchExpressions:-key:appoperator:Invalues:-appBtopologyKey:kubernetes.io/hostnamepodAntiAffinity:preferredDuringSchedulingIgnoredDuringExecution:-weight:100podAffinityTerm:labelSelector:matchExpressions:-key:appoperator:Invalues:-appAtopologyKey:kubernetes.io/hostnamecontainers:-name:appA-containerimage:appA-image```解释:-podAffinity:要求该Pod必须调度到运行了appBPod的节点上(通过标签选择器匹配app=appB,拓扑域为节点)。-podAntiAffinity:倾向于将该Pod调度到没有运行appAPod的节点上(即避免同一个节点上有多个appA的Pod)。这里使用了软规则(preferred),权重为100(在多个软规则中,权重用于区分优先级)。注意事项:1.硬规则(required)必须满足,否则Pod会一直处于Pending状态。2.软规则(preferred)不保证一定满足,但调度器会尽量满足。3.拓扑域的选择:如果使用`kubernetes.io/hostname`,则拓扑域是单个节点。如果使用`topology.kubernetes.io/zone`,则拓扑域是整个可用区。另外,Kubernetes还支持命名空间的选择。默认情况下,亲和性规则只考虑同一个命名空间中的Pod。如果要跨命名空间,可以在`podAffinity`或`podAntiAffinity`中指定`namespaces`字段,或者使用`namespaceSelector`。例如,要选择所有命名空间中标签为`app=appB`的Pod,可以这样配置:```yamlpodAffinity:requiredDuringSchedulingIgnoredDuringExecution:-labelSelector:matchExpressions:-key:appoperator:Invalues:-appBnamespaces:[]#空列表表示所有命名空间topologyKey:kubernetes.io/hostname```或者使用`namespaceSelector`选择特定命名空间:```yamlpodAffinity:requiredDuringSchedulingIgnoredDuringExecution:-labelSelector:matchExpressions:-key:appoperator:Invalues:-appBnamespaceSelector:matchLabels:kubernetes.io/metadata.name:namespace1#需要命名空间有标签topologyKey:kubernetes.io/hostname```注意:跨命名空间的亲和性规则需要谨慎使用,因为可能会影响调度性能。最后,我们引用一些Kubernetes官方文档的内容,但注意用户提供的引用中并没有直接关于亲和性的内容,所以我们不会直接引用它们。不过,我们可以参考官方文档的一般性说明。总结:-Pod亲和性用于将Pod调度到与某些Pod相同的拓扑域。-Pod反亲和性用于将Pod调度到与某些Pod不同的拓扑域。-配置时需要注意规则类型(硬规则/软规则)、标签选择器拓扑域。下面我们生成相关问题。</think>### Kubernetes Pod 亲和性反亲和性规则及配置 #### 一、核心概念 1. **Pod 亲和性 (Affinity)** 将 Pod 调度到**与指定标签 Pod 相同**的拓扑域(如节点、机架、可用区),适用于需要紧密协作的应用(如前端与缓存服务)。 2. **Pod 反亲和性 (Anti-affinity)** 将 Pod 调度到**与指定标签 Pod 不同**的拓扑域,适用于高可用场景(如避免单节点运行多个数据库实例)。 3. **拓扑域 (Topology Key)** 定义调度范围的关键节点标签(如 `kubernetes.io/hostname`=节点级,`topology.kubernetes.io/zone`=可用区级)。 #### 二、配置规则类型 | 规则类型 | 说明 | |----------------------------------------|----------------------------------------------------------------------| | `requiredDuringSchedulingIgnoredDuringExecution` | **硬规则**:必须满足,否则 Pod 处于 Pending 状态 | | `preferredDuringSchedulingIgnoredDuringExecution` | **软规则**:尽量满足,但不保证(通过 `weight` 设置优先级,范围 1-100)| #### 三、配置方法(YAML 示例) ##### 1. 亲和性配置:强制与 Redis 缓存同节点 ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: web-server spec: template: spec: affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: ["redis"] # 目标 Pod 标签 topologyKey: "kubernetes.io/hostname" # 拓扑域(节点级) containers: - name: nginx image: nginx:latest ``` ##### 2. 反亲和性配置:避免同节点运行多个数据库 ```yaml apiVersion: apps/v1 kind: StatefulSet metadata: name: mysql spec: template: spec: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: ["mysql"] # 避免自身副本同节点 topologyKey: "kubernetes.io/hostname" containers: - name: mysql image: mysql:8.0 ``` ##### 3. 混合配置:优先分散部署但允许例外 ```yaml affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 # 优先级权重 podAffinityTerm: labelSelector: matchExpressions: - key: app operator: In values: ["logstash"] topologyKey: "topology.kubernetes.io/zone" # 可用区级分散 ``` #### 四、关键参数详解 | 参数 | 说明 | |---------------------|----------------------------------------------------------------------| | `labelSelector` | 目标 Pod 的标签选择器(支持 `matchLabels` 或 `matchExpressions`) | | `operator` | 匹配操作符:`In`、`NotIn`、`Exists`、`DoesNotExist` | | `topologyKey` | 节点标签键,定义拓扑域范围(需预先存在于节点) | | `namespaces` | 可选,指定目标 Pod 的命名空间(默认当前命名空间) | #### 五、最佳实践 1. **拓扑域选择**: - 节点级:`kubernetes.io/hostname` - 可用区级:`topology.kubernetes.io/zone` - 自定义:如 `rack`(需提前标记节点) 2. **性能优化**: - 硬规则可能导致调度失败,优先使用软规则+权重 - 避免跨集群大范围拓扑匹配(影响调度速度) 3. **故障隔离**: ```yaml podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: critical-app operator: Exists # 匹配所有带此标签的 Pod topologyKey: "topology.kubernetes.io/zone" # 确保跨可用区部署 ``` > 引用说明:拓扑域需通过节点标签预定义[^2],硬规则可能导致 Pod 阻塞需监控调度状态[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值