Amazon FSx for NetApp ONTAP を Terraformでデプロイしてみる (AWSプロバイダ編)

# Amazon FSx for NetApp ONTAP を Terraformで試してみる  : AWSプロバイダ編
[以前の記事](https://qiita.com/yoihoka/items/9989859184c83b87d8db)で Amazon FSx for NetApp ONTAP を Terraform でデプロイする手順を紹介しましたが、AWSプロバイダでもAmazon FSx for NetApp ONTAPをデプロイ可能になりました。さっそく試してみましたので手順を紹介したいと思います。

こちらのやり方では、AWSプロバイダのみで実施ができますので非常にシンプルにデプロイを実施できます。
一方、[以前の記事](https://qiita.com/yoihoka/items/9989859184c83b87d8db)で紹介したNetApp CloudManagerプロバイダを併用するやり方では、Cloud Managerをつかった より利便性の高い利用を行うのに必要な Connectorのデプロイなどもあわせて実施できます。
利用シーンにあわせて使い分けていただければと思います。

なお、Amazon FSx for NetApp ONTAPの紹介は[こちらのブログ](https://www.storage-channel.jp/blog/amazon-fsx-for-netapp-ontap.html)が参考になるかと思いますので興味がありましたらどうぞ。


# Terraform処理概要
Terraformで実行する処理の概要は以下の図の通りです。
Amazon FSx for NetApp ONTAPのデプロイとあわせて、そのデプロイに必要なAWSリソース、NFSマウントを試すためのLinxuサーバも作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/981926/93ddf201-6f6a-39dd-9390-568966bd1e5f.png)




TerraformプロバイダーはAWSプロバイダを利用します。
AWSプロバイダを利用してVPC、Subnet、Internet GWを作成し、さらにNFSマウントを試すためのLinuxサーバ、セキュリティグループ設定、ルーティング設定、ssh接続用Keyペア登録を行います。
また、Amazon FSx for NetApp ONTAPのデプロイも行います。

なお、Amazon FSx for NetApp ONTAPは AWSコンソールから導入可能ですが、他のNetAppのクラウドサービスと同様にCloud Managerからも導入可能です。
[こちら](https://cloud.netapp.com/blog/aws-fsxo-blg-how-to-set-up-amazon-fsx-for-netapp-ontap-with-cloud-manager)のページで操作画面付きで導入手順が紹介されています。GUIに従って情報を入力していくだけで簡単に導入が可能になっています。



#前提
以下の環境で試しています。AWSアカウントは作成済みの前提としています。

- Terrafrom 1.0.3
 - hashicorp/aws 3.60.0
- CentOS7.7
- aws-cli/2.2.41

なお、この記事で書かれている 手順やファイルは動作を保証されたものではありません。
各環境に合わせてテスト・確認をしたうえで自己責任にて利用していただければと思います。

# 作業の流れ
以下の順序で作業を実施してAmazon FSx for NetApp ONTAPをデプロイします。

1. AWSコンソールでの準備
2. 作業用Linuxサーバでの準備
3. Terraform実行

AWSアカウントは作成済みの前提としております。

## 1. AWSコンソールでの準備
terraform用ユーザを作成し、アクセスキー・シークレットアクセスキー情報を取得します。

AWSコンソールにログインして、以下の操作を実施します。

***
 **[ AWSコンソール ]**
　 1.　画面左上の "サービス"から "セキュリティ、ID、およびコンプライアンス"欄の"IAM"を選択
　 2.　画面左側の"アクセス管理"→"ユーザー"を選択
　 3.　"ユーザーを追加"をクリック
　 4.　ユーザー名に"terauser11"を入力して、"アクセスキー - プログラムによるアクセス"にチェックをいれ、"次のステップ: アクセス権限"をクリック
　 5.　"ユーザーをグループに追加" 欄の"Administrators"にチェックをいれて、"次のステップ：タグ"をクリック
　 6.　"次のステップ: 確認"をクリック
　 7.　"ユーザーの作成"をクリック
　 8.　表示された アクセスキーID、シークレットアクセスキーの情報を確認*します。  
　 *　  ※".csvのダウンロード" をクリックしてファイルをダウンロードしておくと安心

***

上記で、ユーザーに適用したグループは権限が高いため、別途最低限の権限を付与したポリシーを作成して適用することをお勧めします。
詳細な情報は[NetAppのドキュメントページ](https://docs.netapp.com/ja-jp/occm/concept_fsx_aws.html)を参照してください。

## 2. 作業用Linuxサーバでの準備
Linuxサーバにterraformを実行する環境を準備します。
CentOS 7を利用しています。

各ディレクトリ・ファイルの構成・配置は以下の前提となります。

```shell:ディレクトリ・ファイル構成
~/terraform
   └─ fsxn
      ├─ aws-resource.tf
      ├─ fsxn.tf  
      ├─ provider.tf  
      ├─ variable.tf  
      └─ ssh_key
         ├─ tera_ssh_key
         └─ tera_ssh_key.pub
```

上記構成から 配置ディレクトリ・ファイル名を変更する場合は、".tfファイル"の対応するパラメータを変更して利用してください。

### 2-1. AWS CLIを導入
作業用Linuxサーバに AWS CLIを導入します。

```shell
$ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
$ unzip awscliv2.zip
$ sudo ./aws/install
$ aws --version
```
最新情報は、AWSのサイトに[導入方法のガイド](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-cliv2-linux.html#cliv2-linux-install)がありますのでそちらを参照ください。


### 2-2. aws credentialを設定
作業用Linuxサーバで、AWS認証用クレデンシャルを設定します。
AWSコンソールの準備で作成したterraformユーザ用のアクセスキー等の情報を設定します。

```shell
$ aws configure --profile terauser11
AWS Access Key ID [None]: "terauser11のアクセスキーID"
AWS Secret Access Key [None]: "terauser11のシークレットアクセスキー"
Default region name [None]: ap-northeast-1
Default output format [None]: json
$  aws configure list-profiles
terauser11
$
```

なお、terraform利用時のaws credential設定方法については[AWS Providerのページ](https://registry.terraform.io/providers/hashicorp/aws/latest/docs)に情報がありますので、必要に応じて参照してください。


### 2-3. terraform初期設定
作業用LinuxサーバでTerraformコマンドを実行可能にするための初期設定を実施します。

なお、terraformの最新バイナリについては[Terraformのサイト](https://www.terraform.io/downloads.html)で確認してください。

```shell:
$ mkdir ~/terraform
$ cd ~/terraform
$ curl -sL https://releases.hashicorp.com/terraform/1.0.3/terraform_1.0.3_linux_amd64.zip > terraform.zip
$ unzip terraform.zip
$ export PATH=$PATH:~/terraform/
```

上記でterraformコマンドを実行可能となります。
以下のようにバージョンの確認コマンドを実行できることを確認してください。

```shell:
$ terraform --version
Terraform v1.0.3
on linux_amd64
```

### 2-4. .tfファイルを作成
terraform用のファイルを配置するディレクトリを作成し、ファイルを配置します。

最初に、.tfファイル及び SSHの秘密鍵,公開鍵のキーペアファイル を 配置するためのディレクトリを作成します。

```shell:
$ mkdir -p ~/terraform/fsxn ~/terraform/fsxn/ssh_key
$ cd ~/terraform/fsxn
```
~/terraform/cloud-managerディレクトリ配下に、以下の.tfファイルを作成します。

※長いので折り畳んでます。
<details><summary>①aws-resource.tf</summary><div>

```plaintext:①aws-resource.tf
resource "aws_instance" "terra-lin01" {
  ami                    = var.tera-linux.ami
  instance_type          = var.tera-linux.instance_type
  key_name               = aws_key_pair.ec2-ssh_key01.id
  vpc_security_group_ids = [aws_security_group.terra-lin01-sg1.id]

  subnet_id = element(aws_subnet.tera-subnet01.*.id, 0)

  tags = {
    Name = var.tera-linux.tagname
  }
}

resource "aws_eip" "terra-lin01-eip01" {
  instance = aws_instance.terra-lin01.id
  vpc      = true
}

output "public_ip01" {
  value = aws_eip.terra-lin01-eip01.public_ip
}


resource "aws_key_pair" "ec2-ssh_key01" {
  key_name   = "ec2-ssh_key01"
  public_key = file("./ssh_key/tera_ssh_key.pub")
}

resource "aws_security_group" "terra-lin01-sg1" {
  name        = "terra-lin01-sg1"
  description = "terraform"
  vpc_id      = aws_vpc.tera-vpc01.id

  # SSH access from anywhere
  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 2049
    to_port     = 2049
    protocol    = "tcp"
    cidr_blocks = [var.tera-network.cidr]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "allow_tls"
  }
}
resource "aws_vpc" "tera-vpc01" {
  cidr_block = var.tera-network.cidr

  tags = {
    Name = var.tera-network.name
  }
}


resource "aws_subnet" "tera-subnet01" {
  count             = length(var.tera-network.subnets)
  cidr_block        = values(var.tera-network.subnets)[count.index].cidr
  availability_zone = values(var.tera-network.subnets)[count.index].availability_zone
  tags = {
    Name = keys(var.tera-network.subnets)[count.index]
  }
  vpc_id = aws_vpc.tera-vpc01.id
}

resource "aws_internet_gateway" "tera-vpc01-gw01" {
  vpc_id = aws_vpc.tera-vpc01.id

  tags = {
    Name = "teraform"
  }
}

resource "aws_route_table" "tera-vpc01-route-table01" {
  vpc_id = aws_vpc.tera-vpc01.id

  tags = {
    Name = "teraform"
  }
}

resource "aws_route" "tera-vpc01-route-table01-route01" {
  gateway_id             = aws_internet_gateway.tera-vpc01-gw01.id
  route_table_id         = aws_route_table.tera-vpc01-route-table01.id
  destination_cidr_block = "0.0.0.0/0"
}

resource "aws_route_table_association" "tera-vpc01-route-table01-subnet01" {
  count          = length(var.tera-network.subnets)
  subnet_id      = element(aws_subnet.tera-subnet01.*.id, count.index)
  route_table_id = aws_route_table.tera-vpc01-route-table01.id
}
```

</div></details>

<details><summary>②fsxn.tf</summary><div>


```plaintext:②fsxn.tf
resource "aws_fsx_ontap_file_system" "aws-fsx01" {
  storage_capacity    = 1024
  subnet_ids          = ["${element(aws_subnet.tera-subnet01.*.id, 1)}", "${element(aws_subnet.tera-subnet01.*.id, 2)}"]
  deployment_type     = "MULTI_AZ_1"
  throughput_capacity = 512
  preferred_subnet_id = element(aws_subnet.tera-subnet01.*.id, 1)
  fsx_admin_password  = var.tera-fsxn.fsx_admin_password
  route_table_ids     = [aws_route_table.tera-vpc01-route-table01.id]
  security_group_ids  = [aws_security_group.terra-lin01-sg1.id]
}
```

</div></details>

<details><summary>③provider.tf</summary><div>

```plaintext:③provider.tf
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "3.60.0"
    }
  }
}

provider "aws" {
  region                  = var.aws.region
  profile                 = var.aws.profile
  shared_credentials_file = var.aws.shared_credentials_file
}

```


</div></details>

<details><summary>④variable.tf</summary><div>


```plaintext:④variable.tf
variable "tera-fsxn" {
  default = {
    name                       = "TerraformAWSFSX"
    region                     = "ap-northeast-1"
    fsx_admin_password         = "＜fsxadmin用 パスワード＞"
    throughput_capacity        = 512
    storage_capacity_size      = 1024
    storage_capacity_size_unit = "GiB"
  }
}

variable "tera-network" {
  default = {
    name = "tera-vpc"
    cidr = "172.19.0.0/16"
    subnets = {
      tera-subnet1 = {
        availability_zone = "ap-northeast-1a"
        cidr              = "172.19.1.0/24"
      }
      tera-subnet2 = {
        availability_zone = "ap-northeast-1c"
        cidr              = "172.19.2.0/24"
      }
      tera-subnet3 = {
        availability_zone = "ap-northeast-1d"
        cidr              = "172.19.3.0/24"
      }
    }
  }
}

variable "tera-linux" {
  default = {
    ami           = "ami-02892a4ea9bfa2192"
    instance_type = "t2.micro"
    tagname       = "terra-lin01"
  }
}

variable "aws" {
  default = {
    region                  = "ap-northeast-1"
    profile                 = "terauser11"
    shared_credentials_file = "~/.aws/credentials"
  }
}
```

</div></details>

④variable.tfファイルに①〜③のtfファイルで利用する変数を宣言しています。
以下の項目を環境にあわせて更新してください。

- fsx_admin_password : fsxadmin用の任意のパスワードを記載(例: Passwd$51)


### 2-5. keyペアファイルを作成
SSHの秘密鍵,公開鍵のキーペアを作成します。
（ec2インスタンスへのssh接続用keyペア）

```shell:
$ cd ~/terraform/fsxn/ssh_key
$ ssh-keygen -t rsa -f tera_ssh_key -N ''
$ ls -l
-rw------- 1 terauser11 terauser11  xxxx mm月 dd hh:mm tera_ssh_key
-rw-r--r-- 1 terauser11 terauser11  xxx  mm月 dd hh:mm tera_ssh_key.pub
```


## 3. Terraformの実行
terraformを実行してAmazon FSx for NetApp ONTAP環境を構成します。
最初にiniコマンドでを初期化処理を行い、その後に planコマンドで 実行内容を確認します。
（terraform planでは、確認のみで処理は実行されません。）


```shell:実行例
$ cd ~/terraform/fsxn
$ terraform init

Initializing the backend...

Initializing provider plugins...
〜〜出力省略〜〜
Terraform has been successfully initialized!
〜〜出力省略〜〜

$ terraform plan

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
  + create
〜〜出力省略〜〜
Plan: 15 to add, 0 to change, 0 to destroy.
〜〜出力省略〜〜

```

※terraform init実行時に "Failed to query available provider packages"といったエラーが出る場合は terraform init -upgrade コマンド(-upgradeオプションを追加)を実行してみると回避できる場合があるので試してみてください

planでの内容確認後、applyコマンドを実行し、"Enter a value:"でyesを入力してEnterを押下すると、実際に terraformが実行されます。

Linuxサーバなどはすぐに作成が完了するかと思いますが、**Amazon FSx for NetApp ONTAPは20-30分程度**でデプロイに時間がかかります。

完了を確認するには、AWS コンソールでファイルシステムが作成されていることを確認してください。

```shell:実行例
$ terraform apply

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
  + create
〜〜出力省略〜〜
Plan: 15 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value:
  ↑ yesを入力してEnter

〜〜出力省略〜〜
Apply complete! Resources: 15 added, 0 changed, 0 destroyed.

Outputs:

public_ip01 = "＜＜ Linuxサーバの EIP ＞＞"
〜〜出力省略〜〜
$ terraform state list
aws_eip.terra-lin01-eip01
aws_instance.terra-lin01
aws_internet_gateway.tera-vpc01-gw01
aws_key_pair.ec2-ssh_key01
aws_route.tera-vpc01-route-table01-route01
aws_route_table.tera-vpc01-route-table01
aws_route_table_association.tera-vpc01-route-table01-subnet01[0]
aws_route_table_association.tera-vpc01-route-table01-subnet01[1]
aws_route_table_association.tera-vpc01-route-table01-subnet01[2]
aws_security_group.terra-lin01-sg1
aws_subnet.tera-subnet01[0]
aws_subnet.tera-subnet01[1]
aws_subnet.tera-subnet01[2]
aws_vpc.tera-vpc01
netapp-cloudmanager_aws_fsx.aws-fsx01
```
"Outputs:"行で、LinuxサーバのIPアドレスを確認します。このIPアドレスを利用してssh接続します。
terraform state listコマンドでリソースが表示されることを確認します。

AWSコンソールでも確認できます。



# NFSボリュームをマウントしてみる

AWSコンソールで以下操作を行い、ストレージ仮想マシン（SVM）とボリュームを作成して NFS接続用のIPアドレスを確認します。

***
1. 画面左上の "サービス"→"ストレージ" - "FSx"を選択
2. 画面左の "Ontap" - "ストレージ仮想マシン"をクリック
3. "ストレージ仮想マシンを作成"をクリック
4. ファイルシステムを選択してストレージ仮想マシン名に"terasvm01"と入力して"Confirm"ボタンをクリック
5. 作成したの ストレージ仮想マシン にチェックをいれて、アクション→詳細を表示
6. エンドポイント欄の"NFS IP アドレス"で、NFS接続用のIPアドレスを確認します。
7. 画面左の "ONTAP" - "ボリューム"をクリック
8. "ボリューム"を作成をクリック
9. ファイルシステム、仮想マシンを選択し、ボリューム名にnfsvol01、ジャンクションパスに /nfsvol01、ボリュームサイズに20を入力して”Confirm"ボタンをクリック

***


作業用Linuxサーバから EC2インスタンスとして作成したLinuxサーバへsshで接続し FSx for NetApp ONTAPのボリュームをNFSマウントします。

```shell
$ ssh -i ssh_key/tera_ssh_key ec2-user@"＜＜ Linuxサーバの EIP ＞＞"
[ec2-user@ip-xxx-xx-x-xxx ~]$ sudo mkdir /fsx
[ec2-user@ip-xxx-xx-x-xxx ~]$ sudo mount "NFS IPアドレス":/nfsvol01 /fsx
[ec2-user@ip-xxx-xx-x-xxx ~]$ df 
```

アンマウントしてLinuxサーバからログアウトします。

```shell
[ec2-user@ip-xxx-xx-x-xxx ~]$ sudo umount /fsx
$ exit
```


# 環境削除
terraform destroyコマンドで デプロイした環境の削除を行います。
必ず**Amazon FSx for NetApp ONTAP削除を確認後**に、他のリソースを削除してください。

Amazon FSx for NetApp ONTAP削除 → Linuxサーバ削除 → その他リソース の順番に 削除します。

## 1.Amazon FSx for NetApp ONTAP削除
ストレージ仮想マシンを手動削除後に、terraform destroyコマンドを実行します。


①-1 手動作成リソースの削除
AWSコンソールから、手動で作成した ストレージ仮想マシン、ボリュームを削除します。

***
1. 画面左上の "サービス"→"ストレージ" - "FSx"を選択
2. 画面左の "ONTAP" - "ボリューム"をクリック
3. nfsvol01にチェックをいれて、 "アクション" → "ボリュームを削除"をクリック
4. 最終バックアップを"いいえ”を選択して、チェックボックスにチェックをいれ、削除の確認に"delete"と入力して"ボリュームの削除"をクリック
5. 画面左の "Ontap" - "ストレージ仮想マシン"をクリック
6. terasvm01にチェックを入れて、"アクション" → "ストレージ仮想マシンを削除"をクリック
7. "ストレージ仮想マシンを削除"をクリック

***



①-2 削除処理の開始
作業用Linuxサーバから terraformでの削除処理を実行します。

※FSx for NetApp Ontapのファイルシステム削除は、関連するストレージ仮想マシンの削除が完了していないと、正常に処理されません。AWSコンソール上で 関連するストレージ仮想マシンが削除されたことを確認後にこの操作を実施してください。


```shell:実行例
$ terraform destroy -target=netapp-cloudmanager_aws_fsx.aws-fsx01
〜〜出力省略〜〜
Enter a value:
 ↑ yesを入力してEnter
〜〜出力省略〜〜
Destroy complete! Resources: 1 destroyed.
$ 
```

削除処理は 10分-15分程度かかります。

①-3 削除完了の確認

AWSコンソール、NetApp Cloud Managerの画面で、削除完了の確認を行います。

- AWS コンソールで画面左上の"サービス"→"ストレージ" - "FSx"を選択し、該当のファイルシステムが表示されなくなったことを確認

## 2.その他リソース削除
AWSプロバイダーのリソースを削除します。
この操作は**Amazon FSx for NetApp ONTAPの削除完了確認後に実施**してください。


```shell:実行例
$ terraform destroy 
〜〜出力省略〜〜
Enter a value: 
 ↑ yesを入力してEnter
〜〜出力省略〜〜
Destroy complete! Resources: 14 destroyed.

$ terraform state list
```
terraform state listコマンドで出力がなくなっていることを確認します。

また、必要に応じてAWS コンソールでリソースが削除されていることを確認します。

# まとめ
Terraformを利用したAmazon FSx for NetApp ONTAPデプロイ手順を紹介させていただきました。

AWSプロバイダのみで操作をできるので、Cloud Managerプロバイダを併用するパターンと比較すると準備プロセスがシンプルになりますが、
ストレージ仮想マシンを手動で作成してあげる必要があるところは注意点になるかと思います。

今後、機能が拡張されればボリューム作成含めてterraformからリソースを展開できるようになる可能性もあるかと思いますので、また試してみたらご紹介したいと思います。