好的,这是一个非常核心的 Kubernetes 问题。创建一个 Pod 的流程涉及多个组件的协同工作,体现了 Kubernetes 声明式 API 和控制器模式的核心思想。
整个流程可以概括为:用户通过 kubectl 提交一个 Pod 的“期望状态”(YAML/JSON 文件)到 API Server,然后一系列控制器和组件通力合作,驱动整个系统达到这个“期望状态”,即最终在某个节点上启动这个 Pod。
下面是详细的步骤分解:
整体流程图(可配合下文阅读)
flowchart TDA[kubectl apply -f pod.yaml] --> B[API Server]subgraph Control PlaneB --> C[写入状态到Etcd]C --> D[Controller Manager<br>检测到无归属的Pod]D -->|通知|BC --> F[Scheduler<br>监听未调度Pod]F -->|决策绑定|Bendsubgraph NodeB --> G[Kubelet<br>监听已绑定Pod]G --> H[容器运行时<br>(如 containerd)]H --> I[拉起Pause/沙箱容器]I --> J[拉起业务容器]endG -.->|报告状态| BH -.->|报告状态| G
步骤详解:从提交到运行
第 1 步:用户提交请求 (kubectl)
- 动作:用户使用
kubectl apply -f pod.yaml
命令。 - 细节:
kubectl
会校验 YAML 文件的语法和基本格式,然后将这个 Pod 的配置信息(即它的“期望状态”或“Spec”)封装成一个 HTTP POST 请求,发送给 Kubernetes 的 API Server。
第 2 步:API Server 处理并持久化
- 动作:API Server 接收请求。
- 细节:
- 认证 (Authentication):检查发送请求的用户/服务账户是否合法(例如,检查证书、Token 等)。
- 授权 (Authorization):检查该用户是否有权限在指定的命名空间(Namespace)创建 Pod(例如,通过 RBAC 规则)。
- 准入控制 (Admission Control):对请求对象进行修改或验证(例如,自动注入 Sidecar 容器、验证资源配额等)。这是可扩展的 webhook 机制。
- 持久化 (Persistence):在通过所有校验后,API Server 将 Pod 的配置信息作为一个对象完整地存储到集群的后端数据库 Etcd 中。
至此,Pod 的第一个元数据 phase: Pending
被写入。
第 3 步:Scheduler 调度 (决策Pod在哪运行)
- 动作:Scheduler 是一个一直在监听 API Server 的控制循环。
- 细节:
- 监听:Scheduler 通过 List-Watch 机制监听 API Server,寻找那些
nodeName
为空的 Pod(即未被调度的 Pod)。 - 过滤 (Filtering):当发现这样一个 Pod 时,Scheduler 会根据 Pod 的配置(如资源请求
requests
、节点选择器nodeSelector
等),运行一系列预选策略 (Predicates),过滤掉所有不满足条件的节点(例如,内存不足、CPU 不够、不匹配标签等)。 - 评分 (Scoring):对通过预选的节点,运行一系列优选策略 (Priorities) 进行打分(例如,选择资源空闲最多的节点、分散部署等)。
- 绑定 (Binding):选择分数最高的节点,然后 Scheduler 会调用 API Server 的接口,将这个 Pod 的
nodeName
字段更新为选中的节点名称。这个更新操作会再次被写入 Etcd。
- 监听:Scheduler 通过 List-Watch 机制监听 API Server,寻找那些
此时,Pod 的状态更新为 phase: Pending
,且 nodeName: <node-name>
。
第 4 步:Kubelet 创建 Pod (驱动节点执行)
- 动作:目标节点上的 Kubelet 也是一个一直在监听 API Server 的组件。
- 细节:
- 监听:Kubelet 通过 List-Watch 机制监听 API Server,过滤出所有被调度到本节点(
nodeName
与自己名称相同)的 Pod。 - 获取配置:当发现一个新的 Pod 被绑定到本节点时,Kubelet 会从 API Server 获取该 Pod 的详细配置。
- 控制容器运行时:Kubelet 会根据 Pod Spec 开始一系列操作:
- 下载镜像:通过容器运行时(如 Containerd、Docker)从镜像仓库拉取 Pod 所需的镜像。
- 创建容器:Kubelet 并不直接创建容器,而是通过 CRI (Container Runtime Interface) 调用本机的容器运行时来完成容器的创建。
- 创建 Pod 沙箱:容器运行时首先会创建一个 “Pod 沙箱”(Infra/pause 容器),这是一个极轻量的容器,它持有 Pod 的 Linux Namespace(网络、IPC 等)。所有后续的业务容器都会共享加入这个沙箱的命名空间。
- 监听:Kubelet 通过 List-Watch 机制监听 API Server,过滤出所有被调度到本节点(
第 5 步:更新状态
- 动作:Pod 启动过程中和完成后,Kubelet 会持续监控容器的状态。
- 细节:Kubelet 会周期性地通过 API Server 报告 Pod 的当前状态(Status),例如
ContainerCreating
、Running
等。这些状态信息也会被写入 Etcd,这样用户就可以通过kubectl get pods
看到 Pod 的最新状态。
关键组件与设计模式总结
组件 | 职责 | 在 Pod 创建流程中的角色 |
---|---|---|
kubectl |
命令行工具 | 提交 Pod 配置的客户端 |
API Server |
集群的唯一入口, RESTful API 网关 | 请求校验、认证、授权、持久化、提供 Watch 接口 |
Etcd |
分布式的键值存储数据库 | 持久化存储集群的所有状态数据(期望状态和当前状态) |
Scheduler |
集群的调度器 | 决策 Pod 应该运行在哪个节点上 |
Kubelet |
运行在每个节点上的代理 | 接收 Pod 定义,驱动容器运行时真正地创建和运行容器 |
Container Runtime |
容器引擎(如 Containerd, CRI-O) | 实际负责管理容器和镜像的生命周期 |
核心设计模式:
- 声明式 API (Declarative API):用户只关心“要什么”(期望状态),而不关心“怎么做”。系统会不断地调整以确保当前状态匹配期望状态。
- 控制器模式 (Controller Pattern):Scheduler, Kubelet, Controller Manager 等都是控制器。它们通过 List-Watch 机制监听 API Server 上资源的变化,将实际状态与期望状态进行对比,并尝试驱使其保持一致。
- 解耦与模块化:各个组件职责单一,通过 API Server 进行通信和协作,耦合度低,易于扩展。例如,更换容器运行时只需实现 CRI 接口即可。
这就是在 Kubernetes 中创建一个 Pod 的完整且详细的主要流程。