如何使用 Docker 实现"One Binary"原则



这里解释的一元原理:http://programmer.97things.oreilly.com/wiki/index.php/One_Binary声明一个人应该。。。

"构建一个二进制文件,您可以在发布管道的所有阶段识别和升级它。在环境中保存特定于环境的详细信息。例如,这可能意味着将它们保存在组件容器、已知文件或路径中。"

我看到许多开发人员违反了这一原则,他们为每个环境创建了一个docker映像(例如,我的应用qa、我的应用prod等等)。我知道Docker喜欢不可变的基础设施,这意味着在部署后不更改映像,因此在部署后不会上传或下载配置。不可变基础设施和一元原理之间是否存在权衡,或者它们是否可以互补?当谈到将配置与代码分离时,Docker世界中的最佳实践是什么???应该采取以下哪种方法。。。

1) 创建一个基本二进制映像,然后有一个配置Dockerfile,通过添加特定于环境的配置来增强该映像。(即我的应用->我的应用产品)

2) 将仅二进制的docker映像部署到容器,并在部署时通过环境变量等传递配置。

3) 将Docker文件部署到容器后上传配置

4) 从配置管理服务器从容器内正在运行的docker映像下载配置。

5) 将配置保留在主机环境中,并通过绑定装载使其可用于正在运行的Docker实例。

还有其他更好的方法没有提到吗?

如何使用不可变的基础设施来执行一个二进制原则?这是可以做到的,还是有一种权衡?什么是最佳实践??

我现在有大约2年的部署Docker容器的经验,所以我将谈谈我已经做了什么和/或知道如何工作。

所以,让我首先说容器绝对应该是不可变的(我甚至把我的标记为只读)。

主要方法:

  • 通过设置静态入口点来使用配置文件,并通过覆盖容器启动命令来覆盖配置文件位置——这就不那么灵活了,因为必须提交更改并重新部署才能启用它;不适用于密码、安全令牌等
  • 通过用环境变量覆盖配置文件的位置来使用配置文件——同样,这取决于是否提前准备好配置文件;不适用于密码、安全令牌等
  • 使用环境变量-这可能需要在部署代码中进行更改,从而减少配置更改的时间,因为它不需要经过应用程序构建阶段(在大多数情况下),部署这样的更改可能非常容易。这里有一个例子——如果将容器化应用程序部署到Marathon,那么更改环境变量可能只会从上次使用的容器映像启动一个新容器(甚至可能在同一主机上),这意味着这只需几秒钟即可完成;不适合密码、安全令牌等,尤其是Docker
  • 将配置存储在像Consul这样的k/v存储中,让应用程序意识到这一点,甚至可以动态重新配置。同时启动功能的好方法-甚至可能跨多个服务;如果使用HashiCorp Vault这样的解决方案来实现,则可以为敏感信息提供安全存储,甚至可以拥有短暂的机密(例如PostgreSQL Vault的机密后端-https://www.vaultproject.io/docs/secrets/postgresql/index.html)
  • 在启动主应用程序之前,让应用程序或脚本创建配置文件-将配置存储在像Consul这样的k/v存储中,使用像Consul模板这样的东西来填充应用程序配置;更安全一点——因为你没有把所有的东西都作为代码通过整个管道
  • 在启动主应用程序之前,让应用程序或脚本填充环境变量,例如envconsur;不适合敏感信息-有权访问Docker API(通过TCP或UNIX套接字)的人将能够读取
  • 我甚至遇到过这样的情况,我们将变量填充到AWS的实例user_data中,并在启动时将它们注入容器中(使用一个在启动时修改容器json-config的脚本)

我要考虑的主要事项:

  • 我暴露的变量是什么?我从何时何地获得它们的值(可能是CD软件或其他什么)-例如,你可以将AWS RDS端点和凭据发布到实例的user_data,甚至可能是带有IAM实例配置文件魔力的EC2标记
  • 我们需要管理多少变量,我们多久更改一次其中的一些变量-如果我们有少数变量,我们可能只使用环境变量,或者使用环境变量来处理最常更改的变量,使用存储在文件中的变量来处理那些我们更改频率较低的变量
  • 以及我们希望以多快的速度看到它们被更改——如果是一个文件,通常需要更多的时间将其部署到生产中;如果我们使用环境变量s、 我们通常可以更快地部署这些更改
  • 我们如何保护其中的一些——我们在哪里注入它们以及如何——例如Ansible Vault、HashiCorp Vault,将它们保存在单独的回购中,等等
  • 我们如何部署-可以是发送到部署框架端点Ansible等的JSON配置文件
  • 我们现在的环境是什么?将Consul这样的东西作为配置数据存储是否现实(Consul有两种不同的代理-客户端和服务器)

我倾向于选择最复杂的情况,将它们存储在一个中心位置(k/v商店、数据库)并动态更改,因为我遇到了以下情况:

  • 部署管道缓慢-这使得更改配置文件并部署它的速度非常慢
  • 有太多的环境变量-这可能真的会失控
  • 必须在整个机队(由数十个服务组成)中同时打开功能标志
  • 一个真正努力通过更好地处理敏感配置数据来提高安全性的环境

我可能错过了一些东西,但我想这应该足以引发思考什么对您的环境最有利

我过去的做法是在执行构建后将标记化结合到打包过程中。这些令牌可以在位于顶部的编排层中进行管理,以管理您的平台工具。因此,对于给定的令牌,有一个匹配的regex或xpath表达式。该令牌链接到一个或多个配置文件,具体取决于所选择的关系。然后,当这个构建部署到容器中时,平台服务(即config-mgmt)将根据其环境为这些令牌戳入正确的值。这些poke值很可能是从vault中提取的。

相关内容

  • 没有找到相关文章

最新更新