Terraform

Terraform(테라폼) 으로 AWS 리소스 프로비저닝하기

이번 포스팅에서는 Terraform을 사용하여 AWS 리소스를 프로비저닝하는 방법에 대해 다루겠습니다.

기본적인 AWS 리소스 생성 예제부터 실제 활용 사례까지 단계적으로 소개하고,

실습 과정을 통해 직접 따라해볼 수 있습니다. 또한 Terraform 상태 메타데이터 활용법과 모범 사례도 함께 확인하겠습니다.

참고 링크 테라폼 공식홈페이지

Terraform에서 AWS 프로바이더 사용

Terraform에서 AWS 리소스를 다루려면 AWS 프로바이더를 설정해야 합니다. provider 블록에 regionprofile(선택사항)을 지정하면 됩니다.

# provider.tf
provider "aws" {
  region  = "ap-northeast-2" # 서울 리전
  profile = "my-aws-profile" # AWS 프로파일 (선택사항)
}

기본 AWS 리소스 프로비저닝

EC2 인스턴스

# ec2.tf
resource "aws_instance" "example" {
  ami           = "ami-0e1c2f5e8fec77e67" # 아마존 리눅스 2 AMI (서울)
  instance_type = "t2.micro"              # 인스턴스 유형

  tags = {
    Name = "TerraformExample" # 인스턴스 이름 태그
  }
}

Virtual Private Cloud (VPC)

# vpc.tf 
resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16" # VPC IPv4 CIDR 블록

  tags = {
    Name = "Main VPC" # VPC 이름 태그
  }
}

보안 그룹

# security_group.tf
resource "aws_security_group" "web" {
  name        = "Allow HTTP"        # 보안 그룹 이름
  description = "Allow inbound HTTP traffic" # 설명
  vpc_id      = aws_vpc.main.id     # VPC ID

  ingress {
    from_port   = 80                # 인바운드 규칙 시작 포트
    to_port     = 80                # 인바운드 규칙 종료 포트  
    protocol    = "tcp"             # 프로토콜
    cidr_blocks = ["0.0.0.0/0"]     # 모든 IP 허용
  }

  tags = {
    Name = "Allow HTTP" # 태그
  }
}

실습

main.tf 파일에는 다음 리소스가 포함되어 있습니다

  1. Provider: AWS 프로바이더를 설정하고 서울 리전을 지정합니다.
  2. VPC: CIDR 블록이 10.0.0.0/16인 VPC를 생성합니다.
  3. Subnet: 10.0.1.0/24 CIDR 블록을 가진 퍼블릭 서브넷을 생성하고, 생성한 VPC에 연결합니다.
  4. Security Group: 인바운드 HTTP(80번 포트), SSh(22번 포트) 트래픽을 허용하는 보안 그룹을 생성하고, 생성한 VPC에 연결합니다.
  5. EC2 Instance: Amazon Linux 2 AMI를 사용하여 t2.micro 인스턴스를 생성합니다. 생성한 서브넷과 보안 그룹에 연결되며, 퍼블릭 IP 주소를 할당받습니다. 또한 사용자 데이터 스크립트를 통해 간단한 웹 서버를 실행합니다.

이 예제를 통해 Terraform으로 VPC, 서브넷, 보안 그룹, EC2 인스턴스를 함께 프로비저닝하는 방법을 확인할 수 있습니다. 실제 배포 시에는 변수 사용, 아웃풋 정의 등의 기능을 더 활용할 수 있습니다.

# main.tf

# AWS 프로바이더 설정
provider "aws" {
  region = "ap-northeast-2" # 서울 리전
}

# EC2 인스턴스 생성
resource "aws_instance" "web" {
  ami           = "ami-0e1c2f5e8fec77e67" # 아마존 리눅스 2 AMI
  instance_type = "t2.micro"              # 인스턴스 유형

  subnet_id                   = aws_subnet.public.id # 서브넷 ID
  vpc_security_group_ids      = [aws_security_group.allow_web.id] # 보안 그룹 ID
  associate_public_ip_address = true # 퍼블릭 IP 할당

  user_data = <<-EOF
    #!/bin/bash
    echo "Hello, Terraform!" > index.html
    nohup busybox httpd -f -p 80 &
    EOF

  tags = {
    Name = "Web Server" # 인스턴스 이름 태그
  }
}

# VPC 생성
resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16" # VPC IPv4 CIDR 블록

  tags = {
    Name = "Main VPC" # VPC 이름 태그
  }
}

# 서브넷 생성
resource "aws_subnet" "public" {
  vpc_id     = aws_vpc.main.id # VPC ID
  cidr_block = "10.0.1.0/24"   # 서브넷 IPv4 CIDR 블록

  tags = {
    Name = "Public Subnet" # 서브넷 이름 태그
  }
}

# 보안 그룹 생성
resource "aws_security_group" "allow_web" {
  name        = "Allow Web Traffic"
  description = "Allow inbound web traffic"
  vpc_id      = aws_vpc.main.id # VPC ID

  ingress {
    from_port   = 80  #HTTP 인바운드 규칙 시작 포트
    to_port     = 80  #HTTP 인바운드 규칙 종료 포트
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"] # 모든 IP 허용
  }

  ingress {
    from_port   = 22  #SSH 인바운드 규칙 시작 포트
    to_port     = 22  #SSH 인바운드 규칙 종료 포트
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"] # 모든 IP 허용
  }

  egress {
    from_port       = 0
    to_port         = 0
    protocol        = "-1" # 모든 프로토콜
    cidr_blocks     = ["0.0.0.0/0"]
  }

  tags = {
    Name = "Allow Web Traffic" # 보안 그룹 이름 태그
  }
}

  1. main.tf 파일에 위 코드를 입력합니다.
  2. terraform init을 실행하여 프로바이더 플러그인을 설치합니다.
  3. terraform plan을 통해 변경사항을 미리 확인합니다.
  4. terraform apply를 실행하여 리소스를 생성합니다.

이렇게 간단한 AWS 리소스 프로비저닝이 가능합니다. Terraform은 자동으로 리소스 간 의존성을 계산하고 순서를 결정합니다.

상태 메타데이터 활용

Terraform은 terraform show와 같은 명령으로 리소스 상태와 메타데이터를 확인할 수 있습니다. 리소스 의존성 관리에도 유용합니다.

aws_instance.example:
  ID = i-0c8dXXXXXX
  ...

aws_vpc.main:
  ID = vpc-0de8XXXXX
  ...

Outputs:

instance_public_ip = 1.2.3.4 # 출력값 예시

Terraform은 데이터 소스를 통해서도 AWS 리소스 정보를 참조할 수 있습니다.

# data_source.tf
data "aws_ami" "amazon_linux" {
  most_recent = true             # 최신 AMI 조회
  owners      = ["amazon"]       # 소유자 ID

  filter {
    name   = "name"              # 필터 이름
    values = ["amzn2-ami-hvm-*-x86_64-gp2"] # 필터 값
  }
}

추가 예제 및 모범 사례

AWS 리소스 연계

EC2 인스턴스를 VPC 및 보안 그룹과 연계하는 예제입니다.

# ec2_with_vpc_sg.tf
resource "aws_instance" "web" {
  ami           = data.aws_ami.amazon_linux.id
  instance_type = "t2.micro"
  vpc_security_group_ids = [aws_security_group.web.id]
  subnet_id              = aws_subnet.public.id

  user_data = <<-EOF
    #!/bin/bash
    echo "Hello, Terraform!" > index.html
    nohup busybox httpd -f -p 80 &
    EOF

  tags = {
    Name = "Web Server"
  }
}

이 예제에서는 aws_subnet, aws_internet_gateway 등의 추가 리소스가 필요합니다.

Terraform 임포트

기존 AWS 리소스를 Terraform 상태 파일에 임포트할 수 있습니다.

terraform import aws_instance.example i-0c8dXXXXXX

리소스 동기화

terraform refresh 명령으로 Terraform 상태와 실제 리소스를 동기화할 수 있습니다.

Terraform 모범 사례

  • 구조화된 코드 작성: 리소스 유형별로 파일을 나누고, 모듈을 활용합니다.
  • 버전 관리: Terraform 코드를 버전 관리 시스템(Git 등)에 저장합니다.
  • 테스트 자동화: Terraform 테스트 프레임워크를 활용하여 리소스 배포를 검증합니다.
  • 상태 파일 관리: 원격 백엔드(S3, Terraform Cloud 등)를 사용하여 상태 파일을 안전하게 관리합니다.
  • 정책 준수: AWS Identity and Access Management(IAM) 정책으로 Terraform 작업을 제어합니다.
Terraform 모듈에 대해서는 추후 별도의 포스팅에서 자세히 다룰 예정입니다. 

모듈은 Terraform 구성 요소를 재사용할 수 있게 해주어 코드 관리를 용이하게 합니다.

댓글남기기