Module

AWS VPC 구성

  1. Terraform 코드를 저장할 디렉토리 생성

    cd ~/environment && mkdir -p terraform/network && cd terraform/network
  2. Terraform Provider 설정을 포함하는 파일 생성

    cat <<EOF | tee provider.tf
    terraform {
      required_providers {
        aws = {
          source = "hashicorp/aws"
          version = "5.35.0"
        }
      }
    }
    EOF
  3. AWS 리소스 생성에 사용할 Terraform 코드를 저장할 파일 생성

    touch main.tf
  4. 해당 문서를 통해서 VPC 생성에 사용되는 코드 블록 확인

  5. VPC를 생성하는 코드 블록 추가하고 저장

    resource "aws_vpc" "this" {
      cidr_block = "10.10.0.0/16"
    }
  6. 인프라 변경 사항 확인

    terraform plan
  7. Terraform 환경 생성

    terraform init
  8. 인프라 변경 사항 확인

    terraform plan
  9. 인프라 변경 사항 반영

    terraform apply --auto-approve
  10. 해당 문서를 통해서 Subnet 생성에 사용되는 코드 블록 확인

  11. Terraform 상태 파일에 저장된 리소스 정보 확인

    terraform state show aws_vpc.this
  12. 해당 문서를 통해서 CIDR를 계산하는 함수 확인

  13. 아래의 코드 블록을 추가해서 함수 검증

    output "subnet_cidr_1" {
      value = cidrsubnet(aws_vpc.this.cidr_block, 8, 0)
    }
    
    output "subnet_cidr_2" {
      value = cidrsubnet(aws_vpc.this.cidr_block, 8, 250)
    }
    
    output "subnet_cidr_3" {
      value = cidrsubnet(aws_vpc.this.cidr_block, 12, 250)
    }
  14. 인프라 변경 사항 확인

    terraform plan
  15. 13번에서 추가한 코드 블록을 삭제하고 아래의 코드 블록 추가

    resource "aws_subnet" "public" {
      vpc_id     = aws_vpc.this.id
      cidr_block = cidrsubnet(aws_vpc.this.cidr_block, 8, 0)
    }
  16. 인프라 변경 사항 확인

    terraform plan
  17. AWS CLI를 통해서 가용영역 목록 확인

    aws ec2 describe-availability-zones \
    --query 'AvailabilityZones[*].ZoneName' \
    --no-cli-pager
  18. 아래의 코드 블록을 추가

    data "aws_availability_zones" "azs" {}
    
    output "availability_zones" {
      value = data.aws_availability_zones.azs
    }
  19. 인프라 변경 사항 확인

    terraform plan
  20. 서브넷 생성하는 코드 블록을 아래와 같이 수정

    resource "aws_subnet" "public" {
      vpc_id            = aws_vpc.this.id
      cidr_block        = cidrsubnet(aws_vpc.this.cidr_block, 8, 0)
      availability_zone = data.aws_availability_zones.azs.names[0]
    }
  21. 인프라 변경 사항 확인

    terraform plan
  22. 해당 문서를 통해서 생성할 리소스 갯수를 지정하는 인자 확인

  23. 서브넷 생성하는 코드 블록을 아래와 같이 수정

    resource "aws_subnet" "public" {
      count = 4
      
      vpc_id            = aws_vpc.this.id
      cidr_block        = cidrsubnet(aws_vpc.this.cidr_block, 8, count.index)
      availability_zone = data.aws_availability_zones.azs.names[count.index]
    }
  24. 인프라 변경 사항 확인

    terraform plan
  25. 해당 문서를 통해서 리스트의 길이를 확인하는 함수 확인

  26. 서브넷 생성하는 코드 블록을 아래와 같이 수정

    resource "aws_subnet" "public" {
      count = length(data.aws_availability_zones.azs.names)
      
      vpc_id            = aws_vpc.this.id
      cidr_block        = cidrsubnet(aws_vpc.this.cidr_block, 8, count.index)
      availability_zone = data.aws_availability_zones.azs.names[count.index]
    }
  27. 인프라 변경 사항 확인

    terraform plan
  28. 해당 문서를 통해서 Terraform에서 제공하는 문자열 관련 함수 확인

  29. 서브넷 생성하는 코드 블록을 아래와 같이 수정

    resource "aws_subnet" "public" {
      count = length(data.aws_availability_zones.azs.names)
      
      vpc_id            = aws_vpc.this.id
      cidr_block        = cidrsubnet(aws_vpc.this.cidr_block, 8, count.index)
      availability_zone = data.aws_availability_zones.azs.names[count.index]
      
      tags = {
        "Name" = format(
          "public-subnet-%s",
          substr(data.aws_availability_zones.azs.names[count.index], -2, 2)
        )
      }
    }
  30. 인프라 변경 사항 확인

    terraform plan
  31. 아래의 코드 블록 삭제

    output "availability_zones" {
      value = data.aws_availability_zones.azs
    }
  32. data.tf 파일을 생성하고 main.tf에 있는 아래의 코드 블록을 data.tf 파일로 이동

    data "aws_availability_zones" "azs" {}
  33. variable.tf 파일을 생성하고 아래의 블록 추가

    variable "environment" {
      description = "환경 이름"
      type        = string
    }
    
    variable "vpc_cidr" {
      description = "VPC 대역대"
      type        = string
      default     = "10.0.0.0/16"
    }
    
    variable "create_private_subnet" {
      description = "프라이빗 서브넷 생성"
      type        = bool
      default     = false
    }
  34. main.tf 파일의 내용을 아래와 같이 수정

    # VPC
    resource "aws_vpc" "this" {
      cidr_block           = var.vpc_cidr
      enable_dns_hostnames = true
    
      tags = {
        "Name" = "${var.environment}-vpc"
      }
    }
    
    # 인터넷 게이트웨이
    resource "aws_internet_gateway" "this" {
      vpc_id = aws_vpc.this.id
    
      tags = {
        "Name" = "${var.environment}-igw"
      }
    }
    
    # 퍼블릭 서브넷
    resource "aws_subnet" "public" {
      count = length(data.aws_availability_zones.azs.names)
    
      vpc_id                  = aws_vpc.this.id
      cidr_block              = cidrsubnet(aws_vpc.this.cidr_block, 8, count.index)
      availability_zone       = data.aws_availability_zones.azs.names[count.index]
      map_public_ip_on_launch = true
    
      tags = {
        "Name" = format(
          "${var.environment}-pub-subnet-%s",
          substr(data.aws_availability_zones.azs.names[count.index], -1, 1),
        )
      }
    }
    
    # 퍼블릭 서브넷용 라우팅 테이블
    resource "aws_route_table" "public" {
      vpc_id = aws_vpc.this.id
    
      tags = {
        "Name" = "${var.environment}-pub-rtb"
      }
    }
    
    # 각각의 퍼블릭 서브넷에 위에서 생성한 라우팅 테이블 연동
    resource "aws_route_table_association" "public" {
      count = length(aws_subnet.public)
    
      subnet_id      = aws_subnet.public[count.index].id
      route_table_id = aws_route_table.public.id
    }
    
    # 퍼블릭 서브넷에 연동된 라우팅 테이블에 인터넷 게이트웨이로 가능 경로 추가
    resource "aws_route" "internet" {
      route_table_id         = aws_route_table.public.id
      gateway_id             = aws_internet_gateway.this.id
      destination_cidr_block = "0.0.0.0/0"
    }
    
    # NAT 게이트웨이에 부여할 EIP
    resource "aws_eip" "nat" {
      count = var.create_private_subnet ? 1 : 0
    
      domain = "vpc"
    }
    
    # NAT 게이트웨이
    resource "aws_nat_gateway" "this" {
      count = var.create_private_subnet ? 1 : 0
    
      allocation_id = aws_eip.nat[0].id
      subnet_id     = aws_subnet.public[0].id
    
      tags = {
        "Name" = "${var.environment}-nat-gw"
      }
    }
    
    # 프라이빗 서브넷
    resource "aws_subnet" "private" {
      count = var.create_private_subnet ? length(data.aws_availability_zones.azs.names) : 0
    
      vpc_id            = aws_vpc.this.id
      cidr_block        = cidrsubnet(aws_vpc.this.cidr_block, 8, count.index + 10)
      availability_zone = data.aws_availability_zones.azs.names[count.index]
    
      tags = {
        "Name" = format(
          "${var.environment}-pri-subnet-%s",
          substr(data.aws_availability_zones.azs.names[count.index], -1, 1),
        )
      }
    }
    
    # 프라이빗 서브넷용 라우팅 테이블
    resource "aws_route_table" "private" {
      count = var.create_private_subnet ? 1 : 0
    
      vpc_id = aws_vpc.this.id
    
      tags = {
        "Name" = "${var.environment}-pri-rtb"
      }
    }
    
    # 각각의 프라이빗 서브넷에 위에서 생성한 라우팅 테이블 연동
    resource "aws_route_table_association" "private" {
      count = var.create_private_subnet ? length(aws_subnet.private) : 0
    
      subnet_id      = aws_subnet.private[count.index].id
      route_table_id = aws_route_table.private[0].id
    }
    
    # 프라이빗 서브넷에 연동된 라우팅 테이블에 NAT 게이트웨이로 가능 경로 추가
    resource "aws_route" "nat" {
      count = var.create_private_subnet ? 1 : 0
    
      route_table_id         = aws_route_table.private[0].id
      nat_gateway_id         = aws_nat_gateway.this[0].id
      destination_cidr_block = "0.0.0.0/0"
    }
  35. 인프라 변경 사항 확인 - 변수를 입력하라는 프롬프트가 나오면 원하는 값을 입력

    terraform plan
  36. 변수를 지정하고 인프라 변경 사항 확인

    terraform plan \
    --var="environment=test" \
    --var="vpc_cidr=10.10.0.0/16" \
    --var="create_private_subnet=true"
  37. 인프라 변경 사항 반영

    terraform apply \
    --var="environment=test" \
    --var="vpc_cidr=10.10.0.0/16" \
    --var="create_private_subnet=true" \
    --auto-approve
  38. 리소스 삭제

    terraform destroy \
    --var="environment=test" \
    --var="vpc_cidr=10.10.0.0/16" \
    --var="create_private_subnet=true" \
    --auto-approve

EC2 인스턴스 생성

  1. Terraform 코드를 저장할 디렉토리 생성

    cd ~/environment && mkdir -p terraform/ec2 && cd terraform/ec2
  2. Terraform Provider 설정을 포함하는 파일 생성

    cat <<EOF | tee provider.tf
    terraform {
      required_providers {
        aws = {
          source = "hashicorp/aws"
          version = "5.45.0"
        }
      }
    }
    EOF
  3. Terraform 환경 생성

    terraform init
  4. AWS 리소스 생성에 사용할 Terraform 코드를 저장할 파일 생성

    touch main.tf
  5. VPC를 생성하는 코드 블록 추가

    module "network" {
      source = "../network"
    
      environment = "demo"
      vpc_cidr    = "10.100.0.0/16"
    }
  6. 인프라 변경 사항 확인

    terraform plan
  7. Terraform 환경 업데이트 - 모듈 설치

    terraform init
  8. 해당 문서를 통해서 Terraform에서 버전을 명시하는 방법 확인

  9. 네트워크 모듈에 명시한 Terraform Provider 설정을 아래와 같이 수정

    terraform {
      required_providers {
        aws = {
          source = "hashicorp/aws"
          version = ">= 5.35.0"
        }
      }
    }
  10. Terraform 환경 업데이트 재시도 - 모듈 설치

    terraform init
  11. 생성된 디렉토리 및 파일 확인

    find .
  12. 모듈 정보를 가지고 있는 파일 내용 확인

    cat .terraform/modules/modules.json | jq
  13. 인프라 변경 사항 확인

    terraform plan
  14. 인프라 변경 사항 반영

    terraform apply --auto-approve
  15. 생성된 리소스 목록 확인

    terraform state list
  16. AWS CLI를 통해서 최신 Amazon Linux 2023 AMI 검색

    aws ec2 describe-images \
    --filters Name=name,Values=al2023-ami-2023* \
    Name=virtualization-type,Values=hvm \
    Name=architecture,Values=x86_64 \
    Name=root-device-type,Values=ebs \
    --query 'sort_by(Images,&CreationDate)[-1].ImageId' \
    --output text
  17. EC2를 생성하는 코드 블록 추가

    data "aws_ami" "amazon_linux_2023" {
      most_recent      = true
      owners           = ["amazon"]
      
      filter {
        name   = "name"
        values = ["al2023-ami-2023*"]
      }
    
      filter {
        name   = "root-device-type"
        values = ["ebs"]
      }
    
      filter {
        name   = "virtualization-type"
        values = ["hvm"]
      }
      
      filter {
        name   = "architecture"
        values = ["x86_64"]
      }
    }
    
    resource "aws_instance" "web" {
      ami           = data.aws_ami.amazon_linux_2023.id
      instance_type = "t2.micro"
      subnet_id     = module.network.aws_subnet.public[0].id
    }
  18. 인프라 변경 사항 확인

    terraform plan
  19. 위에서 추가한 코드에서 subnet_id 부분을 삭제하고 아래의 코드 블록 추가

    output "network_module" {
      value = module.network
    }
  20. 인프라 변경 사항 확인

    terraform plan
  21. 네트워크 모듈 코드가 저장된 디렉토리로 이동해서 output.tf 파일을 생성하고 아래의 내용 추가

    output "public_subnet_ids" {
      value = [for subnet in aws_subnet.public : subnet.id]
    }
  22. EC2 인스턴스를 생성하는 코드 블록을 아래와 같이 수정

    resource "aws_instance" "web" {
      ami           = data.aws_ami.amazon_linux_2023.id
      instance_type = "t2.micro"
      subnet_id     = module.network.output.public_subnet_ids[0]
    }
  23. 인프라 변경 사항 확인

    terraform plan
  24. 위에서 추가한 코드에서 subnet_id 부분을 삭제하고 인프라 변경 사항 확인

    terraform plan
  25. EC2 인스턴스를 생성하는 코드 블록을 아래와 같이 수정

    resource "aws_instance" "web" {
      ami           = data.aws_ami.amazon_linux_2023.id
      instance_type = "t2.micro"
      subnet_id     = module.network.public_subnet_ids[0]
    }
  26. 아래의 코드 블록 삭제

    output "network_module" {
      value = module.network
    }
  27. 인프라 변경 사항 확인

    terraform plan
  28. 인프라 변경 사항 반영

    terraform apply --auto-approve

Module 저장소

  1. 해당 문서를 통해서 Module 저장소 목록 확인

  2. GitHub에 새로운 Git 리포지토리를 생성하고 네트워크 모듈 코드를 업로드

  3. v1.0.0 태그로 새로운 Release 생성

  4. VPC를 생성하는 코드 블록을 아래와 같이 수정

    module "network" {
      source = "github.com/youngwjung/terraform-aws-vpc?ref=v1.0.0"
    
      environment = "demo"
      vpc_cidr    = "10.100.0.0/16"
    }
  5. 인프라 변경 사항 확인

    terraform plan
  6. Terraform 환경 업데이트 - 모듈 설치

    terraform init
  7. 생성된 디렉토리 및 파일 확인

    find .
  8. 인프라 변경 사항 확인

    terraform plan
  9. 네트워크 모듈 코드가 저장된 디렉토리로 이동해서 main.tf 파일에 아래의 내용 추가

    # DB 서브넷
    resource "aws_subnet" "db" {
      count = var.create_db_subnet ? length(data.aws_availability_zones.azs.names) : 0
    
      vpc_id            = aws_vpc.this.id
      cidr_block        = cidrsubnet(aws_vpc.this.cidr_block, 8, count.index + 20)
      availability_zone = data.aws_availability_zones.azs.names[count.index]
    
      tags = {
        "Name" = format(
          "${var.environment}-db-subnet-%s",
          substr(data.aws_availability_zones.azs.names[count.index], -1, 1),
        )
      }
    }
    
    # DB 서브넷용 라우팅 테이블
    resource "aws_route_table" "db" {
      count = var.create_db_subnet ? 1 : 0
    
      vpc_id = aws_vpc.this.id
    
      tags = {
        "Name" = "${var.environment}-db-rtb"
      }
    }
    
    # 각각의 DB 서브넷에 위에서 생성한 라우팅 테이블 연동
    resource "aws_route_table_association" "db" {
      count = var.create_db_subnet ? length(aws_subnet.db) : 0
    
      subnet_id      = aws_subnet.db[count.index].id
      route_table_id = aws_route_table.db[0].id
    }
  10. 네트워크 모듈 코드가 저장된 디렉토리로 이동해서 variable.tf 파일에 아래의 내용 추가

    variable "create_db_subnet" {
      description = "DB 서브넷 생성"
      type        = bool
      default     = true
    }
  11. 변경사항을 Git 리포지토리에 반영하고 v1.0.1 태그로 새로운 Release 생성

  12. VPC를 생성하는 코드 블록을 아래와 같이 수정

    module "network" {
      source = "github.com/youngwjung/terraform-aws-vpc?ref=v1.0.1"
    
      environment = "demo"
      vpc_cidr    = "10.100.0.0/16"
    }
  13. 인프라 변경 사항 확인

    terraform plan
  14. Terraform 환경 업데이트 - 모듈 업데이트

    terraform init
  15. 인프라 변경 사항 확인

    terraform plan
  16. 인프라 변경 사항 반영

    terraform apply --auto-approve
  17. Terraform Registry에서 AWS VPC 모듈 검색

  18. VPC를 생성하는 코드 블록을 아래와 같이 수정

    module "network" {
      source = "terraform-aws-modules/vpc/aws"
      version = "5.7.1"
    
      name = "demo"
      cidr = "10.100.0.0/16"
    
      enable_nat_gateway = true
    }
  19. 인프라 변경 사항 확인

    terraform plan
  20. Terraform 환경 업데이트 - 모듈 설치

    terraform init
  21. 인프라 변경 사항 확인

    terraform plan
  22. 해당 문서에서 VPC 모듈의 Output 목록 확인

  23. EC2 인스턴스를 생성하는 코드 블록을 아래와 같이 수정

    resource "aws_instance" "web" {
      ami           = data.aws_ami.amazon_linux_2023.id
      instance_type = "t2.micro"
      subnet_id     = module.network.public_subnets[0]
    }
  24. 인프라 변경 사항 확인

    terraform plan
  25. data.tf 파일을 생성하고 아래의 코드 블록 추가

    data "aws_availability_zones" "azs" {}
  26. main.tf에 있는 아래의 코드 블록을 data.tf 파일로 이동

    data "aws_ami" "amazon_linux_2023" {
      most_recent      = true
      owners           = ["amazon"]
      
      filter {
        name   = "name"
        values = ["al2023-ami-2023*"]
      }
    
      filter {
        name   = "root-device-type"
        values = ["ebs"]
      }
    
      filter {
        name   = "virtualization-type"
        values = ["hvm"]
      }
      
      filter {
        name   = "architecture"
        values = ["x86_64"]
      }
    }
  27. VPC를 생성하는 코드 블록을 아래와 같이 수정

    module "network" {
      source = "terraform-aws-modules/vpc/aws"
      version = "5.7.1"
    
      name = "demo"
      cidr = "10.100.0.0/16"
    
      azs             = data.aws_availability_zones.azs.names
      public_subnets  = [for idx, _ in data.aws_availability_zones.azs.names: cidrsubnet("10.100.0.0/16", 8, idx)]
      
      map_public_ip_on_launch = true
    }
  28. 인프라 변경 사항 확인

    terraform plan
  29. 인프라 변경 사항 반영

    terraform apply --auto-approve
  30. Terraform Registry에서 AWS VPC 모듈 검색

  31. EC2 인스턴스를 생성하는 코드 블록을 아래와 같이 수정

    module "ec2_instance" {
      source  = "terraform-aws-modules/ec2-instance/aws"
      version = "5.6.1"
      
      subnet_id = module.network.public_subnets[0]
      
      create_iam_instance_profile = true
      
      iam_role_policies = {
        "ssm" = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
      }
    }
  32. Terraform 환경 업데이트 - 모듈 설치

    terraform init
  33. 인프라 변경 사항 확인

    terraform plan
  34. 인프라 변경 사항 반영

    terraform apply --auto-approve

Last updated