目前为止,我们讨论的所有内容都集中在如何将服务的单个实例部署到单个集群上。但实际上几乎每个服务以及每个服务的团队都需要支持将应用程序部署到多套不同的环境上(即使它们共用同一个集群)。即使你是某个应用的唯一开发者,你也可能希望应用至少有一个开发版本和生产版本,这样你在进行迭代开发的同时不会影响生产环境上的用户。考虑到集成测试和CI/CD的因素,即使只有一个服务和少量开发者,你也会希望至少部署到三个不同的环境上,如果考虑到应对数据中心级别的故障,你可能想要部署到更多的环境。
许多团队都会面临一种原始的故障模式,即简单地将文件从一个集群复制到另一个集群。环境上同时维护着frontend-production/和frontend-development/这样一组目录,而不是单一的frontend/目录。这种模式非常危险,原因在于你需要确保这些文件之间保持同步。如果只是保持完全一致可能很容易,但是你可能需要持续地开发新功能,因此开发版本和生产版本之间或多或少地会存在一些差异。确保这种差异既符合期望又易于管理,这一点至关重要。
另一种方式是使用分支和版本控制,生产分支和开发分支从同一个中央仓库衍生出来,它们之间的差异清晰明了。对于某些团队来说,这可能是一个可行的方案,但是当你想要将软件同时部署到不同的环境时(例如,通过CI/CD部署到多个不同的云区域),分支间的切换将会成为极大的挑战。
因此,大多数人最后都会选择模板系统。其中,模板构成了应用程序配置的主框架,模板系统再将它与特定环境的配置参数组合在一起,形成具体的配置。这样你就可以维护一套通用的配置,并以易于理解的方式进行按需定制。支持Kubernetes的模板系统有很多,但目前为止最受欢迎的就是Helm。
在Helm中,应用程序被打包在一个称为chart(chart是海图的意思,在容器和Kubernetes的世界中充斥着航海相关的暗喻)的文件集合中。
chart始于chart.yaml文件,它定义了chart自身的元数据:
该文件位于chart目录的根路径下,例如frontend/。该目录下还有一个templates子目录,用于放置模板。模板基本上就是前面示例中的YAML文件,只是其中的某些值被替换为引用参数。例如,假设你要参数化前端应用程序的副本数。之前的Deployment是这样的:
在模板文件frontend-deployment.tmpl中,它被替换为以下内容:
这意味着你可以在部署chart时使用合适的参数来替换副本数。这些参数被定义在values.yaml文件中。应用程序的每个部署环境中都将有一个values文件。当前示例对应的values文件内容如下:
一切就绪之后,你就可以使用如下的
helm
命令来部署当前的chart:
上述操作能够将应用程序参数化并部署到Kubernetes。随着时间的推移,参数化的范围也将逐渐扩大,以覆盖应用程序的不同环境。