有了container为什么还需要pod
问题: 容器明明对标的是单个进程的概念,物理机里面进程不就是调度的最小单位了吗?为什么k8s还特意搞了一个pod出来?传统玩法:我们先来看下物理机里面调度进程都需要那些资源,cpu、内存、...
问题: 容器明明对标的是单个进程的概念,物理机里面进程不就是调度的最小单位了吗?为什么k8s还特意搞了一个pod出来?
传统玩法:
我们先来看下物理机里面调度进程都需要那些资源,cpu、内存、网络,整个调度都是基于同一个操作系统,并且网络通讯是在本机,内存和硬盘也是在本机。也就是说进程和进程之间的通讯代价很低。当然如果是不同机器之间进程的通讯,网络也是代价比较大。
k8s玩法:
我们再来看下container:
他的调度所需要的资源,k8s里面的cpu、存储和网络,这些资源都是分布式的,不在本机,这三个资源cpu和mem其实还好每个容器使用的都可以是自己所归属的那个node节点。可是网络呢?他是跨机器的,通讯时长会变久。
其实仔细想想这里的container的通讯对标的是不同物理机上面进程的通讯。同一台机器上面具有紧密关系的那部分进程通讯的代价就变得很高了。
那如果把这一组关系比较紧密的container部署到同一个node节点上面不就好了吗?
pod设计出来就是解决这件事情的,我们先来看下pod的特点:
pod是k8s调度的最小单位,1个pod里面可以有多个容器,并且这些容器有的是initcontainer,有的是container。这就说明pod是一个容器组,在这个容器组内很多资源是可以共享的,特别是网络资源。 他对标的是一个关系比较紧密的进程组,而整个进程组的调度总会在同一个node节点上,成功解决了上面的问题。
既然pod是一个进程组,那么不同的进程之间就存在谁先启动,谁后启动的问题,而他们的资源又需要共享特别是网络资源,这个怎么解呢?
一种解法是容器A先启动,容器B再启动,B去共享A的网络资源就可以了。这样貌似可行,不过麻烦的地方是POD需要维护这种启动顺序的拓扑关系,这个还是太麻烦了。
另外一种解法就是先启动一个小而简单的容器,让他一直存活,然后别的容器都后加进来,类似于操作启动时候的启动脚本一样,只要操作系统开机,都先默认执行这个脚本,拉起基本的资源信息。这样一来,pod就不需要管理这些动态的容器之间的拓扑关系了。
pod的设计采用的是后一种解法,k8s里面有一个叫 Infra 容器的,他就做了这么一件事。
备注:Infra 容器占用极少的资源,它使用的是一个非常特殊的镜像,叫作:k8s.gcr.io/pause。这个镜像是一个用汇编语言编写的、永远处于“暂停”状态的容器,解压后的大小也只有 100~200 KB 左右。
补充问题:
如果pod里面的容器之间需要有强依赖关系怎么办,会不会存在因为容器A启动不起来,导致后续容器启动不起来?
关于这个问题我们不妨对比下物理机里面的进程有没有类似问题,我们平时是怎么解决的。这种问题确实存在,不过我们一般是再进程里面去做解耦合,把依赖的内容单独拎出来,或者做补偿策略,例如网络连接的做成弱依赖,然后定时去连接等等。
既然物理机是这个解法,k8s也可以是这个玩法。
参考资料:
Kubernetes权威指南(第五版)
更多推荐
所有评论(0)