Velero復元テスト
経緯
veleroのバックアップの復元テストをしたかったのだけれども、 あまりにも面倒くさくて、Claude Codeに丸投げした。
復元完了後、veleroのrestores/ に復元レポートが保存される。
使用モデル、かかったコストは以下。CLIからは、/statusからのSessionで表示可能。
/status
Total cost: $2.81
Total duration (API): 8m 28s
Total duration (wall): 36m 20s
Total code changes: 362 lines added, 0 lines removed
Usage by model:
claude-haiku-4-5: 303 input, 24 output, 0 cache read, 0 cache write ($0.0004)
claude-sonnet-4-5: 281 input, 22.3k output, 5.1m cache read, 252.0k cache write ($2.80)
500円近くの出費はまあまあ痛いが、人間がやっていると、2時間近く消費するわけで。 AIを積極的に使用した方がいいと思われる。
余談だが、復元したPodの削除もAIに任せたら、コストが約1.5倍まで跳ね上がってしまった。
人でできる作業は、人でした方がいい。 普通に、Docker Desktopの歯車から、リセット->k8sの機能無効すればいいだけだった。 削除指示なんかするんじゃなかった。
以下、ほぼ完全にAI生成の文章になる。
次の手順でこしらえた。Claude Code 生成 -> Claude Code で秘匿情報等をマスク -> kiro で再度マスク -> 私が確認
別にこの手順自体に意味はない。記録として残しておく。
実施日時
2026年6月13日
概要
Cloudflare R2に保存されたVeleroバックアップからKubernetesクラスターへの復元テストを実施しました。
Velero復元テスト レポート(公開版)
環境情報
バックアップソース
- S3エンドポイント: https://<ACCOUNT_ID>.r2.cloudflarestorage.com
- バケット名: <BUCKET_NAME>
- プロバイダー: Cloudflare R2 (S3互換)
- 利用可能なバックアップ: 23個(velero-mybackup-20260529XXXXXX ~ 20260611XXXXXX)
ターゲット環境
- Kubernetesクラスター: Docker Desktop for Windows
- ノード: 1台 (docker-desktop)
- ストレージクラス: hostpath (デフォルト)
- Veleroバージョン: v1.18.1
- Velero Plugin: velero-plugin-for-aws:v1.11.0
実施した手順と対応
1. Veleroのインストール
1.1 認証情報とnamespaceの作成
kubectl create namespace velero
kubectl create secret generic cloud-credentials -n velero \
--from-literal=cloud='[default]
aws_access_key_id=<ACCESS_KEY_ID>
aws_secret_access_key=<SECRET_ACCESS_KEY>'
1.2 Veleroサーバーのインストール
./velero-v1.18.1-windows-amd64/velero-v1.18.1-windows-amd64/velero.exe install \
--provider aws \
--plugins velero/velero-plugin-for-aws:v1.11.0 \
--bucket <BUCKET_NAME> \
--secret-file credentials/cloud \
--backup-location-config region=auto,s3Url=https://<ACCOUNT_ID>.r2.cloudflarestorage.com,s3ForcePathStyle=true \
--use-node-agent \
--namespace velero
重要: 初期設定では誤ってバケット名を<ACCOUNT_ID>(アカウントID)に設定していましたが、正しいバケット名は<BUCKET_NAME>でした。
2. 発生した問題と解決策
問題1: BackupStorageLocationがUnavailable
症状:
BackupStorageLocation "default" is unavailable:
rpc error: code = Unknown desc = operation error S3: ListObjectsV2,
https response error StatusCode: 403, RequestID: , HostID: ,
api error AccessDenied: Access Denied
原因: バケット名が間違っていた(アカウントIDではなく実際のバケット名<BUCKET_NAME>を指定する必要があった)
解決策:
kubectl patch backupstoragelocation default -n velero --type merge \
-p '{"spec":{"objectStorage":{"bucket":"<BUCKET_NAME>"}}}'
結果: BackupStorageLocationがAvailableになり、30個のバックアップが同期された
問題2: node-agentがCreateContainerErrorで起動失敗
症状:
Error: Error response from daemon: invalid volume specification:
'\var\lib\kubelet\pods:/host_pods:rslave': invalid mount config for type "volume":
field BindOptions must not be specified
原因: Windows環境でのパス表記の問題。Velero installコマンドがWindowsパス形式(\var\lib\kubelet\pods)を設定してしまった
解決策:
kubectl patch daemonset node-agent -n velero --type='json' -p='[
{"op": "replace", "path": "/spec/template/spec/volumes/0/hostPath/path", "value": "/var/lib/kubelet/pods"},
{"op": "replace", "path": "/spec/template/spec/volumes/1/hostPath/path", "value": "/var/lib/kubelet/plugins"}
]'
kubectl delete pod -n velero -l name=node-agent
結果: node-agentが正常に起動し、ボリューム復元が可能になった
問題3: PVCがPending状態
症状:
storageclass.storage.k8s.io "local-path" not found
原因: バックアップ元のクラスターではlocal-pathストレージクラスを使用していたが、復元先のクラスターにはhostpathしか存在しなかった
解決策: local-pathストレージクラスを作成
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: local-path
provisioner: docker.io/hostpath
reclaimPolicy: Delete
volumeBindingMode: Immediate
allowVolumeExpansion: false
kubectl apply -f local-path-storageclass.yaml
結果: すべてのPVCがBound状態になり、Podが起動可能になった
問題4: PodVolumeRestoreがFailed
症状:
error to expose PVR: error to get pod volume path:
error identifying unique volume path on host for volume database in pod <commafeed-postgresql-pod>:
expected one matching path: /host_pods/.../volumes/*/pvc-..., got 0
原因: PVCがPending状態だったため、Podが起動前にPodVolumeRestoreが実行され、ボリュームパスが見つからなかった
解決策: ストレージクラス作成後、失敗したPodを削除して再作成
kubectl delete pod -n <commafeed_ns> <commafeed-postgresql-pod> --force --grace-period=0
kubectl delete pod -n <redmine_ns> <redmine-pod> <redmine-mariadb-pod> --force --grace-period=0
kubectl delete pod -n <commafeed_ns> <commafeed-main-pod> --force --grace-period=0
結果: 新しいPodが作成され、ボリューム復元が正常に実行された
問題5: Redmine Podがイメージ取得エラー
症状:
Failed to pull image "docker.io/bitnami/redmine:6.0.6-debian-12-r6":
Error response from daemon: manifest for bitnami/redmine:6.0.6-debian-12-r6 not found:
manifest unknown: manifest unknown
原因: バックアップ時に使用していたBitnamiのRedmineイメージタグが、Docker Hubから削除されたか存在しない
対応: 本レポート作成時点では未解決。MariaDBは正常に復元・起動済み
復元結果
最終ステータス
- 復元名: restore-velero-mybackup-XXXXXXXXXXXXXXXX-XXXXXXXX-XXXXXX
- バックアップ名: velero-mybackup-20260611XXXXXX
- フェーズ: PartiallyFailed
- 開始時刻: 2026-06-13 00:52:25 JST
- 完了時刻: 2026-06-13 01:05:48 JST
- 所要時間: 約13分
- エラー数: 7
- 警告数: 107
復元されたリソース
- 総アイテム数: 694個 (すべて復元完了)
- PersistentVolumeRestore: 11個中5個完了、4個失敗、2個その他
正常に復元されたアプリケーション
Commafeed (<commafeed_ns> namespace)
✅ <commafeed-postgresql-pod> 1/1 Running
✅ <commafeed-main-pod> 1/1 Running
✅ Service: <commafeed-main-svc> (LoadBalancer)
✅ Service: <commafeed-postgresql-svc> (ClusterIP)
✅ PVC: <commafeed-postgresql-pvc> (Bound)
✅ PVC: <commafeed-data-pvc> (Bound)
Redmine MariaDB
✅ <redmine-mariadb-pod> 1/1 Running
✅ PVC: <redmine-mariadb-pvc> (Bound)
✅ PVC: <redmine-pvc> (Bound)
未解決の問題
❌ <redmine-pod> - ImagePullBackOff (Bitnami Redmineイメージが利用不可)
警告とエラーの詳細
警告 (107件)
主に既存のクラスターリソース(CRD、ClusterRole等)が既に存在していたための警告。これは正常な動作。
例:
- CustomResourceDefinition:backuprepositories.velero.io already exists
- ClusterRole:cluster-admin already exists
- 等々
エラー (7件)
主にPodVolumeRestoreの失敗:
- ボリュームパスが見つからない(Pod再作成で解決)
- イメージ取得エラー(Redmine - 未解決)
ベストプラクティスと推奨事項
1. 事前準備
- ✅ ストレージクラスの互換性確認
- ✅ 使用するDockerイメージの可用性確認
- ✅ S3バケット名とエンドポイントの正確な情報
2. Windows環境での注意点
- node-agentのボリュームマウントパスがWindowsパス形式になる問題に注意
- インストール後、必ずDaemonSetの設定を確認・修正
3. 復元手順
- Veleroサーバーをインストール
- BackupStorageLocationの設定と検証
- node-agentのパス修正(Windows環境の場合)
- 必要なストレージクラスの作成
- 復元実行
- 失敗したPodの削除と再作成
4. トラブルシューティング
- BackupStorageLocationのステータス確認:
velero backup-location get - node-agentのログ確認:
kubectl logs -n velero -l name=node-agent - PodVolumeRestoreの状態確認:
kubectl get podvolumerestore -n velero - 失敗したPodは削除して再作成することで解決する場合が多い
必須の設定変更まとめ
1. BackupStorageLocationのバケット名修正
kubectl patch backupstoragelocation default -n velero --type merge \
-p '{"spec":{"objectStorage":{"bucket":"<BUCKET_NAME>"}}}'
2. node-agentのボリュームパス修正(Windows環境)
kubectl patch daemonset node-agent -n velero --type='json' -p='[
{"op": "replace", "path": "/spec/template/spec/volumes/0/hostPath/path", "value": "/var/lib/kubelet/pods"},
{"op": "replace", "path": "/spec/template/spec/volumes/1/hostPath/path", "value": "/var/lib/kubelet/plugins"}
]'
3. local-pathストレージクラスの作成
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: local-path
provisioner: docker.io/hostpath
reclaimPolicy: Delete
volumeBindingMode: Immediate
結論
Veleroによる復元はほぼ成功しました。以下の点が確認できました:
成功した点
✅ S3(Cloudflare R2)からのバックアップ同期
✅ 694個のKubernetesリソースの復元
✅ Persistent Volumeデータの復元
✅ アプリケーション(Commafeed)の完全復元と起動
✅ データベース(PostgreSQL、MariaDB)の復元と起動
課題
⚠️ Windows環境特有のパス問題(対応方法確立)
⚠️ ストレージクラスの互換性問題(対応方法確立)
❌ 廃止されたDockerイメージへの依存(別の問題)
総評
本復元テストにより、Cloudflare R2に保存されたVeleroバックアップからの復元が可能であることが実証されました。Windows Docker Desktop環境特有の問題については、本レポートに記載した対応方法で解決可能です。