Docker 和 Ansible 如何结合起来实施持续 Delivery/Continuous 部署

How Docker and Ansible fit together to implement Continuous Delivery/Continuous Deployment

我是配置管理和部署工具的新手。我必须为我做过的最有趣的项目之一实施连续 Delivery/Continuous 部署工具。

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

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

我的问题是:

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

假设我们有一个源代码存储库,团队成员完成了一项功能并推送了他们的工作。 Jenkins 检测到这一点,运行s 所有 acceptance/unit/integration 测试套件,如果它们都通过了,它就将其声明为稳定构建。 Docker 怎么放在这里?我的意思是,当团队推进他们的工作时,Jenkins 是否必须提取应用程序中编码的 Docker 文件源代码、构建应用程序的图像、启动容器以及 运行 针对它或它的所有测试运行s 以经典方式进行测试,如果一切正常,那么它会从 Docker 文件构建 Docker 图像并将其保存在私人位置? 例如,Jenkins 是否应该使用 x.y.z 标记最终图像!?

Docker 容器配置:

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

Ansible 和 Docker

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

如果问题很长或者我拼错了什么,请原谅,但这是我的想法。过去两周我被封锁了,我想不出正确的工作流程。我希望这可以成为未来读者的参考。

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

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

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

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

更广泛地说,我尝试过完全使用 Ansible 启动我们的应用程序,结果很糟糕,许多配置步骤都很棘手,当您尝试将它们作为剧本实施时会变得更加棘手。当我转而使用 Ansible 单独维护服务器,并使用 Docker 部署应用程序本身时,事情变得容易多了。

我想分部分回答

How does Docker (or Ansible and Docker) extend the Continuous Integration process!?

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

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

Docker containers configuration :

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

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

Does Ansible have to log in the Docker image, before it's running ( this sounds insane to me ) and use its Jinja2 templates the same way with a classic host!? If not, how is this handled?!

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

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

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