KubernetesにおけるDockerイメージ自動クリーンアップCronJobの実装

Kubernetesクラスター内の各ノードで、不要になったDockerイメージを定期的に自動削除するためのCronJob設定について解説します。このソリューションは、ノードのディスク容量を効率的に管理することを目的としており、毎日午前3時に実行されます。

前提条件:

  • Kubernetesバージョン v1.20以降 (kubectl debug機能を利用するため)
  • コンテナランタイムとしてDockerを使用しているノード (containerdやCRI-Oは直接サポートされていません)
  • ClusterRoleおよびClusterRoleBindingを作成するための権限
  • docker:28.0.1およびbitnami/kubectl:latestイメージをプルできるネットワーク環境
  • ノードで稼働しているDockerバージョンと互換性のあるDockerイメージバージョンを使用することを推奨します。

互換性:

  • コンテナランタイム: Dockerのみ直接サポート。containerdやCRI-Oを使用する場合は、crictlコマンドへの適応が必要です。
  • Kubernetesバージョン: v1.20以降ではkubectl debugが利用可能。v1.15からv1.19ではkubectl runによる代替策が必要になる場合があります。v1.15未満はサポート対象外です。

機能概要:

  • 実行スケジュール: 毎日午前3時
  • 対象範囲: クラスター内の全ノード
  • クリーンアップポリシー:
    • 過去24時間以上使用されていないイメージを削除
    • 未使用の(dangling)イメージを削除
  • タイムアウト設定: 各ノードでの操作は120秒以内に完了する必要があります。
  • 履歴管理: 成功したジョブは3件、失敗したジョブは1件保持されます。

CronJob YAML設定例:


apiVersion: batch/v1
kind: CronJob
metadata:
  name: node-image-cleaner
  namespace: kube-system # または任意の管理用ネームスペース
spec:
  schedule: "0 3 * * *"
  successfulJobsHistoryLimit: 3
  failedJobsHistoryLimit: 1
  jobTemplate:
    spec:
      ttlSecondsAfterFinished: 3600 # ジョブ完了後1時間で自動削除
      template:
        spec:
          serviceAccountName: node-cleaner-sa
          containers:
          - name: image-purger
            image: bitnami/kubectl:latest
            command: ["/bin/bash", "-c"]
            args:
            - |
              echo "Starting Docker image cleanup across all nodes..."
              NODE_OPERATION_TIMEOUT=120 # seconds
              kubectl get nodes -o name | while read node_ref; do
                NODE_NAME=$(basename $node_ref)
                echo "Processing node: $NODE_NAME"
                
                # Use kubectl debug to execute cleanup commands on the node
                timeout $NODE_OPERATION_TIMEOUT kubectl debug $NODE_NAME \
                  --image=docker:28.0.1 \
                  --quiet \
                  -- sh -c "
                    echo 'Running cleanup on node ${NODE_NAME}...'
                    # Prune images older than 24 hours
                    chroot /host docker image prune -a -f --filter 'until=24h' >/dev/null 2>&1
                    # Prune dangling images
                    chroot /host docker image prune -f >/dev/null 2>&1
                    echo 'Cleanup completed on node ${NODE_NAME}.'
                  " || echo "Node $NODE_NAME cleanup timed out or failed."
                echo "$NODE_NAME processing finished."
                echo "--------------------"
              done
              echo "All nodes image cleanup finished."
          restartPolicy: Never

デプロイ手順:

  1. Namespaceの作成 (まだ存在しない場合):
    
    kubectl create namespace image-cleanup-ns
    
  2. ServiceAccountの作成:
    
    kubectl create serviceaccount node-cleaner-sa -n image-cleanup-ns
    
  3. ClusterRoleの作成: ノード情報の取得とデバッグPodの作成・削除権限を付与します。
    
    kubectl apply -f - <<EOF
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: node-image-cleaner-role
    rules:
    - apiGroups: [""]
      resources: ["nodes"]
      verbs: ["get", "list", "watch"]
    - apiGroups: [""]
      resources: ["pods"]
      verbs: ["create", "delete", "get", "list", "watch"]
    EOF
    
  4. ClusterRoleBindingの作成: ServiceAccountにClusterRoleを紐付けます。
    
    kubectl apply -f - <<EOF
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: node-image-cleaner-binding
    subjects:
    - kind: ServiceAccount
      name: node-cleaner-sa
      namespace: image-cleanup-ns
    roleRef:
      kind: ClusterRole
      name: node-image-cleaner-role
      apiGroup: rbac.authorization.k8s.io
    EOF
    
  5. CronJobの適用: 上記のYAML設定をファイルに保存し、適用します。
    
    kubectl apply -f your-cronjob-file.yaml -n image-cleanup-ns
    

設定詳細:

  • schedule: "0 3 * * *": UTC午前3時にジョブを実行します。
  • successfulJobsHistoryLimit: 3, failedJobsHistoryLimit: 1: 過去のジョブ実行履歴の保持数を指定します。
  • ttlSecondsAfterFinished: 3600: 完了したジョブは1時間後に自動的に削除されます。
  • --image=docker:28.0.1: ノード上でDockerコマンドを実行するために使用される一時的なコンテナイメージです。ノードのDockerバージョンとの互換性を考慮して、適切なバージョンを指定することが重要です。
  • timeout $NODE_OPERATION_TIMEOUT: 各ノードでのDockerコマンド実行にタイムアウトを設定します。
  • chroot /host docker image prune ...: ノードのルートファイルシステムにchrootしてからDockerコマンドを実行し、ホストOSのDockerデーモンにアクセスします。
  • --filter 'until=24h': 24時間以上使用されていないイメージを対象とします。

注意事項:

  • RBAC権限: ClusterRoleおよびClusterRoleBindingの設定が正しく行われていることを確認してください。
  • リソースへの影響: イメージクリーンアップは一時的にノードのCPUやI/Oに負荷をかける可能性があります。
  • 監視: CronJobの実行状況、ノードのディスク使用率を監視し、問題発生時にはログを確認してください。
  • Dockerバージョンの整合性: --image=docker:X.Y.Z で使用するDockerイメージのバージョンは、ノードにインストールされているDockerエンジンのバージョンと互換性があることを確認してください。バージョンが大きく異なると、コマンドが失敗したり、予期せぬ動作を引き起こしたりする可能性があります。

トラブルシューティング:

  • 権限エラー: kubectl auth can-i ... コマンドでServiceAccountの権限を確認します。
  • イメージプル失敗: ネットワーク設定や、プライベートレジストリを使用している場合は認証情報を確認します。
  • ノードでのコマンド失敗: kubectl logsでジョブのログを確認し、Dockerコマンドのエラーメッセージを調査します。kubectl debugコマンドを直接ノードで実行してテストすることも有効です。

タグ: Kubernetes Docker CronJob image cleanup automation

9月13日 02:11 投稿