2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Kubernetesコントローラー開発におけるFinalizerと削除処理の詳細解説

Last updated at Posted at 2024-11-29

Kubernetesコントローラー開発におけるFinalizerと削除処理の詳細解説

Kubernetesのカスタムコントローラーを開発する際、リソースの作成や更新だけでなく、削除時の適切な処理が重要です。特に、関連する外部リソースのクリーンアップを確実に行うためには、 Finalizer(Finalizer) の活用が不可欠です。

本記事では、HelmReleaseProxyコントローラーにおける削除処理を詳しく解説し、このパターンが一般的なコントローラー開発にも適用可能であることを説明します。また、実装レベルでの詳細や、リソースのクリーンアップが確実に行われるための工夫についても触れます。

はじめに

HelmReleaseProxyは、Kubernetes上でHelmチャートを管理するためのカスタムリソースです。このリソースは、HelmChartProxyを経由して作成されます。リソースの削除時には、関連するHelmリリースや外部リソースを適切にクリーンアップする必要があります。

この削除処理の詳細な実装は、以下のソースコードで確認できます:

削除処理の流れと実装詳細

1. 削除状態の確認

まず、リソースが削除中かどうかを確認します。

if helmReleaseProxy.ObjectMeta.DeletionTimestamp.IsZero() {
    // リソースは削除されていない
} else {
    // リソースは削除中
}
  • DeletionTimestampがゼロ値の場合:リソースは削除されていません。
  • DeletionTimestampが設定されている場合:リソースは削除プロセス中です。

2. Finalizerの追加

削除されていないリソースに対して、以下の条件でFinalizerを追加します。

  • 条件

    • DeletionTimestampが設定されていない。
    • リソースのfinalizersに、指定したFinalizerが含まれていない。

実装

if !controllerutil.ContainsFinalizer(helmReleaseProxy, finalizerName) {
    controllerutil.AddFinalizer(helmReleaseProxy, finalizerName)
    if err := patchHelmReleaseProxy(ctx, patchHelper, helmReleaseProxy); err != nil {
        return ctrl.Result{}, err
    }
}
  • 目的:Finalizerを追加することで、削除時に必要なクリーンアップ処理が完了するまでリソースの削除を遅延させます。
  • 注意点:Finalizerの追加は、コントローラーがリソースを処理をする一番最初のステップで行う必要があります。例えばリソースを処理した後にFinalizerを追加する様な処理の場合だと、Finalizerを追加する前のステップでコントローラーが強制終了されて起動しない状態になったら、Finalizerが追加できなくなり、クリーンアップ処理が実行できなくなる可能性が出てきます。

3. 削除中の処理とクリーンアップ

リソースが削除中で、かつFinalizerが設定されている場合、関連する外部リソースのクリーンアップを行います。

実装

if controllerutil.ContainsFinalizer(helmReleaseProxy, finalizerName) {
    // クラスタの取得
    if err := r.Client.Get(ctx, clusterKey, cluster); err == nil {
        // クラスタが存在する場合
        // クラスタのkubeconfigを取得
        restConfig, err := remote.RESTConfig(ctx, "caaph", r.Client, clusterKey)
        if err != nil {
            return ctrl.Result{}, err
        }
        // 外部リソース(Helmリリース)の削除
        if err := r.reconcileDelete(ctx, helmReleaseProxy, r.HelmClient, restConfig); err != nil {
            return ctrl.Result{}, err
        }
    } else if apierrors.IsNotFound(err) {
        // クラスタが存在しない場合、クリーンアップは不要
    } else {
        // その他のエラー処理
        return ctrl.Result{}, err
    }

    // Finalizerの削除
    controllerutil.RemoveFinalizer(helmReleaseProxy, finalizerName)
    if err := patchHelmReleaseProxy(ctx, patchHelper, helmReleaseProxy); err != nil {
        return ctrl.Result{}, err
    }
}

ポイント

  • クラスタの存在確認
    • クラスタが存在する場合のみ、外部リソースの削除を実行します。
    • クラスタが既に削除されている場合、関連する外部リソース(Helmリリース)も削除できないため、その旨をログで記録し、finalizerを完了させます。

4. Runtime hooksとの連携

問題点

  • クラスタが先に削除されると、関連するHelmリリースが残ったままになる可能性があります。

解決策

  • Runtime hooksを利用HelmChartProxyコントローラーをクラスタのライフサイクルにフックさせ、クラスタ削除前に関連するリソースのクリーンアップを行います。

    • クラスタの削除要求を検知した際に、関連するHelmChartProxyHelmReleaseProxyの削除処理を優先的に実行します。

このproposalの詳細は、以下で確認できます:
20220414-runtime-hooks.md · kubernetes-sigs/cluster-api

5. Finalizerの削除

クリーンアップ処理が完了したら、Finalizerを削除します。これにより、Kubernetesはリソースの最終的な削除を進めることができます。

実装

controllerutil.RemoveFinalizer(helmReleaseProxy, finalizerName)
if err := patchHelmReleaseProxy(ctx, patchHelper, helmReleaseProxy); err != nil {
    return ctrl.Result{}, err
}

6. Reconciliationの終了

return ctrl.Result{}, nil
  • 削除処理が完了したため、Reconciliationを終了します。

一般的なコントローラー開発への適用

この削除処理のモデルは、他のKubernetesコントローラー開発でも広く適用できます。

Finalizer活用の手順(実装レベル)

  1. 削除状態の確認

    if resource.ObjectMeta.DeletionTimestamp.IsZero() {
        // リソースは削除されていない
    } else {
        // リソースは削除中
    }
    
  2. Finalizerの追加

    • 条件

      • DeletionTimestampが設定されていない。
      • finalizersに対象のFinalizerが含まれていない。
    • 実装

      if !controllerutil.ContainsFinalizer(resource, finalizerName) {
          controllerutil.AddFinalizer(resource, finalizerName)
          // リソースの更新
      }
      
  3. 削除中のクリーンアップ処理

    • 条件DeletionTimestampが設定されており、Finalizerが含まれている場合。

    • 実装

      if controllerutil.ContainsFinalizer(resource, finalizerName) {
          // 外部リソースのクリーンアップ
          // Finalizerの削除
      }
      

クリーンアップの確実性とリソースの整合性

  • 問題点:関連リソースが削除される順序によっては、クリーンアップが完全には実行できない場合があります。

HelmChartProxyとの関係

  • HelmReleaseProxyの生成HelmReleaseProxyHelmChartProxyを経由して作成されます。

実装上のポイント

  • エラーハンドリング:外部リソースの削除中にエラーが発生した場合、適切にログを記録し、リソースの状態を更新して再試行を促します。

  • リソースの状態管理:Conditionsを活用して、リソースの現在の状態やエラー情報を明確にします。

  • 依存関係の管理:リソース間の依存関係を明確にし、削除順序を制御します。

まとめ

Kubernetesコントローラー開発において、リソース削除時の適切な処理とFinalizerの活用は、外部リソースの整合性とシステムの健全性を維持する上で不可欠です。本記事で解説したHelmReleaseProxyコントローラーの削除処理は、その一例です。

このモデルは、他のコントローラー開発でも広く適用可能です。実装レベルでの詳細を把握し、自身のコントローラーに適用することで、より堅牢なシステムを構築できます。


参考リンク


注意:本記事で取り上げたコード例はApache License 2.0の下で提供されています。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?