- 容器的本质是一个进程,是一个视图被隔离,资源被受限的进程。
- 容器镜像的本质是一个包含了容器运行时全部所需文件的集合。
- Kubernetes 的本质是是云时代的操作系统,它管理着这些进程(容器)。
实际上,一个生产应用往往需要多个进程之间(进程组)的协同才能完成工作,所以同一个进程组中的进程应该统一被原子性的进行调度、运行和销毁。
可见,Pod 的本质对应的就是一个进程组,是一个最终生产应用的逻辑集合。
Pod 的实现机制像 Pod 这样一个东西,本身是一个逻辑概念。那在机器上,它究竟是怎么实现的呢?
核心就在于如何让一个 Pod 里的多个容器之间最高效的共享某些资源和数据。因为,容器之间原本是被 Linux Namespace 和 cgroups 隔开的,所以现在实际要解决的是怎么去打破这个隔离,然后共享某些事情和某些信息。这就是 Pod 的设计要解决的核心问题所在。
共享网络
比如说现在有一个 Pod,其中包含了一个容器 A 和一个容器 B,它们两个就要共享 Network Namespace。在 Kubernetes 里的解法是这样的:它会在每个 Pod 里,额外起一个 Infra container 小容器来共享整个 Pod 的 Network Namespace。
Infra container 是一个非常小的镜像,大概 100~200KB 左右,是一个汇编语言写的、永远处于 “暂停” 状态的容器。由于有了这样一个 Infra container 之后,其他所有容器都会通过 Join Namespace 的方式加入到 Infra container 的 Network Namespace 中。
所以说一个 Pod 里面的所有容器,它们看到的网络视图是完全一样的。即:它们看到的网络设备、IP地址、Mac地址等等,跟网络相关的信息,其实全是一份,这一份都来自于 Pod 第一次创建的这个 Infra container。这就是 Pod 解决网络共享的一个解法。
在 Pod 里面,一定有一个 IP 地址,是这个 Pod 的 Network Namespace 对应的地址,也是这个 Infra container 的 IP 地址。所以大家看到的都是一份,而其他所有网络资源,都是一个 Pod 一份,并且被 Pod 中的所有容器共享。这就是 Pod 的网络实现方式。
由于需要有一个相当于说中间的容器存在,所以整个 Pod 里面,必然是 Infra container 第一个启动。并且整个 Pod 的生命周期是等同于 Infra container 的生命周期的,与容器 A 和 B 是无关的。这也是为什么在 Kubernetes 里面,它是允许去单独更新 Pod 里的某一个镜像的,即:做这个操作,整个 Pod 不会重建,也不会重启,这是非常重要的一个设计。
共享存储
Pod 共享存储就相对比较简单。
比如说现在有两个容器,一个是 Nginx,另外一个是非常普通的容器,在 Nginx 里放一些文件,让我能通过 Nginx 访问到。所以它需要去 share 这个目录。我 share 文件或者是 share 目录在 Pod 里面是非常简单的,实际上就是把 volume 变成了 Pod level。然后所有容器,就是所有同属于一个 Pod 的容器,他们共享所有的 volume。
例如有一个 volume 叫做 shared-data,它是属于 Pod level 的,所以在每一个容器里可以直接声明:要挂载 shared-data 这个 volume,只要你声明了你挂载这个 volume,你在容器里去看这个目录,实际上大家看到的就是同一份。这个就是 Kubernetes 通过 Pod 来给容器共享存储的一个做法。
所以,如果一个应用容器 App 写了日志,只要这个日志是写在一个 volume 中,只要声明挂载了同样的 volume,这个 volume 就可以立刻被另外一个 LogCollector 容器给看到。以上就是 Pod 实现存储的方式。
Pod 的生命周期在 kubernetes 的官方文档中,对 Pod 的生命周期做出了解释。
和容器类似的,Pod 也是一个具有临时性(而不是长期存在)的实体。Pod 本身不具备自愈能力,在创建时,Pod 会被赋予一个 UUID,然后被调度到某个 Node,在终止(根据重启策略)或删除该 Pod 之前就一直运行在该 Node 上。注意,如果一个 Node 宕机了,那么调度到该 Node 的 Pods 也会在计划给定的超时期限后被删除。
Kubernetes 通过 Controller 来管理这些 “临时性” 的 Pod,当一个 Pod(由 UUID 定义)被删除后,Controller 会启动一个新的、几乎完全相同的 Pod 来进行替代。如果需要的话,新 Pod 的名字保持不变,但是其 UID 也会不同,表示并非是同一个 Pod。
对于 “普通” 的 Volume 而言,其生命周期与 Pod 一样,即:Volume 会伴随 Pod 的整个生命周期,Pod 删除或重建后,那么 Pod 运行期间产生的数据就会随之被删除。