【AWS】TerraformでEC2を構築する際のあれこれ

[前回の記事](https://qiita.com/hidekko/items/19871f8fd14304c13e84)で記載している、副産物の記事になります。

# 構成図
まずは構成図でおさらいです。
![構成図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643392/02cc9622-9957-5ca7-bb12-6ec2402e68fa.png)
今回の副産物はWeb Serverの構成関連です。

# 1.EC2のローカルIPアドレスをDHCPにする。
今までTerraformでEC2を構築する際、ローカルIPアドレスを固定IPアドレスで構築していましたが、今回ALBがDHCPなのでTerraform実行時に何度かIPアドレスが重複して失敗しました。
EC2のIPアドレスをDHCPで構成する場合どうしたら良いか知らなかったので調べてみたのですが、一発で出てこなかったので個人メモに近いですが記載します。

具体的なtfファイル上の記載は以下の通りです。

```ec2.tf
# Front End(Web Server) 1台目
 resource "aws_instance" "ec2_app01" {
   ami                         = data.aws_ssm_parameter.al2023-ami-kernel-default-x86_64.value
   instance_type               = var.ec2_instance_type
   availability_zone           = var.availability_zone.a
   vpc_security_group_ids      = [aws_security_group.sg_ec2_app01.id]
   subnet_id                   = aws_subnet.sn_private_1a.id
#   private_ip                  = "${var.vpc_address_pre}1.21"
   associate_public_ip_address = "false"
   iam_instance_profile        = aws_iam_instance_profile.instance_prof.name
   user_data                   = <<-EOF
                                 #!/bin/bash
                                 sudo hostnamectl set-hostname ${var.env_type}-${var.sys_name}-ec2-app01
                                 sudo dnf update -y
                                 sudo dnf install -y httpd php
                                 sudo systemctl start httpd
                                 sudo systemctl enable httpd
                                 sudo usermod -a -G apache ec2-user
                                 sudo usermod -a -G apache ssm-user
                                 sudo chown -R ec2-user:apache /var/www
                                 sudo chown -R ssm-user:apache /var/www
                                 sudo chmod 2775 /var/www
                                 find /var/www -type d -exec sudo chmod 2775 {} \;
                                 find /var/www -type f -exec sudo chmod 0664 {} \;
                                 echo "<?php phpinfo(); ?>" > /var/www/html/phpinfo.php
                                 echo "It Works! ec2-app01" >/var/www/html/index.html
                                 EOF

   root_block_device {
     volume_size = 30   # GB
     volume_type = "gp3" # 汎用SSD
     encrypted   = false
     tags        = {
       Snapshot = "false"      
     }
   }
   tags = {
     Name = "${var.env_type}-${var.sys_name}-ec2-app01"
   }
   depends_on = [
    aws_route_table_association.associate_rt_sn_private_1a
   ]
 }
```
固定IPアドレスにする場合は
```
private_ip                  = "${var.vpc_address_pre}1.21"
```
なのですが、これをコメントアウトする、つまり<font color="Red">**固定IPアドレスにしない**</font>という設定がDHCPの設定になる、ということでした。

# 2.EC2のヒアドキュメントを正常に実行するため、各リソース構築の順序を制御する
これもec2.tfファイル内で記載している通りなのですが、`sudo dnf update -y`と`sudo dnf install -y httpd php`を実行していますが、NAT Gateway経由でインターネットに接続するようにしているので、NAT Gateway構築前にEC2の構築が完了してしまい、これらのコマンドがコケます。
再現性は100%です。
NAT Gatewayは構築に時間のかかるリソースなので、まぁ仕方ないのかな、という感じですが、これをちゃんと制御できるようにする方法を個人の予想を含めて記載します。
```
depends_on = [
    aws_route_table_association.associate_rt_sn_private_1a
   ]
```
これで順序を制御可能です。
この`depends_on`の処理の後にEC2の構築が行われます。
ちょっと調べたところNAT Gatewayの構築後にEC2を構築する、というだけでいいのであれば、
```
depends_on = [
    aws_nat_gateway.nat_1a
   ]
```
のような記述で良いのですが、これだと3台あるEC2のうち最初の1台だけがdnfコマンドが実行され、残りの2台はdnfコマンドがコケました。
こちらも再現率100%でした。
色々考えたのですが恐らく、EC2の構築順序はNAT Gatewayの後に行われているはずなのですが、NAT Gateway経由でEC2がインターネット接続する、というルートテーブルの定義が間に合ってないのではないか、と考えました。
つまり、

**ルートテーブルでNAT Gateway宛ての通信が定義されている場合、ルートテーブル構築にはNAT Gatewayが必須なので、NAT Gatewayの構築が行われてからルートテーブルの構築が行われる**

ということが予想されることから、各EC2の`depends_on`で`aws_route_table_association.associate_rt_sn_private_1a`と定義しました。
この定義にすると、ルートテーブルの構築後にEC2の構築が行われることとなり、ルートテーブルが構築されているということは暗黙的にNAT Gatewayは構築済みである、ということになるため、EC2がNAT Gateway経由でインターネット接続を行うという前提条件がすべて揃います。
予想が正しかったのか、これでEC2内のヒアドキュメントがコケることはなくなりました。
(本来的にはログを見たり公式の情報を調べたりして裏を取るべきですが、今回は案件ではない検証なのでいったんこのままで良いかなと考えています。)

どちらも小ネタですが、何気に便利な部分なので記事にしました。

本日はここまで。