在上一篇文章中,为大家介绍了 Helm 的初步使用。然而这仍然不能满足我司的工作流,主要问题有:
- Helm 不提供
apply
命令;因此在 CI/CD 场景中必须考虑到判断是 install 还是 upgrade。 - 不方便控制安装的 chart 版本;例如指定版本范围、锁定某一版本等。
- Values 必须是纯文本;不支持模板渲染、不方便区分环境。
因此我们需要 Helm Releases as Code
。我听说过的产品有 Helmsman 和 Helmfile 两款。目前我们团队已经使用后者一段时间,并且有团队成员贡献过部分代码。
至于为什么选择 Helmfile,背后的真正原因是在发现 Helmfile 的时候还没听说过 Helmsman。后来了解 Helmsman 并尝试后发现它并没有解决我们后两个问题,因此也就没有替换了。
接下来我针对以上几个痛点来说说我们是怎么做的。
一键 Apply
Helmfile 的文档非常简明、直接,示例配置文件 就在 README 里。我节选一小段来说几个必要的配置项:
repositories: |
将以上内容保存为 helmfile.yaml
文件,随后执行 helmfile apply
即可。Helmfile 将会帮我们:
- 添加
repositories
中声明的 Helm chart repo。 - 根据
release
小节内的配置,安装或更新 chart。
因此,上篇文章中提到的:
helm repo add ... |
可直接被简化为:
helmfile apply |
同时,如果你安装了 helm-diff 插件,Helmfile 还会在执行操作前输出清晰的 diff:
具体安装过程本文不再详述。
Chart 版本控制
大多数社区提供的 charts 都采用 Semver 2.0 作为版本号。因此大多数情况下我们都希望锁定主版本,防止误升级引入 breaking change。Helmfile 提供了 version
参数可用于指定版本范围,例如:
# ... |
同时,Helmfile 还提供了 lock 文件,功能与常见版本管理器中的 lock 类似。配合 CI 时,除非提交代码改动 lock 文件,否则在任意时间点执行 CI 安装的 chart 版本是一致的。
你可以通过 helmfile deps
命令生成 lock,以上 helmfile.yaml
生成的示例 helmfile.lock
文件长这样:
version: v0.102.0 |
可看出包含具体的 chart 版本、Helmfile 版本、哈希值、生成时间等参数。
当需要更新 lock 文件时,同样执行 helmfile deps
即可。
动态 Values
在 CI 上部署时,有些 values 的值不是固定的,可能来自于环境变量,也可能由于环境差异而不同。
环境变量
在之前的文章中我们介绍过 review apps,其中有一项很重要的需求是,每次开新分支部署的 release 不能同名,否则资源会因为重名而安装失败。所以我们要读取 GitLab CI 的 $CI_ENVIRONMENT_SLUG
环境变量,并拼接到最终的 Helm release name。因此可以这样做:
# ... |
其实 helmfile.yaml
是个 Go template 格式的模板,因此你还可以把环境变量传递给 values,也可以使用 if
之类的语法。例如:
# ... |
区分环境
Helmfile 提供了名为 environments
的配置,此处并不是指环境变量,而是一个专属于 Helmfile 的概念。来看看例子。首先创建两个文件:
# environments/staging/values.yaml |
配置 helmfile.yaml
:
# ... |
在执行 helmfile
时使用 -e
选项即可指定安装的环境:
helmfile -e staging apply |
注意 -e
必须在子命令 apply
之前,它是一个全局选项。
小结
不得不说,Helmfile 的确很灵活,但采用 Go template + YAML 语法编写配置的方式稍有些难以阅读和维护。