EKS上のステートフルアプリケーションをまるごとバックアップ・リストアしてみた【①Astra Control Service導入篇】

# はじめに
突然ですが皆さんは**Kubernetes上のアプリケーションのバックアップや移行**ってどうしてますか？
シンプルなアプリであればデプロイ時のマニフェスト(YAMLファイル)を保管しておけばいつでも再デプロイできるので「k8sって便利だなぁ」と思う反面、永続ストレージ(PV)が絡む所謂**ステートフルアプリケーション**になると途端に面倒くさくなってきます。

具体的にはアプリを構成する**DeploymentやconfigMapなどのリソース群**はマニフェストをGitで管理するであったり、**PVの中のデータ**はvolumeSnapshot使ったりストレージ製品の機能を使ってみたりと、従来システムバックアップ等で一気通貫にバックアップ出来てた部分がk8sでは個別に考える必要が出てきます。
バックアップが二度手間になるだけでも面倒ですが、この2つに別れたバックアップデータの整合性を取ろうとしたりすると「GitのコミットIDとvolumeSnapshotの名前を紐づける？」とか更にややこしいことに考えるハメに…。

そんな折に**ステートフルアプリケーションのバックアップやDRを簡単操作で実現できる**という触れ込みで当社NetAppから[Astra Control Service](https://cloud.netapp.com/ja/astra-control)(以下、ACSと表記)という製品がリリースされました。といってもGAからそれなりに時間が経っていますが…。
導入フェーズも含めた実際の使用感を[公式ドキュメント](https://docs.netapp.com/us-en/astra-control-service/index.html)を読みながら、これから全4回にわたって検証していきたいと思います。

- **Astra Control Service(ACS)の導入 ←イマココ**
- Astra Control Service(ACS)の使い方
    1. [アプリケーションの登録](https://qiita.com/yshimizu22/items/5b6a77a652b3a0b0ec22)
    1. [アプリケーションのスナップショット&バックアップ](https://qiita.com/yshimizu22/items/9e021dabc7db3c30a07b)
    1. [アプリケーションのリストア&クローニング](https://qiita.com/yshimizu22/items/9fd7935e7d78ba2f51ea)

# いきなりまとめ
はじめに全4回分の内容をざっくりまとめちゃいます。
- ACSを使ってEKSにデプロイしたステートフルアプリケーションのバックアップ・リストアができた
    - スナップショット機能はアプリの更新前後のバックアップなどに使えそう
    - バックアップ機能はDRやクラスタ間のアプリ移行に使えそう
- いいところ
    - アプリの構成情報とPVのデータが一括でバックアップできる
    - UIは分かりやすく操作感もいい感じ
- 今後に期待したいところ
    - プライベートクラウドとの連携機能(例：オンプレのアプリをクラウドにリフト&シフト)


# Astra Control Service(ACS)について
超ざっくり言うと、**Kubernetes上のアプリケーションをまるごとバックアップ＆リストアできるSaaS**です。
上記で挙げたk8s上のステートフルアプリケーションを構成する、**アプリケーションの構成情報**(deployment,secret,configMapなど)と**永続ストレージ(PV)内のデータ**を統合してk8sクラスタ外部のS3ストレージなどにバックアップしてくれます。

**無償枠があり10個のアプリケーションまではライセンスフリーで使えます**。今回も無償でできる範囲で検証していきます。

またACSでは以下のマネージドk8s上にデプロイされたアプリケーションに対応しています。
- AWS: Elastic Kubernetes Servie(EKS)
- Microsoft Azure: Azure Kubernetes Service(AKS)
- Google Cloud: Google Kubernetes Engine(GKE)

ちなみにオンプレ環境向けには**Astra Control Center**という別の製品があります。こちらではユーザ自身でプライベートクラウド上のいずれかのk8sクラスタ上にAstra ControlをデプロイすることでACSとほぼ同じデータ保護機能を使うことができます。~~１製品に統一してくれたらいいのに。~~

Astra Controlの機能やライセンス体系など製品の詳しい内容はこちらの記事で解説してくれています。
NetApp Astra とは: https://qiita.com/star76/items/86c1df804fc762b22d8e

# 検証環境作ってみた
ここからがこの記事のメインです。大まかに3ステップで進めていきます。

| 項番 | ページ内リンク |
|:----:|:-------------|
| 1 | [AWS側の事前準備](#1-aws側の事前準備) |
| 2 | [ACSへのサインアップ](#2-acsへのサインアップ) |
| 3 | [ACSへのEKSクラスタの登録](#3-acsへのeksクラスタの登録) |

## 1. AWS側の事前準備
まずは[公式ドキュメント](https://docs.netapp.com/us-en/astra-control-service/get-started/set-up-amazon-web-services.html#eks-cluster-requirements)に従ってACSで管理するEKSの準備を行なっていきます

### クラスタ要件の確認
ACSで管理するEKSクラスタは以下の要件を満たしている必要があります。
- k8sバージョン: 1.20~1.22[^1]
    - 本記事の執筆時点(2022/10)でEKSではk8s 1.23まで利用できますがACSサポート対象外のため注意してください
- イメージタイプ: 各ワーカーノードのイメージタイプがLinuxであること
- クラスタの状態: 最低１つのワーカーノードがオンラインかつ、failed状態のノードが存在しないこと
- スナップショッター: [CSIスナップショッター](https://github.com/kubernetes-csi/external-snapshotter)がインストールされていること
- バックエンドストレージ: ACSでバックアップやリストアを行うPVのバックエンドストレージは**Amazon FSx for NetApp ONTAP**または**Amazon Elastic Block Storage**のいずれかであること
    - **Amazon FSx for NetApp ONTAP**を使う場合: **Astra Trident**がクラスタにインストールされていること
    - **Amazon Elastic Block Storage**を使う場合: EBS向けのCSIドライバーがクラスタにインストールされていること

EKSクラスタ自体のデプロイ手順に関しては[AWSの公式ドキュメント](https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/getting-started.html)の通りで、特別なことはしていませんので割愛します。

CSIスナップショッターに関しては、新規クラスタなどで未インストールの場合は以下の様にインストールできます。
```sh
$ cat snapshot-setup.sh
#!/bin/bash
# Create volume snapshot CRDs
kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/release-5.0/client/config/crd/snapshot.storage.k8s.io_volumesnapshotclasses.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/release-5.0/client/config/crd/snapshot.storage.k8s.io_volumesnapshotcontents.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/release-5.0/client/config/crd/snapshot.storage.k8s.io_volumesnapshots.yaml

$ sh snapshot-setup.sh
customresourcedefinition.apiextensions.k8s.io/volumesnapshotclasses.snapshot.storage.k8s.io created
customresourcedefinition.apiextensions.k8s.io/volumesnapshotcontents.snapshot.storage.k8s.io created
customresourcedefinition.apiextensions.k8s.io/volumesnapshots.snapshot.storage.k8s.io created

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/release-5.0/deploy/kubernetes/snapshot-controller/rbac-snapshot-controller.yaml
serviceaccount/snapshot-controller created
clusterrole.rbac.authorization.k8s.io/snapshot-controller-runner created
clusterrolebinding.rbac.authorization.k8s.io/snapshot-controller-role created
role.rbac.authorization.k8s.io/snapshot-controller-leaderelection created
rolebinding.rbac.authorization.k8s.io/snapshot-controller-leaderelection created

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/release-5.0/deploy/kubernetes/snapshot-controller/setup-snapshot-controller.yaml
deployment.apps/snapshot-controller created
```

ポイントとなるのは最後に記載したPVのバックエンドストレージに関する条件ですが、今回は**Amazon FSx for NetApp ONTAP**を使っていきます。
今回の様にEKSクラスタを新規に構築した場合、以下の作業が必要になります。

1. Amazon FSxファイルシステムの作成
    参考記事: [DevelopersIO - Amazon FSx for NetApp ONTAPを試してみた](https://dev.classmethod.jp/articles/amazon-fsx-for-netapp-ontap/)

1. EKSクラスタへのAstra Tridentのインストール・セットアップ
参考記事: [Amazon FSx for NetApp ONTAPをAmazon EKSのPersistentVolumeのバックエンドとして使ってみた（本編）](https://qiita.com/seijitanabe/items/c6c91eacaa89dcba2864)

いずれもACSの導入というよりはEKS上で永続ストレージ(PV)を使用するためのセットアップの一環であるため、詳細な手順が気になる方は上記の記事からご確認ください。
念の為、今回の設定内容も本記事の補足欄に残しておきます。


さて、この時点で検証環境はこんな感じの構成になりました。
![スクリーンショット 2022-10-14 11.08.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436161/bed47a96-0062-77ac-e679-a0bf851f2255.png)

PVのデータを格納するストレージボリュームはCSIドライバーであるAstra Tridentを介して、FSxのファイルシステム上にデプロイされます。
次回以降、実際にこのEKSクラスタにステートフルアプリケーションのデプロイを行います。

### ACS用IAMユーザの作成
ACSが管理対象クラスタにアクセスするためのIAMユーザを作成します。既存ユーザを使う場合はスキップしてください。
```sh
$ aws iam create-user --user-name astra
{
    "User": {
        "Path": "/",
        "UserName": "astra",
        "UserId": "xxxxxxxxxxxxx",
        "Arn": "arn:aws:iam::xxxxxxxxxxxxx:user/astra",
        "CreateDate": "2022-10-11T06:58:08+00:00"
    }
}
```

またIAMユーザを新規に作成した場合は対象のEKSクラスタにアクセスを行うための設定も忘れずに行なってください。
[AWSドキュメント: クラスターへの IAM ユーザーおよびロールアクセスを有効にする](https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/add-user-role.html)

### 許可ポリシーの作成とアタッチ
IAMユーザに対してACSに必要な権限ポリシーを割り当てていきます。
```sh
# ポリシーファイルの作成
$ vi policy.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "cloudwatch:GetMetricData",
                "fsx:DescribeVolumes",
                "ec2:DescribeRegions",
                "s3:CreateBucket",
                "s3:ListBucket",
                "s3:PutObject",
                "s3:GetObject",
                "iam:SimulatePrincipalPolicy",
                "s3:ListAllMyBuckets",
                "eks:DescribeCluster",
                "eks:ListNodegroups",
                "eks:DescribeNodegroup",
                "eks:ListClusters",
                "iam:GetUser",
                "s3:DeleteObject",
                "s3:DeleteBucket",
                "autoscaling:DescribeAutoScalingGroups"
            ],
            "Resource": "*"
        }
    ]
}
```
中身を見ると基本的にはEKSに関連するリソースを閲覧するぐらいの権限ですが、S3に関してはバケットの作成やオブジェクトの管理を行う、少し強めの権限を要求しています。
これはACSがバックアップしたデータを各クラウドプロバイダー上のS3ストレージに保管する為です。


```sh
# AWS上にポリシー作成
$ POLICY_ARN=$(aws iam create-policy  --policy-name astra-policy --policy-document file://policy.json  --query='Policy.Arn' --output=text)
```
```sh
# IAMユーザにポリシーをアタッチ
$ aws iam attach-user-policy --user-name astra --policy-arn=$POLICY_ARN
```
### 認証情報の保存
IAMユーザのクレデンシャルをローカルに保存します。このファイルは後ほどACSにクラスタをインポートする際に使用します。
```sh
$ aws iam create-access-key --user-name astra --output json > credential.json
$ cat credential.json
{
    "AccessKey": {
        "UserName": "astra",
        "AccessKeyId": "xxxxxxxxxxxxx",
        "Status": "Active",
        "SecretAccessKey": "xxxxxxxxxxxxx",
        "CreateDate": "2022-10-11T07:06:13+00:00"
    }
}
```
ここまででEKS側の事前準備は完了です。

## 2. ACSへのサインアップ
次はSaaSであるACS自体の利用開始手続きを行なっていきます。
こちらも[ACSの公式ドキュメント](https://docs.netapp.com/us-en/astra-control-service/get-started/register.html#sign-up-to-cloud-central)に従って進めていきます。

### NetApp Cloud Centralへのサインアップ
**NetApp Cloud Central**とはNetAppのクラウドサービスに一元的にアクセスできるポータルサイトです。
ACSの利用にはCloud Cenrtalのアカウントが必要となるため以下のURLからサインアップします。
https://cloud.netapp.com/
![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436161/ac201a6b-d06a-73df-9370-f1988d083ece.png)

既にアカウントをお持ちの場合は次の手順へ進んでください。

### Astra Control Serviceへのサインアップ
次に以下URLからACSへのサインアップを行います
https://cloud.netapp.com/astra

**Sign up for the fully-managed service FREE PLAN**のタブからアカウント名、メールアドレス、会社名等々を入力します。
メールアドレスはNetApp Cloud Centralのアカウントと同じものを使用します。
![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436161/22ab6b4c-de0a-a6f2-45db-1f21dd21b12b.png)
サインアップが完了するとACSのダッシュボードへリダイレクトされました。
![スクリーンショット 2022-10-11 20.49.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436161/781d117a-7d4d-de1f-d1c0-b0f12e26dc84.png)

ACSはSaaSというだけあって、いくつかのサインアップ手続きだけですぐにサービスにアクセスできましたね。

## 3. ACSへのEKSクラスタの登録
最後に、今回構築したEKSクラスタをACSの管理対象として登録していきます。
ACSの公式ドキュメントは[こちら](https://docs.netapp.com/us-en/astra-control-service/get-started/add-first-cluster.html#start-managing-kubernetes-clusters)。

ダッシュボードから**Clusters** -> **Add**をクリックし、クラスタの追加ウィザードを開きます。
プロバイダにはAWSを選択し、先ほどの手順で保存したIAMユーザのクレデンシャルをアップロードします。
![スクリーンショット 2022-10-11 20.50.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436161/33161b56-9e3c-199f-4b80-e9a5e881f354.png)

EKSクラスタの準備がきちんと整っていれば**Eligeble**にチェックマークがつきます。
![スクリーンショット 2022-10-11 20.53.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436161/3ac2d670-f1c8-4c78-7a9c-af82324791b4.png)

ACSで管理可能なストレージクラスの一覧が表示されます。今回は１つだけですが、複数ストレージクラスがある環境ではどのストレージクラスをデフォルトにするか、この画面で設定できたりします。
![スクリーンショット 2022-10-11 22.36.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436161/75a3d4c7-2e89-b0f9-ced7-d3da3f9d00bf.png)

最終確認の画面。よく見ると**Create bucket**のセクションで見知らぬS3バケットの名前が表示されていますね。
これまで何度か言及していますが、ACSはバックアップしたデータをクラスタ外部のS3バケットに保管します。
このS3バケットですがACSが初めてk8sクラスタを管理下に置く際に、**そのk8sクラスタと同じクラウドプロバイダー上に自動作成する仕様**になっています。
つまり今回の環境では**AWS S3**上にバックアップデータ格納用のS3バケットが作成されるという事になります。
![スクリーンショット 2022-10-11 22.38.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436161/434ad1ca-da04-6794-d335-ff188b1051d5.png)

**Add**をクリックするとACSのDBへ管理対象k8sクラスタの登録処理が開始します。問題が無ければ数分でクラスタの状態が**Healty**に遷移します。
登録完了後はクラスタ内のワーカーノード、namespace、PVの一覧などが参照できます。
![スクリーンショット 2022-10-12 9.58.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436161/f941a444-5a05-6e7f-031e-d6b12755a4bc.png)

また画面左のメニューから**Buckets**をクリックすると自動作成されたバックアップデータ格納用のS3バケットが見えています。
![スクリーンショット 2022-10-12 10.02.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436161/a168dd23-2b7b-635d-93a2-0a25dfcf6d3d.png)

念の為AWS S3上でも確認してみると、ちゃんと同じ名前のS3バケットがありますね。
![スクリーンショット 2022-10-11 22.50.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436161/56be4b71-f01f-a2c9-8708-fd80385e0dbb.png)

最終的なシステム構成はこちらの図の通りです。
![スクリーンショット 2022-10-14 11.04.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436161/0771a474-5592-9398-5a01-82856bb5d04b.png)

これでACSへのクラスタの登録作業は完了です。

# まとめ＆次回予告
ということで今回はACSでk8sアプリケーションを管理する前準備として、EKSクラスタ新規に作成し、ACSの管理下に登録するところまでを検証してみました。
次回はこのクラスタ上に実際にステートフルアプリケーションをデプロイした上で、ACSの機能であるアプリケーションのバックアップやリストアを試していきたいと思います。

**次回記事** -> [EKS上のステートフルアプリケーションをまるごとバックアップ・リストアしてみた【②アプリケーションの登録篇】](https://qiita.com/yshimizu22/items/5b6a77a652b3a0b0ec22)

# 補足資料
今回作成した検証用EKSクラスタでAmazon FSx for NetApp ONTAPならびにAstra Tridentをセットアップした際の手順を参考までに残しておきます。

## Amazon FSx for NetApp ONTAPの構成内容
公式ドキュメントでは、「バックアップとメンテナンス」のセクションで「毎日の自動バックアップ」を無効にすることが推奨されています。
※スタンダード作成でのみ変更可
![スクリーンショット 2022-10-11 21.22.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436161/ca54c634-caa6-7a29-2438-114788441ecf.png)
![スクリーンショット 2022-10-11 21.22.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436161/e45cb18f-8191-dee2-53c9-79b5cfa66581.png)
![スクリーンショット 2022-10-11 21.22.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436161/ac758a31-b530-0b5f-8b5d-523cd3b41f4d.png)
![スクリーンショット 2022-10-11 21.23.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/436161/ec81b3ff-2460-314f-6ff4-2c39c51a1d8f.png)

## Astra Tridentのセットアップ
### Astra Tridentのインストール
```sh
# Trident用namespaceの作成
$ kubectl create ns trident

# Tridentインストーラのダウンロード(v22.07)
$ wget https://github.com/NetApp/trident/releases/download/v22.07.0/trident-installer-22.07.0.tar.gz

# アーカイブの展開
$ tar -xvf trident-installer-22.07.0.tar.gz

# helm3によるTridentのインストール
$ helm install trident -n trident trident-installer/helm/trident-operator-22.07.0.tgz

# インストール後の確認
$ kubectl get pod -n trident
NAME                                READY   STATUS    RESTARTS   AGE
trident-csi-6b6d9dd7c7-6856h        6/6     Running   0          54m
trident-csi-c7mww                   2/2     Running   0          65m
trident-csi-grgbk                   2/2     Running   0          65m
trident-operator-66cd859976-8svwk   1/1     Running   0          76m
```

### Tridentバックエンドの作成
今回はkubectlを使用してTridentバックエンドを作成していますが、従来のtridentctlを使用した作成方法でも特段問題はありません。

管理ユーザの認証情報をsecretリソースとして作成
```sh
# マニフェスト作成
$ cat secret-fsx.yml
apiVersion: v1
kind: Secret
metadata:
  name: secret-for-fsx
  namespace: trident
type: Opaque
stringData:
  username: fsxadmin
  password: xxxxxxx

# マニフェスト適用
$ kubectl apply -f secret-fsx.yml
secret/secret-for-fsx created
```

TridentBackendConfigリソースの作成
```sh
# マニフェスト作成
$ cat tbc-fsx.yml
apiVersion: trident.netapp.io/v1
kind: TridentBackendConfig
metadata:
  name: backend-nas-config
  namespace: trident
spec:
  version: 1
  backendName: ontap-nas-backend
  storageDriverName: ontap-nas
  managementLIF: management.xxxxxxxxxx.fsx.ap-northeast-1.amazonaws.com
  dataLIF: svm-xxxxxxxxxx.xxxxxxxxxx.fsx.ap-northeast-1.amazonaws.com
  svm: svm1
  credentials:
    name: secret-for-fsx

# マニフェスト適用
$ kubectl apply -f tbc-fsx.yml
tridentbackendconfig.trident.netapp.io/backend-nas-config configured

# バックエンドの作成確認
$ kubectl get tbc -n trident
NAME                 BACKEND NAME        BACKEND UUID                           PHASE   STATUS
backend-nas-config   ontap-nas-backend   5f0e7809-9168-48ff-b4c0-00ab69223465   Bound   Success
```

### ストレージクラスの作成
FSXのバックエンドに対応するストレージクラスを作成
```sh
# マニフェスト作成
$ cat sc.yml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fsx-nfs
provisioner: netapp.io/trident
parameters:
  backendType: "ontap-nas"
allowVolumeExpansion: True

# マニフェスト適用
$ kubectl apply -f sc.yml
storageclass.storage.k8s.io/fsx-nfs created

# EKS初期状態で作成済みのストレージクラス"gp2"をデフォルトのストレージクラスから除外
$ kubectl patch storageclass gp2 -p '{"metadata": {"annotations": {"storageclass.kubernetes.io/is-default-class": "false"}}}'
storageclass.storage.k8s.io/gp2 patched

# FSXのバックエンドに対応するストレージクラスをデフォルトに指定
$ kubectl patch storageclass fsx-nfs -p '{"metadata": {"annotations": {"storageclass.kubernetes.io/is-default-class": "true"}}}'
storageclass.storage.k8s.io/fsx-nfs patched

# ストレージクラスの一覧確認
$ kubectl get sc
NAME                PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
fsx-nfs (default)   csi.trident.netapp.io   Delete          Immediate              true                   79s
gp2                 kubernetes.io/aws-ebs   Delete          WaitForFirstConsumer   false                  3h45m
```

[^1]: EKSにおける対応バージョン。AKSでは1.24まで、GKEでは1.23まで対応。