容器的运行时主要是namespace、cgroup技术去影响的。而容器的镜像主要是通过chroot、rootfs等实现的。容器真正的价值在镜像,而非容器的运行时。
因此,真正重要的是对容器镜像的组织和管理。而能够定义容器组织和管理规范的容器编排技术,成为了容器领域的头把交椅。而容器编排领域的工具,现在最重要的自然是k8s。
k8s的设计理念源于google内部的Borg系统,起点非常高。当然,任何系统都会有一些缺陷,这些缺陷在开源出来后也得到了社区的维护和改善。
k8s的全局架构
node节点与容器高度相关,尤其是kubelet,直接与容器运行时、网络、存储等内容打交道。
master节点呢?
事实上,master节点是borg对k8s指导意义的直接体现。
关系部分
对一个大系统来说,处理不同任务之间错综复杂的关系是最难的部分。比如web应用与数据库之间的关系、负载均衡server与后端服务之间的关系,等等。当然,像web应用与db之间的关系比较简单,通常给定ip、端口即可。在Compose项目里,我们可以给这样的容器之间定义link。可关系复杂起来以后,只是定义link就麻烦了。k8s想提出一套统一的理念,使得复杂的关系也可以被k8s表达。比如,对于一些“紧密联系”的容器,通常是指通过localhost或者本地文件进行通信的容器,会被划分为一个pod。
一个pod里的容器共享同一个网络命名空间、同一组数据卷等等。举例来说,比如一个应用程序进程、以及和他相关的监控进程、日志处理进程、等等。而对于联系相对更松的容器,k8s提供了一种叫service的服务。比如web应用与数据库。然而pod的ip是不固定的,像数据库与web应用这种,需要固定的ip,怎么解决呢?答案是给pod绑定一个service,service的ip是不变的,相当于一个代理。
这里只是举了一个例子,其实“关系”有很多。比如我们可能想扩展pod、想存储用户名和密码、等等。具体地内容可以看图。
定性部分
除了容器间的关系问题,我们还需要给容器定性。一个容器(进程、应用),可能是只希望运行一次的(比如大数据处理任务),这种容器我们定为Job。还有一些容器,我们希望它们长期运行,且只有一个实例,比如起守护作用的容器。为了定性这种,我们定义一个DaemonSet。对于定时任务,我们定性为Cronjob等等。
如何使用k8s项目?
通过声明式API写yaml文件即可。声明式API的威力是很强大的!
其实k8s的核心,还是容器编排。到底什么是编排呢?就是按用户的意愿,自动化的管理好各种各样的容器,处理好他们之间的关系。