CNCFの地図を読む — 成熟度、デリバリ、サービスメッシュ
一言でいうと
CNCFランドスケープの数百個のロゴは、暗記する対象ではありません。どんな問題を解く位置なのかでまとめておけば、新しいプロジェクトが登場しても、位置を見つけて当てはめられます。成熟度の段階は、そのプロジェクトを今本番で使ってよいかどうかについての、コミュニティからのシグナルです。
なぜ必要なのか
Kubernetesは、意図的に未完成です。ネットワーキングはCNIに、ランタイムはCRIに、ストレージはCSIに切り出しました。本体がすべてをやってしまうと保守が不可能になり、特定の実装に縛られてしまうからです。
その代償は、選択の負担です。「CNIは何を使うか」から「ポリシーエンジンは何を使うか」まで、決めることが多くあります。CNCFは、このエコシステムに中立的な管理と成熟度のシグナルを提供する財団です。
どう動くのか
プロジェクト成熟度の3段階
| 段階 | 意味 | 例 |
|---|---|---|
| Sandbox | 実験的。初期採用者向けです。APIが壊れる可能性があります | 新規プロジェクトたち |
| Incubating | 本番利用の事例が複数あり、コミッターが多様になります | (時期によって異なります) |
| Graduated | 成熟しています。セキュリティ監査・ガバナンス・多様な貢献者を確保しています | Kubernetes、Prometheus、Envoy、containerd、etcd、Argo、OPA |
段階は機能の優劣ではなく、ガバナンスと採用の成熟度を意味します。Sandboxだから性能が悪いという意味ではなく、Graduatedだから自分たちの状況に合うという意味でもありません。ただ、「これを使っていて、プロジェクトが消えてしまわないか」というリスクのシグナルとしては、使えます。
拡張インターフェース: Kubernetesが外部を呼び出す方法
- CRI: コンテナランタイム(containerd、CRI-O)
- CNI: ネットワーク(Cilium、Calico、Flannel)
- CSI: ストレージ(各種ドライバー)
- CRD + コントローラー: ユーザーがAPIそのものを拡張する方法
最後のものが特に重要です。Operatorパターンとは、「CRDで新しいリソースの種類を定義し、そのリソースを見守るコントローラーを付けて、ドメイン知識をコードにしたもの」です。Kubernetesのreconciliation loopを、自分の問題に再利用する方式です。
配信: CIとCD、そしてGitOps
CIは「コミットのたびにビルドしてテストする」こと、CDは「その成果物を自動でデプロイする」ことです。GitOpsは、CDをもう一度ひっくり返します。
- パイプラインがクラスターに押し込む(push)のではなく、
- クラスター内のエージェントがGitリポジトリを見続けて差分を自分で縮めます(pull)。
Gitリポジトリがそのまま望ましい状態であり、エージェントがコントローラーのようにreconcileします。Kubernetesの宣言型モデルを、組織のプロセスに拡張したものと見れば正確です。得られるものは、監査可能性(誰がいつ何を変えたかがコミットログに残る)、ドリフトの検知(誰かが手で直しても元に戻る)、ロールバック(コミットを元に戻す)です。Argo CDとFluxが代表的な実装です。
サービスメッシュ
アプリケーションコードを修正せずに、リトライ・タイムアウト・mTLS・トラフィック分割・リクエスト単位の観測を入れたいという要求から出発しました。従来の実装は、Podごとにプロキシ(サイドカー)を付けて、すべてのトラフィックを通過させます。
代償は明確です。Podごとにプロキシが1つずつなので、メモリと遅延が増え、運用するコンポーネントが1つ増えます。そのため最近では、サイドカーなしで、ノードレベルのプロキシやeBPFで同じことをしようという流れ(アンビエントモードなど)が出てきました。
オープンスタンダード
- OpenTelemetry(OTel): トレース・メトリクス・ログを収集・送信する、ベンダー中立の規格とSDKです。計装を一度行えば、バックエンドを入れ替えてもコードを修正しません。
- OpenMetrics: Prometheusの公開形式を標準化したものです。
- SPIFFE/SPIRE: ワークロードに暗号学的なアイデンティティ(SVID)を発行する規格です。「IPアドレスがアイデンティティ」という古い前提に取って代わります。サービスメッシュのmTLSが依拠する基盤でもあります。
現場での姿
筆者のホームラボのプラットフォームスタックは、この地図をそのまま実物で見せてくれます。ネットワークはCilium 1.20(eBPF、kube-proxyなし)、L4ロードバランサーはMetalLB(プール10.0.0.200-215)、ストレージはcsi-driver-nfs + NAS、GitOpsはArgoCD、レジストリはHarbor、観測はkube-prometheus-stack、DBはCloudNativePG(PostgreSQL 18、2インスタンスのストリーミングレプリケーション)、仮想化はKubeVirt v1.9.0です。それぞれの位置に1つずつ差し込まれていることが核心です。ランドスケープを位置ごとに読むと、このように整理されます。
バージョン互換性が引っかかる場面も、実際に出てきました。Cilium Gateway APIを使おうとしたところ、Gateway API CRD v1.6.1が必要でした。v1.2では、tlsroutesとreferencegrantsがv1ではなかったため、コントローラーがそもそも起動を拒否しました。「CRDにもAPIバージョンがあり、それが合わないとコントローラーが起動しない」というのが、拡張モデルの現実です。
最も印象的な教訓は、KubeVirtから得られました。コンポーネントの状態はすべてAllComponentsReadyだったのに、VMが起動しませんでした。virt-launcherのPodのマニフェストを詳しく調べると、initコンテナが実行するバイナリを含むボリュームマウントが抜けていました。筆者の表現をそのまま借りれば、「状態がReady」と「実際に動作する」は別の命題であり、そのクラスターだけで3回目に確認した事実です。観測可能性が、なぜ状態フィールド1つで終わらないのかについての、最も短い説明です。
続けて読むこと
このモジュールにはラボがありません。続く読み物で観測可能性のシグナルを整理し、最後のクイズでコースを締めくくります。