前言

Pod 是 Kubernetes 集群中的基础单元,它们可以组织和运行多个容器。从用户的角度,Pod 可以很方便地被创建和管理,但是它们的实际工作原理却鲜有人关注或者一知半解。在这篇文章中,我们将从 Kubernetes 源码的角度,详细剖析一个 Pod 建立的背后。同时会分析各个组件的工作流程,以及它们如何协同工作,以实现创建和管理 Pod 的目标。同时我们还将在代码解读中,讲解每个组件的职责和实现原理,以更好地理解 Pod 工作的核心机制。

Pod基础知识

Pod 由一个或多个 Container 组成,或者可以说是容器的抽象,所有容器共享一个网络命名空间、存储卷等,可以很方便地共享数据和通信。

首先我们需要通过声明式配置文件来创建 Pod,描述容器的配置和所需的资源,并通过 kubectl 命令提交给 Kubernetes 集群中,而后集群的调度器也就是 Scheduler 组件会根据预先配置的亲和性与对硬件资源的考量,将 Pod 放到一个合适的节点,一旦调度成功,Kubernetes 会启动其中的容器并为其分配网络命名空间、IP 地址和存储卷。

在 Pod 启动成功后,Kubernetes 会不断监视其状态,并提供了更新、扩展和故障转移等编排功能,而在这篇文章中,我将会假设您已经有了对于 Kubernetes 已经具备了一定程度的水平和经验。同时,为了保证学习的流畅性,文章会摒弃例如 PriorityClass 之类的对于主流程关联性没有那么重要的特性

创建Pod的过程

我们在上面基础复习的时候,已经简述了一个 Pod 从组件上是如何被传递并且被创建了,但是如果想要阅读源码,不仅需要查看代码实现,还需要理解 Kubernetes 的架构设计和组件间的通信机制。

过程简述

我们首先将 YAML 声明使用 kubectl 进行提交,kubectl 会通过 Kubeconfig 文件与 kube-apiserver 进行通信。kubeconfig 中的 token 会与 kube-apiserver 进行校验,这个 token 通常被配置在集群中某一个 Secrets 中,与某个具备一定权限的 ServiceAccount 做了绑定,在通过认证后 kube-apiserver 将对提交的 YAML 声明进行语法和逻辑检查,以确保其符合 Kubernetes 的要求。这些检查包括验证声明中的资源是否存在、依赖关系是否正确等,如果没有问题则将其写到 Etcd 中。

至此,这个 Pod 的声明就被视为已经接受并处理了,注意这里有个小的要点,kube-apiserver 从 etcd 中读取数据是因为 etcd 作为 Kubernetes 的后端存储,存放了所有集群数据,包括 Pod 的定义。这样的设计使得 kube-apiserver 成为了唯一直接与 etcd 交互的组件,以确保数据的一致性和集群状态的准确性。

因此整个 kube-apiserver 并不单单只做最前端的接受请求处理,甚至有的时候请求量过大还会成为集群的性能瓶颈

在 Kubernetes 中,kube-scheduler 是控制平面的一个关键组件,负责监控未分配节点的新创建 Pod,并为它们选择合适的节点以便运行,kube-scheduler 通过建立一个 “Watch” 机制来持续监听 kube-apiserver 上关于 Pod 的信息。

当 kube-apiserver 检测到新的 Pod 创建事件(这些事件信息是从etcd中获取的),它会通知 kube-scheduler。kube-scheduler 接收到这些变更后,就会开始处理未分配节点的Pod。

ApiServer的角色

Controller Manager的角色

Scheduler的角色

Kubelet的角色

Pod的运行过程

Kubelet的监视工作

容器的启动与停止

Pod状态的更新与管理

Pod的持久化

Volumes原理