TerraformでAWS環境にApacheサーバを作成

最近Terraformを触ることが多かったので復習を兼ねて試してみました。
ほぼTerraformだけでApacheサーバの起動まで行います。

## 環境
Terraform v0.14.10
aws provider v3.36.0

## 事前準備
### tfstate用のS3バケット作成
今回tfstateファイルの保存先にS3を指定しますので、事前にそれ用のS3バケットを作成しておきます。
Terraformで作成することも出来るのですが、公式で「Terraformはインフラを管理する管理ツールなので、Terraformが使用するインフラは、Terraformが管理するインフラの外側に存在するのが理想です。(DeepL翻訳)」と言われています。Terraformを修正するときに誤って破損させたりすることを避けるためですね。
https://www.terraform.io/docs/language/settings/backends/s3.html#multi-account-aws-architecture

### SSHアクセス用の公開鍵・秘密鍵作成
作成するEC2インスタンスにアクセス出来るよう鍵を作成しておきます。

```bash
$ ssh-keygen -C ""
```

## 実装
以下に作成したコードを記載します。

```bash:ディレクトリ構成
.
├── aws_instance.tf
├── aws_internet_gateway.tf
├── aws_key_pair.tf
├── aws_route_table.tf
├── aws_route_table_association.tf
├── aws_security_group.tf
├── aws_subnet.tf
├── aws_vpc.tf
├── files
│   └── user_data.sh
└── main.tf
```


```tf:main.tf
terraform {
  required_version = "~> 0.14"
  backend "s3" {
    bucket  = "XXXXX" # 作成したバケット名
    region  = "ap-northeast-1"
    key     = "terraform.tfstate"
    encrypt = true
  }
}

provider "aws" {
  region = "ap-northeast-1"
}
```

```tf
# VPC
resource "aws_vpc" "test" {
  cidr_block = "10.0.0.0/16"

  tags = {
    Name = "test-vpc"
  }
}

# サブネット
resource "aws_subnet" "test" {
  vpc_id                  = aws_vpc.test.id
  cidr_block              = "10.0.1.0/24"
  availability_zone       = "ap-northeast-1a"
  map_public_ip_on_launch = true

  tags = {
    Name = "test-subnet"
  }
}

# インターネットゲートウェイ
resource "aws_internet_gateway" "test" {
  vpc_id = aws_vpc.test.id

  tags = {
    Name = "test-igw"
  }
}

# ルートテーブル
resource "aws_route_table" "test" {
  vpc_id = aws_vpc.test.id

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

  tags = {
    Name = "test-route-table"
  }
}

resource "aws_route_table_association" "test" {
  subnet_id      = aws_subnet.test.id
  route_table_id = aws_route_table.test.id
}

# キーペア
resource "aws_key_pair" "test" {
  key_name   = "test-key"
  public_key = "ssh-rsa XXXXX" # 事前に作成した公開鍵を貼り付ける
}

# EC2インスタンス
resource "aws_instance" "apache" {
  ami                         = "ami-06098fd00463352b6" # AmazonLinux 2 (x86)
  instance_type               = "t3.nano"
  subnet_id                   = aws_subnet.test.id
  user_data                   = file("./files/user_data.sh")
  key_name                    = aws_key_pair.test.key_name

  vpc_security_group_ids = [
    aws_security_group.web.id,
    aws_security_group.ssh.id
  ]

  tags = {
    Name = "test-server"
  }
}

# セキュリティグループ
resource "aws_security_group" "web" {
  name   = "web"
  vpc_id = aws_vpc.test.id

  ingress {
    description = "allow http"
    from_port   = "80"
    to_port     = "80"
    protocol    = "tcp"
    cidr_blocks = ["x.x.x.x/32"] # 必要なIP制限を設定
  }

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

resource "aws_security_group" "ssh" {
  name   = "ssh"
  vpc_id = aws_vpc.test.id

  ingress {
    description = "allow ssh"
    from_port   = "22"
    to_port     = "22"
    protocol    = "tcp"
    cidr_blocks = ["x.x.x.x/32"] # 必要なIP制限を設定
  }

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

```bash:user_data.sh
#!/bin/bash
sudo yum update -y
sudo yum install -y httpd
sudo systemctl start httpd
sudo systemctl enable httpd
```

## 確認
実際にアクセスしてみます。
![test_apache_access.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183878/9d52a48a-0865-78d9-635c-057a408b989d.png)

```bash
$ ssh -i ~/test_rsa ec2-user@x.x.x.x
Warning: Permanently added 'x.x.x.x' (ECDSA) to the list of known hosts.
Last login: Sat Apr 10 17:25:59 2021 from p6403009-ipoe.ipoe.ocn.ne.jp

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
[ec2-user@ip-10-0-1-137 ~]$ 
```

ブラウザでのHTTPアクセスでApacheのテストページが見えて、SSHでのアクセスも事前に作成した秘密鍵を使って問題なく出来ました。

## まとめ
事前のS3バケット作成を除いてTerraformのみでApacheサーバの起動までを行いました。
インフラ環境をコード化するのは楽しいですね。引き続き精進したいと思います。

## 参考
- https://registry.terraform.io/providers/hashicorp/aws/latest/docs
- https://www.amazon.co.jp/dp/B07XT7LJLC