k8s之pod亲和性与反亲和性的topologyKey

本文详细介绍了Kubernetes中Pod亲和性和反亲和性的概念,特别是topologyKey的作用。topologyKey用于定义Pod调度时的拓扑域,比如节点、机柜或机房等,通过节点标签来区分不同拓扑。例如,设置为'failure-domain.beta.kubernetes.io/zone'可以实现跨机房调度,确保高可用。同时,文章给出了配置示例,展示了如何利用topologyKey实现特定的调度策略。

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

什么是topology key

pod亲和性调度需要各个相关的pod对象运行于"同一位置", 而反亲和性调度则要求他们不能运行于"同一位置",

这里指定“同一位置” 是通过 topologyKey 来定义的,topologyKey 对应的值是 node 上的一个标签名称,比如各别节点zone=A标签,各别节点有zone=B标签,pod affinity topologyKey定义为zone,那么调度pod的时候就会围绕着A拓扑,B拓扑来调度,而相同拓扑下的node就为“同一位置”。

如果基于各个节点kubernetes.io/hostname标签作为评判标准,那么很明显“同一位置”意味着同一节点,不同节点既为不同位置,
一般用于:

 

1. 我启动一个pod,希望(亲和性)或不希望(反亲和性)调度一台node上,并且这台node上有service=nginx标签的pod
2. 我启动一个2个副本控制器,pod标签为service=tomcat,可以调度到任意node上,不希望两个pod调度到同一个node上

个人理解:pod affinity的调度范围为topology

官方解释:
如果该X已经在运行一个或多个满足规则Y的Pod,则该Pod应该(或者在非亲和性的情况下不应该)在X中运行

Y表示为LabelSelector规则
X是一个拓扑域,例如节点,机架,云提供者区域,云提供者区域等。您可以使用topologyKey这是系统用来表示这种拓扑域的节点标签的密钥

例子:

需求:当前有两个机房( beijing,shanghai),需要部署一个nginx产品,副本为两个,为了保证机房容灾高可用场景,需要在两个机房分别部署一个副本

 

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nginx-affinity-test
spec:
  serviceName: nginx-service
  replicas: 2
  selector:
    matchLabels:
      service: nginx
  template:
    metadata:
      name: nginx
      labels:
        service: nginx
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: service
                operator: In
                values:
                - nginx
            topologyKey: zone
      containers:
      - name: nginx
        image: contos7:latest
        command:
        - sleep
        - "360000000"

 

解释:两个node上分别有zone标签,来标注自己属于哪个机房,topologyKey定义为zone,pod所以在调度的时候,会根据node上zone标签来区分拓扑域,当前用的上 反亲和性调度 根据拓扑纬度调度,beijing机房调度完一个pod后,然后控制器判断beijing 拓扑域已经有server=nginx标签的pod,就在下一个拓扑域的node上调度了

Pod亲和性与反亲和性

Pod 间的亲和性与反亲和性根据已经在 Node 上运行的 Pod 的标签来调度新的 Pod 到哪个 Node 上,这些规则的形式是:

如果 X 已经运行一个或多个符合规则 Y 的 Pod,那么这个 Pod 应该(如果是反亲和性,则不应该)运行在 X 上。

和 Node不同,由于 Pod 都是有命名空间的,所以基于 Pod 标签的标签选择器(Label Selector)必须指定命名空间。可以通过 namespaces(与 labelSelector 和 topologyKey 同一级) 指定,默认情况下为拥有亲和性(或反亲和性)的 Pod 所属的命名空间,如果定义了 namespaces 但值是空的,则表示使用 all 命名空间。

那么,我需要 Pod 亲和性或反亲和性的同时,又能指定 Pod 调度到某个 Node 该如何处理呢?这就要用到接下来讲的 topologyKey 了。

什么是topologyKey

顾名思义,topology 就是 拓扑 的意思,这里指的是一个 拓扑域,是指一个范围的概念,比如一个 Node、一个机柜、一个机房或者是一个地区(如杭州、上海)等,实际上对应的还是 Node 上的标签。这里的 topologyKey 对应的是 Node 上的标签的 Key(没有Value),可以看出,其实 topologyKey 就是用于筛选 Node 的。通过这种方式,我们就可以将各个 Pod 进行跨集群、跨机房、跨地区的调度了。

如何使用topologyKey

看下面的例子:

apiVersion: v1
kind: Pod
metadata:
  name: with-pod-affinity
spec:
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: security
            operator: In
            values:
            - S1
        topologyKey: failure-domain.beta.kubernetes.io/zone
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: security
              operator: In
              values:
              - S2
          topologyKey: kubernetes.io/hostname
  containers:
  - name: with-pod-affinity
    image: k8s.gcr.io/pause:2.0

这里 Pod 的亲和性规则是:这个 Pod 要调度到的 Node 必须有一个标签为 security: S1 的 Pod,且该 Node 必须有一个 Key 为 failure-domain.beta.kubernetes.io/zone 的 标签,即 Node 必须属于 failure-domain.beta.kubernetes.io/zone 拓扑域。

Pod 的反亲和性规则是:这个 Pod 尽量不要调度到这样的 Node,其包含一个 Key 为 kubernetes.io/hostname 的标签,且该 Node 上有标签为 security: S2 的 Pod。

topologyKey详解

既然 topologyKey 是拓扑域,那 Pod 之间怎样才是属于同一个拓扑域?

如果使用 k8s.io/hostname,则表示拓扑域为 Node 范围,那么 k8s.io/hostname 对应的值不一样就是不同的拓扑域。比如 Pod1 在 k8s.io/hostname=node1 的 Node 上,Pod2 在 k8s.io/hostname=node2 的 Node 上,Pod3 在 k8s.io/hostname=node1 的 Node 上,则 Pod2 和 Pod1、Pod3 不在同一个拓扑域,而Pod1 和 Pod3在同一个拓扑域。

如果使用 failure-domain.k8s.io/zone ,则表示拓扑域为一个区域。同样,Node 的标签 failure-domain.k8s.io/zone 对应的值不一样也不是同一个拓扑域,比如 Pod1 在 failure-domain.k8s.io/zone=beijing 的 Node 上,Pod2 在 failure-domain.k8s.io/zone=hangzhou 的 Node 上,则 Pod1 和 Pod2 不属于同一个拓扑域。

当然,topologyKey 也可以使用自定义标签。比如可以给一组 Node 打上标签 custom_topology,那么拓扑域就是针对这个标签了,则该标签相同的 Node 上的 Pod 属于同一个拓扑域。

注意事项

原则上,topologyKey 可以是任何合法的标签 Key。但是出于性能和安全原因,对 topologyKey 有一些限制:

  1. 对于亲和性和 requiredDuringSchedulingIgnoredDuringExecution 的 Pod 反亲和性,topologyKey 不能为空。
  2. 对于 requiredDuringSchedulingIgnoredDuringExecution 的 Pod 反亲和性,引入 LimitPodHardAntiAffinityTopology 准入控制器来限制 topologyKey 只能是 kubernetes.io/hostname。如果要使用自定义拓扑域,则可以修改准入控制器,或者直接禁用它。
  3. 对于 preferredDuringSchedulingIgnoredDuringExecution 的 Pod 反亲和性,空的 topologyKey 表示所有拓扑域。截止 v1.12 版本,所有拓扑域还只能是 kubernetes.io/hostnamefailure-domain.beta.kubernetes.io/zone 和 failure-domain.beta.kubernetes.io/region 的组合。
  4. 除上述情况外,topologyKey 可以是任何合法的标签 key。

参考

<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]。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值