Pod在云原生中扮演的角色
如果把K8s类比成操作系统(linux),那容器就相当于进程(linux Thread),容器中PID=1的进程就是应用本身,而Pod则相当于进程组(linux 线程组)。
管理虚拟机就是管理基础设施,管理容器就是管理应用。
容器的单进程设计
容器的设计本身是一种“单进程”模型,单进程指的是容器的生命周期等同于 PID=1 的进程(容器应用进程)的生命周期,而不是说容器里不能创建多进程。
容器管理模型的两面性
一般情况下,容器应用进程并不具备进程管理能力,所以你通过 exec 或者 ssh 在容器里创建的其他进程,一旦异常退出(比如 ssh 终止)是很容易变成孤儿进程的。
反过来,我们可以在容器里面 run 一个 systemd,用它来管理其他所有的进程。这样会导致没办法直接管理我的应用了,因为我的应用被 systemd 给接管了,那么这个时候应用状态的生命周期就不等于容器生命周期,管理模型就变复杂了。
Pod = 进程组
Helloword应用在linux上的表现
我们可以看到一个应用是由一组进程组成的。
Pod yaml 配置
Hellowork应用在pod中的表现
在K8s中,会将main api log main compute放在4个独立的容器中启动,而这四个容器部署在一个pod中,共享pod中的网络,存储等资源,
Pod 必须是原子调度单位
Task co-scheduling 问题
假如现在有两个容器,它们是紧密协作的,所以它们应该被部署在一个 Pod 里面。具体来说,第一个容器叫做 App,就是业务容器,它会写日志文件;第二个容器叫做 LogCollector,它会把刚刚 App 容器写的日志文件转发到后端的 ElasticSearch 中。
两个容器的资源需求是这样的:App 容器需要 1G 内存,LogCollector 需要 0.5G 内存,而当前集群环境的可用内存是这样一个情况:Node_A:1.25G 内存,Node_B:2G 内存。
假如说现在没有 Pod 概念,就只有两个容器,这两个容器要紧密协作、运行在一台机器上。可是,如果调度器先把 App 调度到了 Node_A 上面,接下来会怎么样呢?这时你会发现:LogCollector 实际上是没办法调度到 Node_A 上的,因为资源不够。其实此时整个应用本身就已经出问题了,调度已经失败了,必须去重新调度。
Pod间的亲密关系与Pod内部的超亲密关系
亲密关系
两个应用需要部署在同一台宿主机上,我们可以通过调度解决。
超亲密关系
1.比如说两个进程之间会发生文件交换,前面提到的例子就是这样,一个写日志,一个读日志;
2.两个进程之间需要通过 localhost 或者说是本地的 Socket 去进行通信,这种本地通信也是超亲密关系;
3.这两个容器或者是微服务之间,需要发生非常频繁的 RPC 调用,出于性能的考虑,也希望它们是超亲密关系;
4.两个容器或者是应用,它们需要共享某些 Linux Namespace。最简单常见的一个例子,就是我有一个容器需要加入另一个容器的 Network Namespace。这样我就能看到另一个容器的网络设备,和它的网络信息。
Pod解决了什么问题?
- 我们怎么去描述超亲密关系;
- 我们怎么去对超亲密关系的容器或者说是业务去做统一调度,这是 Pod 最主要的一个诉求。
Pod的实现机制
Pod的核心设计就在于如何让一个 Pod 里的多个容器之间打破namespace和cgroups的隔离,从而实现最高效的共享某些资源和数据。
1.共享网络
Infra container容器 100~200k,汇编编写,永远出于暂停
k8s会在每个Pod中额外起一个 Infra container 中间容器来共享整个 Pod 的 Network Namespace,其他所有容器都会通过 Join Namespace 的方式加入到 Infra container 的 Network Namespace 中。
也就是说同一个Pod中的所有容器看到的网络视图都是一样的,即:它们看到的网络设备、IP地址、Mac地址等等,跟网络相关的信息,其实全是一份,这一份都来自于 Pod 第一次创建的这个 Infra container。
2.共享存储
share 文件或者是 share 目录在 Pod 里面的过程实际上就是把 volume 变成了 Pod level。然后**所有同属于一个 Pod 的容器,他们共享所有的 volume。 **
share-data对应在宿主机上的目录会被同时挂在进两个容器中
所以在之前的例子中,应用容器 App 写了日志,只要这个日志是写在一个 volume 中,只要声明挂载了同样的 volume,这个 volume 就可以立刻被另外一个 LogCollector 容器给看到。
总结
Pod作为一个进程组,其中可能会有多个相互协作的进程(容器),这些容器共享网络和存储等资源,而Pod最主要的工作就是如何打破隔离,做到资源共享。