TT Lab
はじめる
学ぶ 学習パス コース

CRDとオペレータ

valuesの山をAPIに変える

TT Labで続きを見る

一言でいうと

CRDは新しい機能を追加する装置ではありません。APIサーバーがすでに持っている能力を、自分が定義した型にそのまま貸し出す装置です。

なぜ必要なのか

社内サービスをデプロイするHelmチャートを想像してみてください。最初はimageとreplicasの2つだったvalues.yamlが、1年後には40行になります。そして、次のようなことが繰り返されます。

問題の根は1つです。values.yamlはAPIサーバーから見ると、ただの文字列の塊です。検証してくれる主体がなく、保存場所がreleaseのSecretの中なので参照しにくく、誰がいつ変更したかが監査ログにリソース単位で残らず、値1つだけを変更する権限をRBACで分けることもできません。

CRDはこの問題を、「それなら、それを本物のAPIオブジェクトにしよう」という発想で逆転させます。

どう動くのか

CRDを1つ適用すると、APIサーバーが/apis/<그룹>/<버전>/namespaces/<ns>/<복수형>(プレースホルダーはグループ、バージョン、ネームスペース、複数形です)というエンドポイントを開き、その瞬間から次の能力が無料で付いてきます。

能力 values.yaml CR
スキーマ検証 なし(レンダリング後にようやく発見) OpenAPI v3でapply時点に拒否
デフォルト値の注入 テンプレート内のdefault関数 スキーマのdefaultをAPIサーバーが埋める
未知のフィールド 黙って無視 pruningで切り落とす、または明示的に保存
保存 releaseのSecret etcdにオブジェクトとして
参照 helm get values kubectl get、ラベルセレクター、カスタムカラム
変更の監視 なし watchストリーム
権限の分離 チャート全体の単位 リソース・サブリソース単位のRBAC
監査 パイプラインログ APIの監査ログにオブジェクト単位で

さらにもう1つ付いてきます。スキーマの中でCELルールを使えます。self.tier != 'prod' || self.replicas >= 2のようなフィールド間の制約を、Webhookサーバーなしで、APIサーバーの中で検査します。以前は検証Webhookを立てなければできなかったことが、今ではスキーマの1行で済みます。

そして、必ず覚えておいてください。CRDだけでは何も起きません。CRを適用すると、検証済みのデータがetcdにきちんと保存されるだけで、Podが起動することもバックアップが走ることもありません。そこに、その型をwatchして調整するコントローラーが加わって、はじめてOperatorになります。

CRD          = 새 어휘 (무엇을 원하는지 말하는 언어)
컨트롤러      = 그 어휘를 현실로 만드는 두뇌
오퍼레이터    = CRD + 컨트롤러

このコードブロックの韓国語の3行は、順に、CRDは新しい語彙(何がほしいかを伝える言語)、コントローラーはその語彙を現実にする頭脳、OperatorはCRDとコントローラーの組み合わせ、という意味です。

現場での姿

1つ目は、プラットフォームチームのセルフサービスです。内部開発者プラットフォームをつくるチームの多くは、CRDで抽象化を提供します。開発者はWebServiceを1枚書くだけで、プラットフォームがそれをDeployment・Service・Ingress・HPA・NetworkPolicyに変換します。開発者が学ぶ必要のある表面が、40行のvaluesから5行のCRに減ります。

2つ目は、Prometheus OperatorのServiceMonitorです。巨大なPrometheusの設定ファイルを人が編集する代わりに、各チームが小さなCRを作って「自分のサービスのメトリクスを収集してください」と宣言します。1つの設定ファイルを複数のチームが編集して起きていた衝突が、リソース単位の所有権に置き換わります。

3つ目は、使ってはいけない場面がはっきりあることです。次のうち1つでも当てはまるなら、CRDは過剰です。

4つ目は、CRDはコードではなくAPI契約であることです。コントローラーのコードはいつでも再デプロイできますが、すでにetcdに溜まった数千個のCRや、ユーザーがGitにコミットしたマニフェストは、気軽には変えられません。フィールドを1つ間違って作ると、v1alpha1からv1まで何年も付いて回ります。だからAPIの表面は小さく始め、進化の道をあらかじめ用意しておく必要があります。

次の確認で見ること

続くクイズでは、CRDを単なるYAMLの形式ではなく、長期的な互換性を持つAPI契約として設計しなければならない理由を確認します。名前・スコープ・スキーマ・バージョン変換の判断基準を点検したうえで、次のモジュールでapps.labhub.ioグループのWebService型を自分で定義します。