カスタムコントローラーなしで動的なKubernetes APIを構築する
Cozystackのエンジニアが、Kubernetes API集約レイヤーを使用して動的かつ命令型のエンドポイントを作成し、etcdストレージの制限を回避する方法について解説します。
英語の原文から自動翻訳されました。
2024年11月のKubernetes Blogへの投稿で、ÆnixのAndrei Kvapil氏は、彼のチームがCozystack用に動的な拡張APIサーバーをどのように構築したかを詳細に説明しました。この記事では、Kubernetes API集約レイヤーの技術的な実装を探り、標準的なカスタムリソース定義(CRD)やオペレーターとの対比を行っています。
何が起きたか
Kvapil氏は、ほとんどのKubernetes拡張機能はCRDとコントローラーに依存していますが、このアプローチには特定のユースケースにおいて制限があると説明しました。標準的なオペレーターは宣言的な状態の整合性(reconciliation)においては優れていますが、命令型ロジック、リアルタイムデータ生成、複雑な検証要件には苦戦します。これらのギャップを埋めるため、Cozystackチームは、集約レイヤーを通じてKubernetes APIフレームワークに直接統合されるカスタム拡張APIサーバーを実装しました。
この実装の核心は、クラスター内で APIService オブジェクトを登録することです。この登録により、メインのKubernetes APIサーバーは、特定のグループのリソースに対するリクエストを外部の拡張サーバーへプロキシするように指示されます。Cozystackの場合、これによりコードの変更や再コンパイルを必要とせずに、利用可能なHelmチャートに基づいて新しいリソースタイプを動的に公開することが可能になりました。システムは、Postgres や Redis といったユーザーフレンドリーなkindを、基盤となるHelmリリースに直接マッピングし、エンドユーザーから複雑さを抽象化しています。
このアプローチはまた、重大なRBAC(ロールベースアクセス制御)の問題も解決しました。標準的なKubernetes RBACでは、ラベルや特定のspecフィールドによるリスト操作のフィルタリングができず、リソース名でのみフィルタリングが可能です。サービスタイプごとに異なるリソースkindを生成することで、CozystackはネイティブのRBACポリシーを活用して、アクセスを正確に制限できるようになりました。さらに、拡張サーバーは新しいカスタムkindと内部の HelmRelease リソース間での双方向変換を処理し、既存のダッシュボードやツールとの後方互換性を確保しています。
仕組み
API集約レイヤーは、Kubernetesコントロールプレーン内のプロキシとして機能します。ユーザーが拡張機能によって提供されるリソースグループに対してKubernetes APIへリクエストを送信すると、メインAPIサーバーはそのリクエストを拡張APIサーバーへ転送します。このサーバーはプライマリコントロールプレーンコンポーネントとは独立して動作し、独自のビジネスロジック、検証、ストレージメカニズムを実装できます。

状態をetcdに同期する標準的なコントローラーとは異なり、拡張APIサーバーはレスポンスをその場で生成できます。これは、データを保存するのではなくKubeletからリアルタイムデータを取得する metrics-server の動作と同様です。Cozystackの場合、サーバーは利用可能なサービスを動的に検出し、それらをAPIリソースとして登録します。入力値を検証し、HelmRelease オブジェクトに変換してクラスターへ送信しますが、その際、ユーザー向けAPIと内部実装の間で明確な分離を維持します。
主要な詳細
- API集約レイヤーにより、拡張サーバーは命令型ロジックや
/exec、/logなどのサブリソースを処理できます。 - 拡張APIは
APIServiceオブジェクトを通じて登録され、特定のAPIグループへのトラフィックを外部サーバーへ向けます。 - CRDとは異なり、拡張サーバーは状態をetcdに保存する必要がないため、リアルタイムデータ生成が可能になり、ストレージオーバーヘッドが削減されます。
- Cozystackはこのモデルを使用し、コードの再コンパイルなしで
Postgresなどのサービスkindを基盤となるHelmチャートに動的にマッピングします。 - この実装は、CRDの能力を超える複雑なサーバーサイド検証やカスタムテーブル出力フォーマットをサポートします。
- 不安定な拡張サーバーは名前空間の削除をブロックしたり、API遅延を引き起こしたりするため、信頼性が極めて重要です。
なぜ重要なのか
プラットフォームエンジニアにとって、集約レイヤーを理解することは、CRDだけでは困難または不可能な設計パターンを開拓することにつながります。これにより、ネイティブなKubernetesリソースのように振る舞うものの、命令型ロジックや外部バックエンドで動作するAPIを作成できます。これは特に、レガシーシステムの統合、リアルタイムメトリクスの公開、複雑なアプリケーション向けの簡素化されたインターフェース作成に有用です。
しかし、この強力さには運用上のリスクが伴います。拡張APIサーバーが利用不能になると、クラスター全体のパフォーマンスを低下させる可能性があります。名前空間の削除などの操作は、拡張機能がリソースクリーンアップを確認するのを待っている間にハングする場合があります。エンジニアは、カスタムAPI動作のメリットと、追加のAPIサーバーを実行することによる複雑性の増加および潜在的な安定性への影響を天秤にかける必要があります。
できること
- CRDと拡張サーバーのどちらを選ぶべきか判断する前に、ユースケースが命令型ロジックやリアルタイムデータを必要とするかどうかを評価してください。
- 拡張APIサーバーが利用不能になった場合の影響を考慮し、信頼性向上のための対策を講じてください。
- ネイティブRBACの制限を回避するために、サービスタイプごとに異なるリソースkindを生成する戦略を検討してください。
- etcdストレージの負荷を減らしつつリアルタイムデータを処理したい場合に、このアプローチが適しているか確認してください。
- 既存のツールやダッシュボードとの互換性を保つために、リソースの変換ロジックを慎重に設計してください。


