EKSのStatefulSetのストレージをEBSのスナップショットでバックアップする

Amazon EKS

StatefulSet の PersistentVolume のバックアップを取る方法はいくつかあります。個人的には AWS ブログでも紹介されている Velero が良いと思いますが、導入が少し面倒です。もう少し手軽な方法として、EBS ボリュームのスナップショットによるバックアップとリストアを試してみたので備忘録。AWS の機能だけで手軽にバックアップが取れるので、選択肢として知っておくとよいかと思います。

動作確認をした EKS のバージョンは 1.25 です。

目次

  1. StatefulSet を作成する
  2. ストレージへデータを書き込む
  3. PersistentVolumeClaim(PVC) の情報を取得する
  4. PersistentVolume(PV) の情報を取得する
  5. EBS ボリュームのスナップショットを作成する
  6. スナップショットから新しい EBS ボリュームを作成する
  7. リソースを削除する
  8. PV を作成する
  9. PVC を作成する
  10. StatefulSet を再作成する

StatefulSet を作成する

StatefulSet Basics | Kubernetes のサンプルを参考に動作確認用の StatefulSet を作成します。

web.yaml を作成します。

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
    - port: 80
      name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "nginx"
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: registry.k8s.io/nginx-slim:0.8
          ports:
            - containerPort: 80
              name: web
          volumeMounts:
            - name: www
              mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
    - metadata:
        name: www
      spec:
        accessModes: [ "ReadWriteOnce" ]
        resources:
          requests:
            storage: 1Gi

StatefulSet を作成します。

kubectl apply -f web.yaml

動作確認

kubectl get po

Pod が Running になっていれば OK です。

NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          2m

ストレージへデータを書き込む

index.html を作成します。これで EBS にデータが書き込まれます。

kubectl exec web-0 -- sh -c 'echo "$(hostname)" > /usr/share/nginx/html/index.html'

リクエストを送信して index.html の内容を確認します。web-0 とホスト名が表示されれば OK です。

kubectl exec -i -t web-0 -- curl http://localhost/
web-0

PersistentVolumeClaim(PVC) の情報を取得する

StatefulSet により作成された PVC の情報をファイルに出力しておきます。

kubectl get pvc www-web-0 -o yaml > pvc.yaml

PersistentVolume の情報を後で使うのでメモしておきます。

kubectl get pvc www-web-0 -o jsonpath='{.spec.volumeName}'
pvc-c573891d-7e86-4186-b4b4-39a3bfc2a126

PersistentVolume(PV) の情報を取得する

StatefulSet により作成された PV の情報をファイルに出力しておきます。

kubectl get pv pvc-c573891d-7e86-4186-b4b4-39a3bfc2a126 -o yaml > pv.yaml

EBS の VolumeID と zone を後で使うのでメモしておきます。

kubectl get pv pvc-c573891d-7e86-4186-b4b4-39a3bfc2a126 -o jsonpath='{.spec.awsElasticBlockStore.volumeID} {.metadata.labels.topology\.kubernetes\.io/zone}'
vol-03ca5f9fa09254358 ap-northeast-1a

EBS ボリュームのスナップショットを作成する

スナップショットを作成します。AWS マネジメントコンソールでスナップショットを作成しても良いです。

aws ec2 create-snapshot --volume-id vol-03ca5f9fa09254358 --region ap-northeast-1 --description 'Created from pvc www-web-0' --tag-specifications 'ResourceType=snapshot,Tags=[{Key=Name,Value=pvc-www-web-0}]'

作成されたスナップショット ID をメモしておきます。

{
...
    "SnapshotId": "snap-04da0777d3afe3a8e",
...
}

スナップショットから新しい EBS ボリュームを作成する

ここからがリストアの手順になります。

先程メモしたスナップショット ID を使って、新しい EBS ボリュームを作成します。AWS マネジメントコンソールから EBS を作成しても良いです。

aws ec2 create-volume --snapshot-id snap-04da0777d3afe3a8e --volume-type gp2 --region ap-northeast-1 --availability-zone ap-northeast-1a --tag-specifications 'ResourceType=volume,Tags=[{Key=Name,Value=pvc-www-web-0}]'

作成された EBS のボリューム ID をメモします。

{
...
    "VolumeId": "vol-0c56be5881814274a",
...
}

リソースを削除する

StatefulSet を削除します。

kubectl delete sts web

PVC を削除します。PV も削除されるので最初に作成された EBS ボリュームが削除されます。

kubectl delete pvc www-web-0

PV を作成する

以下のコマンドを参考に PV を作成します。spec.volumeID はスナップショットから作成した EBS ボリュームの ID にします。zone スナップショットから作成した EBS の AZ と同じにします。そのほかの内容は先程ファイルに出力した pv.yaml を参考に置き換えます。

cat <<'EOF' | kubectl create -f -
apiVersion: v1
kind: PersistentVolume
metadata:
  labels:
    topology.kubernetes.io/region: ap-northeast-1
    topology.kubernetes.io/zone: ap-northeast-1a
  name: pvc-c573891d-7e86-4186-b4b4-39a3bfc2a126
spec:
  accessModes:
    - ReadWriteOnce
  awsElasticBlockStore:
    fsType: ext4
    volumeID: vol-0c56be5881814274a
  capacity:
    storage: 1Gi
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: topology.kubernetes.io/zone
          operator: In
          values:
          - ap-northeast-1a
        - key: topology.kubernetes.io/region
          operator: In
          values:
          - ap-northeast-1
  persistentVolumeReclaimPolicy: Delete
  storageClassName: gp2
  volumeMode: Filesystem
EOF

PVC を作成する

PVC を作成します。spec.volumeName は一つ前の手順で作成した PV の metadata.name と同じにします。その他の内容は先程ファイルに出力した pvc.yaml を参考にして合わせます。

cat <<'EOF' | kubectl create -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  labels:
    app: nginx
  name: www-web-0
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: gp2
  volumeMode: Filesystem
  volumeName: pvc-c573891d-7e86-4186-b4b4-39a3bfc2a126
EOF

PVC の STATUS が Bound になるまで待ちます。

kubectl get pvc www-web-0
NAME        STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
www-web-0   Bound    pvc-c573891d-7e86-4186-b4b4-39a3bfc2a126   1Gi        RWO            gp2            11m

StatefulSet を再作成する

もう一度 StatefulSet を作ります。

kubectl apply -f web.yaml

Pod の STATUS が Running になるまで待ちます。

kubectl get po
NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          2m

書き込んだ情報が復元されているか確認します。ホスト名が表示されれば EBS の情報が復元されています。

kubectl exec -i -t web-0 -- curl http://localhost/
web-0

-技術ブログ
-