Docker 和 Ansible 如何配合以实现持续交付/持续部署

Posted

技术标签:

【中文标题】Docker 和 Ansible 如何配合以实现持续交付/持续部署【英文标题】:How Docker and Ansible fit together to implement Continuous Delivery/Continuous Deployment 【发布时间】:2016-09-26 17:45:29 【问题描述】:

我是配置管理和部署工具的新手。我必须为我参与过的最有趣的项目之一实施持续交付/持续部署工具。

首先,就个人而言,我对AWS 很满意,我知道Ansible 是什么,它背后的逻辑及其用途。我对Docker 的理解程度不同,但我明白了。我浏览了很多互联网资源,但我无法了解大局。

我一直在努力的是它们如何结合在一起。使用Ansible,我可以将我的基础架构作为代码进行管理;构建EC2 实例、安装包...我什至可以通过拉取其代码、修改配置文件和启动 Web 服务器来部署完整的应用程序。 Docker 本身就是一个打包应用程序并确保它可以在您部署的任何地方运行的工具。

我的问题是:

Docker(或 Ansible 和 Docker)如何扩展持续集成流程!?

假设我们有一个源代码存储库,团队成员完成了一项功能的工作并推送他们的工作。 Jenkins 检测到这一点,运行所有验收/单元/集成测试套件,如果它们都通过了,它会声明它是一个稳定的构建。 Docker 如何适合这里?我的意思是当团队推动他们的工作时,Jenkins 是否必须提取应用程序中编码的 Docker 文件源、构建应用程序的映像、启动容器并针对它运行所有测试,或者它以经典方式运行测试,如果一切都很好,然后它从 Docker 文件构建 Docker 映像并将其保存在私有位置? 例如,Jenkins 是否应该使用 x.y.z 标记最终图像!?

Docker 容器配置:

假设我们有一个由Jenkins 构建的图像存储在某个地方,如何处理将相同的图像部署到不同的环境,甚至不同的配置参数(Vhosts 配置、DB 主机、队列 URL、S3 端点等... ) 在不违反Docker 原则的情况下处理此问题的最灵活方法是什么?这些配置在构建时或基于它的容器启动时是否支持在镜像中,如果是,它们是如何注入的?

Ansible 和 Docker

Ansible 提供了一个Docker 模块来管理Docker 容器。假设我解决了上面提到的问题,当我想部署我的应用程序的新版本 xtz 时,我告诉 Ansible 从它存储的位置拉取该图像,启动应用程序容器,那么如何注入配置设置! ? Ansible 是否必须在运行之前登录 Docker 映像(这对我来说听起来很疯狂)并以与经典主机相同的方式使用其 Jinja2 模板!?如果没有,这怎么处理?!

如果这是一个很长的问题或者我拼错了什么,请原谅,但这是我的想法。过去两周我被阻止了,我无法弄清楚正确的工作流程。我希望这可以作为未来读者的参考。

请阅读您的经验和解决方案非常有帮助,因为这看起来像是一个常见的工作流程。

【问题讨论】:

Ansible + Docker == 魔法!这是一篇很棒的博文:developer.rackspace.com/blog/ansible-and-docker,ansiblefordevops.com 中还有一个专门介绍 Ansible + Docker 的部分 【参考方案1】:

关于您关于使用同一个 Docker 映像处理多个环境配置的问题,我一直计划使用像 Consul 这样的服务发现工具作为集中式配置/属性管理工具。所以,当你启动你的容器时,你设置了一个 ENV 变量,告诉它它是什么应用程序(appID),它应该使用什么环境配置(例如:MyApplication:Dev),它会在启动时从 Consul 中提取它的配置。我仍然需要调查 Consul 周围的安全性(例如,就好像我们在其中存储数据库连接凭据一样,我们如何限制谁可以查询/更新这些值)。我不想只将它用于容器,而是用于所有应用程序。另一个很酷的功能是更改 Consul 中的配置值,并在您的应用程序中有一个挂钩以立即应用更改(可能就像应用程序上的 REST 端点将更改推送到并动态应用它)。当然,必须编写您的应用程序来支持这一点!

您可能有兴趣查看 Martin Fowler 在 immutable infrastructure 和 Phoenix servers 上的博客文章。

【讨论】:

【参考方案2】:

我想分部分回答

Docker(或 Ansible 和 Docker)如何扩展持续集成过程!?

由于 docker 镜像在任何地方都相同,因此您可以像使用生产镜像一样使用您的 docker 镜像。因此,当有人提交代码时,您将构建您的 docker 映像。你对它运行测试。当所有测试都通过时,您相应地标记该图像。由于 docker 速度很快,这是一个可行的工作流程。 码头工人的变化也是增量的;因此,您的图像对存储的影响最小。此外,当您的测试失败时,您也可以选择保存该图像。这样,开发人员将提取该图像并轻松调查您的测试失败的原因。开发人员也可以选择在他们的机器上运行测试,因为 jenkins 中的 docker 镜像和他们的机器没有什么不同。

这会带来什么,所有开发人员将拥有相同的环境,所有软件的相同版本,因为您决定将在 docker 映像中使用哪一个。我遇到过由于开发人员机器之间的差异而导致的错误。例如在同一操作系统中,unicode 设置可能会影响您的代码。但在 docker 镜像中,所有开发人员都将针对相同的设置、相同的软件版本进行测试。

Docker 容器配置:

如果您使用的是私有存储库,并且应该使用一个,那么配置更改不会对硬盘空间造成太大影响。因此,除了安全配置,例如 db 密码,您可以将配置更改应用于 docker 镜像(Baking the Configuration into the Container)。然后,您可以使用 ansible 在启动之前/之后使用环境变量或 Docker 卷将未存储的配置应用于已部署的映像。

https://dantehranian.wordpress.com/2015/03/25/how-should-i-get-application-configuration-into-my-docker-containers/

Ansible 在运行之前是否必须登录 Docker 映像( 这对我来说听起来很疯狂)并以同样的方式使用它的 Jinja2 模板 与经典主机!?如果没有,这怎么处理?!

不,ansible 不会登录 Docker 镜像,但是可以使用带有 Jinja2 模板的 ansible 来更改 dockerfile。您可以使用模板更改 dockerfile 并将您的配置注入不同的文件。相应地标记您的文件,并且您已将图像配置为启动。

【讨论】:

我只是不明白 Ansible 适合哪里??!编排的事?!【参考方案3】:

虽然不是一个完整的解决方案,但我对您的两个问题提出了建议。尽管它们可能并不完美,但这些是我们在工作流程中使用的做法,并且到目前为止证明了自己。

    定义不同的环境 - 假设您为启动的每个环境编写了不同的 Ansible 角色,我们定义一个环境变量来设置我们希望容器所属的环境。然后,我们使用之前设置的 env 变量从 S3 存储桶下载合适的配置文件到容器中(如果您提供 AWS 凭据或为您的服务器提供 IAM 角色,这应该是可能的)并在构建时将这些参数注入代码中。

    Ansible 不需要登录 docker 应用,但解决方案有点棘手。我尝试了两种解决这个问题的方法,但都不是很理想。第一个是下载配置文件作为 docker image 命令行的一部分,并在容器启动时构建应用程序。虽然此解决方案有效 - 它违反了 Docker 理念,并使映像极易出现构建错误。 另一种解决方案是将多个图像推送到您的 docker hub 存储库,然后根据手头的环境拉取适当的图像。

在更广泛的范围内,我尝试完全使用 Ansible 启动我们的应用程序,这简直是地狱,许多配置步骤很棘手,当您尝试将它们实现为剧本时会变得更加棘手。当我转而使用 Ansible 单独维护服务器,并使用 Docker 部署应用程序本身时,事情变得容易得多。

【讨论】:

刚开始时,最好将 Docker 视为一种应用程序打包技术。这有助于解释为什么 Ansible 能很好地补充它。最简单的是需要安装 Docker 并启动容器。最后,我建议查看一些支持直接部署 Docker 应用程序的新兴技术:Docker Swarm、Kubernetes 和 Marathon/Mesos。诚然,与 Ansible 相比更复杂,但还有其他值得探索的优点。

以上是关于Docker 和 Ansible 如何配合以实现持续交付/持续部署的主要内容,如果未能解决你的问题,请参考以下文章

利用Docker/Ansible实现轻量集群服务部署

使用Vagrant和Ansible

Ansible和Docker的作用和用法

基于Ansible+Docker快速实现DCOS云平台部署(有彩蛋)

如何使用Ansible自动化部署Docker镜像

如何使用Ansible自动化部署Docker镜像