【ITニュース解説】A Quick Dive into Kubernetes Operators - Part 4
2025年09月29日に「Dev.to」が公開したITニュース「A Quick Dive into Kubernetes Operators - Part 4」について初心者にもわかりやすく解説しています。
ITニュース概要
Kubernetes Operatorは、標準APIでは難しい複雑なデータ連携や独自の処理を実現する。本記事では、Aggregation APIを使ってKubernetes上に完全にカスタマイズされたAPIを実装する方法を紹介。TaskとEventを統合した「CombinedTask」のような独自リソースを構築し、柔軟な運用を可能にする。
ITニュース解説
Kubernetesは、コンテナ化されたアプリケーションのデプロイ、管理、スケーリングを自動化するための強力なプラットフォームである。このプラットフォームをより便利に、そして特定の用途に特化して利用するために、「Kubernetes Operator」という仕組みが存在する。Operatorは、人間が行う運用作業を自動化し、Kubernetesの組み込み機能だけでは実現できない高度なタスクをこなすためのプログラムだ。
これまでのシリーズでは、このOperatorの基本的な作り方、独自のデータ型(カスタムリソース)をKubernetesで扱えるようにする方法、そしてカスタムの検索APIを実装する方法を学んできた。今回の焦点は、さらに一歩進んで、Kubernetesの内部に完全に独自のAPI(アプリケーションプログラミングインターフェース)を実装することにある。これにより、より複雑なデータ処理や、特定の業務に特化したロジックを、Kubernetesの標準的なAPIとして直接提供できるようになる。
なぜ、このように「完全にカスタムなAPI」が必要になるのだろうか。 Kubernetesが提供する標準的なAPIや、これまで扱ってきたOperatorの機能は非常に強力だが、時にはそれだけでは不十分なケースが出てくる。特に、アプリケーションのデータが複雑な関係性を持っていたり、データを取得するプロセスを非常に細かく制御したい場合には、限界がある。
例えば、従来のアプリケーション開発では、データベースから関連するデータを一度にまとめて取得する「Eager Loading」のような手法がよく用いられる。これは、一対一や一対多のようなシンプルなデータ関係ではうまく機能する。しかし、システムが大規模になり、以下のような状況になると、この方法では効率が悪くなったり、管理が難しくなったりする。
- 多対多の関係にあるデータが多数存在する
- 取得したデータに対して複雑な変換処理が必要になる
- データが深い階層構造でネストしている
このような場合に「集約API(Aggregation API)」という仕組みを使うことで、フロントエンド(ユーザーインターフェースなど)と、その裏側にある複雑なデータ取得ロジックを分離できる。この分離によって、データの取得プロセスを完全に制御できるようになり、パフォーマンスの最適化、ネットワーク上での無駄な通信量の削減、そしてクライアントの特定の要求に合わせてデータを正確に整形することが可能になる。
具体的な実装例として、今回は「ClusterTask」と「CustomTask」という二つのサービスを構築する。
「ClusterTask」はクラスタ全体に影響を与えるリソース(クラスタスコープ)として設計され、「CustomTask」は特定の名前空間内でのみ有効なリソース(名前空間スコープ)として作られる。
これらのサービスは、KubernetesのAPIリソースとして登録され、それぞれget(取得)、list(一覧表示)、watch(監視)、create(作成)、update(更新)、delete(削除)といった標準的なAPI操作をサポートする。
実際のコードでは、それぞれの操作に対してHTTPリクエストを受け取った際の具体的な処理(ハンドラ関数)を定義する。このハンドラ関数の中に、独自のデータ処理ロジックや、他のKubernetesリソースとの連携ロジックを実装することになる。
デプロイ後には、kubectl create --rawのようなコマンドを使って、これらのカスタムAPIに直接リクエストを送り、リソースを作成したり、取得したり、削除したりできるようになる。これは、あたかもKubernetesの標準リソース(PodやDeploymentなど)を操作するのと同じように、独自のロジックを持つリソースを扱えるようになることを意味する。
次に、既存のKubernetesリソースを拡張する「集約エンドポイント」の実装について解説する。
ここでは「combinedtasks」という新しいエンドポイントを作成する。このエンドポイントは、get、list、watchといったKubernetesの標準的なリソース操作と同じように機能するが、単に「Task」というリソースを返すだけでなく、そのTaskに関連するすべての「イベント」(Event)も合わせて提供する。
つまり、「CombinedTask」は、Taskオブジェクト(優先度、期限、詳細など)と、そのTaskのライフサイクル中に発生したすべての運用上のシグナル(イベント)を一つのレスポンスとして結合した、よりリッチな情報を持つリソースとなる。
この「CombinedTask」のような設計は、開発者にとって非常に有用である。通常、あるTaskの状態を詳細に把握するためには、Taskリソースを単独で取得するだけでなく、そのTaskに関連するEventリソースも別途クエリして確認する必要がある。しかし、「CombinedTask」エンドポイントを一度呼び出すだけで、ビジネス上のオブジェクトであるTaskと、そのTaskがどのように進行しているかを示す運用上のシグナルであるEventの両方を、一元的に確認できるようになる。これにより、複数の情報を手動で結合する手間が省け、より効率的に状況を把握できる。
この集約エンドポイントを実装する際には、まずKubernetesのイベント情報を取得するための権限をOperatorに追加する必要がある。具体的には、eventsリソースに対するgetとlistの権限を付与する。
その後、「CombinedTask」と、そのリストである「CombinedTaskList」のデータ構造を定義する。CombinedTaskは、既存のTaskの構造に加えて、statusフィールド内にeventsというイベントのリストを持つように拡張される。
実装の核となるのは、集約APIサーバーの設定にこの「combinedtasks」サービスを追加する部分だ。
特に重要なのがListCallbackとWatchCallbackという関数である。
ListCallbackは、複数のCombinedTaskを一覧で取得する際に呼び出される。この関数内では、まず通常のTaskリストを取得し、そのTaskそれぞれに関連するEventを取得する。このとき、もし各Taskに対して個別にEventを問い合わせると、問い合わせ回数が膨大になりパフォーマンスが悪化する「N+1クエリ問題」が発生してしまう。これを避けるため、ここでは取得したすべてのTaskのUID(ユニークなID)を基にラベルセレクタを生成し、一度の問い合わせで関連するすべてのEventを一括で取得する工夫をしている。取得したEventは、どのTaskに紐づくかをUIDで判別し、それぞれのTask情報と結合してCombinedTaskとして整形し、最終的にCombinedTaskListとして返す。
WatchCallbackは、個々のCombinedTaskの変更を監視する際に呼び出され、同様にTaskと関連イベントを結合して返す。
これらのカスタムAPIが正しく機能するためには、元のTaskを管理するコントローラーも修正する必要がある。具体的には、Taskがイベントを発生させた際に、そのイベントに「TaskのUID」をラベルとして付与するように変更する。このラベルがあることで、集約API側でTaskとEventを正確に関連付けて取得できるようになる。
これらの変更を加えてアプリケーションを再デプロイすると、kubectlコマンドで新しい「combinedtasks」エンドポイントを操作できるようになる。例えば、kubectl get combinedtasks -Aで全名前空間のCombinedTaskを一覧表示したり、kubectl get combinedtasks -n default task-sample-5 -o yamlで特定のCombinedTaskの詳細をYAML形式で取得し、その中にTaskの情報だけでなく、関連するEventも含まれていることを確認できる。
このように、Kubernetesは強力なプラットフォームだが、その組み込みAPIだけでは複雑なビジネスロジックやドメイン固有の要件に完全に適合できない場合がある。しかし、「API Aggregation Layer」という機能を利用することで、Kubernetesの既存機能を拡張し、これらの課題を解決するための完全にカスタマイズされたAPIを作成できる。このアプローチにより、特定のデータ集約や変換を行う専門のエンドポイントを実装し、Kubernetesの管理能力を飛躍的に高めることが可能となる。