问题描述
在持续部署过程中遇到了一个问题,他的CD(Continuous Deployment)流水线包括以下步骤:
1. 获取由CI(Continuous Integration)阶段创建和推送的Docker镜像。
2. 将docker-compose.yml模板复制到目标服务器。
3. 运行应用程序。
用户想要直接讨论第三个步骤。他可以使用docker-compose up
命令来运行应用程序,但是他不知道如何处理配置。目标服务器是由AWS上的Chief创建的Ubuntu服务器,用户可以访问所有AWS服务,如Parameter Store等。
用户对于管理配置有以下几个想法:
1. 在运行应用程序之前,将机密信息保存到配置文件中,并将该文件附加到docker-compose模板的特定位置(用户不喜欢这个解决方案,可以通过一些bash脚本将机密信息注入到文件中来处理)。
2. 在运行应用程序之前设置环境变量(用户与一些DevOps人员交流后,他们基本上喜欢这个解决方案)。
3. 从AWS Parameter Store获取机密信息(不幸的是,用户无法通过角色管理访问,只能通过需要在服务器上设置的密钥来访问)。
用户想知道在实际情况下,如何管理配置?他担心服务器崩溃或类似情况。第一种解决方案可以解决这个问题,但是对于第二种和第三种解决方案,环境变量将在崩溃/重启后丢失。在这里,什么是最佳解决方案?
解决方案
请注意以下操作注意版本差异及修改前做好备份。
方案1
在Docker或docker-compose中,如果使用环境变量启动容器,那么这些变量将成为容器定义的一部分。优点是,当服务器重新启动时,容器重新启动时,相同的变量将存在。但是,缺点是,任何具有对docker API访问权限的人都可以以明文形式查看该机密信息,并且某些应用程序在调试时会记录其环境。
使用Swarm模式(Kubernetes有自己类似的解决方案),您可以在管理器上定义密钥,并且它将根据需要将密钥提供给在工作节点上运行容器的节点。密钥在容器内部作为文件可访问,但该文件仅在工作节点的内存中存储,并且您可以在容器中使用入口点脚本将其加载到环境中(如果应用程序期望如此)。Swarm模式的密钥和配置具有可移植性,因为在工作节点崩溃时,容器将在其他节点上重新调度。从docker-compose安装迁移到单节点Swarm集群并部署堆栈是一项非常简单的任务。
还有一些外部解决方案,可以将配置和机密信息存储在CoreOS的etcd和Hashicorp的Vault等键/值存储中。Swarm模式和Kubernetes都使用键/值存储来存储自己的设置,这给出了如何将其视为最佳实践的想法。缺点是,您通常希望配置应用程序直接从其中一个键/值存储中读取和写入配置。如果使用类似Swarm模式的密钥和配置,这些将存储在docker的内部键/值数据库中,因此您可以在不费吹灰之力的情况下获得类似的解决方案。
方案2
使用docker-compose和k8s之间的解决方案可能会过于复杂,对于两个节点的系统来说,k8s可能过于庞大。目前还没有在docker-compose和k8s之间找到合适的解决方案。
我们的情况与您的非常相似。我们的配置是一个明文的YAML文件,存储在主机上,并通过绑定挂载到容器中。
这并不理想,因为机密信息是明文的。在两个节点之间保持一致性也是有问题的。
正如评论中提到的,k8s是一个潜在的解决方案,但对于两个节点的系统来说,它可能过于庞大。目前,我还没有找到docker-compose和k8s之间的任何解决方案。
另一种方法是使用一些第三方工具来管理配置。这些工具可以将配置存储在外部存储中,并在容器启动时将其注入到环境变量中。这样,您可以在不更改docker-compose文件的情况下更新配置。
结论
在持续部署中,管理应用程序配置的最佳实践是使用Swarm模式或类似的解决方案。这些解决方案可以将配置和机密信息存储在安全的键/值存储中,并在容器启动时将其注入到环境变量中。这样,您可以在不更改docker-compose文件的情况下更新配置,并且在工作节点崩溃时,容器可以在其他节点上重新调度。
如果您的系统只有两个节点,并且k8s对您来说过于庞大,那么目前还没有找到docker-compose和k8s之间的合适解决方案。您可以考虑使用一些第三方工具来管理配置,这些工具可以将配置存储在外部存储中,并在容器启动时将其注入到环境变量中。
请根据您的具体需求选择适合您的解决方案,并确保在实施之前做好备份和测试。