目录

Pod 的本质是什么?
  • 容器的本质是一个进程,是一个视图被隔离,资源被受限的进程。
  • 容器镜像的本质是一个包含了容器运行时全部所需文件的集合。
  • 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 不会重建,也不会重启,这是非常重要的一个设计。

Kubernetes — 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 运行期间产生的数据就会随之被删除。