一位开发者的 Linux 容器之旅
================================================================================
![](https://deis.com/images/blog-images/dev_journey_0.jpg)

我告诉你一个秘密：使得我的应用程序进入到全世界的 DevOps 云计算之类的东西对我来说仍然有一点神秘。但随着时间流逝，我意识到理解大规模的机器增减和应用程序部署的来龙去脉对一个开发者来说是非常重要的知识。这类似于成为一个专业的音乐家，当然你肯定需要知道如何使用你的乐器，但是，如果你不知道一个录音棚是如何工作的，或者如何适应一个交响乐团，那么你在这样的环境中工作会变得非常困难。

在软件开发的世界里，使你的代码进入我们的更大的世界如同把它编写出来一样重要。DevOps 重要，而且是很重要。

因此，为了弥合开发（Dev）和部署（Ops）之间的空隙，我会从头开始介绍容器技术。为什么是容器？因为有强力的证据表明，容器是机器抽象的下一步：使计算机成为场所而不再是一个东西。理解容器是我们共同的旅程。

在这篇文章中，我会介绍容器化（containerization）背后的概念。包括容器和虚拟机的区别，以及容器构建背后的逻辑以及它是如何适应应用程序架构的。我会探讨轻量级的 Linux 操作系统是如何适应容器生态系统。我还会讨论使用镜像创建可重用的容器。最后我会介绍容器集群如何使你的应用程序可以快速扩展。

在后面的文章中，我会一步一步向你介绍容器化一个示例应用程序的过程，以及如何为你的应用程序容器创建一个托管集群。同时，我会向你展示如何使用 Deis 将你的示例应用程序部署到你本地系统以及多种云供应商的虚拟机上。

让我们开始吧。

### 虚拟机的好处 ###

为了理解容器如何适应事物发展，你首先要了解容器的前任：虚拟机。

[虚拟机][1] （virtual machine (VM)）是运行在物理宿主机上的软件抽象。配置一个虚拟机就像是购买一台计算机：你需要定义你想要的 CPU 数目、RAM 和磁盘存储容量。配置好了机器后，你为它加载操作系统，以及你想让虚拟机支持的任何服务器或者应用程序。

虚拟机允许你在一台硬件主机上运行多个模拟计算机。这是一个简单的示意图：

![](https://deis.com/images/blog-images/dev_journey_1.png)

虚拟机可以让你能充分利用你的硬件资源。你可以购买一台巨大的、轰隆作响的机器，然后在上面运行多个虚拟机。你可以有一个数据库虚拟机以及很多运行相同版本的定制应用程序的虚拟机所构成的集群。你可以在有限的硬件资源获得很多的扩展能力。如果你觉得你需要更多的虚拟机而且你的宿主硬件还有容量，你可以添加任何你需要的虚拟机。或者，如果你不再需要一个虚拟机，你可以关闭该虚拟机并删除虚拟机镜像。

### 虚拟机的局限 ###

但是，虚拟机确实有局限。

如上面所示，假如你在一个主机上创建了三个虚拟机。主机有 12 个 CPU，48 GB 内存和 3TB 的存储空间。每个虚拟机配置为有 4 个 CPU，16 GB 内存和 1TB 存储空间。到现在为止，一切都还好。主机有这个容量。

但这里有个缺陷。所有分配给一个虚拟机的资源，无论是什么，都是专有的。每台机器都分配了 16 GB 的内存。但是，如果第一个虚拟机永不会使用超过 1GB 分配的内存，剩余的 15 GB 就会被浪费在那里。如果第三个虚拟机只使用分配的 1TB 存储空间中的 100GB，其余的 900GB 就成为浪费空间。

这里没有资源的流动。每台虚拟机拥有分配给它的所有资源。因此，在某种方式上我们又回到了虚拟机之前，把大部分金钱花费在未使用的资源上。

虚拟机还有*另一个*缺陷。让它们跑起来需要很长时间。如果你处于基础设施需要快速增长的情形，即使增加虚拟机是自动的，你仍然会发现你的很多时间都浪费在等待机器上线。

### 来到：容器 ###

概念上来说，容器是一个 Linux 进程，Linux 认为它只是一个运行中的进程。该进程只知道它被告知的东西。另外，在容器化方面，该容器进程也分配了它自己的 IP 地址。这点很重要，重要的事情讲三遍，这是第二遍。**在容器化方面，容器进程有它自己的 IP 地址。**一旦给予了一个 IP 地址，该进程就是宿主网络中可识别的资源。然后，你可以在容器管理器上运行命令，使容器 IP 映射到主机中能访问公网的 IP 地址。建立了该映射，无论出于什么意图和目的，容器就是网络上一个可访问的独立机器，从概念上类似于虚拟机。

这是第三遍，容器是拥有不同 IP 地址从而使其成为网络上可识别的独立 Linux 进程。下面是一个示意图：

![](https://deis.com/images/blog-images/dev_journey_2.png)

容器/进程以动态、合作的方式共享主机上的资源。如果容器只需要 1GB 内存，它就只会使用 1GB。如果它需要 4GB，就会使用 4GB。CPU 和存储空间利用也是如此。CPU、内存和存储空间的分配是动态的，和典型虚拟机的静态方式不同。所有这些资源的共享都由容器管理器来管理。

最后，容器能非常快速地启动。

因此，容器的好处是：**你获得了虚拟机独立和封装的好处，而抛弃了静态资源专有的缺陷**。另外，由于容器能快速加载到内存，在扩展到多个容器时你能获得更好的性能。

### 容器托管、配置和管理 ###

托管容器的计算机运行着被剥离的只剩下主要部分的某个 Linux 版本。现在，宿主计算机流行的底层操作系统是之前提到的 [CoreOS][2]。当然还有其它，例如 [Red Hat Atomic Host][3] 和 [Ubuntu Snappy][4]。

该  Linux 操作系统被所有容器所共享，减少了容器足迹的重复和冗余。每个容器只包括该容器特有的部分。下面是一个示意图：

![](https://deis.com/images/blog-images/dev_journey_3.png)

你可以用它所需的组件来配置容器。一个容器组件被称为**层（layer）**。层是一个容器镜像，（你会在后面的部分看到更多关于容器镜像的介绍）。你从一个基本层开始，这通常是你想在容器中使用的操作系统。（容器管理器只提供你所要的操作系统在宿主操作系统中不存在的部分。）当你构建你的容器配置时，你需要添加层，例如你想要添加网络服务器时这个层就是 Apache，如果容器要运行脚本，则需要添加 PHP 或 Python 运行时环境。

分层非常灵活。如果应用程序或者服务容器需要 PHP 5.2 版本，你相应地配置该容器即可。如果你有另一个应用程序或者服务需要 PHP 5.6 版本，没问题，你可以使用 PHP 5.6 配置该容器。不像虚拟机，更改一个版本的运行时依赖时你需要经过大量的配置和安装过程；对于容器你只需要在容器配置文件中重新定义层。

所有上面描述的容器的各种功能都由一个称为容器管理器（container manager）的软件控制。现在，最流行的容器管理器是 [Docker][5] 和 [Rocket][6]。上面的示意图展示了容器管理器是 Docker，宿主操作系统是 CentOS 的主机情景。

### 容器由镜像构成 ###

当你需要将我们的应用程序构建到容器时，你就要编译镜像。镜像代表了你的容器需要完成其工作的容器模板。（容器里可以在容器里面，如下图）。镜像存储在注册库（registry）中，注册库通过网络访问。

从概念上讲，注册库类似于一个使用 Java 的人眼中的 [Maven][7] 仓库、使用 .NET 的人眼中的 [NuGet][8] 服务器。你会创建一个列出了你应用程序所需镜像的容器配置文件。然后你使用容器管理器创建一个包括了你的应用程序代码以及从容器注册库中下载的部分资源。例如，如果你的应用程序包括了一些 PHP 文件，你的容器配置文件会声明你会从注册库中获取 PHP 运行时环境。另外，你还要使用容器配置文件声明需要复制到容器文件系统中的 .php 文件。容器管理器会封装你应用程序的所有东西为一个独立容器，该容器将会在容器管理器的管理下运行在宿主计算机上。

这是一个容器创建背后概念的示意图：

![](https://deis.com/images/blog-images/dev_journey_4.png)

让我们仔细看看这个示意图。

（1）代表一个定义了你容器所需东西以及你容器如何构建的容器配置文件。当你在主机上运行容器时，容器管理器会读取该配置文件，从云上的注册库中获取你需要的容器镜像，（2）将镜像作为层添加到你的容器中。

另外，如果组成镜像需要其它镜像，容器管理器也会获取这些镜像并把它们作为层添加进来。（3）容器管理器会将需要的文件复制到容器中。

如果你使用了配置（provisioning）服务，例如 [Deis][9]，你刚刚创建的应用程序容器做成镜像，（4）配置服务会将它部署到你选择的云供应商上，比如类似 AWS 和 Rackspace 云供应商。

### 集群中的容器 ###

好了。这里有一个很好的例子说明了容器比虚拟机提供了更好的配置灵活性和资源利用率。但是，这并不是全部。

容器真正的灵活是在集群中。记住，每个容器有一个独立的 IP 地址。因此，能把它放到负载均衡器后面。将容器放到负载均衡器后面，这就上升了一个层面。

你可以在一个负载均衡容器后运行容器集群以获得更高的性能和高可用计算。这是一个例子：

![](https://deis.com/images/blog-images/dev_journey_5.png)

假如你开发了一个资源密集型的应用程序，例如图片处理。使用类似 [Deis][9] 的容器配置技术，你可以创建一个包括了你图片处理程序以及你图片处理程序需要的所有资源的容器镜像。然后，你可以部署一个或多个容器镜像到主机上的负载均衡器下。一旦创建了容器镜像，你可以随时使用它。当系统繁忙时可以添加更多的容器实例来满足手中的工作。

这里还有更多好消息。每次添加实例到环境中时，你不需要手动配置负载均衡器以便接受你的容器镜像。你可以使用服务发现技术让容器告知均衡器它可用。然后，一旦获知，均衡器就会将流量分发到新的结点。

### 全部放在一起 ###

容器技术完善了虚拟机缺失的部分。类似 CoreOS、RHEL Atomic、和 Ubuntu 的 Snappy 宿主操作系统，和类似 Docker 和 Rocket 的容器管理技术结合起来，使得容器变得日益流行。

尽管容器变得更加越来越普遍，掌握它们还是需要一段时间。但是，一旦你懂得了它们的窍门，你可以使用类似 [Deis][9] 这样的配置技术使容器创建和部署变得更加简单。

从概念上理解容器和进一步实际使用它们完成工作一样重要。但我认为不实际动手把想法付诸实践，概念也难以理解。因此，我们该系列的下一阶段就是：创建一些容器。

--------------------------------------------------------------------------------

via: https://deis.com/blog/2015/developer-journey-linux-containers

作者：[Bob Reselman][a]
译者：[ictlyh](http://www.mutouxiaogui.cn/blog/)
校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出

[a]:https://deis.com/blog
[1]:https://en.wikipedia.org/wiki/Virtual_machine
[2]:https://coreos.com/using-coreos/
[3]:http://www.projectatomic.io/
[4]:https://developer.ubuntu.com/en/snappy/
[5]:https://www.docker.com/
[6]:https://coreos.com/blog/rocket/
[7]:https://en.wikipedia.org/wiki/Apache_Maven
[8]:https://www.nuget.org/
[9]:http://deis.com/learn