Pod是K8s中的最小API对象,更专业的表述是,Pod是K8s项目的原子调度单位,Pod可以看做是一个进程组,K8s则是操作系统
一, 问题
现在有三个服务需要部署在同一个节点上,A占用1G内存,B ,C也都占用1 G内存,如果用Docker Swarm来部署,需要在B , C容器上设置affinity=A 的约束,即他们必须和A在同一台机器上运行,这样这三个容器都会进入Swarm的待调度队列,然后A先调度到了node-1上,但是node1上只有2.5G内存,轮到C时,Swarm懵了,可用资源只有0,5G了,不足以运行C,可以根据亲密性约束,C又必须在node-1上运行,这就是成组调度没有妥善处理
但是在K8s中,因为Pod是原子调度单位,也就是说,K8s会按照pod而非容器的资源需求进行计算,那么一开始就不会考虑资源不够的节点进行调度
如果容器A和容器B需要共享网络和Volume资源,如何实现,在docker中可以县启动A,然后将B加入A的网络和volume中,但是这么做的话,A就必须在B之前启动,那么就形成了依赖关系,也就是一个拓扑关系
但是在K8s中,Pod使用一个中间容器,infra容器,这是一个用汇编语言写的,并且很小的,一启动就会永远处于暂停状态的容器,而且infra容器永远是第一个被创建的。对于同一个Pod中的所用用户容器来说,他们的进出流量也可以认为都是通过infra容器完成的,
二,统一Pod中容器的关系
1. 可以直接使用localhost通信
2. 看到的网络设备和infra完全一致
3. 共同拥有一个IP地址
4.共享网络资源
5. 生命周期和infra一致
三,解决的问题
1. War包和Web服务器
现有一个javaweb应用的war包,需要放在tomcat中的webapps目录下运行,如果只用docker,这种组合关系如何处理
第一种:吧war直接放在tomcat镜像中的webapps目录下,做成一个新的镜像,这种如果要更新war包,就需要升级tomcat镜像,重新发布镜像
第二种:不管war包,永远只发布一个tomcat容器,不过这个容器的webapps目录必须声明一个hostpath类型的volume,从而吧宿主机上的war包挂载进tomcat中运行起来,这样就必须解决一个问题,如何让每台宿主机都预先准备好这个存储有war包的目录
K8s中,有了POd,我们可以把两个分别做成镜像,然后作为一个Pod的两个容器,组合在一起,配置如下
不过这里的war包容器不是一个普通的容器,而是一个Init Container类型的容器,在Pod中,Init container定义的容器,都会比spec.container定义的用户容器先启动,并且Init Container容器会按顺序逐一启动,知道他们都启动退出了,用户容器才启动,这里war包容器启动后将war包拷贝到一个目录下,然后tomcat容器共享同一目录,就可以获取到这个war包了,而这里Init Container容器就扮演了一个sidecar的角色
2.日志收集
现有一个应用,需要不断吧日志文件输出到容器的/var/log目录中,这时我就可以吧一个Pod里的volume挂载到应用容器的/var/log目录上,然后在这个Pod里同时运行一个sidecar容器,他也声明挂载同一个volume到自己的/var/log目录上,
这样,接下来sidecar就只需要做一件事,就是不断从自己的/var/log读取日志文件,然后转发到mongodb或者es中,这样一个基本的日志收集工作就完成了。但是不要忘记,Pod的一个重要特性是共享同一个network namespace ,因此很多网络相关的配置和管理都可以交个sidecar来完成,完全无须干涩用于容器