关于 Pod 最重要的一个理解是:它只是一个逻辑概念。也就是说,Kubernetes 真正处理的,还是宿主机操作系统上 Linux 容器的 Namespace 和 Cgroups,而并不存在一个所谓的 Pod 的边界或者隔离环境。那么,Pod 又是怎么被“创建”出来的呢?答案是:Pod,其实是一组共享了某些资源的容器。具体的说:Pod 里的所有容器,共享的是同一个 Network Namespace,并且可以声明共享同一个 Volume,甚至根据pod多资源限制,更加贴近应用,而不必针对每个docker容器做cgroup的限制(这样会更麻烦,也不贴近应用)。
因此可以理解为Pod=windows进程组,一个pod中包含多个容器(单进程),共同完成一个任务,共享一组网络栈和存储卷。当容器故障后,只需要产生新的容器,即可快速接管,而应用容器无需关注它运行所依赖的网络、存储等。如果开发k8s的容器插件,也只需要跟pod打交道,而不用关注容器应用(如nginx)本身。这也是容器比虚拟机灵活、高效的地方。
总结一下,Pod也是k8s管理的最小原子单位,通过调度pod实现一组应用容器的部署。而容器的本质天生就是单进程,基于linux操作系统开发的应用,无论如何也是无法无缝移植到一个容器中,而pod通过共享存储和网络的模型,能够容纳多个容器运行,基本上对等于linux操作系统中进程组。而K8s更像调度各类进程组Pod的指挥中心,k8s更像操作系统级别的。
Pod 网络共享的实现
每个pod中的所有容器共用一套网络设计,只有一个ip地址,这个实现是通过pod默认的infra容器实现的,infra只有几百k的汇编语言,当pod启动时,infra默认首先启动,会处理网络挂载。pod的网络和生命周期依赖于infra容器,当用户容器A、B在pod中运行或关闭,都不用考虑网络的实现,因为pod的生命周期与infra容器密切相关。
多容器组合以及Volume共享
在一个pod中把两个容器组合起来,实现某些操作。譬如在下面涛哥的pod yaml文件中,要启动两个容器war和tomacat。实际如果data文件被绑死到一个tomcat容器,那么更新网站文件,tomcat容器也要更新与数据卷相关的操作,这样及其不便。通过war容器实现war包copy到宿主机的/app目录,然后挂载到容器的app-volume,这样采用initcontainer的方式,在初始化pod是首先启动了war容器,实现了数据卷的copy和挂载。然后再启动tomcat容器时,app-volume已经有war的数据了,tomcat直接使用这个文件启动网站。实现数据和tomcat容器的解耦。这种机制也称之为sidecar。如果实现容器的日志分析,同样的方法,构建一个event容器,从tomcat运行的日志文件中拿到数据,存储到event容器的volume中,实现日志和容器的解耦。
apiVersion: v1
kind: Pod
metadata:
name: javaweb-2
spec:
**initContainers**:
- image: taoge/sample:v2
name: war
command: ["cp", "/sample.war", "/app"]
volumeMounts:
- mountPath: /app
name: app-volume
containers:
- image: taoge/tomcat:7.0
name: tomcat
command: ["sh","-c","/root/apache-tomcat-7.0.42-v2/bin/start.sh"]
volumeMounts:
- mountPath: /root/apache-tomcat-7.0.42-v2/webapps
name: app-volume
ports:
- containerPort: 8080
hostPort: 8001
volumes:
- name: app-volume
emptyDir: {}
形象化理解:Pod,而不是容器,才是 Kubernetes 项目中的最小编排单位。将这个设计落实到 API 对象上,容器(Container)就成了 Pod 属性里的一个普通的字段。那么,一个很自然的问题就是:到底哪些属性属于 Pod 对象,而又有哪些属性属于 Container 呢?要彻底理解这个问题,你就一定要牢记一个结论:Pod 扮演的是传统部署环境里”虚拟机“的角色。这样的设计,是为了使用户从传统环境(虚拟机环境)向 Kubernetes(容器环境)的迁移,更加平滑。而如果你能把 Pod 看成传统环境里的“机器”、把容器看作是运行在这个“机器”里的“用户程序”,那么很多关于 Pod 对象的设计就非常容易理解了。而如果把 Pod 看成传统环境里的“机器”、把容器看作是运行在这个“机器”里的“用户程序”,那么很多关于 Pod 对象的设计就非常容易理解了。比如,凡是调度、网络、存储,以及安全相关的属性,基本上是 Pod 级别的。
暂无评论