2026年8月30日
2026年8月30日
KubernetesのOperatorパターンの概要|仕組み・使いどころ・導入前に確認すること
Kubernetes の Operator は、データベースやメッセージキューのような「運用に手間のかかるソフトウェア」の管理手順を、独自のリソース(カスタムリソース)とそれを監視するコントローラーとしてクラスターに組み込む仕組みです。利用者は「3台構成の PostgreSQL がほしい」と宣言するだけで、構築、フェイルオーバー、バックアップなどを Operator が代わりに行います。この記事では、Operator の仕組み、Helm との違い、既存の Operator を選ぶときの確認点、自作する場合の入口までを説明します。
Operator を構成する2つの部品
Operator は、次の2つの組み合わせです。
- カスタムリソース定義(CRD): Kubernetes に新しい種類のリソースを追加します。たとえば
PostgresClusterやKafkaのような、標準には無いリソースを作れるようになります。 - カスタムコントローラー: そのリソースを監視し、宣言された状態に実際のクラスターを近づけるプログラムです。クラスター内の Pod として動きます。
Kubernetes の標準機能も同じ仕組みで動いています。Deployment を作ると、Deployment コントローラーが ReplicaSet を作り、ReplicaSet コントローラーが Pod を作ります。Operator はこの仕組みを、特定のアプリケーションの運用知識に応用したものです。
リコンサイルループ:Operator の動き方
コントローラーの中心は「リコンサイル(reconcile、調整)」と呼ばれる処理です。
- カスタムリソースに書かれた「あるべき状態」を読む
- クラスターの「今の状態」を確認する
- 差があれば、それを埋める操作を1つ行う
- 結果をカスタムリソースの
statusに書き戻す
この処理は、リソースが変更されたとき、関連するリソースが変わったとき、そして一定時間ごとに繰り返し呼ばれます。「何が起きたか」というイベントに反応するのではなく、毎回「今どうなっているか」を見て判断するため、途中でコントローラーが再起動しても、次の呼び出しで正しい状態に戻せます。自作する場合は、同じ処理を何度実行しても結果が変わらない(冪等な)作りにすることが重要です。
具体的な例で考えます。データベースの Operator に instances: 3 と宣言すると、Operator は StatefulSet や Pod、Service、Secret を作ります。1台の Pod が落ちれば、Operator は状態の差に気づき、レプリカを昇格させたり Pod を作り直したりします。人が手順書を見ながら行っていた作業を、コードが繰り返し確認し続ける形です。
Helm との違い
Helm も Operator も「アプリケーションをまとめてデプロイする」点では似ていますが、役割が異なります。
- Helm は、テンプレートからマニフェストを作って適用する道具です。適用した後のことには関与しません。Pod が落ちたときの対処は Kubernetes の標準機能に任されます。
- Operator は、適用した後も動き続け、アプリケーション固有の運用(レプリカの昇格、バージョンアップの順序、バックアップの取得など)を継続して行います。
Web サーバーのように、Deployment と Service だけで運用できるものなら Helm で十分です。データの一貫性やクラスターの構成管理が必要なステートフルなソフトウェアで、Operator の価値が出ます。実際には、Operator 自体を Helm でインストールすることもよくあります。
Operator Framework というプロジェクトは、Operator ができることの成熟度を、基本的なインストールから、シームレスなアップグレード、ライフサイクル全体の管理、詳細な監視、自動運転的な調整まで、5段階で整理しています。選ぶときの目安になります。
既存の Operator の例
よく使われる Operator には次のようなものがあります。いずれも活発に開発されていますが、対応範囲や推奨構成は版によって変わるため、導入時は各プロジェクトのドキュメントを確認してください(2026年10月現在)。
- Prometheus Operator: Prometheus と Alertmanager を管理し、
ServiceMonitorなどのリソースで監視対象を宣言できます。 - CloudNativePG: PostgreSQL のクラスターを管理します。
- Strimzi: Apache Kafka を管理します。
- cert-manager: 証明書の発行と更新を行います。厳密には Operator を名乗っていませんが、CRD とコントローラーで動く同じ構造です。
CloudNativePG を例にすると、次のマニフェストを適用するだけで、3台構成の PostgreSQL クラスターが作られます。
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: pg-sample
spec:
instances: 3
storage:
size: 10Gi
kubectl apply -f pg-sample.yaml
kubectl get cluster pg-sample
kubectl describe cluster pg-sample
describe の Status 欄に、プライマリがどの Pod か、レプリカの状態はどうかなど、Operator が把握している情報が出ます。カスタムリソースの status を読むことが、Operator を使った運用の基本の確認方法になります。
既存の Operator を選ぶときの確認点
Operator はクラスター内で強い権限を持って動き続けるソフトウェアです。導入する前に次の点を確認します。
- 保守の状況。 最近のリリースがあるか、対応している Kubernetes のバージョンはどこまでか、Issue への対応が続いているかを見ます。開発が止まった Operator は、Kubernetes のアップグレードの妨げになります。
- 必要な権限。 多くの Operator は、クラスター全体の Secret や Pod を操作する ClusterRole を求めます。監視対象を特定の Namespace に限定できるかを確認し、必要以上の権限を与えないようにします。
- アンインストールの影響。 CRD を削除すると、そのリソースはすべて消えます。データベースの Operator であれば、データを持つリソースごと消える可能性があります。削除手順と、データが残る条件を事前に把握しておきます。
- バックアップと復元の手順。 Operator がバックアップ機能を持っていても、復元を実際に試すまでは使えるかどうか分かりません。検証環境で復元まで通しておきます。
- アップグレードの方法。 Operator 自体のバージョンアップと、管理対象のソフトウェアのバージョンアップは別の作業です。CRD の変更を伴う場合もあるため、リリースノートを確認してから行います。
Operator の配布や更新を管理する仕組みとして Operator Lifecycle Manager(OLM)があり、OperatorHub.io では公開されている Operator を探せます。OLM は OpenShift では標準で使われていますが、一般的なクラスターでは Helm でのインストールを案内している Operator も多く、どちらを使うかはプロジェクトの案内に従います。
自作する場合の入口
社内のシステム固有の運用を自動化したい場合は、Operator を自作することもできます。主な開発ツールは次のとおりです。
- Kubebuilder: Go で開発するための公式のフレームワークです。内部では controller-runtime というライブラリを使います。
- Operator SDK: Kubebuilder を土台に、Helm チャートや Ansible をもとにした Operator も作れます。
- Kopf(Python)、Java Operator SDK など、他の言語向けのものもあります。
Kubebuilder でプロジェクトとリソースの雛形を作るコマンドの例です。
kubebuilder init --domain example.com --repo example.com/webapp-operator
kubebuilder create api --group webapp --version v1alpha1 --kind WebApp
生成されたコードの中で、自分で書く中心部分が Reconcile 関数です。次は、カスタムリソース WebApp に対応する Deployment が無ければ作る、という最小限の処理の抜粋です(deploymentFor は、WebApp の内容から Deployment を組み立てる関数として別に書く想定です)。
func (r *WebAppReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
logger := log.FromContext(ctx)
var app webappv1alpha1.WebApp
if err := r.Get(ctx, req.NamespacedName, &app); err != nil {
// 削除済みのリソースなら何もしない
return ctrl.Result{}, client.IgnoreNotFound(err)
}
var dep appsv1.Deployment
err := r.Get(ctx, req.NamespacedName, &dep)
if apierrors.IsNotFound(err) {
newDep := r.deploymentFor(&app)
// WebApp を親として登録し、WebApp の削除時に Deployment も消えるようにする
if err := ctrl.SetControllerReference(&app, newDep, r.Scheme); err != nil {
return ctrl.Result{}, err
}
logger.Info("creating Deployment", "name", newDep.Name)
return ctrl.Result{}, r.Create(ctx, newDep)
}
if err != nil {
return ctrl.Result{}, err
}
// ここで dep と app.Spec を比べ、差があれば更新する
return ctrl.Result{}, nil
}
エラーを返すと、controller-runtime が間隔を空けて再試行します。SetControllerReference で親子関係(ownerReference)を付け、SetupWithManager で Owns(&appsv1.Deployment{}) を指定しておくと、Deployment が変更・削除されたときにも親の WebApp のリコンサイルが呼ばれます。
自作するときにつまずきやすいのは、削除時の後始末です。外部のリソース(クラウドのストレージなど)を作る Operator では、ファイナライザーを使って、カスタムリソースが消える前に外部リソースを片付ける処理が必要になります。また、CRD の仕様を変えるときはバージョンを分け、既存のリソースを壊さない移行方法を考える必要があります。小さく始め、まずは検証用のクラスターで動かしてください。
まとめ
- Operator は「カスタムリソース」と「それを監視するコントローラー」の組み合わせで、アプリケーション固有の運用をクラスターに組み込みます。
- 中心はリコンサイルループです。毎回あるべき状態と今の状態を比べて差を埋めるため、冪等な作りが前提になります。
- デプロイだけなら Helm で十分です。ステートフルで運用手順の多いソフトウェアで Operator が役立ちます。
- 既存の Operator は、保守の状況、必要な権限、アンインストール時の影響、復元手順を確認してから導入します。
- 自作するなら Kubebuilder や Operator SDK から始め、削除時の後始末と CRD のバージョン管理を設計に含めます。