K8s集群中的Pod调度约束亲和性与反亲和性

目录

一、pod生命周期

1.1.pod生命周期含义

1.2.Pod 生命周期/启动过程

二、调度约束

2.1.调度约束是什么

2.2.Pod 启动典型创建过程(工作机制)

三、调度过程介绍

3.1.Scheduler 是 kubernetes 的调度器

3.2. 调度策略

3.2.1 分类

3.2.2 Predicate(预选)常见算法

3.2.3 priorities(优选)常见算法

3.3.指定调度节点

3.3.1.nodeName 调度

3.3.2.nodeSelector 调度

 区别

3.4.k8s 节点的标签管理

3.5.node 亲和性

3.6. 节点亲和性(Node Affinity)

3.7.Pod 亲和性(Pod Affinity)

3.8.硬策略和软策略 

3.8.1.硬策略

3.8.2.软策略

3.9.键值运算关系

3.10.示例

3.10.1.node 硬策略

3.10.2.node 软策略 

3.10.3.node 软策略权重配置

3.10.4.node 硬策略软策略组合

3.10.5.node 硬策略软策略组合,硬策略条件不满足

3.11. Pod 亲和性与反亲和性

3.11.1. node 亲和性、pod 亲和性与反亲和性对比

3.11.2. 亲和性示例

3.11.3.反亲和性示例


一、pod生命周期

1.1.pod生命周期含义

Pod 的生命周期是指从 Pod 被创建到最终被销毁的整个过程,涉及多个阶段和状态转换,以及可能执行的各种操作。

1.2.Pod 生命周期/启动过程

收到kubectl指令-->初始化容器(init container),生成文件(init可以有多个,但是不可以同时运行)-->创建容器成功-->start容器-->readnessProbe(就绪性特征):就绪检测--> liveness Probe (存活性探针):生存检测-->stop容器 


    Pause 阶段:当 Pod 中的容器被暂停时,Pod 会进入 Pause 阶段。这通常发生在节点上发生调度变化时,为了确保容器状态的一致性,Pod 会被暂停并且等待恢复。

    Init 阶段:如果 Pod 中定义了 Init 容器,那么在主容器启动之前,Init 容器会先启动并执行其初始化任务。Pod 进入 Init 阶段直到所有 Init 容器都成功完成。

    应用启动阶段:一旦所有的 Init 容器成功完成,主容器将会启动并开始执行应用程序。

    存活阶段:Pod 中的容器正在运行,并且没有出现致命错误,此时 Pod 处于存活状态。

    就绪阶段:Pod 中的容器已经准备好接收流量。如果 Pod 中的所有容器都已经就绪,那么整个 Pod 就处于就绪状态,可以开始接收请求。

二、调度约束

2.1.调度约束是什么

Kubernetes 是通过 List-Watch 的机制进行每个组件的协作,保持数据同步的,每个组件之间的设计实现了解耦。

用户是通过 kubectl 根据配置文件,向 APIServer 发送命令,在 Node 节点上面建立 Pod 和 Container。
APIServer 经过 API 调用,权限控制,调用资源和存储资源的过程,实际上还没有真正开始部署应用。这里    需要 Controller Manager、Scheduler 和 kubelet 的协助才能完成整个部署过程。

在 Kubernetes 中,所有部署的信息都会写到 etcd 中保存。实际上 etcd 在存储部署信息的时候,会发送 Create 事件给 APIServer,而 APIServer 会通过监听(Watch)etcd 发过来的事件。其他组件也会监听(Watch)APIServer 发出来的事件。

2.2.Pod 启动典型创建过程(工作机制)

 

(1)这里有三个 List-Watch,分别是 Controller Manager(运行在 Master),Scheduler(运行在 Master),kubelet(运行在 Node)。 他们在进程已启动就会监听(Watch)APIServer 发出来的事件。

(2)用户通过 kubectl 或其他 API 客户端提交请求给 APIServer 来建立一个 Pod 对象副本。

(3)APIServer 尝试着将 Pod 对象的相关元信息存入 etcd 中,待写入操作执行完成,APIServer 即会返回确认信息至客户端。

(4)当 etcd 接受创建 Pod 信息以后,会发送一个 Create 事件给 APIServer。

(5)由于 Controller Manager 一直在监听(Watch,通过https的6443端口)APIServer 中的事件。此时 APIServer 接受到了 Create 事件,又会发送给 Controller Manager。

(6)Controller Manager 在接到 Create 事件以后,调用其中的 Replication Controller 来保证 Node 上面需要创建的副本数量。一旦副本数量少于 RC 中定义的数量,RC 会自动创建副本。总之它是保证副本数量的 Controller(PS:扩容缩容的担当)。

(7)在 Controller Manager 创建 Pod 副本以后,APIServer 会在 etcd 中记录这个 Pod 的详细信息。例如 Pod 的副本数,Container 的内容是什么。

(8)同样的 etcd 会将创建 Pod 的信息通过事件发送给 APIServer。

(9)由于 Scheduler 在监听(Watch)APIServer,并且它在系统中起到了“承上启下”的作用,“承上”是指它负责接收创建的 Pod 事件,为其安排 Node;“启下”是指安置工作完成后,Node 上的 kubelet 进程会接管后继工作,负责 Pod 生命周期中的“下半生”。 换句话说,Scheduler 的作用是将待调度的 Pod 按照调度算法和策略绑定到集群中 Node 上。

(10)Scheduler 调度完毕以后会更新 Pod 的信息,此时的信息更加丰富了。除了知道 Pod 的副本数量,副本内容。还知道部署到哪个 Node 上面了。并将上面的 Pod 信息更新至 API Server,由 APIServer 更新至 etcd 中,保存起来。

(11)etcd 将更新成功的事件发送给 APIServer,APIServer 也开始反映此 Pod 对象的调度结果。

(12)kubelet 是在 Node 上面运行的进程,它也通过 List-Watch 的方式监听(Watch,通过https的6443端口)APIServer 发送的 Pod 更新的事件。kubelet 会尝试在当前节点上调用 Docker 启动容器,并将 Pod 以及容器的结果状态回送至 APIServer。

(13)APIServer 将 Pod 状态信息存入 etcd 中。在 etcd 确认写入操作成功完成后,APIServer将确认信息发送至相关的 kubelet,事件将通过它被接受。

注意:

① 整个过程中,上方的命令、组件均通过 https 6443 监听 kube-apiserver 接口;

② 在创建 pod 的工作就已经完成了后,kubelet 依然保持监听。如:扩充 Pod 副本数量、镜像文件升级等需求。

三、调度过程介绍

3.1.Scheduler 是 kubernetes 的调度器

Scheduler 是 kubernetes 的调度器,主要的任务是把定义的 pod 分配到集群的节点上。其主要考虑的问题如下:
●公平:如何保证每个节点都能被分配资源
●资源高效利用:集群所有资源最大化被使用
●效率:调度的性能要好,能够尽快地对大批量的 pod 完成调度工作
●灵活:允许用户根据自己的需求控制调度的逻辑

Sheduler 是作为单独的程序运行的,启动之后会一直监听 APIServer,获取 spec.nodeName 为空的 pod,对每个 pod 都会创建一个 binding,表明该 pod 应该放到哪个节点上。

3.2. 调度策略

3.2.1 分类

预选策略:首先是过滤掉不满足条件的节点,这个过程称为预算策略(predicate);

优选策略:然后对通过的节点按照优先级排序,这个是优选策略(priorities);

优先级:最后从中选择优先级最高的节点。若中间步骤有误,返回错误。

3.2.2 Predicate(预选)常见算法

Predicate 是一种策略函数,用于评估节点是否适合放置特定的 Pod。Predicate 函数会检查节点的特性和 Pod 的要求,以确定是否可以将 Pod 放置在该节点上

PodFitsResources

   节点上剩余的资源是否大于 pod 请求的资源nodeName,检查节点名称是否和 NodeName 匹配。

PodFitsHost

  如果 pod 指定了 NodeName,检查节点名称是否和 NodeName 匹配。

PodFitsHostPorts

节点上已经使用的 port 是否和 pod 申请的 port 冲突。

PodSelectorMatches

过滤掉和 pod 指定的 label 不匹配的节点。 

NoDiskConflict

 已经 mount 的 volume 和 pod 指定的 volume 不冲突,除非它们都是只读。
如果在 predicate(预选)过程中没有合适的节点,pod 会一直在 pending(等待 running)状态,不断重试调度,直到有节点满足条件。 经过这个步骤,如果有多个节点满足条件,就继续 priorities(优选)过程:按照优先级大小对节点排序。 

3.2.3 priorities(优选)常见算法

优先级由一系列键值对组成,键是该优先级项的名称,值是它的权重(该项的重要性)。常见的优先级选项包括:

LeastRequestedPriority

  • 通过计算CPU和Memory的使用率来决定权重,使用率越低权重越高。也就是说,这个优先级指标倾向于资源使用比例更低的节点。

BalancedResourceAllocation

  • 节点上 CPU 和 Memory 使用率越接近,权重越高。这个一般和上面的一起使用,不单独使用。比如 node01 的 CPU 和 Memory 使用率 20:60,node02 的 CPU 和 Memory 使用率 50:50,虽然 node01 的总使用率比 node02 低,但 node02 的 CPU 和 Memory 使用率更接近,从而调度时会优选 node02。

ImageLocalityPriority

  • 倾向于已经有要使用镜像的节点,镜像总大小值越大,权重越高。

通过算法对所有的优先级项目和权重进行计算,得出最终的结果。

3.3.指定调度节点

3.3.1.nodeName 调度

pod.spec.nodeName 将 Pod 直接调度到指定的 Node 节点上,会跳过 Scheduler 的调度策略,该匹配规则是强制匹配

vim myapp.yaml
apiVersion: apps/v1  
kind: Deployment  
metadata:
  name: myapp
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      nodeName: node01
      containers:
      - name: myapp
        image: soscscs/myapp:v1
        ports:
        - containerPort: 80
		
kubectl apply -f myapp.yaml

kubectl get pods -o wide
NAME                     READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
myapp-6bc58d7775-6wlpp   1/1     Running   0          14s   10.244.1.25   node01   <none>           <none>
myapp-6bc58d7775-szcvp   1/1     Running   0          14s   10.244.1.26   node01   <none>           <none>
myapp-6bc58d7775-vnxlp   1/1     Running   0          14s   10.244.1.24   node01   <none>           <none>

//查看详细事件(发现未经过 scheduler 调度分配)
kubectl describe
<think>我们正在讨论Kubernetes中的Pod亲和性(affinity)和反亲和性(anti-affinity)规则及其配置方法。根据用户的问题,我们需要解释这两个概念,并展示如何配置它们。亲和性反亲和性Kubernetes调度机制的一部分,允许用户指定Pod如何被调度到节点上,例如将Pod调度某些其他Pod相同或不同的节点(或拓扑域)上。亲和性有两种类型:-nodeaffinity:类似于节点选择器,但功能更强大。-podaffinity/anti-affinity:根据其他Pod标签调度Pod。用户询问的是podaffinity和anti-affinity。配置方法:在Pod的spec中,有一个`affinity`字段,其中包含`podAffinity`和`podAntiAffinity`两个子字段。关键概念:-拓扑域(topologyKey):用于定义拓扑域(例如节点、机架、云供应商区域等)的节点标签的键。调度器将根据这个键的值来划分拓扑域。-标签选择器(labelSelector):用于选择具有特定标签Pod。规则类型:-requiredDuringSchedulingIgnoredDuringExecution:硬规则,必须满足。-preferredDuringSchedulingIgnoredDuringExecution:软规则,调度器会尽量满足,但不保证。配置示例:假设我们有两个应用:appA和appB,我们希望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、付费专栏及课程。

余额充值