一、为什么需要 Pod:
1、容器的基本概念:
容器的本质实际上是一个进程,是一个视图被隔离,资源受限的进程。容器里面 PID=1 的进程就是应用本身,这意味着管理虚拟机等于管理基础设施,但管理容器却等于直接管理应用本身。
Kubernetes 是云时代的操作系统,容器镜像就是这个操作系统的软件安装包。
2、真实操作系统中的例子:
Helloworld 程序实际上是由一组进程组成的,从 Linux 系统中去查看 Helloworld 中的 pstree,将会看到这个 Helloworld 实际上是由四个线程组成的,分别是 {api、main、log、compute}。也就是说,四个这样的线程共同协作,共享 Helloworld 程序的资源,组成了 Helloworld 程序的真实工作情况。
3、进程组的概念:
容器可以类比为进程,那么 Pod 就是进程组。
(1) 容器实际上是一个“单进程”模型,意思是容器的生命周期等同于 PID=1 的进程(容器应用进程)的生命周期,不是说容器里不能创建多进程。
一般情况下,容器应用进程并不具备进程管理能力,所以通过 exec 或者 ssh 在容器里创建的其他进程,一旦异常退出(比如 ssh 终止)很容易变成孤儿进程。
(2) Pod 实际上是 kubernetes 项目抽象出来的一个可以类比为进程组的概念。
由四个进程共同组成的一个应用 Helloworld,在 Kubernetes 里面,实际上会被定义为一个拥有四个容器的 Pod。
Pod 在 Kubernetes 里面只有一个逻辑单位,没有一个真实的东西对应 Pod,真正起来在物理上存在的东西,就是四个容器。这四个容器,或者说是多个容器的组合就叫做 Pod。
Pod 是 Kubernetes 分配资源的一个单位,因为里面的容器要共享某些资源,所以 Pod 也是 Kubernetes 的原子调度单位。
(3) Pod 是 Kubernetes 里的原子调度单位:Pod 是 Kubernetes 中最小的调度单位,包含一个或多个容器。通过将容器打包到 Pod 中,Kubernetes 可以更好地管理资源分配和调度。Pod 作为原子单位可以保证容器之间共享资源和网络等方面的一致性。
二、Pod 的实现机制:
容器之间原本是被 Linux Namespace 和 cgroups 隔开的,Pod 要解决的核心问题就是如何让一个 Pod 里的多个容器之间最高效的共享某些资源和数据。
1、共享网络:
(1) 有一个 Pod,其中包含了一个容器 A 和一个容器 B,它们两个要共享 Network Namespace。在 Kubernetes 里,它会在每个 Pod 中,额外起一个 Infra container 小容器来共享整个 Pod 的 Network Namespace。
(2) 一个 Pod 里面的所有容器,它们的网络设备、IP地址、Mac地址等等,跟网络相关的信息完全是一样的,都来自于 Pod 第一次创建的这个 Infra container。
(3) 所以整个 Pod 里面,必然是 Infra container 第一个启动。并且整个 Pod 的生命周期是等同于 Infra container 的生命周期的,与容器 A 和 B 无关。
2、共享存储:
把 volume 变成了 Pod level,在每一个容器里可以直接声明要挂载的volume,只要声明了挂载这个 volume,在容器里去看这个目录,大家看到的就是同一份。
三、容器设计模式 Sidecar
Sidecar 是说在 Pod 里面,可以定义一些专门的容器,来执行主业务容器所需要的一些辅助工作。
Sidecar 应用场景:
1、日志收集:
业务容器将日志写在一个 Volume 里面,由于 Volume 在 Pod 里面是被共享的,所以日志容器即 Sidecar 容器可以通过共享该 Volume,直接把日志文件读出来,然后存到远程存储里面。
2、代理容器:
假如有个 Pod 需要访问一个外部系统,但是这些外部系统是一个集群,可以通过 Sidecar 代理容器处理对接外部的服务集群,它对外暴露出来只有一个 IP 地址。业务容器主要访问 Proxy,然后由 Proxy 去连接这些服务集群。
3、适配器容器:
将业务容器暴露出来的接口转换为另一种格式。