🐷

【AWS入門】EC2(+Nginx)を立ててみた #Terraform編

2024/11/29に公開

1. はじめに

こんにちは!ta8i2chi8です。
AWS学習日記の第二弾です。

前回、EC2にNginxをインストールした簡単なWebサーバーの構築をGUIで実施しました。
https://zenn.dev/moribook/articles/24cd77ff1690c9

今回は、Terraformを使って構築してみたいと思います。

今回構築したい構成(前回と同様)

ソースコード(完成版)はこちら

https://github.com/ta8i2chi8/aws-vpc-publicsubnet-ec2


2. 前提条件

  • AWSアカウントを作成済みであること
  • Terraformを使用できる環境があること

3. ディレクトリ構造

- modules
  - compute
    - main.tf         # コンピューティングリソース
    - outputs.tf      # コンピューティングリソースの出力
    - variables.tf    # コンピューティングリソースの入力
  - network
    - main.tf         # ネットワークリソース
    - outputs.tf      # ネットワークリソースの出力
    - variables.tf    # ネットワークリソースの入力
- backend.tf          # tfstateの設定(保存先など)
- provider.tf         # providerの設定
- main.tf             # モジュールの呼び出し

以下ブログを参考に、moduleディレクトリ内でmoduleブロックを定義して呼び出す形式を採用しました。
現段階ではmoduleに分ける必要はないかもしれないですが、実務を想定してこの形で実装しています。
https://blog.engineer.adways.net/entry/2024/04/12/120000#ディレクトリファイル構成


4. 各ファイルの実装

/module/compute/main.tf
data "aws_ssm_parameter" "amzn2" {
  name = "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2"
}

resource "aws_instance" "web_server" {
  ami                         = data.aws_ssm_parameter.amzn2.value
  instance_type               = "t2.micro"
  subnet_id                   = var.subnet_id
  vpc_security_group_ids      = [aws_security_group.web_server.id]
  # キーペアのみマネージメントコンソールで作成しておく必要あり。ここでは作成済のキーペア名を入力する。
  key_name                    = "nginx-web-server-key" 
  associate_public_ip_address = true

  tags = {
    Name = "${var.pj_name}-ec2"
  }

  user_data = <<-EOF
                #!/bin/bash
                sudo yum update -y
                sudo amazon-linux-extras install nginx1 -y
                sudo yum install nginx -y
                sudo systemctl start nginx
                sudo systemctl enable nginx
              EOF
}

resource "aws_security_group" "web_server" {
  name        = "${var.pj_name}-sg"
  description = "${var.pj_name} sg"
  vpc_id      = var.vpc_id

  tags = {
    Name = "${var.pj_name}-sg"
  }
}

resource "aws_vpc_security_group_ingress_rule" "web_server" {
  count = length(var.security_group_ingress_rules)

  security_group_id = aws_security_group.web_server.id
  cidr_ipv4         = var.security_group_ingress_rules[count.index].cidr
  ip_protocol       = "TCP"
  from_port         = var.security_group_ingress_rules[count.index].from_port
  to_port           = var.security_group_ingress_rules[count.index].to_port
}

resource "aws_vpc_security_group_egress_rule" "web_server" {
  security_group_id = aws_security_group.web_server.id
  cidr_ipv4         = "0.0.0.0/0"
  ip_protocol       = "-1"
  from_port         = "0"
  to_port           = "0"
}
/module/compute/outputs.tf
# 記述なし
/module/compute/variables.tf
variable "pj_name" {
  type        = string
  description = "PJ名"
}

variable "vpc_id" {
  type        = string
  description = "VPCのID"
}

variable "subnet_id" {
  type        = string
  description = "サブネットのID"
}

variable "security_group_ingress_rules" {
  type = list(
    object({
      cidr      = string
      from_port = string
      to_port   = string
    })
  )
}
/module/network/main.tf
resource "aws_vpc" "main" {
  cidr_block           = var.vpc_cidr
  enable_dns_support   = true
  enable_dns_hostnames = true

  tags = {
    Name = "${var.pj_name}-vpc"
  }
}

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

  tags = {
    Name = "${var.pj_name}-igw"
  }
}

# パブリックサブネット
resource "aws_subnet" "public_1a" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = var.subnet_cidr
  availability_zone = "ap-northeast-1a"

  tags = {
    Name = "${var.pj_name}-subnet"
  }
}

# パブリックサブネット用RT
resource "aws_route_table" "main" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name = "${var.pj_name}-rt"
  }
}
resource "aws_route" "default_route" {
  route_table_id         = aws_route_table.main.id
  destination_cidr_block = "0.0.0.0/0"
  gateway_id             = aws_internet_gateway.main.id
}
resource "aws_route_table_association" "public_1a" {
  subnet_id      = aws_subnet.public_1a.id
  route_table_id = aws_route_table.main.id
}
/module/network/outputs.tf
output "vpc_id" {
  value       = aws_vpc.main.id
  description = "VPCのID"
}

output "subnet_id" {
  value       = aws_subnet.public_1a.id
  description = "サブネットのID"
}
/module/network/variables.tf
variable "pj_name" {
  type        = string
  description = "PJ名"
}

variable "vpc_cidr" {
  type        = string
  description = "VPCのCIDR"
}

variable "subnet_cidr" {
  type        = string
  description = "サブネットのCIDR"
}
backend.tf
# ちゃんとリモートで管理したいときはコメントアウト解除
# terraform {
#   backend "s3" {
#     bucket         = "*****-tfstate"
#     key            = "*****/terraform.tfstate"
#     encrypt        = true
#     dynamodb_table = "*****-tfstate-lock"
#     region         = "ap-northeast-1"
#   }
# }
provider.tf
terraform {
  required_version = "= 1.9.8"

  required_providers {
    aws = {
      version = "= 5.78.0"
      source  = "hashicorp/aws"
    }
  }
}

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

  default_tags {
    tags = {
      owner = "tm"
    }
  }
}

main.tf
# マイIPを外部から取得
data "http" "my_ip" {
  url = "https://ifconfig.me"
}

module "network" {
  source = "./modules/network"

  pj_name     = "training-tf"
  vpc_cidr    = "13.0.0.0/16"
  subnet_cidr = "13.0.0.0/24"
}

module "compute" {
  source = "./modules/compute"

  pj_name   = "training-tf"
  vpc_id    = module.network.vpc_id
  subnet_id = module.network.subnet_id
  security_group_ingress_rules = [
    {
      cidr      = "${data.http.my_ip.response_body}/32"
      from_port = "22"
      to_port   = "22"
    },
    {
      cidr      = "0.0.0.0/0"
      from_port = "80"
      to_port   = "80"
    }
  ]
}

5. Terraformの初期化

以下コマンドを実行します。

terraform init

6. リソースの作成

以下コマンドを実行します。

terraform apply

7. ブラウザからの動作確認

GUI編と同様、ブラウザを開き、以下URLにアクセスしてNginxのデフォルトページが表示されるか確認します。

http://インスタンスのパブリックIP

以下のような画面が表示されれば無事Nginxサーバが完成しました!

不要であれば、リソースを削除しましょう。

terraform destroy

8. おわりに

今回は、Terraformを使ってEC2でNginxサーバーを構築してみました。
最後まで、読んでいただきありがとうございました!


参考

https://qiita.com/yokku21/items/fc7153e974339adb7b1f
https://qiita.com/jun_aws/items/18570faa3e62aa2f8456
https://zenn.dev/ochi_shoichi/scraps/1e224c1501cc29

Discussion