Linux容器技术进化史(4)

在一个中等到大型规模基于DevOps的持续集成/持续交付环境中,效率、速度和安全性是非常重要的。而一旦相关的工具符合OCI规范,那么开发和运维就能够在持续集成/持续交付管道和生产环境中使用最佳的工具。大部分容器操作工具都隐藏在容器编排框架或者其他上层容器平台技术之下。可以预见到未来容器运行时和镜像工具的选择会成为容器平台的一个安装选项。

系统(独立)容器

Atomic项目中,我们引入了atomic host,这是一个构建操作系统的新方式,其中的软件可以“原子的”更新,并且大部分应用程序都以容器的方式运行。使用该平台的目的是为了证明大部分软件能够被移植到OCI镜像格式,并能够使用标准的协议从镜像仓库下载并安装到系统中。将软件以容器镜像的方式提供,可以让用户的操作系统和应用软件以不同的速度进行更新。传统的RPM/yum/DNF方式分发软件包会将应用程序版本限定在主机操作系统的生命周期中。

这种将基础设置作为容器来分发的一个问题是,有的时候应用程序需要在容器运行时守护进程启动前执行。让我们来看一个使用Docker守护进程的Kubernetes例子:Kubernetes在启动前需要先完成网络设置,这样它才能够将pods分配到独立的网络环境中。该场景下目前我们使用的默认守护进程是flanneld,它必须在Docker守护进程启动之前运行,以设置Docker守护进程的网络接口。同时,flanneld使用etcd作为数据存储。该守护进程需要在flanneld之前启动。

如果我们将etcd和flanneld通过镜像分发,就会遇到先有鸡还是先有蛋的问题。在启动容器化应用程序之前需要一个容器运行时守护进程,但是这些应用程序又需要在容器运行时守护进程之前启动。为了解决这个问题,我找到了一些hack的方式,但是没有一种方式是彻底的。同时,Docker守护进程目前还没有一个像样的方式来设置容器启动的优先级。我看见过这方面的建议,但是目前的实现都是使用类似于老的SysVInit方式来启动服务(当然我也知道这带来的复杂性。)

systemd

使用systemd来替代SysVInit的一个原因是用来处理启动服务的优先级和顺序,为什么容器不能利用这项技术呢?在Atomic项目中,我们决定在主机上运行容器的时候不再需要容器运行时守护进程,尤其是那些启动早期需要的服务。因此我们增强了atomic命令行接口,允许用户安装容器镜像。当用户执行atomic install --system etcd时,atomic会使用skopeo从镜像仓库拉取etcd的OCI镜像,然后将镜像释放到OSTree存储中。因为我们在生产环境中运行etcd,因此该镜像是只读的。下一步atomic命令从容器镜像中抓取systemd的unit文件模板,并在硬盘上创建unit文件用以启动镜像。该unit文件通常使用runc在主机上启动容器(虽然runc不是必须的)。

如果运行atomic install --system flanneld命令会发生类似的事情,除了这次生成flanneld的unit文件将会指定etcd需要在它启动前运行。

当系统启动时,systemd确保etcd会在flanneld之前运行,并且容器运行时会在flanneld启动之后再运行。该特性可以让用户将Docker守护进程和Kubernetes放到系统容器中。这意味着用户可以启动一个atomic host或者传统基于rpm的操作系统,其中的整个容器编排框架以容器的方式运行。这项功能非常强大,因为我们知道客户希望能够独立于这些组件,持续给他们的容器主机打补丁。此外,它能够将主机操作系统占用空间最小化。

当然,关于将传统应用程序放到容器中使其既能够作为独立/系统容器运行,又能够成为可编排容器仍然有所争论。考虑一个Apache容器,我们可以使用atomic install --system httpd命令安装。这个容器镜像可以和基于rpm的httpd服务一样的启动(systemctl start httpd,除了httpd进程将会启动在容器中)。存储仍然可以使用本地的,意味着可以将主机的/var/www目录挂载到容器中,这个容器也监听这本地网络的80端口。这表明我们可以在主机的容器中运行传统工作负载,而无需一个容器运行时守护进程。

构建容器镜像

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/12978.html