# Helm 和 Kustomize：不只是含谷量的区别

Kustomize 问世的时候，我是比较鄙视的——非要造个谷歌的轮子么？不过最近抽出时间熟悉了一下 Kustomize，发现我还是带了有色眼镜。二者功能虽然有所重叠，但是工作思路的差别还是很大的，下面就简单做一点比较，权当引玉之砖。

## Helm

Helm 是 Kubernetes 中的第一个对应用程序进行管理的支撑工具，经常会拿来同 Yum、apt 等工具进行类比。Helm 由几个不同的组件构成：

- CLI：客户端工具，有几大功能
    - 从 Chart 服务器获取列表、搜索 Chart 项目
    - 安装 Chart
    - 构建 Chart
    - 充当 Chart 服务器
    - 和 Tiller 协同管理应用生命周期
    - 渲染 Chart 为 Kubernetes 生成 YAML
- Tiller：需要用特定授权和 API Server 进行通信，Kubernetes 集群内外部署都可以。
    - 它是 Helm 的内鬼，负责接收来自 Cli 的指令，完成对集群内应用生命周期的控制。
    - 3.0 中将取消 Tiller。
- Repository：
    - 是存储 Helm Chart 的仓库，可以被 Cli 工具缓存、检索，CLI 也可以获取 Chart 进行后续操作。
    - 和 Tiller 一样，Repository 也不是必要组件，CLI 完全可以仅在本地工作。

### Helm Chart

Helm 使用 Chart 对应用程序进行描述，它使用 Go Template 对应用部署所需的 YAML 进行抽象，形成应用部署模板，在需要进行部署时，可以编写 yaml 为模板中的变量进行赋值，也可以在 Helm CLI 的命令行中使用 `--set name=value` 的方式来对简单变量进行赋值，完成赋值之后，可以选择使用 `helm template` 指令将 Chart + Value 的组合渲染成为 YAML 供 `kubectl` 使用，也可以使用 `helm install` 直接通过 Tiller 进行安装。

### Helm 的特色

- 强大的生命周期管理：有 Tiller 的帮助，可以实现对应用程序实例（Release）的查询、安装、卸载、升级、回滚等复杂操作。
- 严格的基础版本管控：Chart 是一种模板，Chart 的用户仅能通过对 `values` 的控制来定制应用的部署行为，模板中没有提供变量的位置，是无法在下游直接进行变更的。
- 方便的命令行：对于简单变量，可以在部署的同时直接指定内容，方便部署。
- 插件和工具：Helm 拥趸众多，提供了不少用于 CICD 或者其它方面辅助功能的插件和工具。

## Kustomize

Kustomize 是一个新晋选手，只有一个 CLI 工具，在 Kubernetes 1.14 之后，甚至这唯一的工具也成为 kubectl 的一部分，可以说是很轻量级了。

### Base + Overlay

在 Kustomize 的文档中明确说明：

> kustomize is a command line tool supporting template-free, structured customization of declarative configuration targetted to k8s-style objects.

它放弃了对模板的要求，改用 Base + Overlay 的方式对应用的原始 YAML 进行`派生`。`Overlay`，顾名思义，就是覆盖。Kustomize 的 Overlay 可以在 Base 的基础上，通过对 `resource`、`generator`、`transformer` 等的定义，形成新的应用定义，不论 Base 
还是 Overlay，都可以通过 `kustomize build` 生成有效的 YAML。

### Kustomize 的特色

- 功能简单清晰，kubectl 直接支持。
- 不考虑派生，仅作为应用的 YAML 组织方式也很有帮助。
- 也有自己的插件系统。例如可以用简单的 YAML 定义，使用文件生成 Configmap/Secret。

## 比较

Kustomize 自称因为去掉了模板语法，更易使用，对此我保留看法，如果仅就入门使用来看，二者差异并不大。

Tiller 和 Repository 都并非必须，因此在部署上，Kustomize 的优势也不是很大。

我认为他们的区别主要在工作流程上：

- Helm 的基础流程比较`瀑布`：定义 Chart->填充->运行，在 Chart 中没有定义的内容是无法更改的；
- Kustomize 的用法比较`迭代`：Base 和 Overlay 都是可以独立运作的，增加新对象，或者对编写 Base 时未预料的内容进行变更，都不在话下。

例如我们定义了一个很基础的应用，由 Deployment + Service 组成，如果后续部署中需要完成两个变更：

- 新建 Ingress 对象
- 修改镜像地址/名称/TAG

在 Helm 中需要：

- 在 Chart 中加入对 Ingress 的定义
- 用变量控制 Ingress 是否进行渲染
- Ingress 模板应该包含特定的主机名、注解等变量
- 把镜像也定义成变量
- 在 Values.yaml 中对这些变量进行赋值。

而在 Kustomize 中：

- 无需对 Base 进行修改
- 直接在新的 Overlay 中写入 Ingress Resource
- 使用内置的 `image transformer` 替换原有镜像

## 结论

要公开发布一个较为复杂的应用，例如 `Istio`，编写良好的 Chart 能给用户很大帮助，用户在缺失一点发挥空间的情况下，通过对 `values.yaml` 的阅读，就能对这种复杂的部署产生一个较为深入的认识。

如果是常见的业务应用，因为不同部署之间的差异不大，但是未必可以提前做好变化限制，用 Kustomize 可能会是一个更好的选择。

## 相关链接

- Helm：`https://helm.sh/`
- Kustomize：`https://github.com/kubernetes-sigs/kustomize`
- Helm 3.0：`https://helm.sh/blog/helm-3-preview-pt1/`
- Helm 工具：`https://www.infoq.cn/article/UemPsPu_AlzemkGEqb4Z`
- Awesome Helm：`https://github.com/cdwv/awesome-helm`

