容器为何物?为什么它对OpenStack很重要?

jopen 9年前
 

【编者的话】本文原文地址: here 。本文主要介绍了容器的发展、容器技术、容器类型、Docker、Open Container Initiative、微服务以及OpenStack中容器的应用。

容器现在正经历着一次重生,部分原因是由于云计算的发展。

容器化不是一个革命性想法——容器技术已经存在很多年并且被大量应用程序所使用,但现在,容器几乎不考虑系统体结构。

今天,相信很多人都听说过Docker。一年多以来,很多公司都在评估Docker,也有很多公司想要使用Docker,但是很少公司真正把Docker应用在生产环境中。那这一年发生了什么变化呢?

Docker让容器化变得更加简单。

在Docker出现之前,运行容器需要成群的骇客,需要对整个系统有深入的理解,还需要一定的勇气。进程隔离或者网络堆栈是存在已久的一些技术,想想FreeBSD中的Jails或者其他类似的工具。但现在有了Docker,只需要使用( docker )命令就能在几秒钟内让一些东西运行起来。

即时满足感不是Docker成功的唯一原因。大量免费应用程序的镜像能够吸引很多想要快速部署微服务以达到更大体系架构的人,但这些人不希望每次都重新部署虚拟化堆栈。

事实上,避免了虚拟化堆栈,相对于虚拟机几分钟的启动时间,容器能够在数秒之内启动,这加快了整个基础设施的部署。

当然,容器也不是完全没有问题,例如安全性和其他一些不够成熟技术带来的问题。在关键系统上运行容器之前这些问题都需要被解决,但容器化对于所有人来说都是一种期待。

容器是什么,容器的结构是什么,它们和虚拟机的关系是什么

很多人将容器比作虚拟化,但是容器并不能运行所有的东西。例如,你不能在一个容器中设置iptables的防火墙规则;因为容器共享了宿主机的 内核,它们不像虚拟机一样抽象化了硬件层。由于缺乏经验,在你开始使用容器之前,将容器看成一种“简单虚拟化”工具会给你的业务层埋下潜在的危险。

显然我们需要花时间更好地理解容器,那他们是什么?

容器是一种技术,这种技术让开发者下载一些基础镜像,载入他们的应用程序,拆分成几个组件,在持续集成系统上一一部署和测试,然后将这些组件注册到仓库中,让系统工程师在现存的基础设施上进行部署,然后发布给外界使用。

一个容器是操作系统层虚拟化特征的一种抽象。通过开拓这些特征,容器系统能够将进程和网络隔离成类似于系统沙盒的东西,因此将一个应用程序载入 一个容器就好像把它从操作系统上隔离出来一样:在容器中的进程是独立的;它们看到的是自己的文件系统,也能够与外界进行通信等等。很多能够跑在虚拟机里的 应用程序也能够跑在容器里面。

容器和虚拟机的不同在于解耦了虚拟化堆栈;虚拟机将内核到用户空间二进制文件与库文件再到应用程序本身的一切都压入了堆栈中进行隔离和独立存放。而容器管理程序则让容器使用相同的内核,共享相同的用户空间二进制文件,共享其他的库文件,然后让应用程序直接运行在这些层上。

一个镜像可以作为其他镜像的Base。在Docker中,在一个镜像之上构建新镜像来获得功能结果非常正常。你也许会在一个Ubuntu镜像上添加Apache 2.4 web服务器来构建一个基于Web的微服务,然后生成新的镜像。

镜像是容器运行的基础,你需要在镜像(building block)上启动一个容器(runtime)。镜像中包括了容器的应用程序,类似于一个快照但是还具备两个额外的特征。首先,它们在用户空间文件系统之 上进行构建,能够进行堆叠和共享一些内容。其次,它们可移植。这就允许用户在不同的系统上使用相同的镜像,重新利用这些镜像或者通过公共仓库提供给其他用 户使用,并且能够轻松地更新这些镜像,然后存放到任何地方。

容器类型

最开始的时候是chroot。Chroot()是*NIX操作系统内核的一个系统调用,用来改变当前运行进程的root目录。进程运行在chroot jail(环境名称)上并不知道真实文件系统的root目录,但知道user choice的表层root目录。

这个函数能够让你隔离应用程序,让进程将其他目录视为根目录,例如将 /mnt/root 视为 / 。这就意味着应用程序只能看到 /mnt/root 上的文件,因此构建一个完整的环境来运行这个应用程序需要 /mnt/root 目录下构建软件完整目录树的操作权。包括存放二进制文件的 /bin 目录,存放用户空间程序与库文件的 /usr 目录,存放配置的 /etc 目录等等。这些操作没那么容易,特别是对于更加复杂的应用程序来说,就更难了。

LXC是历史上第一个试图普及容器化技术的工具。和Linux容器生态系统的其他工具一起,LXC成为了容器化系统中被广泛采用的工具。它完成 了一套系统API让Linux内核的容器特征能够被用户层使用:在不脱离Linux标准下通过共享内核,LXC在chroots和虚拟机之间构建了一个体 系结构。

Docker

Docker是最具有吸引力的一种容器技术,它易于理解,可快速启动,运行方式简单,同时带来了容器编排工具的一个巨大生态系统。

从工程角度,Docker通过API实现,它有自己的服务端(daemon),命令行客户端以及从注册中心到精美UI界面等大量可以使用的工具。

Docker的强大在于之前提到的chroot、进程分组、进程隔离等功能都可以通过它的一些命令来实现。在其他容器化技术中开发人员或者管理人员需要频 繁手动操作的一些事情,例如拉取补丁、工具与部署等,在Docker中已经不在需要,因为所有的操作都封装在了命令行客户端工具 docker 中。

客户端和REST API都是与Docker服务端进行交互,它是可以远程访问的一个标准可接入守护进程,用来接收和处理所有的请求。这个守护进程负责在Docker宿主机 之上操控镜像和容器,并已经通过IANA官方确认,将端口绑定到tcp/2375和tcp/2376。

Docker最初基于LXC,但现在放弃了LXC,而使用Libcontainer。Libcontainer通过GO完全重写了用来抽象Linux内核虚拟化机制的基础库和API。

Open Container Initiative的细节

随着Docker的成功,引发了更多类似产品的出现:CoreOS的Rkt、亚马逊的容器服务(Amazon Container Service)、Apcera的Kurma等等。这种分化发展不由让人担心容器技术领域的分裂,好在通过今年在旧金山举办的DockerCon15,这 些组织已经开始共同努力,期望为容器创建统一的格式。这就是 Open Container Initiative 的由来,它基于Linux基金会,致力于为容器镜像和容器的运行制定标准化。通过Open Container规定格式创建的容器可以在不同的生态环境中共存。Open Container Initiative的成员包括了所有的容器参与者,例如亚马逊(Amazon)、CoreOS、谷歌、Oracle等等,当然也包括Docker。

Open Container的规格说明书(github地址为 https://github.com/opencontainers/specs )还在制定过程中,鼓励所有的组织或者个人都可以参与其中。到目前为止依据不同平台和内容、工业级别交付流程以及自动化最小需求,规格说明书已经定义了一些容器的统一接口和标准。支持Open Container的所有企业将完全依赖这些规格说明书来制作容器。

同时,开发RunC运行库(github地址为 https://github.com/opencontainers/runc )也是为了给各种容器提供统一运行库命令行工具的顶级封装器(而不是使用专有的命令,例如Docker的 docker 或者Rocket的 rkt )。

微服务

随着云计算的不断发展该利用容器做什么?在云计算中我们能看到的的微服务的不断发展。

在云上,整体的应用程序开发已经是过去的事情了,新的范例称为微服务体系结构。利用微服务,庞大的应用程序可以根据其诸多的功能进行解耦,分成多个微小且只有单一目的的服务,这些服务之间通过规定的接口进行通信,例如API。微服务被称为云计算中的乐高积木玩具。

在许多方面,容器都是实现微服务的一种杰出的技术:每一个容器化的微服务具有唯一的角色(数据库、队列、web服务器),然后使用容器编排工具(在许多容器开发生态系统中是非常有用的)使所有的容器相互通信来组装成整个应用程序。

上述方式有很多好处:可组合性、更快的工作流、功能的分离、可维护性和可升级性。进一步来讲,对微服务框架进行扩容变得更加容易。在不影响系统 其他功能的前提下,微服务能够更加快速、更加容易地置换到更加高效的对等服务上,或者是当遇到问题时进行回滚处理。多种不同的技术都可以用来分离微服务, 不同的团队可以根据自身手头上的任务来选择更加合适的技术。

一些大公司,像Amazon或者Netflix,在生产环境中已经有了一些基于微服务的应用程序。

因此,我们所具备的是借助容器技术能够在云环境上实现一种完美的程序设计范式,即微服务。

总结

对于软件程序和依赖关系来说,容器是一种轻量的可移植的工具。这么说看起来有些繁琐,但是容器真的改变了我们开发、部署和运行软件程序的方式。

Docker的发展是令人惊讶的,容器与云基础架构的结合也受到越来越多的关注。事实上,OpenStack有三个工程的核心组件都和容器有着 密切关系:Kolla使用容器化服务来部署OpenStack、Murano使用Kubernetes提供一种简单的方式来部署容器化应用程序以及 Magnum为容器或者“容器即服务”提供了完整的编排系统。

在随后的文章中,我们将会着重讲述如何通过使用OpenStack或者其他一些环境来构建你自己的容器化应用程序。最后问一句,你在使用容器吗?你想要学习容器中的什么呢?