我应该如何存储环境变量?


11

这是一个有关环境变量/结构的方法和建议的非常广泛的问题。但是最终,我正在寻找非常具体的问题“我应该如何存储环境变量?”的答案。

首先进行一些澄清:

  • 对我来说,环境可以是3到10台服务器,并且是包含特定客户基础结构的一种方式。
  • 在每个环境中,都有一些变量,这些变量通常是由一些关键输入(名称,大小等)自动生成的。

就目前而言,我们将所有环境变量存储在这样的结构中:

<playbook>.yml                   # Various playbooks for deployment
roles/windows                    # Ansible role for Ubuntu
roles/ubuntu                     # Ansible role for Ubuntu
config/hosts/<name>.yml          # Ansible inventory
config/hosts/vars/<name>.json    # Environment specific variables 

现在,配置已被初始化为上述git存储库中的子模块。由于变量文件的更改非常频繁,这导致了数据更改的问题,两次提交之间发生了一次,两次甚至三遍,使得更改越来越难以跟踪。

正如我个人看到的那样,我们应该寻求以集中/可扩展的方式存储我们所有的客户变量,然后将其与的动态库存挂钩。

我了解有几种技术似乎可以满足要求,例如Consul,但它们似乎在服务于一个大型应用程序而不是许多较小的略有不同的应用程序的环境中效果最佳。

我基本上看到我们必须编写清单脚本,然后将所有数据推送到一个非专用的内置数据库中,然后继续进行,就好像什么都没有改变一样。我认为这可能是一种减少当前存储的大量数据的方法,也许是研究存储数据的不同方法,而不仅仅是扩展再次提供服务的方法。

我希望有人在必须处理许多较小的环境而不是一个,两个或三个大环境时,具有将基础结构实现为代码的某种经验。

有什么建议么?

Answers:


13

我已经以可扩展的方式运行了两次环境变量,但都没有达到理想的效果,因为正如我所发现的那样,正确处理是一件非常棘手的事情。我将在下面总结我的两种经验:

共同因素

  • 环境变量与原始源代码存储在单独的存储库中(它们一起被子调制,但仍基于单独的存储库)
  • 该工件及其变量有一个单独的“构建”过程。
  • 没有对环境变量不同的释放过程。如果要更改环境变量,则需要经过相同的更改审核委员会和常规

使用领事KV对

例如,环境变量是从工件存储库加载的(绝非原始git repo),并加载到命名空间的KV对树中

/env/dev1/my/application/v1.1.1

其中前面的dev1是环境的名称,my / application是应用程序的名称空间,而v1.1.1是要使用的环境变量的版本。

对于开发人员而言,所有这些都是看不见的。在运行时,平台会检查环境是否在当前领事群集中存在(如果没有问题且出错),然后它会检查应用程序名称空间的子树(这样,在一个应用程序中就不会有交叉污染的情况)引用另一个应用变量),然后从连接到可部署工件的标签获取配置的版本号。更新此标签是这里的关键,因为这意味着如果我们丢失了两个生产数据中心,则可以通过简单地从可部署工件中读取元数据并将所有环境变量加载到KV存储中来再次站起来。

这种方法的问题 开发人员总是(我每次都表示)总是找到一种将配置更改引入环境的方法,该更改对应用程序的运行方式有重大影响。因为最终总是比配置更改更容易获得批准的配置更改。

存储带有嵌入式变量的“部署”工件

这将工件的确切版本与配置版本紧密耦合。如果更改了配置,则必须重建此部署工件。

部署工件本身实际上是一个yaml文件,其中包含可发布二进制文件的URL以及附加到该文件的所有配置。

该平台包含用于读取变量的组件,然后在启动时将其输出到应用程序的进程树中。

到目前为止,这已经取得了很大的成功,因为存在一个我们可以追踪其历史的工件,并且可以将其保存到任何审查委员会中,并说:“这是我们唯一关心的工件,我们无需关注任何其他更改,仅对此事物进行更改”(即,要部署的应用程序版本,包含的环境变量等。

这使得开发人员尝试在其应用程序中构建逻辑将变得有些困难,该逻辑将根据变量更改其行为,因此他们可以在不经过适当测试周期的情况下进行更改。

奖励积分

考虑应用程序的机密。到目前为止,我们对此的解决方案是提供一个公共RSA密钥,开发团队可以使用它来加密扩展的Java密钥存储区(几乎每种语言的某个地方都有可以读取Java密钥存储区的库),然后将其视为第三种工件并被拉到服务器上,用我们的平台私钥解密,并在运行时提供给应用程序。

不可否认,机密管理是蠕虫病毒本身的罐头。但这可能值得考虑。


2
回复:申请的秘密,我建议考虑看看库(vaultproject.io),因为它也是Hashicorp的工具链和整合的一部分,而整齐地领事(和其他工具从盒)
迈克尔·布拉沃

鉴于hashicorp通常是多么出色,我对保管库实在不知所措。从本质上说,他们的产品与市场上其他产品的三个主要差距-1.“秘密秘密”本质上就是该模型所要解决的问题。我正在分片或使用HSM。但实际上,这只是秘密交易。2.工具兼容性,与其他工具不同,它不支持插件3.价格。当我告诉公司我认为保管库很昂贵时,我不敢相信。他们拒绝了产品,因为它们太便宜了,结果搞砸了。但是金库如此之大,以至于他们甚至都没有考虑。
hvindin

值得注意的是,如果您使用付费版本,这只会使成本高昂。Vault的核心产品是开源的。当然,他们没有在他们的网站上列出专业版/企业版的价格,因此我不知道这些版本的价格有多不合理。
阿德里安

嗯,我没有注意到我的评论中有遗漏的地方,尽管为了公平起见,我关于保险库的前两个问题仍然存在。虽然,与其他hashicorp产品相比,这些是我对保险库的想法,但我认为所有这些都很棒。与市场上的其他产品相比,执行类似功能的功能可能相当,只是出于某些原因比预期贵得多。
hvindin

您能否举一个“在其应用程序中构建逻辑,该逻辑将基于变量更改其行为,以便他们无需进行适当的测试周期就可以进行更改的示例”?听起来确实很普通,但是我无法想象一个具体的例子。
kenchew

3

如果您的环境是针对每个客户的,那么我建议您在特定情况下每个客户建立一个存储库。(通常是每个环境的存储库。)该存储库将具有标准目录结构,用于环境变量,ansable变量和清单,高度加密的机密(帐户访问令牌,私钥等)。您可以将代码git子模块到那些存储库中。我可能会在多个存储库中这样做。一个用于烦人的角色和模块,一个用于维护和部署脚本,一个用于环境中运行的每个主要应用程序。

现在,您可以选择实际地分叉代码,或者将子模块固定在特定的标签上以进行发布,从而确保管理客户环境的代码除非经过测试和发布,否则不会更改。

如果您正在使用工件存储库,请确保对工件进行了正确的版本控制,并且已在环境变量中正确指定了这些版本。

自动化很重要,因为环境变量不应由人在可能的情况下更新,而应由脚本生成。确保每个客户库存中几乎没有手动更新,并且开发人员仅更新代码存储库。如果他们想更改配置,则应对生成脚本之一进行更改,然后运行生成脚本来生成变量,并将差异提交到客户存储库中。为此过程需要设置持续集成。在某些情况下,如果没有此功能,将无法维护太多的存储库。


只有一个反对意见:机密不应该进入版本控制存储库,除非它具有严格的访问控制支持。Git不会-谁拉存储库的人都可以看到秘密,这可能是一个问题-它们不再是秘密。
Dan Cornilescu

接得好。它是加密的机密。解密密钥具有欺骗性。
Jiri Klouda '17
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.