Argo Workflowsを使ったPersistentVolumeの定期バックアップ

Argo Workflowsを使ったPersistentVolumeの定期バックアップ

こんにちは。
インフラグループKubernetesチームの福田です。
今回はPV(PersistentVolume)の定期バックアップシステムについて紹介したいと思います。

PVのバックアップについて

PVのバックアップといっても色々とありますが、本記事ではスナップショットの取得を意味します。
スナップショットの取得はCSIが対応していれば、external-snapshotterを利用することで、CustomResourceを書くだけで実現できます。

extenal-snapshotterを全く知らない方は以下のAWSの記事が概要を掴む参考になるかと思います。

aws.amazon.com

バックアップシステムの仕組み

概要

システムの概要は以下のようになっています。

  • Argo Workflowsが定期的にVolumeSnapshotリソースを作成し、それをGitLabへプッシュする。
  • GitLabのCIがマニフェストをバリデーションする。
  • Argo CDがマニフェストのあるコードリポジトリの変更を検出して、それをKubernetesにデプロイする。

詳細

定期的に実行する処理

定期的な処理の実行はCronWorkflowで行っています。 単にCronJobとせず、CronWorkflowとした理由は、一度だけの実行や、定期処理の一時停止などがGUIで簡単にできるからです。

VolumeSnapshotリソースの生成

VolumeSnapshotリソースの生成を行うアプリケーションはGolangで実装した自前のコンテナアプリになります。
コンテナアプリは前述したCronWorkflowで実行されます。

世代管理機能

コンテナアプリはVolumeSnapshotマニフェストを生成すると共に、古いVolumeSnapshotマニフェストを削除するローテーション機能を持っています。
何世代分までのVolumeSnapshotマニフェストを維持するかは環境変数で指定可能になっています。
VolumeSnapshotマニフェスト間の新旧の比較はVolumeSnapshotマニフェスト生成時のタイムスタンプを独自のアノテーションに記載し、それを比較することで実現しています。

管理対象フラグ

ローテーション管理の対象とする否かのフラグを表現する独自のアノテーションもあります。
原則、コンテナアプリで生成されたVolumeSnapshotはこのフラグが立っています。
手動で作成したVolumeSnapshotやコンテナアプリによって作成された永続的に残しておきたいスナップショットについては、このフラグを下ろすことでローテーションの管理対象から外れて自動で削除されないようにできます。

生成されるマニフェストのサンプル

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: SAMPLE_NAME
  namespace: SAMPLE_NAMESPACE
  annotations:
    snapshot-tools.enigmo.co.jp/rotation: "true"
    snapshot-tools.enigmo.co.jp/rtime: 12345678
spec:
  source:
    persistentVolumeClaimName: SAMPLE_PVC
  volumeSnapshotClassName: SAMPLE_VSC
コードプッシュ

コンテナアプリはVolumeSnapshotマニフェストを作成、削除するとその変更をプッシュします。 プッシュ時のオプションでMergeRequest(githubでいうPullRequest)を作成し、CIが成功したら自動でMRをマージするようにしています。

CIの実行

MRに対しては手動によるマニフェストのデプロイと同じ条件でCIが周り、問題がなければそれをマージするようになっています。
これにより、システムが生成したマニフェストコードを特別扱いすることなく、統一したポリシー(例えば、フォーマッタやセキュリティチェック等のマニフェストに対するバリデーション)を適用できます。

Argo CDによるデプロイ

masterにマージされた変更を検出し、それをクラスタへ自動で適用するようにauto-syncを有効化しています。
また、世代管理機能によってVolumeSnapshotマニフェストの削除される場合もあるので、auto-pruneも有効化しています。
以下がArgoCD Applicationのサンプルになります。

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: snapshots
spec:
  generators:
  - list:
      elements:
      - namespace: SAMPLE_NS1
      - namespace: SAMPLE_NS2
      - namespace: SAMPLE_NS3
  template:
    metadata:
      name: '{{namespace}}-snapshot'
    spec:
      project: SAMPLE-PROJECT
      source:
        repoURL: GITLAB_URL
        targetRevision: master
        path: SAMPLE_PATH
      destination:
        server: K8S_ENDPOINT
        namespace: '{{namespace}}'
      syncPolicy:
        automated:
          prune: true

純粋なApplicationでなく、ApplicationSetとしている理由は我々は複数ネームスペースの運用をしているためです。 (Argo CDのApplicationは1つのネームスペースしかデプロイ先として指定できない。)

まとめ

Argo Workflowsを使ったPersistentVolumeの定期バックアップシステムについて紹介させていただきました。
実装方法としてオペレータパターンで開発する選択肢もありましが、cronの一時停止やカウントダウンタイマーなどをGUIで管理できる点からArgo WorkflowsのCronWorkflowを利用する実装を選択しました。
今回の記事がKubernetesネイティブな自動化システムの開発の参考になれば幸いです。

エニグモではエンジニアを含む各種ポジションで求人を募集しております。

株式会社エニグモ すべての求人一覧

hrmos.co