StageGatway (NFS)をterraformで構築

Amazon S3 ファイルゲートウェイをterraformで構築しました。

下記記事を参考に（SMBによるファイル共有）、NFSとしてstorage gateway及びファイル共有をterraformで作成しました。

https://dev.classmethod.jp/articles/create-s3-storage-gateway-using-terraform/

先に結論から色々書いてしまうと、まずterraformで構築する利点はあまりないなと感じました。
今回storage gateway VMの移行があり、対象ファイル共有も多数あったのでterraformで一気に作っちゃいましょうという流れでした。

terraformで構築する利点として、ファイル共有の増減が容易に出来る。
stoage gateway本体をterraformで構築するメリットはあまりない（アクティベートキーの取得部分）用に感じました。

また、storage gatawayによるNFSファイル共有は双方向ではないことに注意が必要です。
マウント先で設置したファイルはS3にアップロードされますが、S3に直接アップロードしたファイルはマウント先には反映されません。

今回vpcやらkey/secやらproviderやらの設定は割愛します。
この辺の記事を参考にしていただけたら幸いです。

https://qiita.com/instant_baby/items/7552d9e69c8546d2f1fd

ではいきましょう。


```
$ terraform version
Terraform v1.0.9
on darwin_amd64
+ provider registry.terraform.io/hashicorp/aws v3.62.0
```

作成するもの
・storage gateway用インスタンス一台（m4.xlarge）
・ファイル共有
・ファイル共有用のIAM role及びpolicy

今回はprivate subnet上に構築するため、gatewayをアクティベートするためのキーは別途取得する必要があります。
つまり、アクティベートキーの取得前と後でapplyは二回叩く必要があるということです。
※というかstorage gatewayをpublic上に置く機会自体あまりなさそう

まずは一回目のapplyでstorage gatewayで使用するEC2インスタンスの立ち上げます。
storage gatewayのcache用に、root以外に別途EBSをぶら下げてます。
※rootでもいいっちゃいいけど外付けで切り離せるようにしておいたほうが後々楽そうなので。

storage用S3バケットは今回terraform外で作成済みです。


AMIに関してはstorage gateway用のAMIがあるので引っ張ってきてます。
インスタンスのサイズは公式が推奨しているサイズ以上のものを用意してあげましょう。

https://docs.aws.amazon.com/ja_jp/storagegateway/latest/userguide/ec2-gateway-file.html

```:ec2_sgw.tf
data "aws_ssm_parameter" "sgw_ami" {
  name = "/aws/service/storagegateway/ami/FILE_S3/latest"
}

resource "aws_instance" "sgw_test" {
  ami                    = data.aws_ssm_parameter.sgw_ami.value
  vpc_security_group_ids = ["sg-00000000"]
  subnet_id              = "subnet-00000000"
  key_name               = "hoge-key"
  instance_type          = "m4.xlarge"
  tags = {
    Name = "sgw_test"
  }
  root_block_device {
    volume_type           = "gp3"
    iops                  = 3000
    throughput            = 125
    volume_size           = 80
    delete_on_termination = true
    encrypted             = false
    tags = {
      Name = "sgw_root"
    }
  }
  ebs_block_device {
    device_name           = "/dev/sdf"
    volume_type           = "gp3"
    iops                  = 3000
    throughput            = 125
    volume_size           = 150
    delete_on_termination = true
    encrypted             = false
    tags = {
      Name = "sgw_cache"
    }
  }
}
```

このEC2自体にstorage gatewayに関する IAM roleは不要です。
後に作成するファイル共有に必要となってきます。

とりあえずインスタンス一台だけ書けたらapply。
上がったらIP addressを控えておきましょう。

次に作成したインスタンスをstorage gatewayとして使用するためにアクティベートキーを取得します。

実行コマンドは以下

```
curl 'ec2_instance_ip_address/?activationRegion=activation_region&no_redirect'
```

先に立てたインスタンスはprivate subnet内に立ててるので、別のインスタンスかどっか別の場所から叩く必要があります。

今回はpublic上にある別インスタンスがsgw用インスタンスと疎通ができるので、そこから以下コマンドを実行します。
IP addressとregionはsgw用インスタンスのものを指定しましょう。

https://docs.aws.amazon.com/ja_jp/storagegateway/latest/userguide/get-activation-key.html

```
$ curl '10.10.116.97/?activationRegion=us-west-2&no_redirect'
```

疎通が取れる別インスタンスから実行した結果

```
[root@ip-10-10-7-106 ec2-user]# ping 10.10.116.97
PING 10.10.116.97 (10.10.116.97) 56(84) bytes of data.
64 bytes from 10.10.116.97: icmp_seq=1 ttl=255 time=0.347 ms
64 bytes from 10.10.116.97: icmp_seq=2 ttl=255 time=0.303 ms
64 bytes from 10.10.116.97: icmp_seq=3 ttl=255 time=0.332 ms
^C
--- 10.10.116.97 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2031ms
rtt min/avg/max/mdev = 0.303/0.327/0.347/0.023 ms
[root@ip-10-10-7-106 ec2-user]# curl '10.10.116.97/?activationRegion=us-west-2&no_redirect'
IF1FV-UMTIJ-00000-00000-00000[root@ip-10-10-7-106 ec2-user]#
```

```
IF1FV-UMTIJ-00000-00000-00000[
```

無事アクティベーションキーが発行されました。
このキーを使って2回目のapplyをしていきます。

ファイル共有に必要なIAM roleとpolicyを作成します。
policyをtfファイル内に直書きするのは個人的に見にくいので別途jsonファイルにしてfile関数で参照する書き方をしています。

書き方についてはこのあたりを参考にどうぞ。

https://qiita.com/instant_baby/items/3327a553f0d8108ec95a

```iam.tf
# Policy
resource "aws_iam_role_policy" "s3_policy_01" {
  name   = "s3_sgw-test1"
  role   = aws_iam_role.s3_role.id
  policy = file("./s3_sgw-test1.json")
}

# Role
resource "aws_iam_role" "s3_role" {
  name               = "sgw_s3_role"
  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "storagegateway.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF
}
```

```:s3_sgw-test1.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "s3:GetAccelerateConfiguration",
                "s3:GetBucketLocation",
                "s3:GetBucketVersioning",
                "s3:ListBucket",
                "s3:ListBucketVersions",
                "s3:ListBucketMultipartUploads"
            ],
            "Resource": "arn:aws:s3:::sgw-test1",
            "Effect": "Allow"
        },
        {
            "Action": [
                "s3:AbortMultipartUpload",
                "s3:DeleteObject",
                "s3:DeleteObjectVersion",
                "s3:GetObject",
                "s3:GetObjectAcl",
                "s3:GetObjectVersion",
                "s3:ListMultipartUploadParts",
                "s3:PutObject",
                "s3:PutObjectAcl"
            ],
            "Resource": "arn:aws:s3:::sgw-test1/*",
            "Effect": "Allow"
        }
    ]
}
```

sgwをアクティベートする設定とファイル共有を作成します。

以下の欄に先に取得したアクティベーションキーを転記します。

```
resource "aws_storagegateway_gateway" "sgw" {
  activation_key   = "IF1FV-UMTIJ-00000-00000-00000"
```

timezoneの書き方がGMTを基準にプラスマイナスで記載しなければいけないことに注意してください。


```sgw.tf
resource "aws_storagegateway_gateway" "sgw" {
  activation_key   = "IF1FV-UMTIJ-00000-00000-00000"
  gateway_name     = "terraform-test"
  gateway_timezone = "GMT+9:00"
  gateway_type = "FILE_S3"
}

data "aws_storagegateway_local_disk" "sgw" {
  gateway_arn = aws_storagegateway_gateway.sgw.arn
  disk_node   = "/dev/sdf"
}

resource "aws_storagegateway_cache" "sgw" {
  gateway_arn = aws_storagegateway_gateway.sgw.arn
  disk_id     = data.aws_storagegateway_local_disk.sgw.id
}

resource "aws_storagegateway_nfs_file_share" "share01" {
  client_list  = ["0.0.0.0/0"]
  gateway_arn  = aws_storagegateway_gateway.sgw.arn
  location_arn = "arn:aws:s3:::sgw-test1"
  role_arn     = aws_iam_role.s3_role01.arn
  object_acl   = "bucket-owner-full-control"
  nfs_file_share_defaults {
    directory_mode = "0777"
    file_mode      = "0666"
    group_id       = "65534"
    owner_id       = "65534"
  }
}
```

上の設定でsgwのアクティベートと、ファイル共有が作成可能になりました。
ココまで来たらterraformでの作業は終了です。

コンソールからファイル共有が作成されていることを確認します。
コマンド例にmountコマンドが記載されているので、適当なサーバーにマウントしてファイルを置いてみましょう。

![スクリーンショット 2021-10-22 18.31.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1526421/b0a0f017-05ae-fba2-85d7-47d71ed0d4a8.png)

S3へアップロードができていれば無事完了です。

お疲れさまでした。