为什么需要pod
最为熟知的一句话:pod是k8s的最小调度单位。刚开始听到这句话时会想,已经有容器了,k8s为什么还要搞个pod出来?容器和pod是什么关系?容器的本质是进程,而k8s本质上类似操作系统。
熟悉Linux的都知道,一个应用往往不只一个进程孤伶伶地运行,而是以进程组的方式协同运行。更确切地说,Linux中“进程”都是线程,多个线程组成一个线程组,它们之间共享文件、信号、数据内存等,通过紧密协作完成一个应用程序的职责。
在Linux中pid=1的进程是init,后续所有进程都是它的子进程,它负责维护进程数(pstree查看进程树)状态,如回收子进程等。但是容器中pid=1的进程是应用,在一个容器中很难管理pid不等于1的其他进程。这就是容器的设计是单进程模型,不具有管理多进程的能力。所以对于Linux进程组中每一个进程,k8s中都需要一个单独的容器,这些容器需要互相依赖紧密合作,pod的概念就应运而生。
容器和pod的关系
pod由一个或多个容器组成,它们共享网络、存储和容器的运行配置。pod中的容器总是同时被调度,有共同的运行环境。
pod的意义
pod只是逻辑的概念,pod内的容器共享了某些资源,k8s引入pod目的是容器设计模式。
pod是如何实现的
一个有A、B两个容器的pod,如果使用docker拉起,那AB会存在依赖关系,如A先启动,B共享A的Volume等资源。而在pod设计中容器是对等关系,所以k8s引入Infra中间容器。在一个pod中Infra容器是第一个被创建的,其他的容器通过Join Network Namespace的方式与Infra关联。
Infra容器必须占用足够小的资源,它使用k8s.gcr.io/pause的特殊镜像,是一个由汇编语言编写、永远处于暂停状态的容器,只有100-200KB。
Infra容器“Hold住”Network Namespace后,用户容器会可以加入到Infra容器的Network Namespace。Pod内的容器看到的网络设备跟Infra容器一样,共享这个Network Namespace的IP地址与端口号,可以直接使用localhost进行通信。 k8s在调度时将pod作为一个整体调度到某个节点,容器内可以用过所以基于容器内共享的网络、磁盘等信息,需要基于pod层级去设计。单独对用户容器配置是不可取的,因为中间容器Infra的rootfs里几乎什么都没有,没有随意发挥的空间。所以pod的本质类似于虚拟机,容器类似于虚拟机里的应用程序。