前面提到Es部署的问题,不可能手动去在每个集群节点上安装Es,要实现自动化部署和运维的方法最好的就是利用docker的性能来实现。
简单说下docker,里面有三个重要的概念:仓库、镜像、容器
Docker镜像
Docker镜像是一个只读的模板。举个例子,一个镜像可以包含一个运行在Apache上的Web应用和其使用的Ubuntu操作系统。
镜像是用来创建容器的。Docker提供了简单的放来来建立新的镜像或者升级现有的镜像,你也可以下载别人已经创建好的镜像。Docker镜像是Docker的 构造 部分。
Docker仓库
Docker仓库用来保存镜像。可以理解为代码控制中的代码仓库。同样的,Docker仓库也有公有和私有的概念。公有的Docker仓库名字是Docker Hub。Docker Hub提供了庞大的镜像集合供使用。这些镜像可以是你自己创建的,或者你也可以在别人的镜像基础上创建。Docker仓库是Docker的 分发 部分。
Docker容器
Docker容器和文件夹很类似。一个Docker容器包含了所有的某个应用运行所需要的环境。每一个Docker容器都是从Docker镜像创建 的。Docker容器可以运行、开始、停止、移动和删除。每一个Docker容器都是独立和安全的应用平台。Docker容器是Docker的 运行 部分。
Docker镜像是如何工作的
我们已经看到了,Docker镜像是Docker容器运行时的只读模板。每一个镜像由一系列的层(layers)组成。Docker使用UnionFS来将这些层联合到一二镜像中。Union文件系统允许独立文件系统中的文件和文件夹(称之为分支)被透明覆盖,形成一个单独连贯的文件系统。
正因为有了这些层的存在,Docker是如此的轻量。当你改变了一个Docker镜像,比如升级到某个程序到新的版本,一个新的层会被创建。因此, 不用替换整个原先的镜像或者重新建立(在使用虚拟机的时候你可能会这么做),只是一个新的层被添加或升级了。现在你不用重新发布整个镜像,只需要升级。层 使得奋发Docker镜像变得简单和快速。
每个镜像都是从一个基础的镜像开始的,比如ubuntu
,一个基础的Ubuntu镜像,或者是fedora
,一个基础的Fedora镜像。你可以使用你自己的镜像作为新镜像的基础,例如你有一个基础的安装了Apache的镜像,你可以使用该镜像来建立你的Web应用程序镜像。
Docker仓库是如何工作的
Docker仓库是Docker镜像的存储仓库。你可以推送你的镜像到你的Docker仓库中。
通过Docker客户端,你可以从Docker仓库中搜索镜像。
Docker容器是如何工作的
一个Docker容器包含了一个操作系统、用户添加的文件和元数据(meta-data)。我们可以看到,每个容器都是从镜像建立的。镜像告诉 Docker容器内包含了什么,当容器启动时运行什么程序,还有许多配置数据。Docker镜像是只读的。当Docker运行一个从镜像建立的容器,它会 在镜像顶部添加一个可读写的层,应用程序可以在这里运行。
当你运行docker容器时发生了什么
不论你使用docker
命令或者是RESTful API,Docker客户端都会告诉Docker守护进程运行一个容器。
$ sudo docker run -i -t ubuntu /bin/bash
让我们来分析这个命令。Docker客户端使用docker
命令来运行,run
参数表名客户端要运行一个新的容器。Docker客户端要运行一个容器需要告诉Docker守护进程的最小参数信息是:
- 这个容器从哪个镜像创建,这里是
ubuntu
,基础的Ubuntu镜像。 - 在容器中要运行的命令,这里是
/bin/bash
,在容器中运行Bash shell。
那么运行这个命令之后在底层发生了什么?
按照顺序,Docker做了这些事情:
- 拉取
ubuntu
镜像: Docker检查ubuntu
镜像是否存在,如果在本地没有该镜像,Docker会从Docker Hub下载。如果镜像已经存在,Docker会使用它来创建新的容器。 - 创建新的容器: 当Docker有了这个镜像之后,Docker会用它来创建一个新的容器。
- 分配文件系统并且挂载一个可读写的层: 容器会在这个文件系统中创建,并且一个可读写的层被添加到镜像中。
- 分配网络/桥接接口: 创建一个允许容器与本地主机通信的网络接口。
- 设置一个IP地址: 从池中寻找一个可用的IP地址并且服加到容器上。
- 运行你指定的程序: 运行指定的程序。
- 捕获并且提供应用输出: 连接并且记录标准输出、输入和错误让你可以看到你的程序是如何运行的。
你现在拥有了一个运行着的容器!从这里开始你可以管理你的容器,与应用交互,应用完成之后,可以停止或者删除你的容器。
底层技术
Docker使用Go语言编写,并且使用了一系列Linux内核提供的性能来实现我们已经看到的这些功能。
命名空间(Namespaces)
Docker充分利用了一项称为namespaces
的技术来提供隔离的工作空间,我们称之为 container(容器)。当你运行一个容器的时候,Docker为该容器创建了一个命名空间集合。
这样提供了一个隔离层,每一个应用在它们自己的命名空间中运行而且不会访问到命名空间之外。
一些Docker使用到的命名空间有:
pid
命名空间: 使用在进程隔离(PID: Process ID)。net
命名空间: 使用在管理网络接口(NET: Networking)。ipc
命名空间: 使用在管理进程间通信资源 (IPC: InterProcess Communication)。mnt
命名空间: 使用在管理挂载点 (MNT: Mount)。uts
命名空间: 使用在隔离内核和版本标识 (UTS: Unix Timesharing System)。
群组控制
Docker还使用到了cgroups
技术来管理群组。使应用隔离运行的关键是让它们只使用你想要的资源。这样可以确保在机器上运行的容器都是良民(good multi-tenant citizens)。群组控制允许Docker分享或者限制容器使用硬件资源。例如,限制指定的容器的内容使用。
联合文件系统
联合文件系统(UnionFS)是用来操作创建层的,使它们轻巧快速。Docker使用UnionFS提供容器的构造块。Docker可以使用很多种类的UnionFS包括AUFS, btrfs, vfs, and DeviceMapper。
容器格式
Docker连接这些组建到一个包装中,称为一个 container format(容器格式)。默认的容器格式是libcontainer
。Docker同样支持传统的Linux容器使用LXC。在未来,Docker也许会支持其它的容器格式,例如与BSD Jails 或 Solaris Zone集成。