🤖

kubernetesのマニフェスト管理 比較検討(Helm/Kustomize)

2023/08/17に公開

はじめに

実務において、kubernetesのマニフェスト作成(管理)の方法としてHelm or Kustomizeという選択肢がとられている。

ここでは、クライアント組織への導入したときの話をしたいと思う。

クライアント組織の要求事項と特性を整理した上で、どちら(または同時使用)が適切か判断するための調査を行う

TL;DR

個人的にはHelmの使用を推奨したい

アプリケーション / インフラ / SREと多くのレイヤーの人が関わる組織統制を考慮したときに、Helmを使用した方がバランスの取れた運用に近づくのではないか

調査

背景

大規模な組織であるクライアント組織では、開発に際して日々、多くのステークホルダーが関わっている

その中で、開発組織や技術レベルに対して統制をとることの難易度は高く、高度なマニフェスト管理はチーム内や他ベンダーとの技術連携のギャップを生んでしまう

そこでマニフェスト管理の際には以下のような考慮が必要である

- マニフェスト配布の容易性(再配布性)
- 環境差分の吸収と見える化
- 運用時の変更/レビュー負荷の低減
- バージョン管理・ロールバック

Kustomzie / Helm 比較

それぞれにおける特徴をざっくりと比較した。Pros, Consなどの詳細はAppendixに掲載。

Comparison item Kustomize Helm
Native Kubernetes integration Yes No
Ease of use Simple Complex
Approach Overlays Templates
Declarative/imperative Declarative Imperative
Packaging No Yes
Version control/Rollbacks No Yes

Example:

devとprod環境の構成を持つシンプルなk8sクラスターのマニフェスト構成を比較すると、Kustomize、Helmではそれぞれ以下のようになる

Kustomize

base
│  └─portal
│     ├─kustomization.yaml
│     ├─deployment.yaml
│     └─service.yaml
overlays
   ├─prod
   │  └─portal
   │     ├─kustomization.yaml
   │     ├─deployment-patch.yaml
   │     └─service-patch.yaml
   └─dev
      └─portal
         ├─kustomization.yaml
         ├─deployment-patch.yaml
         └─service-patch.yaml

Helm

.
├── Chart.yaml
├── templates
│   ├── NOTES.txt
│   ├── _helpers.tpl
│   ├── deployment.yaml
│   ├── hpa.yaml
│   ├── ingress.yaml
│   ├── service.yaml
│   └── serviceaccount.yaml
├── environment
│   ├── prod.yaml
│   └── dev.yaml
└── values.yaml

ここに新たにstg環境を構築する場合を考えると以下のような構成となり、KustomizeはDRY原則から大きく外れる構成となってしまう。また単純なファイル数の増加を見たときにも、Kustomizeは、1ディレクトリ + 3ファイル増加に対して、Helmはstg用の1ファイルに留まっている。

base
│  └─portal
│     ├─kustomization.yaml
│     ├─deployment.yaml
│     └─service.yaml
overlays
   ├─prod
   │  └─portal
   │     ├─kustomization.yaml
   │     ├─deployment-patch.yaml
   │     └─service-patch.yaml
   ├─stg(配下新規作成)
   │  └─portal
   │     ├─kustomization.yaml
   │     ├─deployment-patch.yaml
   │     └─service-patch.yaml
   └─dev
      └─portal
         ├─kustomization.yaml
         ├─deployment-patch.yaml
         └─service-patch.yaml
.
├── Chart.yaml
├── templates
│   ├── NOTES.txt
│   ├── _helpers.tpl
│   ├── deployment.yaml
│   ├── hpa.yaml
│   ├── ingress.yaml
│   ├── service.yaml
│   └── serviceaccount.yaml
├── environment
│   ├── prod.yaml
│   ├── stg.yaml(新規作成)
│   └── dev.yaml
└── values.yaml

アプリケーションや環境が肥大化するにつれ、ファイル数やディレクトリ構造が複雑化するため、常にこれらの可読性と運用時の負荷を天秤にかけつつ比較する必要がある。

kubernetesとの統合

すでに稼働しているk8sクラスターに統合することを考えたときには、セキュリティリスクと複雑な管理がもたらす運用負荷の増加が考えられる

Kustomize

Kustomizeのoverlaysは、全環境統一のbaseマニフェストを元にシンプルなyamlベースで自由に記述できて柔軟性は高いが、それゆえに上書きが発生しやすく環境ごとの差分が生じやすい

→ 開発側での自由なマニフェスト管理ができてしまう
→この量が増えると認知負荷があがり統制しづらい

環境差分がライトであれば、マニフェストの視覚化や差分の吸収など容易である。

→ 複数のアプリケーションや多くの環境を持つk8sクラスターへの展開を考えたときには、運用負荷上がる

Helm

Helmはchartバージョンを宣言的に管理し、template内に明示的に記載する必要があるため、意図しない環境ごとの差分が生じにくい

→ 学習コストはKustomizeと比較すると上がってしまうが、**Kubernetesでのソフトウェアインストールライフサイクルを簡素化**
→ OSSデファクトスタンダードとして機能しており、運用実績もあるため学習コストをサンプル数でカバー可能
→ ステークホルダーへのバージョン管理された再配布性が高い

valuesファイルを環境ごとに作成して、環境差分となるパラメーターのみを記載する

→ 差分吸収のためのコード量が比較的少なく、運用・レビュー負荷の低減
→ 将来的に、複雑なマニフェスト構造を表現したい場合でも、helmのテンプレート関数で表現できることが多いため対応可能な範囲が広い

選定基準

Kustomizeは複雑なカスタマイズを素早く行うことができるが、パッチとレイヤーがどのように組み合わされるかを視覚化できる必要がある。

開発者へのyamlベースの記述の統制を考慮しないのであれば、Kustomizeを選択するのが、即効性のある選択肢となる。

一方、開発者への配布と安全で簡単な方法で新しいアプリやサービスを追加できるようにしたいのであれば、Helmチャートを作成するのがより良い。

Helmを選択するもう1つの理由は、yamlファイルに費やす時間を減らす必要があること

パッケージ化が可能なため、容易なバージョン管理とロールバックオプションが提供される点も選定基準となる。

GitOpsやCI/CDという観点からも考慮する必要があり、Helmはkubectlのネイティブ機能では無いため、Pipelineプラットフォームによっては、提供されないオプションとなってしまう。

しかし、今回、CD Pipelineとして想定するHarnessにおいては、Helmに対応しているためPipelineプラットフォームとても連携は問題ないと考える。

一緒に使用することは可能か?

結論から言うと可能である。考えうるシナリオ例としては以下のような場合。

  • Helmチャートを所持していない場合(未作成含む)
  • SecretやConfigMapをHelmチャートで使用したい時
  • 複数のリソースのフィールドを同時に編集したい場合

これらへのアプローチ方法としては大きく2つある。

  1. helm templateを使ってマニフェストを生成し、Kustomizeでパッチを適用する(上書きする)
    • 欠点はHelmが全てのリリースを管理しないこと。
  2. helm install (または helm upgrade --install)を使い、クラスタに適用する前にKustomizeがマニフェストを修正する。

簡単なdemo: https://trstringer.com/helm-kustomize/

※ただし両者の特性を考慮する必要があるので、運用時の負荷はとても高くなる

まとめ

以上のような内容からKustomize、Helmの理解を改めて簡単にいうと以下になる

Kustomize

  • kubectlのネイティブ機能と統合したマニフェスト管理ツール
  • 純粋なyamlベースで複数環境のデプロイを管理しやすくするのに優れており、既存のKubernetes上のアプリの迅速な修正に最適

Helm

  • Kubernetesアプリケーションの開発と共有を容易にするパッケージマネージャ

競合するものではないが、両者のPros, Consをきちんと把握した上で、達成したい要件に対して最適なものを選択(または両方使用)する必要ことが望ましい

その上でクライアントにおいては、組織統制の強化の観点からパッケージマネージャ(Helm)を使用することが良いのではと考える

Appendix

Kustomize / Helm、それぞれにおいてマニフェストを開発・運用・管理していく上で5つの観点でどういった特徴があるかをまとめる。

可読性

kustomize helm
Pros 素のyamlのためシンプルで可読性が高い golangのテンプレート関数をうまく使ってコード化することでコード量を減らすことができる
https://helm.sh/docs/chart_template_guide/functions_and_pipelines/#helm
Cons 環境差分がある場合、overlays配下のkustomziation.yamlへの記述が増えていくため、差分が増えるにつれて可読性が下がる ループや条件分岐のようなロジックを多用すると可読性が悪くなる。学習コストがかかる

ファイルのメンテナンス性

kustomize helm
Pros (特になし) 公式チャートが豊富にある。OSSツールについて自前実装・管理する必要がない場合が多い。参考にできる実装サンプルが多い
helmチャート一覧のリンク: https://artifacthub.io/packages/search?kind=0
valuesファイルの値を変更するのが基本のコード改修であるため、チャートの型ができると変更が属人化しにくい
Cons 新しいファイルに上書きしたい内容を記載していくため、ファイル数が環境数以上に増える。どの単位でkustomizations.yamlを作成するか、ルールがないとばらつきが生じる。kustomizations.yamlにてファイル名を指定するため、ファイル名の変更がしづらい スパゲッティコードとならないようにレビューなどで構文や実装方法まで見ながら運用する必要がある

バージョン管理

kustomize helm
Pros git での管理となるため、ブランチ戦略に紐づく マニフェスト群をパッケージとして管理し、バージョン管理できる。前のバージョンに簡単にロールバック可能。https://helm.sh/docs/helm/helm_package/#helm
Cons パッケージとしてのバージョン管理はできない (特になし)

運用負荷

kustomize helm
Pros git での管理となるため、ブランチ戦略に紐づく gitでのブランチ戦略に基づいてバージョン管理することも可能だが、chartバージョンも活用することで迅速なロールバックも可能。複数のhelm chartを同時に扱う場合にhelmfileというツールが使える
複数のhelm chartを同時にデプロイ・アップデートすることができる
使用するvaluesファイルやchartバージョンを宣言的に管理できる
既に使用している外部のチャートにリソースを足したい場合にも新たにマニフェストを追加してapplyするリストに加えることで運用を変えずに対応できる
Cons パッケージとしてのバージョン管理はできない (特になし)
コマンド例 kustomize build overlays/stg kubectl apply -f -

環境差分の吸収

kustomize helm
Pros 環境ごとにディレクトリを作成するため見た目はシンプル。少量の環境差分であればライトで使いやすい valuesファイルを環境ごとに作成して、環境差分となるパラメーターのみを記載する。差分吸収のためのコード量が比較的少ない
Cons 環境差分が多い場合に、記載するコードが増える (特になし)

Reference

GitHubで編集を提案

Discussion