前言

本文聚焦 Kubernetes 核心运行机制,详解组件协作、Pod 创建流程、调度器工作逻辑及亲和性调度策略,夯实 K8s 运维与部署基础。


一、Kubernetes 组件协作机制

1、kubernetes组件

Kubernetes 通过 List-Watch 机制使各个组件协作、数据同步,从而实现解耦与实时一致性。
组件列表如下
kubectl / API 客户端:向 APIServer 发起资源创建或管理请求
APIServer:负责 API 调用、权限校验、存储交互,是集群控制的核心入口
etcd:存储集群所有状态信息
Controller Manager:维持副本数、执行自愈逻辑(扩容、重建等)
Scheduler:调度器,将未分配节点的 Pod 分配到合适的 Node
kubelet:节点代理,负责 Pod 生命周期管理和容器运行状态上报

2、组件协助流程概述

用户是通过 kubectl 根据配置文件,向 APIServer 发送命令,在 Node 节点上面建立 Pod 和 Container。 APIServer 经过 API 调用,权限控制,调用资源和存储资源的过程,实际上还没有真正开始部署应用。这里 需要 Controller Manager、Scheduler 和 kubelet 的协助才能完成整个部署过程。
在 Kubernetes 中,所有部署的信息都会写到 etcd 中保存。实际上 etcd 在存储部署信息的时候,会发送 Create 事件给 APIServer,而 APIServer 会通过监听(Watch)etcd 发过来的事件。其他组件也会监听(Watch)APIServer 发出来的事件。

二、Pod创建和工作流程机制

Pod 创建的整个生命周期由多组件配合完成
典型创建过程(List-Watch 模型)
1) 三大组件启动监听(List-Watch)
Controller Manager、Scheduler、kubelet 启动后会分别通过 Watch API Server(HTTPS 6443 端口)监听集群资源事件变化。
Controller Manager:监听副本控制类对象(如 ReplicaSet、Deployment)
Scheduler:监听未调度的 Pod
kubelet:监听分配到本节点的 Pod

2)用户创建 Pod 对象
用户通过 kubectl 或其他 API 客户端发送创建 Pod 的请求给 API Server。

kubectl apply -f pod.yaml

3)API Server 将 Pod 信息写入 etcd、

  • API Server 校验请求后,将 Pod 的元数据存入 etcd。
  • 写入成功后返回确认给客户端。

4)etcd 通知事件(Create)

  • etcd 接受到 Pod 信息后,触发 Create 事件。
  • 该事件被发送给 API Server。

5)Controller Manager 监听到 Pod 创建事件
Controller Manager 通过 Watch 机制收到 API Server 发出的 Pod 创建事件。

6)Replication Controller(RC)/ ReplicaSet 保证副本数

  • Controller Manager 在接到 Create 事件以后,如果发现副本数量不足,则由 RC/ReplicaSet 创建所需副本。
  • 扩容、缩容操作也都由此机制控制。

7)API Server 更新 etcd(记录详细信息)

  • Controller Manager 创建完 Pod 副本后,API Server 会将 Pod 的详细信息更新写入 etcd。包括副本数量、副本模板、容器规格等

8)etcd 触发 Pod 信息更新事件
etcd 再次发送更新事件给 API Server。

9)Scheduler 监听到待调度的 Pod

  • Scheduler Watch 到新创建的 Pod 处于 “Pending” 状态(尚未分配节点)。
  • 通过调度算法(资源、亲和性、污点等)为其选择一个合适的 Node。

10)Scheduler 更新调度结果

  • Scheduler 将选定的 Node 信息写回到 API Server。
  • API Server 更新 etcd 中该 Pod 的 Node 绑定信息。

11)etcd 确认更新 & API Server 同步结果

  • etcd 更新成功后向 API Server 返回确认。
  • API Server 同步 Pod 的最新状态(包括 Node 绑定结果)。

12)kubelet 在 Node 上拉取并运行容器

  • kubelet 监听到分配给自己的新 Pod。
  • 调用容器运行时(Docker/containerd):
  1. 拉取镜像
  2. 创建容器
  3. 启动容器
    启动成功后将 Pod 状态(Running、Failed 等)上报给 API Server。

13)API Server 更新 Pod 状态

  • API Server 将 kubelet 上报的状态写入 etcd。
  • etcd 确认写入成功后,集群状态完成同步,Pod 正式进入 Running 状态

三、Scheduler过程(调度器)

1、核心任务

将 未绑定 Node 的 Pod( spec.nodeName == “” ) 分配到合适的节点。

2、调度目标

公平性:节点间资源分配均衡
高效性:集群所有资源最大化被使用
效率:调度的性能要好,能够尽快地对大批量的 pod 完成调度工作
灵活性:允许自定义策略(调度策略、插件)

3、调度流程概述

Sheduler 是作为单独的程序运行的,启动之后会一直监听 APIServer,获取 spec.nodeName 为空的pod,对每个 pod 都会创建一个 binding,表明该 pod 应该放到哪个节点上。
调度分为几个部分:首先是过滤掉不满足条件的节点,这个过程称为预算策略(predicate);然后对通过的节点按照优先级排序,这个是优选策略(priorities);最后从中选择优先级最高的节点。如果中间任何一步骤有错误,就直接返回错误。

四、调度详细流程

1、过滤阶段(Predicate)

常见过率算法
PodFitsResources:检查节点剩余资源是否满足 Pod 需求
PodFitsHost:检查 NodeName 是否匹配
PodFitsHostPorts:检查端口冲突
PodSelectorMatches :label 匹配
NoDiskConflict:Volume 挂载冲突检测

2、优选阶段(Priorities)

常见算法
LeastRequestedPriority:资源使用率越低,权重越高
BalancedResourceAllocation
CPU 与内存使用率越接近越好(这个一般和上面的一起使用,不单独使用。比如 node01 的 CPU 和 Memory 使用率20:60,node02 的 CPU 和 Memory 使用率 50:50,虽然node01 的总使用率比 node02 低,但 node02 的 CPU 和Memory 使用率更接近,从而调度时会优选 node02。)
ImageLocalityPriority:优先节点上已有目标镜像的节点

五、指定调度方式

1、强制绑定(nodeName)

pod.spec.nodeName 将 Pod 直接调度到指定的 Node 节点上,会跳过 Scheduler 的调度策略,该匹配规则是强制匹配
以nginx为例:写入pod.spec.nodeName:node01,则Pod都在node01上创建

# nginx-stack.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: default
spec:
  replicas: 3 # 初始Pod数量
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      nodeName: node01
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
        resources:
          # 关键点2: 必须设置资源请求,这是HPA计算利用率的基础
          requests:
            cpu: "200m" # 请求0.2个CPU核心
          limits:
            cpu: "500m" # 限制最多使用0.5个CPU核心

结果如图所示:

kubectl apply -f test3.yaml
kubectl get pod -o wide

在这里插入图片描述
查看事件描述,发现未经过Scheduler调度,由kubelet直接启动
kubectl describe pod nginx-deployment-696d847d6c-7742c
在这里插入图片描述

2、基于标签匹配(nodeSelector)

pod.spec.nodeSelector:通过 kubernetes 的 label-selector 机制选择节点,由调度器调度策略匹配 label,然后调度 Pod 到目标节点,该匹配规则属于强制约束

# 设置k8s的node节点标签
# 获取标签使用帮助
kubectl label --help
# 获取node名称
kubectl get node
# 设置标签
kubectl label nodes node01 yjs=a
kubectl label nodes node02 yjs=b
# 查看标签
kubectl get nodes --show-labels

在这里插入图片描述
还是使用上述的nginx模板,增添属性pod.spec.nodeSelector:yjs=b

# nginx-stack.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: default
spec:
  replicas: 3 # 初始Pod数量
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      nodeSelector:
        yjs: b
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
        resources:
          # 关键点2: 必须设置资源请求,这是HPA计算利用率的基础
          requests:
            cpu: "200m" # 请求0.2个CPU核心
          limits:
            cpu: "500m" # 限制最多使用0.5个CPU核心

验证结果Pod是否创建在node02上
kubectl get pod -o wide
在这里插入图片描述
查看pod详细信息发现经过了调度
kubectl describe pod nginx-deployment-89c698d86-fdskb
在这里插入图片描述

3、管理Node标签命令

# 设置标签
kubectl label nodes node01 yjs=a
# 指定标签查询
Kubectl get node -l yjs=a
# 修改label
kubectl label nodes node02 yjs=b overwrite
# 删除label
kubectl label nodes node02 yjs-

六、节点亲和性和Pod亲和性

1、节点亲和性

1.1、节点亲和性介绍和标签运算关系

affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution: # 硬策略
    preferredDuringSchedulingIgnoredDuringExecution: # 软策略

操作符支持
In 、 NotIn 、 Exists 、 DoesNotExist 、 Gt 、 Lt
Kubernetes 中 label selector 的键值运算关系 ,在 Kubernetes 中,很多资源(比如 Pod、Deployment、Service)都会用 label selector(标签选择器) 来筛选对象。 运算符决定“选谁”或“不选谁”。
在这里插入图片描述

1.2、案例-硬策略

设置硬策略,结合NotIn,使得kubelet创建Pod时只创建在标签为yjs,标签值不为a的节点上,本文只有两个节点,最终显示结果为只在node02上创建

# 查看节点标签和标签值,已设置好node01 yjs=a  和 node02 yjs=b
kubectl get nodes --show-labels

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: default
spec:
  replicas: 3 # 初始Pod数量
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
       # 亲和性配置的根节点,用于定义Pod与节点/其他Pod的亲和/反亲和规则
      affinity: 
      # 节点亲和性,控制Pod调度到哪些节点上(区别于podAffinity:Pod间亲和性)
        nodeAffinity:
# requiredDuringSchedulingIgnoredDuringExecution:核心规则类型,分为两部分理解:
# 1. requiredDuringScheduling:调度阶段必须满足该规则,不满足则Pod无法调度(强制约束)
# 2. IgnoredDuringExecution:Pod调度成功后,如果节点标签发生变化(比如node02的hostname标签被修改),不会驱逐已运行的Pod
          requiredDuringSchedulingIgnoredDuringExecution:
# 节点选择器规则列表(可以配置多个,满足任意一个即可)
            nodeSelectorTerms:
# 基于表达式的节点匹配规则(另一种是matchFields,基于节点字段)
              - matchExpressions:
               # 要匹配的节点标签的「键」
                - key: yjs #指定node的标签
              # operator:匹配运算符,NotIn 表示「标签值不在指定的values列表中」
                  operator: NotIn #设置Pod安装到kubernetes.io/hostname的标签值不在values列
                  values: 
                  - a

kubectl apply -f test3.yaml
kubectl get pod -o wide
验证结果如下:
在这里插入图片描述

1.3、案例-软策略

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: default
spec:
  replicas: 3 # 初始Pod数量
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
      affinity:
        nodeAffinity:
          # 软策略:可以配置多个偏好规则,每个规则有独立权重
          preferredDuringSchedulingIgnoredDuringExecution:
          # 规则1:优先调度到node03(权重80,优先级最高)
          - weight: 80
            preference:
              matchExpressions:
              - key: kubernetes.io/hostname
                operator: In
                values:
                - node02
          # 规则2:其次调度到node01(权重50,优先级次之)
          - weight: 50
            preference:
              matchExpressions:
              - key: kubernetes.io/hostname
                operator: In
                values:
                - node01

因为node02权重大,所以会优先在node02上创建
在这里插入图片描述

1.4、案例-硬软策略优先级

如果把硬策略和软策略合在一起使用,则要先满足硬策略前提下才会满足软策略

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: default
spec:
  replicas: 3 # 初始Pod数量
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
      affinity:
        nodeAffinity:
          # 软策略:可以配置多个偏好规则,每个规则有独立权重
          preferredDuringSchedulingIgnoredDuringExecution:
          # 规则1:优先调度到node03(权重80,优先级最高)
          - weight: 80
            preference:
              matchExpressions:
              - key: kubernetes.io/hostname
                operator: In
                values:
                - node02
          # 规则2:其次调度到node01(权重50,优先级次之)
          - weight: 50
            preference:
              matchExpressions:
              - key: kubernetes.io/hostname
                operator: In
                values:
                - node01
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: kubernetes.io/hostname
                operator: NotIn
                values:
                - node02   

受硬策略影响,选择了软策略中权重小的
在这里插入图片描述

2、Pod亲和性与反亲和性

2.1、什么是Pod亲和性

Pod 亲和性(podAffinity) 是 Kubernetes 中一种基于已有 Pod 标签的调度规则,用于控制新 Pod的调度位置 —— 让新 Pod 和某些已运行的 Pod「靠近」或「远离」,核心作用是优化 Pod 间的网络延迟、实现服务聚合 / 隔离。
Pod亲和性和节点亲和性(nodeAffinity) 的核心区别是:

  • 节点亲和性:依据节点的标签调度 Pod(Pod → 节点标签)
  • Pod 亲和性:依据目标节点上已运行 Pod 的标签调度 Pod(Pod → 已运行 Pod 的标签 → 节点)

2.2、调度策略

在这里插入图片描述

2.3、Pod亲和性调度案例

kubectl label nodes node01 yjs=a pod1
kubectl label nodes node02 yjs=b pod2

# 先在节点node02上创建一个运行的Pod
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment2
  namespace: default
spec:
  replicas: 1 # 初始Pod数量
  selector:
    matchLabels:
      app: myapp01
  template:
    metadata:
      labels:
        app: myapp01
    spec:
      nodeName: node02
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80

在这里插入图片描述
创建亲和性Pod

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment3
  namespace: default
spec:
  replicas: 3 # 初始Pod数量
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
      affinity:
      # Pod亲和性(区别于nodeAffinity节点亲和性)
        podAffinity:
        # 硬约束规则:调度时必须满足,运行后忽略节点变化
          requiredDuringSchedulingIgnoredDuringExecution:
          # 目标Pod的标签选择器(要匹配的已有Pod标签)
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                # 匹配标签值为myapp01的Pod
                values:
                - myapp01
            # 拓扑维度:按节点的yjs标签维度判断“同一位置”
            topologyKey: yjs

结果示例:都创建在node02上,因为myapp01标签运行中的pod在node02上
在这里插入图片描述

2.4、Pod反亲和性调度案例

调度这个 myapp10 Pod 时,优先避免 将它调度到「运行着带有 app=myapp01 标签的 Pod」的同一节点上

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment4
  namespace: default
spec:
  replicas: 3 # 初始Pod数量
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
      affinity:
        podAntiAffinity: # 反亲和性规则
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - myapp01
            topologyKey: yjs

Pod反亲和性结果,新的Pod都不在标签为app, 标签值为myapp01, 维度为yjs=b的节点上。
在这里插入图片描述

七、污点(Taint) 和 容忍(Tolerations)

1、污点(Taint)

1.1、污点概述

节点亲和性,是Pod的一种属性(偏好或硬性要求),它使Pod被吸引到一类特定的节点。Taint 则相反,它使节点能够排斥一类特定的 Pod。Taint 和 Toleration 相互配合,可以用来避免 Pod 被分配到不合适的节点上。每个节点上都可以应用一个或多个 taint ,这表示对于那些不能容忍这些 taint 的 Pod,是不会被该节点接受的。如果toleration 应用于 Pod 上,则表示这些 Pod 可以(但不一定)被调度到具有匹配 taint 的节点上。
使用 kubectl taint 命令可以 给某个 Node 节点设置污点,Node 被设置上污点之后就和 Pod 之间存在了一种相斥的关系,可以让 Node 拒绝 Pod 的调度执行,甚至将 Node 已经存在的 Pod 驱逐出去。

1.2、污点格式

key=value:effect
每个污点有一个 key 和 value 作为污点的标签,其中 value 可以为空,effect 描述污点的作用。

当前 taint effect 支持如下三个选项:
NoSchedule:不调度到此节点
PreferNoSchedule:尽量避免调度具有该污点的 Node 上
NoExecute:不调度 + 驱逐已存在 Pod

1.3、命令示例

# 查看node
kubectl get nodes
kubectl describe node master01
>>>输出
CreationTimestamp:  Mon, 05 Jan 2026 15:33:37 +0800
Taints:             node-role.kubernetes.io/master:NoSchedule

# 设置污点  key=value给污点打的自定义标签,可以自己定义
kubectl taint node node02 key=value:NoExecute
kubectl taint node node02 key=value:NoSchedule
kubectl taint node node02 key=value:PreferNoSchedule
# 去除污点
kubectl taint node node02 key=value:NoExecute-

NoExecute测试:
在这里插入图片描述

2、容忍(Tolerations)

2.1、容忍概述

设置了污点的 Node 将根据 taint 的 effect:NoSchedule、PreferNoSchedule、NoExecute 和 Pod 之间产生互斥的关系,Pod 将在一定程度上不会被调度到 Node 上。但我们可以在 Pod 上设置容忍(Tolerations),意思是设置了容忍的 Pod 将可以容忍污点的存在,可以被调度到存在污点的 Node 上。

2.2、容忍示例

# 将仅有的两个节点都设置污点,发现Pod创建不了
kubectl taint node node01 key=value:NoExecute
kubectl taint node node02 key2=value2:NoExecute
# 在创建Pod的yaml文件加上容忍即可创建成功
## yaml文件内容
apiVersion: v1
kind: Pod
metadata:
  name: myapp01
  labels:
    app: myapp01
spec:
  containers:
  - name: with-node-affinity
    image: nginx
  tolerations:
  - key: "key" # 污点的键
    operator: "Equal" #operator: "Equal" #Equal意味着这个值等于value,如果是Exists,则不需要填写value,只要有这个key就容忍
    value: "value" # 污点的值
    effect: "NoExecute" # 污点的类型
    tolerationSeconds: 3600 # 污点被驱逐存活的时间

创建Pod
kubectl apply -f Pod1.yaml
在这里插入图片描述
查看pod所在node01的污点设置
在这里插入图片描述
其他注意事项:

1)当不指定 key 值时,表示容忍所有的污点 key
tolerations:
- operator: "Exists"
2)当不指定 effect 值时,表示容忍所有的污点作用
tolerations:
- key: "key"
operator: "Exists"
3)有多个 Master 存在时,防止资源浪费,可以如下设置
kubectl taint node Master-Name node-role.kubernetes.io/master=:PreferNoSchedule

2.3、node更新升级操作

1)如果某个 Node 更新升级系统组件,为了防止业务长时间中断,可以先在该 Node 设置 NoExecute 污点,把该 Node 上的 Pod 都驱逐出去。
kubectl taint node node01 check=mycheck:NoExecute
2)此时如果别的 Node 资源不够用,可临时给 Master 设置 PreferNoSchedule 污点,让 Pod 可在Master 上临时创建。
kubectl taint node master node-role.kubernetes.io/master=:PreferNoSchedule
3)待所有 Node 的更新操作都完成后,再去除污点
kubectl taint node node01 check=mycheck:NoExecute-

八、节点维护

在这里插入图片描述
drain 等价于 “cordon + 驱逐”。
在 Kubernetes 中,驱逐(Eviction)是指将运行中的 Pod 从一个节点上迁移到另一个节点的过程,同时释放原节点上的资源以供其他使用。驱逐通常发生在以下情况:

  • 需要将 Pod 迁移到其他节点以维护节点或进行软硬件升级。
  • 某个节点的资源不足以容纳新的 Pod,需要将旧的 Pod 驱逐以释放资源。

Kubernetes 可以使用自动驱逐机制来管理 Pod 的迁移。它可以基于节点负载、Pod 优先级等条件来自动选择需要驱逐的 Pod,并将它们迁移到其他节点上。在执行驱逐时,Kubernetes 会首先将 SIGTERM 信号发送给 Pod,然后等待一段时间,让 Pod 自行终止。如果自我终止未成功,则Kubernetes 会强制终止 Pod 并进行清理工作。
驱逐是 Kubernetes 集群中必不可少的机制之一,它可以确保系统的高冗余性和高可用性,并优化集群中的资源利用率。

九、Pod生命周期(Phase)

在这里插入图片描述
详解phase 的可能状态有:
● Pending:表示APIServer创建了Pod资源对象并已经存入了etcd中,但是它并未被调度完成(比如还没有调度到某台node上),或者仍然处于从仓库下载镜像的过程中。
● Running:Pod已经被调度到某节点之上,并且Pod中所有容器都已经被kubelet创建。至少有一个容器正在运行,或者正处于启动或者重启状态(也就是说Running状态下的Pod不一定能被正常访问)。
● Succeeded:有些pod不是长久运行的,比如job、cronjob,一段时间后Pod中的所有容器都被成功终止,并且不会再重启。需要反馈任务执行的结果。
● Failed:Pod中的所有容器都已终止了,并且至少有一个容器是因为失败终止。也就是说,容器以非0状态退出或者被系统终止,比如 command 写的有问题。
● Unknown:表示无法读取 Pod 状态,通常是 kube-controller-manager 无法与 Pod 通信。

十、故障排除命令

1)查看事件
kubectl describe pod
2)查看日志
kubectl logs [-c 容器名]
3)进入容器
kubectl exec -it bash
4)查看集群状态
kubectl cluster-info
5)查看节点状态
kubectl get nodes
6)查看 kubelet 日志
journalctl -xefu kubelet

十一、小结

kubectl → APIServer → etcd
           ↓ ↑
Controller Manager ←→ Scheduler ←→ kubelet(Node)

核心调度策略层次:
1)nodeName(直接绑定)
2)nodeSelector(Label 匹配)
3)nodeAffinity / podAffinity(亲和性调度)
4)Taint & Toleration(污点/容忍机制)
5)cordon & drain(节点维护与Pod迁移)
注意:“调度是吸引,污点是排斥,亲和性是偏好,容忍是例外。”


总结

本文系统梳理 K8s 组件协作、Pod 创建与调度全流程,深入解析调度算法及亲和性策略,提供容器调度的方法。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐