k8s中的集群调度

文章目录

k8s中的集群调度

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

在 Kubernetes 集群中,Pod 是最小的部署单元,它包含一个或多个容器。Pod 的创建和调度是由 Kubernetes 的多个组件共同完成的,包括 API Server、Controller Manager、Scheduler 和 kubelet。本文将带您深入了解这一过程。

Pod 创建流程

  1. 用户请求 :用户通过 kubectl 或其他 API 客户端向 API Server 发送创建 Pod 的请求。
  2. 存储请求:API Server 将 Pod 的元数据存储到 etcd 中。一旦存储成功,API Server 向客户端确认请求完成。
  3. 事件通知:etcd 在存储操作完成后,会向 API Server 发送一个创建事件。
  4. Controller Manager 监听:Controller Manager 通过 List-Watch 机制监听 API Server 的事件。当它接收到 Pod 创建事件时,会检查是否有对应的 Replication Controller (RC) 或其他控制器来确保所需的 Pod 副本数量。
  5. 调度准备:如果 Pod 副本数量不足,Controller Manager 会创建新的 Pod 副本,并在 API Server 中记录详细信息。
  6. Scheduler 监听:Scheduler 也通过 List-Watch 机制监听 API Server 的事件。当它接收到新的 Pod 创建事件时,它将决定将该 Pod 调度到哪个 Node 上。
  7. 调度决策:Scheduler 根据一系列的调度算法和策略(如资源需求、节点亲和性等)来选择最佳的 Node。
  8. 绑定 Pod:Scheduler 更新 Pod 的信息,包括其被调度到的 Node,并将这些信息写回 API Server,由 API Server 更新到 etcd。
  9. kubelet 监听:在每个 Node 上运行的 kubelet 通过 List-Watch 机制监听 API Server,等待被调度到该 Node 上的 Pod 事件。
  10. 容器启动:当 kubelet 发现有一个新的 Pod 被调度到它所在的 Node 时,它会调用 Docker(或其他容器运行时)来启动 Pod 中的容器。
  11. 状态反馈:kubelet 将 Pod 及其容器的状态反馈给 API Server,API Server 再将这些状态信息存储到 etcd 中。

通过指定节点来创建pod所在的node节点

没有设置指定节点时会通过调度器来进行pod创建的调度

yaml 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web1
  labels:
    app: web1
spec:
  replicas: 4
  selector:
    matchLabels:
      app: web1
  template:
    metadata:
      labels:
        app: web1
    spec:
      containers:
      - name: nginx
        image: nginx:1.16
        ports:
          - containerPort: 80

可以看到pod节点会平均创建在node01 和 node02 上

通过指定节点来指定创建在node01节点上

yaml 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web1
  labels:
    app: web1
spec:
  replicas: 4
  selector:
    matchLabels:
      app: web1
  template:
    metadata:
      labels:
        app: web1
    spec:
      nodeName: node01                           # 添加nodeName: node01 
      containers:
      - name: nginx
        image: nginx:1.16
        ports:
          - containerPort: 80

不通过调度器,直接通过指定节点将所有pod节点都部署在了node01节点上了

通过标签来指定pod创建在哪个节点上

给node节点添标签

bash 复制代码
kubectl label nodes node02 pji=a
kubectl label nodes node01 pji=b

可以看见node02 的标签为 pji=a ,node01 的标签为pji=b

yaml 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web1
  labels:
    app: web1
spec:
  replicas: 4
  selector:
    matchLabels:
      app: web1
  template:
    metadata:
      labels:
        app: web1
    spec:
      nodeSelector:         #添加标签
        pji: a              #标签值pji: a
      containers:
      - name: nginx
        image: nginx:1.16
        ports:
          - containerPort: 80

以上配置可以将pod节点部署到node02节点上

yaml 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web1
  labels:
    app: web1
spec:
  replicas: 4
  selector:
    matchLabels:
      app: web1
  template:
    metadata:
      labels:
        app: web1
    spec:
      nodeSelector:       
        pji: b
      containers:
      - name: nginx
        image: nginx:1.16
        ports:
          - containerPort: 80

以上配置可以将pod部署到node01上

pod 的亲和性

在 Kubernetes 中,Pod 亲和性(Pod Affinity)是一种调度策略,用于确保 Pod 调度到特定的节点上。这种策略可以通过标签选择器(Label Selector)来实现,使得具有特定标签的 Pod 倾向于调度到具有相同标签的节点上。

Pod 亲和性可以分为以下几种类型:

  1. 软亲和性(Soft Affinity)
    • podAffinityTerm:指定 Pod 应该调度的节点集合。
    • preferredDuringSchedulingIgnoredDuringExecution:定义 Pod 应该优先调度到哪些节点上。
  2. 硬亲和性(Hard Affinity)
    • podAffinityTerm:指定 Pod 必须调度的节点集合。
    • requiredDuringSchedulingIgnoredDuringExecution:定义 Pod 必须调度到哪些节点上。
      例如,如果您有一个包含两个节点的集群,并且希望将特定的 Pod 调度到具有标签 node-role.kubernetes.io/master: "" 的节点上,

硬策略 匹配标签pji=a的node的节点配置如下

yaml 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web1
  labels:
    app: web1
spec:
  replicas: 4
  selector:
    matchLabels:
      app: web1
  template:
    metadata:
      labels:
        app: web1
    spec:
      containers:
      - name: nginx
        image: nginx:1.16
        ports:
          - containerPort: 80
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: pji
                operator: In
                values:
                - a

若是配置一个不存在的标签这会如下

出现Pending状态

软策略

设置标签为bcde但是此集群没有标签bcde的主机

yaml 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web1
  labels:
    app: web1
spec:
  replicas: 20
  selector:
    matchLabels:
      app: web1
  template:
    metadata:
      labels:
        app: web1
    spec:
      containers:
      - name: nginx
        image: nginx:1.16
        ports:
        - containerPort: 80
      affinity:
        nodeAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 1
            preference:
              matchExpressions:
              - key: pji
                operator: In
                values:
                - bcde

则会调度在node01 (b)和 node02©上

Pod的亲和性和反亲和性

在 Kubernetes 中,亲和性(Affinity)和反亲和性(Anti-Affinity)是调度策略的一部分,用于影响 Kubernetes 调度器如何将 Pod 调度到集群中的节点上。这些特性可以帮助您确保 Pod 之间或 Pod 与节点之间保持特定的关系。

亲和性(Affinity)

亲和性是指调度器倾向于将 Pod 调度到满足特定条件的节点上。它包括以下几种类型:

  1. 节点亲和性(Node Affinity)
    • 软亲和性(Soft Affinity):如果节点不满足条件,调度器可以忽略亲和性。
    • 硬亲和性(Hard Affinity):如果节点不满足条件,调度器将不会调度 Pod。
  2. Pod 亲和性(Pod Affinity)
    • 软亲和性:如果其他 Pod 不满足条件,调度器可以忽略亲和性。
    • 硬亲和性:如果其他 Pod 不满足条件,调度器将不会调度 Pod。
  3. Pod 反亲和性(Pod Anti-Affinity)
    • 软反亲和性:如果其他 Pod 不满足条件,调度器可以忽略反亲和性。
    • 硬反亲和性:如果其他 Pod 不满足条件,调度器将不会调度 Pod。

反亲和性(Anti-Affinity)

反亲和性是亲和性的对立面。与亲和性不同,反亲和性用于防止 Pod 调度到某些节点上,或者避免与某些 Pod 一起调度。反亲和性通常用于避免资源争用或实现高可用性。

亲和性配置

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: web5
  labels:
    app: web2
spec:
  containers:
  - name: nginx
    image: nginx:1.16
    ports:
    - containerPort: 80
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app
            operator: In
            values:
            - web2                      # 在有pod标签app=web2的标签上创建
        topologyKey: pji                #在拥有pji标签的节点上创建

反亲和性

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: web5
  labels:
    app: web1
spec:
  containers:
  - name: nginx
    image: nginx:1.14
    ports:
    - containerPort: 80
  affinity:
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: "app"
              operator: In
              values:
              - web2
          topologyKey: "kubernetes.io/hostname"

之前的pod标签为web2 ,设置非亲缘性后 web5创建会避开node02

当然可以。

污点与容忍

污点(Taint)

污点是向节点添加的一个标签,它告诉 Kubernetes 调度器不要将 Pod 调度到具有该污点的节点上。这通常用于防止 Pod 调度到不希望它们运行的节点上,例如,当节点正在进行维护或出现问题时。

污点可以具有以下三个属性:

  • 键(Key):污点的键,用于标识污点。
  • 值(Value):与键关联的值。
  • 效果(Effect) :当污点匹配时,Pod 应该受到的影响。有效果包括 NoSchedulePreferNoScheduleNoExecute

污点的创建

给node01创建一个键值对为ry=87的污点,使用NoSchedule策略

bash 复制代码
kubectl taint node node01 ry=87:NoSchedule
yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: nginx4
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx:latest
    ports:
    - containerPort: 80

创建新的Pod都创建在node02下,而不会创建在node01上

容忍(Tolerations)

容忍是 Pod 上的一个标签,它告诉 Kubernetes 调度器,尽管节点具有某个污点,但该 Pod 应该被调度到该节点上。容忍可以有多个键值对,并且可以设置不同的效果和时间范围。

设置容忍

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: nginx4
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx:latest
    ports:
    - containerPort: 80
  tolerations:
  - key: "ry"
    operator: "Equal"
    value: "87"
    effect: "NoSchedule"

可以看见,node01的污点被无视了

相关推荐
weixin_399380691 小时前
k8s一键部署tongweb企业版7049m6(by why+lqw)
java·linux·运维·服务器·云原生·容器·kubernetes
IT成长日记1 小时前
【Docker基础】Docker数据卷管理:docker volume ls及其参数详解
运维·docker·容器·volume ls
偷萧逸苦茶1 小时前
docker常见命令
docker·容器·eureka
慌糖10 小时前
微服务介绍
微服务·云原生·架构
高山莫衣15 小时前
Docker Desktop导致存储空间不足时的解决方案
docker·容器·eureka
鹏大师运维15 小时前
在银河麒麟V10 SP1上手动安装与配置高版本Docker的完整指南
linux·运维·docker·容器·麒麟·统信uos·中科方德
Ahlson15 小时前
【fnNAS】docker的nginx配置html
nginx·docker·容器·fnnas
LuckyLay15 小时前
Compose 常用命令详解——AI教你学Docker
docker·容器·eureka
阿里云云原生15 小时前
阿里云可观测 2025 年 6 月产品动态
云原生
阿里云云原生16 小时前
30 秒锁定黑客攻击:SLS SQL 如何从海量乱序日志中“揪”出攻击源
云原生