如何用 Ansible用docker 部署集群 Kubernetes 集群到 OpenStack

中国领先的IT技术网站
51CTO旗下网站
如何让 Ansible 和 Docker 愉快地在一起
Docker 和它的容器工作流可封装、共享和部署您的应用程序环境。Ansible 是一个与 Docker 高度兼容的自动化工具,它使用一个强大的接口来管理远程服务器上的容器。在本文中,我将探索为何和如何使用 Ansible 的可扩展设计来将 Docker 和 Ansible 的最佳功能合并在一起。
作者:Xavier Bruhiere来源:ibm developerWorks 中国| 16:48
Docker 之所以如此流行,是因为它创造了一种采用方便的命令行接口 (CLI) 和 HTTP API 工具来封装、运行和维护容器的独特方式。这种简化降低了此技术的入门门槛,使得将应用程序及其运行时环境封装到一个简单 Dockerfile 中的独立镜像中变得可行。Docker 使您能够开发更复杂的项目,但您仍需要配置这些容器。在本文中,我将展示 Ansible 如何通过更清晰的语法带来配置管理器的特性。您将学习如何仅使用已安装的 Python 和 Docker 构建任何堆栈。
在介绍 Ansible 的细节之前,我首先将介绍 Ansible 的 分析 中提到的一些要点:
尽管容器导致一些新工作流出现,但编排和配置工具仍然非常活跃。
Ansible 和 Salt 等新参与者正在挑战现有的工具,比如 Chef 和 Puppet。
许多与 Docker 有关联的开发人员也很关心这些工具。
更确切地讲,借助 Docker,您可以在几秒内实现完全隔离的堆栈环境,或者在服务器之间复制准确的设置。但是,Docker 不包含提供端到端体验的可靠工具,无论是针对开发还是生产。Docker 团队通过新的集群工具解决了这些不断演变的挑战,尝试将 Docker 转变为一个大规模运行容器的可靠解决方案。然而,Docker 仍然需要您手动硬编码任务和重复常见的设置。所以,针对容器的编排和配置管理的关键 Docker 流程仍有待解决。在本文中,您将学习如何结合使用 Ansible 和 Docker 来帮助解决这些问题。
DevOps 的兴起
在部署到生产中之前,现代应用程序通常涉及到一个复杂的部署管道。最佳实践建议在每次小型迭代后尽早地、频繁地发布代码。任务的手动执行无法扩展,组织已开始完善介于开发人员与系统管理员之间的流程,所以 DevOps 就诞生了。从那时起,敏捷团队就开始尝试强化和自动化测试代码,以及将其交付给用户的方式。
通过实现最新的技术和方法,公司对其服务器上的代码建立了信心。然而,随着应用程序在规模和复杂性上不断增长,开发人员和系统管理员继续面临着无数挑战。现在比以往更需要为产品提供受支持的社区驱动工具。
Ansible 的可扩展设计
在此环境中,Ansible 提供了一个有趣的框架来管理基础架构。您可以获得服务器定义的控制权,比如要安装的包或要复制的文件,并将该配置扩展到数千个服务器。Ansible playbook 构成了集群的目标状态的一种安全表示。它的 YAML 语法和庞大的模块列表生成了任何开发人员都能快速理解的易读性配置文件。不同于 Chef 或 Puppet,Ansible 是无代理的,这意味着您要在远程主机上运行命令,只需一个 SSH 连接即可。可以看到,Ansible 可轻松地处理 DevOps 复杂性。
但是,Ansible 是在容器快速兴起和它们在云开发环境中带来革命之前设计的。那么 Ansible 是否仍然有用?微型服务的范式和复杂开发环境引入了新的需求:
轻量型镜像。为了容易传输或节省成本,镜像被剥离到仅剩下最低限度的依赖项。
单一用途,单一流程。如果应用程序不是非常需要 SSH 守护进程,则无需运行它。
短暂性。容器随时可能死亡、转移和复活。
在此上下文中,Ansible 的可扩展架构解决了这些问题。一个 Docker 模块在较高层面上管理主机和容器。尽管您可能会争论哪个编排工具(来自 Google 的 Kubernetes,还是来自 New Relic 的 Centurion)最适合此环境,但 Docker 模块执行效率很高,这正是我在本文中使用它的原因。但是,您还可以构建从其官方 Ansible 镜像启动的容器,然后在本地模式下从内部运行 playbook。尽管此方法非常适合 Packer,而且肯定也适合许多使用情况,但它的缺点通常极为关键。
您被锁定在一个基础镜像中,无法再利用特殊的秘诀或其他堆栈。
最终的工件已安装 Ansible 和它的依赖项,它们与实际应用程序毫无关系,这让工件变得更笨重。
尽管 Ansible 可管理数千个服务器,但它只配备(Provision)了一个容器。
此方法将容器视为小型 VM,您可以在其中使用一个特定的解决方案。幸运的是,Ansible 拥有模块化设计。模块分散在不同的存储库中,而且 Ansible 的大部分功能都可以通过插件进行扩展。
在下一节中,您将设置一个有效的环境,针对您的需求来调整 Ansible。
设置一个 Ansible 环境
假设您想要一个很容易部署的工具,它在轻量型容器中配置应用程序环境。由于与这些容器分离,您需要一个安装了 Ansible 的客户端,您将使用它来向 Docker 守护进程发送命令。此设置如 图 1 中所示。
图 1. 使用 Ansible 配备容器所需的组件
您在此配置中必须管理的依赖项,已通过从容器中运行 Ansible 来最小化。此架构将主机限制为容器与命令之间的一个通信桥梁。
可通过许多选项在您服务器上安装 Docker:
使用 docker-machine 将它安装在远程主机上。
安装在本地。顺便说一下,您可能不想亲自管理一个严格基于容器的基础架构;在这种情况下,可以考虑采用外部提供程序。
依赖于外部提供程序。
使用 boot2docker,这是一个在 Windows 和 Mac 上运行 Docker 容器的轻量型 Linux 发行版。
无论选择何种解决方案,请确保部署了 Docker 1.3 版或更高版本(1.3 版引入了进程注入)。您还需要运行一个 SSH 服务器来安全地处理 Ansible 命令。
清单 1 中的命令使用公钥设置了一种方便可靠的身份验证方法。
清单 1. 使用公钥设置身份验证的命令
#&install&dependencies&sudo&apt-get&install&-y&openssh-server&libssl-dev&#&generate&private&and&public&keys&ssh-keygen&-t&rsa&-f&ansible_id_rsa&#&allow&future&client&with&this&public&key&to&connect&to&this&server&cat&ansible_id_rsa.pub&&&&~/.ssh/authorized_keys&#&setup&proper&permissions&chmod&0700&&~/.ssh/&chmod&0600&&~/.ssh/authorized_keys&#&make&sure&the&daemon&is&running&sudo&service&ssh&restart&
配置 SSH 和安全性问题不属于本文的讨论范围。细心的读者可查阅 /etc/ssh/sshd_config 文件,进一步了解配置 SSH 的可用选项。
下一步是将公钥加载到运行 Ansible 的客户端容器上并配备构建器容器。使用一个 Dockerfile 来配备构建器。参见 清单 2。
清单 2. 配备构建器的 Dockerfile
FROM&python:2.7&&#&Install&Ansible&from&source&(master)&RUN&apt-get&-y&update&&&&\&&&&&apt-get&install&-y&python-httplib2&python-keyczar&python-setuptools&python-pkg-resources&git&python-pip&&&&\&&&&&apt-get&clean&&&&rm&-rf&/var/lib/apt/lists/*&/tmp/*&/var/tmp/*&RUN&pip&install&paramiko&jinja2&PyYAML&setuptools&pycrypto&=2.6&six&\&&&&&requests&docker-py&&#&docker&inventory&plugin&RUN&git&clone&http:&&&&&cd&/opt/ansible&&&&\&&&&&git&reset&--hard&fbec8bfb90df1d2e8a0a4df7ac1ddde&&&&\&&&&&git&submodule&update&--init&&ENV&PATH&/opt/ansible/bin:$PATH&ENV&PYTHONPATH&$PYTHONPATH:/opt/ansible/lib&ENV&ANSIBLE_LIBRARY&/opt/ansible/library&&#&setup&ssh&RUN&mkdir&/root/.ssh&ADD&ansible_id_rsa&/root/.ssh/id_rsa&ADD&ansible_id_rsa.pub&/root/.ssh/id_rsa.pub&&#&extend&Ansible&#&use&an&inventory&directory&for&multiple&inventories&support&RUN&mkdir&-p&/etc/ansible/inventory&&&&\&&&&&cp&/opt/ansible/plugins/inventory/docker.py&/etc/ansible/inventory/&ADD&ansible.cfg&&/etc/ansible/ansible.cfg&ADD&hosts&&/etc/ansible/inventory/hosts&
这些指令改编自官方构建版本,自动化了一次来自 Ansible 主分支上的提交 fbec8bfb90df1d2e8a0a4df7ac1ddde 有效安装。
主机和 ansible.cfg 配置文件(参见 清单 3 和 清单 4)已封装。通过使用容器,可以确保您将共享同一个环境。在本示例中,Dockerfile 安装了 Python 2.7.10 版和 Ansible 2.0.0。
清单 3. 主机配置文件
#&hosts&#&this&file&is&an&inventory&that&Ansible&is&using&to&address&remote&servers.&&Make&sure&to&replace&the&information&with&your&specific&setup&and&variables&&that&you&don't&want&to&provide&for&every&command.&&[docker]&#&host&properties&where&docker&daemon&is&running&192.168.0.12&ansible_ssh_user=xavier&
清单 4. Ansible 配置文件
#&ansible.cfg&&[defaults]&&#&use&the&path&created&from&the&Dockerfile&inventory&=&/etc/ansible/inventory&&#&not&really&secure&but&convenient&in&non-interactive&environment&host_key_checking&=&False&#&free&you&from&typing&`--private-key`&parameter&priva_key_file&=&~/.sh/id_rsa&&#&tell&Ansible&where&are&the&plugins&to&load&callback_plugins&&&=&/opt/ansible-plugins/callbacks&connection_plugins&=&/opt/ansible-plugins/connections&
在构建 Ansible 容器之前,您必须导出 DOCKER_HOST 环境变量,因为 Ansible 将使用它连接到远程 Docker 守护进程。在使用 HTTP 端点时,需要修改 /etc/default/docker(参见 清单 5)。
清单 5. 修改 /etc/default/docker
#&make&docker&to&listen&on&HTTP&and&default&socket&DOCKER_OPTS=&-H&tcp://0.0.0.0:2375&-H&unix:///var/run/docker.sock&&
输入命令 sudo service docker restart 来重新启动 Docker 守护进程,以便让对它的配置文件的更改生效。
以下命令将会构建并验证您用来输入命令的 Ansible 容器(参见 清单 6)。
清单 6. 构建和验证 Ansible 容器的命令
#&you&need&DOCKER_HOST&variable&to&point&to&a&reachable&docker&daemon&#&pick&the&method&that&suits&your&installation&&#&for&boot2docker&users&eval&&$(boot2docker&shellinit)&&#&for&docker-machine&users,&provisioning&the&running&VM&was&named&&dev&&eval&&$(docker-machine&env&dev)&&#&for&users&running&daemon&locally&export&DOCKER_HOST=tcp:&#&finally&users&relying&on&a&remote&daemon&should&provide&the&server's&public&ip&export&DOCKER_HOST=tcp:&&#&build&the&container&from&Dockerfile&docker&build&-t&article/ansible&.&&#&provide&server&API&version,&as&returned&by&`docker&version&|&grep&-i&&server&api&`&#&it&should&be&at&least&greater&or&equal&than&1.8&export&DOCKER_API_VERSION=1.19&&#&create&and&enter&the&workspace&docker&run&-it&--name&builder&\&&&&&#&make&docker&client&available&inside&&&&&-v&/usr/bin/docker:/usr/bin/docker&\&&&&&-v&/var/run/docker.sock:/var/run/docker.sock&\&&&&&#&detect&local&ip&&&&&-e&DOCKER_HOST=$DOCKER_HOST&\&&&&&-e&DEFAULT_DOCKER_API_VERSION=DOCKER_API_VERSION&\&&&&&-v&$PWD:/app&-w&/app&\&&#&mount&the&working&space&&&&&article/ansible&bash&&#&challenge&the&setup&$&container&&&ansible&docker&-m&ping&192.168.0.12&|&SUCCESS&=&&{&&&&&&invocation&:&{&&&&&&&&&&module_name&:&&ping&,&&&&&&&&&&module_args&:&{}&&&&&},&&&&&&changed&:&false,&&&&&&ping&:&&pong&&}&
目前为止,一切顺利。您能够从容器输入命令。在下一节中,将对 Ansible 使用特定于 Docker 的扩展。
使用 playbook 和插件扩展 Ansible 环境
实质上,Ansible 通过 playbook 自动化了它的执行,这些 playbook 是指定要执行的每个任务和它们的属性的 YAML 文件(参见清单 7)。
Ansible 还使用了清单 (inventory) 来将用户提供的主机映射到基础架构中的具体端点。不同于上一节中使用的静态 hosts 文件,Ansible 也支持动态内容。内置的列表包含一个 Docker 插件,该插件可查询 Docker 守护进程并向 Ansible playbook 共享大量信息。
清单 7. 一个 Ansible playbook
#&provision.yml&&-&name:&debug&docker&host&&&hosts:&docker&&&tasks:&&&-&name:&debug&infrastructure&&&&&#&access&container&data&:&print&the&state&&&&&debug:&var=hostvars[&builder&][&docker_state&]&&#&you&can&target&individual&containers&by&name&-&name:&configure&the&container&&&hosts:&builder&&&tasks:&&&&-&name:&run&dummy&command&&&&&&command:&/bin/echo&hello&world&
清单 8 中的命令查询 Docker 主机,导入事实,打印一些事实,并使用它们对构建器容器执行第二个任务(如 清单 7 中所示)。
清单 8. 查询 Docker 主机的命令
ansible-playbook&provision.yml&-i&/etc/ansible/inventory&#&...&TASK&[setup]&********************************************************************&fatal:&[builder]:&FAILED!&=&&{&msg&:&&ERROR!&SSH&encountered&an&unknown&error&during&the&connection.&Re-run&the&command&using&-vvvv,&which&enables&SSH&debugging&output&to&help&diagnose&the&issue&,&&failed&:&true}&#&...&
Ansible 不能连接容器,因为它没有运行 SSH 服务器。SSH 服务器是一个要管理的额外进程,它与实际应用程序完全无关。在下一节中,我们将使用一个连接插件来排除此困难。
连接插件是实现传输命令(比如 SSH 或本地执行)的类。Docker 1.3 随带了 docker exec,并能够在容器命名空间内运行任务。此外,因为您之前已学习如何连接特定的目标容器,所以您可以使用此功能来处理 playbook。
像其他插件类型一样,连接挂钩(参见 清单 9)继承一个抽象类,会在您将其放到预期的目录(您在配置文件 ansible.cfg 中定义的是 /opt/ansible-plugins/connections)时自动可用。
清单 9. 连接插件
#&saved&as&./connection_plugins/docker.py&&import&subprocess&from&ansible.plugins.connections&import&ConnectionBase&&class&Connection(ConnectionBase):&&&&&@property&&&&&def&transport(self):&&&&&&&&&&&&&Distinguish&connection&plugin.&&&&&&&&&&&&&return&'docker'&&&&&def&_connect(self):&&&&&&&&&&&&&Connect&to&the&container.&Nothing&to&do&&&&&&&&&&&&&return&self&&&&&def&exec_command(self,&cmd,&tmp_path,&sudo_user=None,&sudoable=False,&&&&&&&&&&&&&&&&&&&&&&executable='/bin/sh',&in_data=None,&su=None,&&&&&&&&&&&&&&&&&&&&&&su_user=None):&&&&&&&&&&&&&Run&a&command&within&container&namespace.&&&&&&&&&&if&executable:&&&&&&&&&local_cmd&=&[&docker&,&&exec&,&self._connection_info.remote_addr,&executable,&'-c',&cmd]&&&&&else:&&&&&&&&&local_cmd&=&'%s&exec&&%s&&%s'&%&(&docker&,&self._connection_info.remote_addr,&cmd)&&&&&&self._display.vvv(&EXEC&%s&&%&(local_cmd),&host=self._connection_info.remote_addr)&&&&&p&=&subprocess.Popen(local_cmd,&&&&&&&&&shell=isinstance(local_cmd,&basestring),&&&&&&&&&stdin=subprocess.PIPE,&stdout=subprocess.PIPE,&&&&&&&&&stderr=subprocess.PIPE)&&&&&&stdout,&stderr&=&municate()&&&&&return&(p.returncode,&'',&stdout,&stderr)&&&&&&def&put_file(self,&in_path,&out_path):&&&&&&&&&&&&&Transfer&a&file&from&local&to&container&&&&&&&&&&&&&pass&&&&&&def&fetch_file(self,&in_path,&out_path):&&&&&&&&&&&&&Fetch&a&file&from&container&to&local.&&&&&&&&&&&&&pass&&&&&&def&close(self):&&&&&&&&&&&&&Terminate&the&connection.&Nothing&to&do&for&Docker&&&&&&&&&&&&pass&
此代码挂钩到 Ansible 模块中,以便通过一个本地 docker exec 而不是默认的 ssh 来运行命令。您需要重新排列一些设置步骤来告诉 Ansible 使用此插件(参见 清单 10)。
清单 10. docker exec 的连接插件
#&modify&the&builder&Dockerfile&to&upload&the&plugin&code&&where&Ansible&is&expecting&connection&plugins&echo&&ADD&connection_plugins/docker.py&/opt/ansible-plugins/connections/docker.py&&&&&Dockerfile&&#&then,&you&need&to&explicitly&tell&which&connection&hook&to&use&&when&executing&playbooks.&#&you&can&achieve&this&by&inserting&the&'connection'&property&at&the&top&&of&provision&tasks&in&provision.yml&&-&name:&configure&the&container&&&connection:&docker&&&hosts:&builder&&#&you&are&ready&to&redeploy&the&builder&container&&#&(providing&DOCKER_HOST&and&DOCKER_API_VERSION&are&still&set&like&before)&&#&rebuild&the&image&docker&build&-t&article/ansible&.&&#&restart&the&builder&environment&docker&run&-it&--name&builder&\&&&&&#&make&docker&client&available&inside&&&&&-v&/usr/bin/docker:/usr/bin/docker&\&&&&&-v&/var/run/docker.sock:/var/run/docker.sock&\&&&&&#&detect&local&ip&&&&&-e&DOCKER_HOST=$DOCKER_HOST&\&&&&&-e&DEFAULT_DOCKER_API_VERSION=DOCKER_API_VERSION&\&&&&&-v&$PWD:/app&-w&/app&\&&#&mount&the&working&space&&&&&article/ansible&bash&&#&rerun&provisioning&from&inside&ansible-playbook&-i&/etc/ansible/inventory&provision.yml&#&...&Hurrah,&full&green&output&...&
目前为止,您在容器中运行 Ansible 任务,对容器或主机没有太多需求。尽管此实现满足了初始需求,但仍有一些不严密的地方需要解决。
前面的代码在同一个节点上运行任务。一种更逼真的工作流会启动一个新基础镜像,配置它,最终提交、推送和关闭得到的工件。得益于 Ansible 中内置的 Docker 模块,这些步骤无需额外的代码即可实现(参见 清单 11)。
清单 11. Ansible 中启动一个新基础镜像的 Docker 模块
---&-&name:&initialize&provisioning&&&hosts:&docker&&&&-&name:&start&up&target&container&&&&&docker:&&&&&&&image:&python:2.7&&&&&&&name:&lab&&&&&&&pull:&missing&&&&&&&detach:&yes&&&&&&&tty:&yes&&&&&&&command:&sleep&infinity&&&&&&&state:&started&&&#&dynamically&update&inventory&to&make&it&available&down&the&playbook&&&-&name:&register&new&container&hostname&&&&&add_host:&name=lab&&-&name:&provision&container&&&connection:&docker&&&hosts:&lab&&&tasks:&&&&&&&#&...&&-&name:&finalize&build&&&hosts:&docker&&&tasks:&&&&&-&name:&stop&container&&&&&&&docker:&&&&&&&&&name:&lab&&&&&&&&&image:&python:2.7&&&&&&&&&state:&stopped&
前面已经提到过,自动命名和存储在成功配备后构建的镜像会很方便。不幸的是,Ansible 中的 Docker 模块没有实现方法来标记和推送镜像。您可以使用简单的 shell 命令来克服此限制(参见 清单 12)。
清单 12. 命名和存储镜像的 shell 命令
#&name&the&resulting&artifact&under&a&human&readable&image&tag&docker&tag&lab&article/lab:experimental&&#&push&this&image&to&the&official&docker&hub&#&make&sure&to&replace&'article'&by&your&own&Docker&Hub&login&()&#&(this&step&is&optional&and&will&only&make&the&image&available&from&any&docker&host.&&You&can&skip&it&or&even&use&your&own&registry)&docker&push&article/lab:experimental&
我们的工具正在成形,但它仍缺少一个必要特性:层缓存。
在使用 Dockerfile 构建容器时,通常需要迭代许多次才能完成。为了显著加快该过程,成功的步骤会被缓存并在后续运行中重用。
要复制此行为,我们的工具在每次成功完成任务后提交了容器状态。如果发生构建错误,该工具会从上次的快照位置重新启动配备过程。Ansible 承诺实现幂等的任务,所以以前成功的任务不会处理两次。
借助 Ansible,您可以使用回调插件来挂住任务事件(参见 清单 13)。这些类应实现了特定的回调,这些回调在 playbook 生命周期的各个步骤上触发。
清单 13. 挂住任务事件的回调插件
#&save&as&callback_plugins/docker-cache.py&import&hashlib&import&os&import&socket&&#&Hacky&Fix&`ImportError:&cannot&import&name&display`&#&pylint:&disable=unused-import&import&ansible.utils&import&requests&import&docker&&&class&DockerDriver(object):&&&&&&&&&Provide&snapshot&feature&through&'docker&commit'.&&&&&&&&&&def&__init__(self,&author='ansible'):&&&&&&&&&self._author&=&author&&&&&&&&&self._hostname&=&socket.gethostname()&&&&&&&&&try:&&&&&&&&&&&&&err&=&self._connect()&&&&&&&&&except&(requests.exceptions.ConnectionError,&docker.errors.APIError),&error:&&&&&&&&&&&&&ansible.utils.warning('Failed&to&contact&docker&daemon:&{}'.format(error))&&&&&&&&&&&&&#&deactivate&the&plugin&on&error&&&&&&&&&&&&&self.disabled&=&True&&&&&&&&&&&&&return&&&&&&&&&&self._container&=&self.target_container()&&&&&&&&&self.disabled&=&True&if&self._container&is&None&else&False&&&&&&def&_connect(self):&&&&&&&&&#&use&the&same&environment&variable&as&other&docker&plugins&&&&&&&&&docker_host&=&os.getenv('DOCKER_HOST',&'unix:///var/run/docker.sock')&&&&&&&&&#&default&version&is&current&stable&docker&release&(10/07/2015)&&&&&&&&&#&if&provided,&DOCKER_VERSION&should&match&docker&server&api&version&&&&&&&&&docker_server_version&=&os.getenv('DOCKER_VERSION',&'1.19')&&&&&&&&&self._client&=&docker.Client(base_url=docker_host,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&version=docker_server_version)&&&&&&&&&return&self._client.ping()&&&&&&def&target_container(self):&&&&&&&&&&&&&Retrieve&data&on&the&container&you&want&to&provision.&&&&&&&&&&&&&def&_match_container(metadatas):&&&&&&&&&&&&&return&metadatas['Id'][:len(self._hostname)]&==&self._hostname&&&&&&&&&&matchs&=&filter(_match_container,&self._client.containers())&&&&&&&&&return&matchs[0]&if&len(matchs)&==&1&else&None&&&&&&def&snapshot(self,&host,&task):&&&&&&&&&tag&=&hashlib.md5(repr(task)).hexdigest()&&&&&&&&&try:&&&&&&&&&&&&&feedback&=&self._mit(container=self._container['Id'],&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&repository='factory',&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&tag=tag,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&author=self._author)&&&&&&&&&except&docker.errors.APIError,&error:&&&&&&&&&&&&&ansible.utils.warning('Failed&to&commit&container:&{}'.format(error))&&&&&&&&&&&&&self.disabled&=&True&&&#&pylint:&disable=E1101&class&CallbackModule(object):&&&&&&&&Emulate&docker&cache.&&&&&Commit&the&current&container&for&each&task.&&&&&&This&plugin&makes&use&of&the&following&environment&variables:&&&&&&&&&-&DOCKER_HOST&(optional):&How&to&reach&docker&daemon.&&&&&&&&&&&Default:&unix:&&&&&&&&&-&DOCKER_VERSION&(optional):&Docker&daemon&version.&&&&&&&&&&&Default:&1.19&&&&&&&&&-&DOCKER_AUTHOR&(optional):&Used&when&committing&image.&Default:&Ansible&&&&&&Requires:&&&&&&&&&-&docker-py&&=&v0.5.3&&&&&&Resources:&&&&&&&&&-&http:&&&&&&&&&&&&&&_current_task&=&None&&&&&&def&playbook_on_setup(self):&&&&&&&&&&&&&initialize&client.&&&&&&&&&&&&&self.controller&=&DockerDriver(self.conf.get('author',&'ansible'))&&&&&&def&playbook_on_task_start(self,&name,&is_conditional):&&&&&&&&&self._current_task&=&name&&&&&&def&runner_on_ok(self,&host,&res):&&&&&&&&&if&self._current_task&is&None:&&&&&&&&&&&&&#&No&task&performed&yet,&don't&commit&&&&&&&&&&&&&return&&&&&&&&&self.controller.snapshot(host,&self._current_task)&
因为您已将代码上传到期望的位置,并重新构建了构建器容器,所以您可以像 docker exec 连接插件一样注册此插件。
清单 14. 注册回调插件的命令
#&modify&the&builder&Dockerfile&to&upload&the&code&where&Ansible&is&expecting&callback&plugins&echo&&ADD&callback_plugins/docker-cache.py&/opt/ansible-plugins/callbacks/docker-cache.py&&&&&Dockerfile&
重新构建构建器容器并重新运行 Ansible playbook 后,该模块会自动加载,您可以查看中间容器是如何创建的(参见 清单 15)。
清单 15. Docker 镜像
REPOSITORY&&&&&&&&&&TAG&&&&&&&&&&&&&&&&&&&&&IMAGE&ID&&&&&&&&&&&&CREATED&&&&&&&&&&&&&VIRTUAL&SIZE&factory&&&&&&&&&&&&&bc0fbc&&&&bbdfab2bd904&&&&&&&&32&seconds&ago&&&&&&829.8&MB&factory&&&&&&&&&&&&&d19d39e0f0e5c133&&&&ec&&&&&&&&55&seconds&ago&&&&&&785.2&MB&
配备是一个复杂流程,您在本教程中执行的实现为未来的开发奠定了基础。代码本身已经过简化,而且一些步骤仍需人类干预。缓存实现肯定值得更多关注,例如更具体的提交命名或清理技能。
尽管如此,您创建了一个可运行 Ansible playbook 来管理容器配置的工具。借助此实现,您可以通过为基础架构的微型服务来组合、重用和设置陈述性的构建文件,充分利用 Ansible 的全部威力。此解决方案可帮助避免锁定问题。您开发的插件包装了 playbook,您可对不同的目标重用这些 playbook,而且极低的需求使得该项目能兼容大部分提供程序。
原文链接:【编辑推荐】【责任编辑: TEL:(010)】
大家都在看猜你喜欢
聚焦热点热点聚焦关注
24H热文一周话题本月最赞
讲师:528人学习过
讲师:14526人学习过
讲师:706人学习过
精选博文论坛热帖下载排行
本书通过大量实例代码,以ECMA-262版本3为基础,结合JavaScript 1.5和JavaScript 5.5,由浅入深、循序渐进地介绍了JavaScript知识要点与编...
订阅51CTO邮刊

我要回帖

更多关于 weblogic集群部署应用 的文章

 

随机推荐