1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

VeleroによるEKS PersistentVolume/PersistentVolumeClaimのバックアップとリストア

Last updated at Posted at 2025-12-23

はじめに

AWS EKSの運用をしていると、標準サポートが切れるので定期的にEKSのバージョンアップをする必要があります。
弊社では新しいEKSクラスターを作成してBlue/Greenデプロイで切り替えるのですが、現行EKSクラスターで利用中のアプリケーションの永続データ(EBSを用いたPV/PVC)を移行するのが結構大変です。
何か良いツールないかなと思って探してVeleroを知ったので、実際にバックアップとリストアを試してみることにしました。

バックアップ取得

Veleroのインストール

今回はローカルから手動でバックアップとリストアをするので、brew install veleroでVeleroをインストールします。

IAM/IRSA/S3/EBSの権限設定

terraformで必要なリソースを作成します。

iam.tf
resource "aws_s3_bucket" "velero" {
  bucket = "dev-velero"

  tags = {
    Name        = "dev-velero"
    Environment = "dev"
  }
}

resource "aws_s3_bucket_policy" "velero" {
  bucket = aws_s3_bucket.velero.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Principal = {
          AWS = aws_iam_role.velero.arn
        }
        Action = [
          "s3:GetObject",
          "s3:DeleteObject",
          "s3:PutObject",
          "s3:AbortMultipartUpload",
          "s3:ListMultipartUploadParts",
          "s3:ListBucket"
        ]
        Resource = [
          "${aws_s3_bucket.velero.arn}",
          "${aws_s3_bucket.velero.arn}/*"
        ]
      }
    ]
  })
}

resource "aws_iam_policy" "velero" {
  name        = "VeleroAccessPolicy"
  description = "Policy for Velero backup and restore"
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Action = [
          "s3:GetObject",
          "s3:DeleteObject",
          "s3:PutObject",
          "s3:AbortMultipartUpload",
          "s3:ListMultipartUploadParts",
          "s3:ListBucket"
        ]
        Resource = [
          "${aws_s3_bucket.velero.arn}",
          "${aws_s3_bucket.velero.arn}/*"
        ]
      },
      {
        Effect : "Allow",
        Action : [
          "ec2:DescribeVolumes",
          "ec2:DescribeSnapshots",
          "ec2:CreateTags",
          "ec2:CreateVolume",
          "ec2:CreateSnapshot",
          "ec2:DeleteSnapshot"
        ],
        Resource : "*"
      }
    ]
  })
}

resource "aws_iam_role" "velero" {
  name = "eks-velero-recovery"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Principal = {
          Federated = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:oidc-provider/${var.current_eks_oidc_provider}"
        }
        Action = "sts:AssumeRoleWithWebIdentity"
        Condition = {
          StringEquals = {
            "${var.current_eks_oidc_provider}:sub" = "system:serviceaccount:velero:velero-server"
          }
        }
      },
      {
        Effect = "Allow"
        Principal = {
          Federated = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:oidc-provider/${var.new_eks_oidc_provider}"
        }
        Action = "sts:AssumeRoleWithWebIdentity"
        Condition = {
          StringEquals = {
            "${var.new_eks_oidc_provider}:sub" = "system:serviceaccount:velero:velero-server"
          }
        }
      }
    ]
  })
}

resource "aws_iam_role_policy_attachment" "velero" {
  role       = aws_iam_role.velero.name
  policy_arn = aws_iam_policy.velero.arn
}

HelmでVeleroをデプロイ

新旧のEKSクラスターに対してveleroのnamespaceを作成し、Helmでveleroをインストールします。
defaultのvalueから以下の点を変更してます。

values.yaml
# ...(省略)...
kubectl:
  image:
    repository: docker.io/bitnamilegacy/kubectl
# Bitnamiイメージのセキュリティ対応により、bitnamilegacy のリポジトリで使えるのはlatestタグのイメージのみとなる。
# https://github.com/bitnami/containers/issues/83267
+   tag: latest

# ...(省略)...
configuration:
  backupStorageLocation:
    - name:
+     provider: aws
+     bucket: dev-velero

# ...(省略)...
volumeSnapshotLocation:
    - name:
+     provider: aws
      credential:
        name:
        key:
      config:
+       region: ap-northeast-1

# ...(省略)...
serviceAccount:
  server:
    create: true
    name:
    annotations:
# terraformで作成したIAM roleを使ってveleroのServiceAccountを作成
+    eks.amazonaws.com/role-arn: "arn:aws:iam::123456789012:role/eks-velero-recovery"
namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: velero

BackupStorageLocationの確認

veleroのデプロイが出来たら、kubectlやveleroのコマンドでBackupStorageLocationが作成されているか確認します。

$ kubectl -n velero get backupstoragelocation
NAME      PHASE       LAST VALIDATED   AGE   DEFAULT
default   Available   51s              24h   true
$ velero backup-location get
NAME      PROVIDER   BUCKET/PREFIX             PHASE       LAST VALIDATED                  ACCESS MODE   DEFAULT
default   aws        dev-velero   Available   2025-12-23 18:06:05 +0900 JST   ReadWrite     true

バックアップ作成

kubectlコンテキストを現行クラスターに切り替え、velero backup create を使ってpersistentvolumeのバックアップを取得していきます。

$ velero backup create <バックアップ名> --include-namespaces <バックアップ対象のnamespace> --include-resources persistentvolumes,persistentvolumeclaims
Backup request "<バックアップ名>" submitted successfully.
Run `velero backup describe <バックアップ名>` or `velero backup logs <バックアップ名>` for more details.

バックアップの状態確認

エラーなくPhase: Completedになっていることを確認します。

$ velero backup describe <バックアップ名>                                                                          
Name:         <バックアップ名>
Namespace:    velero
Labels:       velero.io/storage-location=default
Annotations:  velero.io/resource-timeout=10m0s
              velero.io/source-cluster-k8s-gitversion=v1.31.13-eks-3025e55
              velero.io/source-cluster-k8s-major-version=1
              velero.io/source-cluster-k8s-minor-version=31

Phase:  Completed


Namespaces:
  Included:  <バックアップ対象のnamespace>
  Excluded:  <none>

Resources:
  Included:        persistentvolumes, persistentvolumeclaims
  Excluded:        volumesnapshots.snapshot.storage.k8s.io, volumesnapshotcontents.snapshot.storage.k8s.io
  Cluster-scoped:  auto

Label selector:  <none>

Or label selector:  <none>

Storage Location:  default

Velero-Native Snapshot PVs:    auto
File System Backup (Default):  false
Snapshot Move Data:            false
Data Mover:                    velero

TTL:  720h0m0s

CSISnapshotTimeout:    10m0s
ItemOperationTimeout:  4h0m0s

Hooks:  <none>

Backup Format Version:  1.1.0

Started:    2025-12-23 18:46:36 +0900 JST
Completed:  2025-12-23 18:46:39 +0900 JST

Expiration:  2026-01-22 18:46:36 +0900 JST

Total items to be backed up:  4
Items backed up:              4

Backup Volumes:
  Velero-Native Snapshots:
    pvc-43704220-5e87-433a-a299-a6c953211281: specify --details for more information
    pvc-f077283e-4306-459f-8a91-de2c71d05bc1: specify --details for more information

  CSI Snapshots: <none included>

  Pod Volume Backups: <none included>

HooksAttempted:  0
HooksFailed:     0

backup先に指定したs3にデータが取得できていることも確認します。

$ aws s3 ls s3://dev-velero/backups/<バックアップ名>/
2025-12-23 18:46:39         29 <バックアップ名>-csi-volumesnapshotclasses.json.gz
2025-12-23 18:46:39         27 <バックアップ名>-itemoperations.json.gz
2025-12-23 18:46:39       5582 <バックアップ名>-logs.gz
2025-12-23 18:46:39         29 <バックアップ名>-podvolumebackups.json.gz
2025-12-23 18:46:39        169 <バックアップ名>-resource-list.json.gz
2025-12-23 18:46:39         49 <バックアップ名>-results.gz
2025-12-23 18:46:39        368 <バックアップ名>-volumeinfo.json.gz
2025-12-23 18:46:39        331 <バックアップ名>-volumesnapshots.json.gz
2025-12-23 18:46:39       2154 <バックアップ名>.tar.gz
2025-12-23 18:46:40       3673 velero-backup.json

リストア

kubectlコンテキストを新クラスターに切り替え、velero restore create を使って取得したバックアップからリストアを実行します。

$ velero restore create --from-backup <バックアップ名> --include-resources persistentvolumes,persistentvolumeclaims
Restore request "<バックアップ名>-20251223220846" submitted successfully.
Run `velero restore describe <バックアップ名>-20251223220846` or `velero restore logs <バックアップ名>-20251223220846` for more details.

velero restore describeで結果を確認します。
エラーなくPhase: Completedが表示されていたら問題なしです。

$ velero restore describe <バックアップ名>-20251223220846
Name:         <バックアップ名>-20251223220846
Namespace:    velero
Labels:       <none>
Annotations:  <none>

Phase:                       Completed
Total items to be restored:  4
Items restored:              4

Started:    2025-12-23 22:08:47 +0900 JST
Completed:  2025-12-23 22:08:51 +0900 JST

Backup:  <バックアップ名>

Namespaces:
  Included:  all namespaces found in the backup
  Excluded:  <none>

Resources:
  Included:        persistentvolumes, persistentvolumeclaims
  Excluded:        nodes, events, events.events.k8s.io, backups.velero.io, restores.velero.io, resticrepositories.velero.io, csinodes.storage.k8s.io, volumeattachments.storage.k8s.io, backuprepositories.velero.io
  Cluster-scoped:  auto

Namespace mappings:  <none>

Label selector:  <none>

Or label selector:  <none>

Restore PVs:  auto

CSI Snapshot Restores: <none included>

Existing Resource Policy:   <none>
ItemOperationTimeout:       4h0m0s

Preserve Service NodePorts:  auto

Uploader config:


HooksAttempted:   0
HooksFailed:      0

リストア後、新クラスターの対象アプリのデータが現行クラスターと同じになっていることを確認します。

$ kubectl get pvc -n <バックアップ対象のnamespace> 
NAME                    STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
pvcxxxxxx-xxxxxxxxxx1   Bound    pvc-43704220-5e87-433a-a299-a6c95321128a   10Gi       RWO            gp3            <unset>                 97s
pvcxxxxxx-xxxxxx2       Bound    pvc-f077283e-4306-459f-8a91-de2c71d05bc7   8Gi        RWO            gp3            <unset>                 96s

注意点

新クラスターで同名のPVがある場合はリストア時に already exists エラーとなるので、事前削除が必要です。現行クラスターのリソースをコピーして新クラスターを作成する時は対応が必要です。

まとめ

Veleroを使って、EKSの永続データのバックアップ・リストアが出来ることを確認しました。

参考

1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?