[AWS] TerraformでデフォルトEBS最適化のEC2インスタンスを作成するときの注意点

# TL;DR

デフォルトでEBS最適化となるインスタンスタイプでは、AWSコンソール上はEBS最適: FalseでもEBS最適化は有効となっている（らしい）。
TerraformでEC2インスタンスを作成するときは、ebs_optimizedの指定を気にしなくてもよさそう。

# 検証環境

- macOS Catalina
- Terraform v0.12.20

# EBS最適化とは

EC2インスタンスの記憶領域にはEBSを割り当てることができ、インスタンスとEBSはネットワークで接続しています。
EBS最適化とは、このネットワークに専用帯域を割り当てることです。

EC2のインスタンスタイプによって、EBS最適化を利用できるかどうかが決まっており、利用できるタイプの中でも最適化の設定がデフォルトで有効になっているものとインスタンス作成時に明示的に設定する必要があるものが存在します。

[Amazon EBS – 最適化インスタンス](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ebs-optimized.html)

開発環境や検証でよく利用するt系のインスタンスでは、t3シリーズからEBS最適化がデフォルトで有効となっています。
下図は、AWSコンソールからt3-microのEC2インスタンスを起動した際の、インスタンスの情報です。

<img width="420" alt="ebs_true.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282895/8a385819-29a1-90a6-bea1-7349a9627ee3.png">

起動時にEBSの設定には特に触っていませんが、EBS最適化はTrueとなっています。

# TerraformでデフォルトEBS最適化のインスタンスを作成してみる

今回問題となったのは　TerraformからEC2インスタンスを作成した場合です。

検証として、以下のtfファイルを作成します。

VPCやサブネット等のネットワーク周りのリソースを用意し、その上でEC2インスタンスを一台起動するシンプルな内容です。

```terraform:main.tf
provider "aws" {
  version = "~> 2.0"
  profile = "default"
  region  = "ap-northeast-1"
}

resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"

  tags = {
    Name = "sample_vpc"
  }
}

resource "aws_subnet" "public" {
  vpc_id            = "${aws_vpc.main.id}"
  cidr_block        = "10.0.0.0/24"
  availability_zone = "ap-northeast-1a"

  tags = {
    Name = "sample_public_subnet"
  }
}

resource "aws_internet_gateway" "main" {
  vpc_id = "${aws_vpc.main.id}"

  tags = {
    Name = "sample_internet_gateway"
  }
}

resource "aws_route_table" "main" {
  vpc_id = "${aws_vpc.main.id}"

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = "${aws_internet_gateway.main.id}"
  }

  tags = {
    Name = "sample_route_table"
  }
}

resource "aws_route_table_association" "public" {
  subnet_id      = "${aws_subnet.public.id}"
  route_table_id = "${aws_route_table.main.id}"
}

resource "aws_security_group" "ec2" {
  name        = "sample-ec2-sg"
  description = "This is sample"
  vpc_id      = "${aws_vpc.main.id}"

  ingress {
      from_port   = 22
      to_port     = 22
      protocol    = "tcp"
      cidr_blocks = ["0.0.0.0/0"]
  }
  egress {
      from_port   = 0
      to_port     = 0
      protocol    = "-1"
      cidr_blocks = ["0.0.0.0/0"]
  }
  tags = {
    Name = "sample_ec2_security_group"
  }
}

data "aws_ssm_parameter" "latest_amzn2_ami" {
  name = "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2"
}

resource "aws_instance" "sample" {
  ami                    = "${data.aws_ssm_parameter.latest_amzn2_ami.value}"
  instance_type          = "t3.micro"
  vpc_security_group_ids = ["${aws_security_group.ec2.id}"]
  subnet_id              = "${aws_subnet.public.id}"
  # 各々のキーペアに置き換え
  key_name               = "your-key-pair"

  tags = {
    Name = "sample_ec2_instance"
  }
}
```

terraform applyコマンドでAWSリソースを作成します。

```sh
terraform apply
```

作成されたEC2インスタンスの情報をコンソールから確認すると、

<img width="420" alt="ebs_false.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282895/dfad000f-386e-9e56-6f46-b939ff178b8c.png">


EBS最適化の項目がFalseになってしまっています。

## EBS最適化をTrueにするには

`ebs_optimized = true`オプションを追加しましょう。

```terraform
resource "aws_instance" "sample" {
  ami                    = "${data.aws_ssm_parameter.latest_amzn2_ami.value}"
  instance_type          = "t3.micro"
  vpc_security_group_ids = ["${aws_security_group.ec2.id}"]
  subnet_id              = "${aws_subnet.public.id}"
  # 各々のキーペアに置き換え
  key_name               = "your-key-pair"
  ebs_optimized          = true  # 追加

  tags = {
    Name = "sample_ec2_instance"
  }
}
```

この設定でapplyすれば、AWSコンソール上でもEBS最適化の項目がTrueになります。

# EBS最適化がFalseでもEBS最適化は無効にはなっていない？

> EBS 最適化 (デフォルト)
> 次の表は、EBS 最適化をサポートするインスタンスタイプを示します。EBS 最適化はデフォルトで有効になっています。EBS 最適化を有効にする必要はなく、EBS 最適化を無効にすると効果はなくなりません。

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ebs-optimized.html

こちらのAWSのドキュメントによると、デフォルトEBS最適化のインスタンスはEBS最適化を無効にしようとしても無効にはならないようです。

（実際にパフォーマンスを比較したりはしていないので、100%は言い切れません...）

Terraformのドキュメントにも下記のように記載がありますね。

> Note that if this is not set on an instance type that is optimized by default then this will show as disabled but if the instance type is optimized by default then there is no need to set this and there is no effect to disabling it.

https://www.terraform.io/docs/providers/aws/r/instance.html#ebs_optimized

また、インスタンスタイプを変更する場合に次のような注意点があることから、`ebs_optimized`は指定しないほうが無難かもしれません。

[【小ネタ】EBS最適化インスタンスをCLIツールでスペックダウンするときの注意点](https://dev.classmethod.jp/operation/optimized-ebs-tips/)


# その他参考

- [Terraformで最新のAmazon Linux 2のAMI IDを取得してEC2を構築する](https://dev.classmethod.jp/cloud/aws/launch-ec2-from-latest-amazon-linux2-ami-by-terraform/)