Finalizer と Owner Reference を用いた Kubernetes の削除メカニズムの理解
2021 年のガイドでは、Finalizer がリソースの削除をブロックする方法と、Owner Reference が Kubernetes クラスターでのカスケード削除を管理する方法について解説しています。
英語の原文から自動翻訳されました。
2021 年 5 月の Kubernetes Blog の投稿で、Aaron Alpar は Kubernetes 内でのオブジェクト削除の内部メカニズムについて詳細に説明しました。この記事は、delete コマンドを発行した後もリソースがなぜ残存することがあるのかを明確にし、クラスター状態の管理における Finalizer と Owner Reference の役割を解説しています。
何が起きたか
Kubernetes では、オブジェクトの作成、読み取り、更新、削除のための標準的なコマンドが提供されていますが、削除プロセスはストレージからの単純な除去よりも複雑です。ユーザーが kubectl delete コマンドを発行しても、システムは必ずしもそのオブジェクトをレジストリである etcd から即座に削除するわけではありません。代わりに、Finalizer の存在や複雑な所有者関係など、特定の条件が満たされた場合、操作は保留状態に入ることがあります。
記事では、余分なメタデータを持たない ConfigMap などのシンプルなリソースに対する基本的な削除は期待通りに動作する一方で、Finalizer を追加すると挙動が大きく変化することを示しています。Finalizer は削除前のフックとして機能し、リソースが完全に削除される前にクリーンアップ操作を実行する必要があることをコントローラーに通知します。これらのフックが解決されない場合、オブジェクトは終了中の状態のまま残り、削除タイムスタンプが表示されますが、クラスター内に存在し続けます。
さらに、Owner Reference によって定義されるリソース間の関係は、オブジェクトのグループがどのように一緒に削除されるかを決定します。親オブジェクトを削除すると、その子オブジェクトの削除がトリガーされることがあり、このプロセスはカスケードと呼ばれます。しかし、この挙動は伝播ポリシー(Propagation Policies)を使用して変更でき、開発者は子オブジェクトを孤立化させたり、削除順序を制御したりできます。これらのメカニズムを理解することは、スタックした名前空間や残存するリソースのデバッグにおいて極めて重要です。
仕組み
Finalizer は、即時のガベージコレクションを防ぐためにリソースのメタデータに添付されるキーです。アノテーションと同様に機能しますが、コントローラーにとって意味のある重みを持っています。Finalizer を持つオブジェクトに対して削除要求が行われると、Kubernetes はオブジェクトに deletionTimestamp を追加して更新しますが、etcd からの削除はブロックします。オブジェクトは、コントローラーが Finalizer キーを削除してクリーンアップ完了を示すまで、この状態のまま残ります。もし Finalizer を管理するコントローラーが存在しない場合、それは「死んだ」Finalizer となり、キーを削除して削除処理を進めるために patch コマンドによる手動介入が必要になります。

Owner Reference は、同じ名前空間内のリソース間に親子関係を確立します。各参照には、親オブジェクトの名前と一意な識別子(UID)が含まれます。親が削除されると、Kubernetes はこれらの参照を確認し、子も削除すべきかどうかを判断します。このカスケード削除は伝播ポリシーによって制御されます。デフォルトのポリシーは kubectl v1.20 で background に変更され、親が最初に削除され、子は非同期に削除されるようになります。他のオプションには、子が親より先に削除される foreground や、Owner Reference を無視して子をそのまま残す orphan があります。
主要な詳細
- Finalizer は、コントローラーに削除前の操作を通知するためのリソース上のキーのリストです。
- Finalizer を持つオブジェクトは即座には削除されません。
deletionTimestampが付与され、Finalizer がクリアされるまで表示されたままになります。 - Owner Reference は名前と UID を通じてリソースをリンクし、親が削除された際に子オブジェクトのカスケード削除を可能にします。
- kubectl v1.20 以降のデフォルトのカスケード挙動は
backgroundですが、それ以前のバージョンではデフォルトがtrueでした。 - 伝播ポリシー(
Foreground、Background、Orphan)は削除順序を制御し、標準的な kubectl フラグではなく、API への直接呼び出しでのみ設定できます。 - スタックした名前空間は、API 経由で
finalizeサブリソースを更新することで強制的に確定させることができますが、これにより孤立したオブジェクトが残るリスクがあります。
なぜ重要なのか
Kubernetes プラットフォームの構築と保守を行うエンジニアにとって、削除メカニズムを理解することは、リソースが期待通りに消えない際の混乱を防ぎます。よくあるシナリオとしては、カスタムリソースやサードパーティ製コントローラーによって追加された Finalizer がもはや処理されていないため、名前空間が Terminating 状態のまま残る場合があります。Finalizer の検査とパッチ方法を知らないと、オペレーターはクラスターのクリーンアップに苦戦し、リソースリークやデプロイ失敗につながる可能性があります。

また、Owner Reference を正しく管理することは、アプリケーションのティアダウン(解体)がクリーンかつ予測可能であることを保証します。開発者がカスケールルールを理解せずに Deployment を削除した場合、リソースを消費する Pod や Service を意図せず残してしまうかもしれません。逆に、orphan ポリシーの使用方法を知っていれば、元々の親の削除後も子リソースを生存させる必要がある安全なマイグレーション戦略が可能になります。この知識は、Kubernetes API と連携する堅牢なオペレーターや自動化スクリプトを作成するために不可欠です。
できること
- 削除中にスタックしているオブジェクトを検査するには、YAML 出力で
finalizersおよびdeletionTimestampフィールドを確認してください。 - 死んだ Finalizer は、メタデータから特定の Finalizer キーを削除する JSON 操作を用いて
kubectl patchで手動削除してください。 - 一括削除を実行する前に、リソース間の依存関係を可視化するために、Owner Reference を使用して
kubectl getを実行してください。 - 本番環境以外の環境で、親子関係にある ConfigMap を作成し、異なる削除コマンドの影響を観察することで、カスケード挙動をテストしてください。
ForegroundやBackgroundなどの伝播ポリシーを指定する必要がある場合は、kubectl proxyを利用して API へ直接呼び出しを行ってください。- API 経由で名前空間の確定を強制する際は注意が必要です。手動でのクリーンアップが必要な孤立リソースが残る可能性があるためです。


