設計思想と想定ユースケース
Tazuna は「マルチクラスタ Kubernetes のブートストラップライフサイクルを管理する CLI」です。 ここでは、なぜそういうツールが必要になるのか、Tazuna が何を肩代わりし、何は肩代わりしないのか、 という設計上のスタンスを整理します。
解こうとしている問題
Kubernetes クラスタは、API サーバが立ち上がっただけでは実用には使えません。 そこから「自分たちのクラスタ」と呼べる状態にするまでには、
- CNI / Ingress / cert-manager のような インフラ層のアドオン
- ArgoCD / Flux のような デプロイ基盤そのもの
- 各種オペレータや CRD
といったレイヤを、正しい順序で、依存関係を保ちながら クラスタに入れる必要があります。
これを手作業や 複雑な運用手順書、シンプルなシェルスクリプトで代用すると、
- どこまで適用したか分からなくなる(=「state がない」)
- クラスタのブートストラップ手順が古くなる
といった問題が積み上がります。Tazuna はここに 単一の宣言的な設定ファイル と 統一された CLI を持ち込み、ブートストラップという「特定の段階」だけを明示的に扱います。
Kubernetesクラスタをイミュータブルに運用するアイデア
Tazuna の背景にある考え方のひとつが、Kubernetes クラスタそのものを イミュータブル(不変)なリソースとして扱う という発想です。 ここでいうイミュータブルとは、「動いているクラスタを継ぎ足しで直していく」のをやめて、 クラスタは常に同じ手順で作り直せる状態にしておく ことを指します。
ここで「不変」と言っているのは クラスタの土台レイヤ の話です。 Deployment で動いているアプリケーションの Pod が新しいイメージに置き換わったり、 HPA でレプリカ数が変化したりすることを mutate と呼んでいるわけではありません。 対象にしているのは、CNI / Ingress / cert-manager / ArgoCD といった インフラアドオンや、それらが依存する CRD やオペレータといった、 クラスタを「クラスタとして成立させている」基盤レイヤです。 アプリケーションレイヤは、その上で GitOps によって自由に mutate されてかまいません。
長期間運用していると、クラスタには次のような変更が少しずつ溜まっていきます。
- 障害対応のなかで誰かが
kubectl applyした暫定マニフェスト - バージョン調査のために手で入れ替えた CRD やオペレータ
- 手元の
helm installで入った add-on
これらが積み重なると、「実際に動いているクラスタ」と「コードで宣言したクラスタ」が 徐々にずれていく(コンフィグレーションドリフト)状態になります。 こうなるとクラスタを作り直すコストが跳ね上がり、DR / リージョン追加 / Kubernetes バージョンアップといった「クラスタごと入れ替えたい」場面で動けなくなります。
イミュータブルに運用するというのは、この状況を裏返して、
- クラスタの中身は すべて宣言された設定から再生成できる ことを前提にする
- ブートストラップ後の add-on レイヤは、必要なら 一度クラスタを捨てて作り直しても同じになる
- 手で入れたものは「いつ消えても良いもの」と割り切るか、宣言側に取り込む
という運用スタイルを選ぶことです。アプリケーションレイヤであれば、これは ArgoCD や Flux のような GitOps ツールがすでに担保しています。 一方で、その GitOps ツール自身を含む「ブートストラップ層」 は、 従来は手順書とシェルスクリプトに頼りがちで、イミュータブルさが最も崩れやすい場所でした。
Tazuna は、このブートストラップ層をイミュータブル運用の枠に乗せるための部品として位置付けています。
tazuna.yamlという 単一の宣言的な設定ファイル に CNI / Ingress / cert-manager / ArgoCD などの構成順序を書き切ることで、クラスタの初期状態を コードから一意に再生成できるようにします。tazuna applyは、その宣言と実クラスタの差分を埋める操作です。 「新規クラスタの初日」と「既存クラスタへの追従」を 同じコマンド で扱うので、 作り直したクラスタも既存クラスタも、最終的に同じ宣言に収束します。stateによって「いま何が入っているか」を持ち、context_matchesで どのクラスタに対する宣言なのかを縛ることで、 「別のクラスタに間違って適用する」「適用したかどうか分からない」 を仕組みで防ぎます。- ブートストラップが終わったあとのアプリケーション運用は ArgoCD / Flux に渡します。 ここでイミュータブル運用のバトンがアプリケーションレイヤに引き継がれ、 ブートストラップ層と継続的デリバリ層の両方 が宣言から再現可能になります。
なお Tazuna は「クラスタを毎回作り直して運用すること」を強制するわけではありません。 実際にイミュータブルに運用する(クラスタごと作り直して切り替える)スタイルも 想定の中に入っていますが、より重視しているのは、その一歩手前の性質、すなわち 「Kubernetes クラスタが任意のタイミングで壊れたとしても、保証された手順で 自動的に再構築できる」 状態を常に保てることです。
この性質さえあれば、
- 普段は同じクラスタを使い続けて運用する
- DR や大きなバージョンアップのタイミングだけ、別のクラスタを丸ごと立てて切り替える
- 検証用の使い捨てクラスタを必要なときに立ち上げる
といった選択肢を そのときの状況に応じて選べる ようになります。
Tazuna は、その「保証された再構築手順」を tazuna.yaml というコードと
tazuna apply という一つのコマンドに集約することで、
イミュータブル運用を選べる状態を維持し続ける ための土台を提供します。
Tazuna が肩代わりしないこと
意図的に踏み込まない領域もあります。
- 継続的デリバリ — ArgoCD や Flux の代替ではありません。Tazuna の役目は、 そうしたツールをクラスタに 入れるまで です。入ったあとは ArgoCD/Flux に渡します。
- マニフェストの中身を書く — kustomize の overlay、helmfile の構成、Helm chart の値は、 既存の各ツールの作法で書きます。Tazuna はそれらを 呼び出して結果をクラスタへ流す だけです。
- コントロールプレーンの作成 —
kubeadm/kops/ マネージドサービスのクラスタ自体は前提です。 Tazuna はkubeconfigを介して既存クラスタへ接続します。 - Secret 管理基盤そのもの — Secret の格納先の参照を宣言しますが、 Tazuna 自身は秘密を保管しません。
- GitOps のロールバック・履歴管理 —
stateは「いま何が入っているか」を表すもので、 歴史的なバージョン管理は git に任せます。
想定ユースケース
具体的に Tazuna が嬉しい場面はおおむね次のようなときです。
- 新規クラスタを立ち上げる初日 —
tazuna apply1 発で、 CNI からデプロイ基盤までを所定の順序で入れたい。 - Kubernetesクラスタの構築手順が妥当であることを自動検証する
- 同じ役割のクラスタを複数立てる — staging / production / dr といった
類似クラスタを、ほぼ同じ
tazuna.yamlで立ち上げたい。
次は 全体アーキテクチャ で、これらをどんな部品で実現しているかを見ます。