【kubernetes】-5节点的亲和与反亲和

集群调度

1、kubernetes 调度机制

各组件(如 controller-managerschedulerkubelet)通过监听 API Server 事件协同工作。

1.1 default-scheduler 调度策略

1.1.1 预选策略(predicates):过滤不满足条件的节点
  • PodFitsResources:检查节点剩余资源是否满足 requests
  • PodFitsHostPorts:检查节点端口是否冲突。
  • NoDiskConflict:检查存储卷冲突。
1.1.2 优选策略(Priorities):计算节点优先级。
  • LeastRequestedPriority:优先选择资源利用率低的节点。
  • BalancedResourceAllocation:优先选择 CPU/内存使用均衡的节点。
  • ImageLocalityPriority:优先选择已缓存镜像的节点。
1.1.3 打分评定最终调度节点

2、简单标签操作命令

# 添加/修改标签
kubectl label -n <namespace> <resource-type> <resource-name> key=value [--overwrite]

# 删除标签
kubectl label -n <namespace> <resource-type> <resource-name> key-

# 查看标签
kubectl get <resource-type> -n <namespace> --show-labels
kubectl get <resource-type> -n <namespace> -l key=value

2.1 指定node节点部署pod

  1. nodeName:直接指定节点名称。
spec:
  nodeName: node01
  1. nodeSelector:通过节点标签选择。
spec:
  nodeSelector:
    disktype: ssd
  1. 亲和性(Affinity)
  • 节点亲和性:匹配节点标签。
  • Pod 亲和性/反亲和性:匹配其他 Pod 的标签。
  1. 污点与容忍(Taint & Toleration)
  • 节点设置污点(kubectl taint nodes node01 key=value:NoSchedule)。
  • Pod 配置容忍以调度到污点节点。

3、kube-scheduler

3.1 调度过程

Kubernetes 的调度器(Scheduler)负责将定义的 Pod 分配到集群的节点上。调度过程主要关注公平性、资源高效利用、效率和灵活性。调度器运行为一个独立的程序,持续监听 APIServer,并处理 spec.nodeName 为空的 Pod。
调度过程分为以下几个步骤:

Kubernetes 的调度器(Scheduler)负责将定义的 Pod 分配到集群的节点上。调度过程主要关注公平性、资源高效利用、效率和灵活性。调度器运行为一个独立的程序,持续监听 APIServer,并处理 spec.nodeName 为空的 Pod。
调度过程分为以下几个步骤:

  1. Predicate(过滤阶段)

    • 调度器首先会过滤掉不满足条件的节点。
    • 常见的 Predicate 算法包括:PodFitsResources(检查节点资源是否足够)、PodFitsHost(检查节点名称是否与 Pod 指定的 NodeName 匹配)、PodFitsHostPorts(检查节点端口是否与 Pod 请求的端口冲突)、PodSelectorMatches(过滤掉与 Pod 指定的 label 不匹配的节点)和 NoDiskConflict(检查已挂载的 volume 是否与 Pod 指定的 volume 冲突)。
  2. Priorities(优选阶段)

    • 如果有多个节点满足条件,调度器会根据优先级对节点进行排序。
    • 优先级由一系列键值对组成,表示不同的优先级项目和其权重。
    • 常见的优先级选项包括:LeastRequestedPriority(倾向于资源使用比例更低的节点)、BalancedResourceAllocation(倾向于 CPU 和 Memory 使用率更接近的节点)和 ImageLocalityPriority(倾向于已经有要使用镜像的节点)。
  3. Binding(绑定阶段)

    • 调度器选择优先级最高的节点,并创建一个 binding,表明该 Pod 应该被调度到哪个节点上。

3.1 Kubernetes Scheduler 工作原理

Scheduler 是 Kubernetes 的核心组件,负责将 Pod 分配到集群的合适节点上。其调度过程主要关注以下方面:

  • 公平性:确保每个节点都能被分配资源。
  • 资源高效利用:最大化集群资源的利用率。
  • 效率:快速调度大批量的 Pod。
  • 灵活性:允许用户根据需求自定义调度逻辑。

Scheduler 启动后会持续监听 APIServer,获取 spec.nodeName 为空的 Pod,并为每个 Pod 创建一个 binding,指明其应部署的节点。

3.2 示例操作 :指定节点调度

使用 nodeName 指定调度节点

  • 创建一个 Deployment,指定 nodeNamenode01
  • 应用 YAML 文件后,所有 Pod 都会被调度到 node01 上。
  • 通过 kubectl describe pod 查看 Pod 事件,发现未经过 Scheduler 调度分配。

使用 pod.spec.nodeName

  • 通过在 Pod 定义中指定 nodeName,可以直接将 Pod 调度到指定的节点上,这会跳过调度器的调度策略。
  • 示例 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

3.3 修改和删除label

  • 使用 kubectl label 命令修改和删除节点标签。
  • 修改节点的 label 需要使用 --overwrite 参数:
kubectl label nodes node02 myname=a --overwrite

删除节点的 label 只需在命令行最后指定 label 的 key 名,并在其后加上减号:

kubectl label nodes node02 myname-

可以使用 -l 参数根据 label 查询节点:

kubectl get node -l myname=a

4、亲和性和反亲和性

4.1 node节点亲和性概述

在 Kubernetes 中,亲和性(Affinity)和反亲和性(Anti-Affinity)用于定义 Pod 调度到节点的规则。主要分为两类:

  1. 节点亲和性(Node Affinity):定义 Pod 与节点的关系。
  2. Pod 亲和性(Pod Affinity)Pod 反亲和性(Pod Anti-Affinity):定义 Pod 与 Pod 之间的关系。

每种亲和性都可以进一步细分为硬策略和软策略:

  • 硬策略(requiredDuringSchedulingIgnoredDuringExecution):必须满足的条件,不满足则 Pod 无法调度。
  • 软策略(preferredDuringSchedulingIgnoredDuringExecution):优先满足的条件,不满足时仍会调度 Pod,但会尽量满足。

4.2 键值运算关系

在定义亲和性规则时,可以使用以下键值运算关系:

  • In:label 的值在某个列表中
  • NotIn:label 的值不在某个列表中
  • Gt:label 的值大于某个值(数值比较)
  • Lt:label 的值小于某个值(数值比较)
  • Exists:某个 label 存在
  • DoesNotExist:某个 label 不存在

示例

4.2.1 节点亲和硬策略
apiVersion: v1
kind: Pod
metadata:
  name: affinity
  labels:
    app: node-affinity-pod
spec:
  containers:
  - name: with-node-affinity
    image: soscscs/myapp:v1
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/hostname
            operator: NotIn
            values:
            - node02

可见该文件中定义了一个 Pod,要求该Pod调度到 kubernetes.io/hostname 不为 node02 的节点上。
如果所有节点都不满足条件,Pod 将一直处于 Pending 状态。

4.2.2 节点亲和软策略
apiVersion: v1
kind: Pod
metadata:
  name: affinity
  labels:
    app: node-affinity-pod
spec:
  containers:
  - name: with-node-affinity
    image: soscscs/myapp:v1
  affinity:
    nodeAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: kubernetes.io/hostname
            operator: In
            values:
            - node01

这个文件中定义了的Pod,被优先调度到 kubernetes.io/hostnamenode01 的节点上。
但不满足时也会调度到其他节点。

4.2.3 硬策略和软策略结合
apiVersion: v1
kind: Pod
metadata:
  name: affinity
  labels:
    app: node-affinity-pod
spec:
  containers:
  - name: with-node-affinity
    image: soscscs/myapp:v1
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/hostname
            operator: NotIn
            values:
            - node02
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: myname
            operator: In
            values:
            - a

这个文件定义的 Pod,首先要求调度到 kubernetes.io/hostname 不为 node02 的节点上,然后在满足硬策略的基础上,优先调度到 mynamea 的节点上。

4.3 pod的亲和性和反亲和性

Pod 亲和性(Pod Affinity)和反亲和性(Pod Anti-Affinity)是用于定义 Pod 调度策略的两种机制。
可以使 Pod 可以根据其他 Pod 的标签和位置来决定自己的调度位置。

调度策略与匹配标签

  • nodeAffinity:基于节点的标签进行调度。不支持拓扑域。
  • podAffinity:基于其他 Pod 的标签进行调度,并支持拓扑域。
  • podAntiAffinity:基于其他 Pod 的标签进行调度,但要求不在同一拓扑域。

操作符与拓扑域支持

  • 操作符In, NotIn, Exists, DoesNotExist, Gt, Lt(对于 nodeAffinity 的特定场景)。
  • 拓扑域支持:podAffinity 和 podAntiAffinity 支持拓扑域,通过 topologyKey 指定。

4.4 实际调度

  1. 给节点打标签

    kubectl label nodes node01 myname=a
    kubectl label nodes node02 myname=a
    
  2. 创建第一个 Pod

    apiVersion: v1
    kind: Pod
    metadata:
      name: myapp01
      labels:
        app: myapp01
    spec:
      containers:
      - name: with-node-affinity
        image: soscscs/myapp:v1
    
    kubectl apply -f pod3.yaml
    
  3. 使用 Pod 亲和性调度第二个 Pod

    apiVersion: v1
    kind: Pod
    metadata:
      name: myapp02
      labels:
        app: myapp02
    spec:
      containers:
      - name: myapp02
        image: soscscs/myapp:v1
      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - myapp01
            topologyKey: myname
    
    kubectl apply -f pod4.yaml
    
    • myapp02 将被调度到与 myapp01 相同的拓扑域(myname=a 的节点)上。
  4. 使用 Pod 反亲和性调度第三个 Pod

    • 示例 1:首选调度(Preferred)

      apiVersion: v1
      kind: Pod
      metadata:
        name: myapp10
        labels:
          app: myapp10
      spec:
        containers:
        - name: myapp10
          image: soscscs/myapp:v1
        affinity:
          podAntiAffinity:
            preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 100
              podAffinityTerm:
                labelSelector:
                  matchExpressions:
                  - key: app
                    operator: In
                    values:
                    - myapp01
                topologyKey: kubernetes.io/hostname
      
      kubectl apply -f pod5.yaml
      
      • myapp10 将尽量避免与 myapp01 在同一节点上调度(kubernetes.io/hostname 表示节点级别)。
    • 示例 2:强制调度(Required)

      apiVersion: v1
      kind: Pod
      metadata:
        name: myapp20
        labels:
          app: myapp20
      spec:
        containers:
        - name: myapp20
          image: soscscs/myapp:v1
        affinity:
          podAntiAffinity:
            requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - myapp01
              topologyKey: myname
      
      kubectl apply -f pod6.yaml
      
      • myapp20 强制要求不在与 myapp01 相同的拓扑域上调度。如果所有节点都在同一拓扑域,Pod 将保持 Pending 状态。
  5. 调整节点标签以允许调度

    kubectl label nodes node02 myname=b --overwrite
    
    • 修改 node02 的标签后,myapp20 可以被调度到 node02 上,因为它现在处于不同的拓扑域。

4.5 总结

三种亲和性类型

类型定义策略
Node Affinity根据节点的标签,将 Pod 调度到满足条件的节点上。- 硬策略 (requiredDuringSchedulingIgnoredDuringExecution):必须满足条件,否则 Pod 处于 Pending 状态。
- 软策略 (preferredDuringSchedulingIgnoredDuringExecution):优先满足条件,不满足仍可调度。
Pod Affinity根据同一命名空间下其他 Pod 的标签,将 Pod 调度到与指定 Pod 在同一拓扑域的节点上。- 硬策略:必须与指定 Pod 在同一拓扑域。
- 软策略:优先与指定 Pod 在同一拓扑域。
Pod Anti-Affinity根据同一命名空间下其他 Pod 的标签,将 Pod 调度到与指定 Pod 不同拓扑域的节点上。- 硬策略:必须与指定 Pod 在不同拓扑域。
- 软策略:优先与指定 Pod 在不同拓扑域。

拓扑域判断规则

亲和性类型规则topologyKey 作用示例 topologyKey
Pod AffinityPod 必须或优先调度到与目标 Pod 同一拓扑域的节点上。通过节点标签的键(如 kubernetes.io/hostname)判断是否属于同一逻辑域(如同一主机、可用区)。- kubernetes.io/hostname(节点主机名)
- failure-domain.beta.kubernetes.io/zone(可用区)
Pod Anti-AffinityPod 必须或优先调度到与目标 Pod 不同拓扑域的节点上。通过节点标签的键确定逻辑域,确保 Pod 分布在不同域中以提高容灾能力。- kubernetes.io/hostname
- topology.kubernetes.io/region(区域)
Node Affinity不依赖 topologyKey,直接通过节点标签匹配调度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值