Terraform 을 사용한 Iac ( Infrastructure as a code )

1. Terraform 이란?

오늘날 기술의 빠른 변화와 함께 클라우드 인프라의 관리와 배포는 더욱 복잡해지고 있습니다. 이러한 환경에서 Terraform은 혁신적인 해결책을 제시합니다. Terraform은 HashiCorp에 의해 개발된 오픈 소스 Infrastructure as Code (IaC) 도구로, 인프라를 이루는 서버, 미들웨어 그리고 서비스 등 인프라 구성요소들을 코드를 통해 구축하는 것을 의미 합니다.

 

2. Terraform 구성 요소

– Provider

Provider는 Terraform이 리소스를 관리할 수 있도록 하는 플러그인입니다. AWS, Google Cloud Platform, Azure 등 다양한 클라우드 제공업체뿐만 아니라, GitHub이나 Docker와 같은 서비스도 지원합니다. Provider를 통해 Terraform은 해당 서비스의 API와 통신하여 인프라 상태를 확인하고 변경사항을 적용합니다.

– Resource

Resource는 Terraform에서 관리하는 기본 구성 요소입니다. 가상 머신, 네트워크 인터페이스, 로드 밸런서 등 인프라의 실제 구성 요소를 정의합니다. Terraform 코드 내에서 리소스 블록을 통해 이러한 인프라 구성 요소를 선언적으로 정의하고, Terraform이 이를 실제 클라우드 환경에 적용하도록 합니다.

– State

State는 Terraform이 관리하는 인프라의 현재 상태를 추적하는 파일입니다. Terraform은 이 state 파일을 참조하여 인프라의 실제 상태와 코드의 목표 상태 간의 차이를 파악하고, 필요한 변경사항을 적용합니다. State 파일은 매우 중요하므로 안전하게 관리되어야 합니다.

– Output

Output 변수는 Terraform 모듈의 출력값을 정의합니다. 예를 들어, 생성된 리소스의 IP 주소나 도메인 이름과 같은 중요 정보를 출력 변수로 지정할 수 있습니다. 이를 통해 Terraform 코드의 한 부분에서 생성된 정보를 다른 부분이나 외부에서 참조할 수 있습니다.

– Module

Module은 Terraform 코드를 재사용 가능한 단위로 묶는 방법입니다. 모듈은 특정 인프라 구성 요소나 서비스를 캡슐화하여 다른 Terraform 프로젝트에서 재사용할 수 있도록 합니다. 모듈을 사용하면 코드의 재사용성을 높이고, 관리를 용이하게 할 수 있습니다.

– Remote

Remote는 Terraform 상태 파일을 원격으로 관리할 수 있도록 하는 기능입니다. 일반적으로 Terraform Cloud나 Terraform Enterprise, S3 버킷, Google Cloud Storage와 같은 서비스를 사용하여 상태 파일을 안전하게 저장하고, 팀 내에서 상태 파일을 공유할 수 있습니다. 원격 상태 관리를 통해 여러 사람이 동일한 Terraform 구성을 안전하게 협업할 수 있습니다.

 

3. Terraform 기본 명령어

– terraform init

Terraform 프로젝트를 초기화하는 데 사용됩니다. 이 명령어는 Terraform 구성 파일이 있는 디렉토리에서 처음 한 번 실행되고,
필요한 Terraform Provider Plug-in 을 다운로드하고, 백엔드를 구성합니다.

– terraform plan

실행 계획을 생성하여 어떤 변경이 인프라에 적용될지 미리 보여주고,
현재 인프라 상태와 구성 파일을 비교하여 실제로 변경될 사항을 보여줍니다.

– terraform apply

terraform plan에서 생성된 실행 계획에 따라 실제 변경을 적용하고, 인프라를 생성, 수정, 삭제하는 데 사용됩니다.
실행 전에 변경 사항을 사용자에게 다시 한 번 확인시키고, 사용자의 승인을 받아 진행합니다.

– terraform import

이미 존재하는 인프라를 Terraform 관리 하에 가져오는 데 사용됩니다. 이 명령어는 Terraform이 아닌 다른 방법으로 생성된 리소스를 Terraform 구성에 연결할 때 유용합니다.

– terraform state

Terraform 상태 파일을 관리하는 데 사용되는 명령어 모음입니다.
예를 들어, terraform state list는 관리 중인 리소스의 목록을 보여주고, terraform state show는 특정 리소스의 상태 정보를 보여줍니다.

– terraform destroy

Terraform으로 관리되는 모든 리소스를 삭제합니다. 구성 파일에 정의된 모든 인프라를 제거하며, 이 때 상태 파일도 업데이트 됩니다.
이 명령어는 주의해서 사용해야 합니다, 왜냐하면 적용된 인프라를 모두 제거하기 때문입니다.

 

4. Terraform 으로 AWS 인프라 생성

앞서 설명한 개념들을 바탕으로 Terraform 으로 AWS 인프라를 생성해 보겠습니다. 본 실습에서는 Terraform을 사용하기 위해 미리 세팅된 서버에서 진행 합니다.

4.1 Terraform Provider.tf 작성

현재 아무런 코드를 작성하지 않았기 때문에, 아무것도 실행이 되질 않습니다. Terraform 코드를 실행하기 위해 먼저 Provider.tf 파일을 작성합니다.

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

# Configure the AWS Provider
provider "aws" {
  region = "ap-northeast-2"
}
  • required_providers 블록은 사용할 프로바이더와 해당 버전을 Terraform에 알립니다. 이 예제에서는 AWS 프로바이더를 사용하며, 버전은 5.x 버전대를 사용하도록 설정되어 있습니다.
  • source는 프로바이더의 소스를 지정합니다. hashicorp/aws는 Terraform Registry에 등록된 공식 AWS 프로바이더입니다.
  • version은 사용할 프로바이더의 버전을 지정합니다. “~> 5.0″은 메이저 버전은 5로 고정하고, 마이너 버전은 가장 최신을 사용하겠다는 의미입니다.
  • provider "aws" 블록은 AWS 프로바이더에 대한 구성을 포함합니다. 여기서는 사용할 AWS 리전을 ap-northeast-2(서울)로 설정합니다.
 
4.2 Terraform init 실행

terraform init을 실행하면 .terraform 폴더가 생성되고, 이 폴더에 실제 aws의 API들을 호출하기 때문에, 라이브러리가 필요한데, 라이브러리를 다운받는것도 terraform init의 역할입니다.

4.3 S3 Bucket 생성

이 코드는 "terraform-test-bucket-kyobo" 라는 이름의 S3 버킷을 생성하며, 또한, tags를 사용하여 버킷에 추가 메타데이터를 제공합니다.

terraform plan 명령어를 치면 S3 버킷이 하나 생성되는것을 확인할 수 있고 이제 terraform apply 명령어를 실행하여 실제로 리소스가 배포 되는지 확인합니다.

terraform apply 명령어가 실행되고 실제 AWS S3 리소스가 생성되었는지 확인합니다.

“terraform-test-bucket-kyobo” S3 Bucket이 생성된 걸 확인할 수 있습니다.

4.4 VPC 생성

위와 같이 코드를 작성하여 이제 10.100.0.0/16 VPC CIDR를 가진 “main-vpc” 를 생성 해보도록 하겠습니다.

terraform apply를 실행시켜 실제 VPC 가 생성 되었는지 확인 합니다.

main-vpc 가 성공적으로 생성 되었습니다.

4.5 Subnet 생성
resource "aws_vpc" "main" {
  cidr_block = "10.100.0.0/16"

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

resource "aws_subnet" "public" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.100.1.0/24"
  map_public_ip_on_launch = true

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

resource "aws_subnet" "private" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.100.2.0/24"

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

output "vpc_id" {
  value = aws_vpc.main.id
}

output "public_subnet_id" {
  value = aws_subnet.public.id
}

output "private_subnet_id" {
  value = aws_subnet.private.id
}

위 테라폼 코드는 위에서 생성한 VPC에 이어서 Subnet을 생성하는 코드로 Public Subnet (10.100.1.0/24) Private Subnet (10.100.2.0/24) 을 생성합니다. Public Subnet 은 인스턴스가 퍼블릭 IP를 할당받도록 설정되어 있으며, 각각의 Subnet ID는 출력됩니다. 이제 terraform apply 를 실행하여 실제 리소스가 생성 됐는지 확인합니다.

Subnet이 성공적으로 생성된 걸 확인할 수 있습니다.

4.6 Internet gateway , NAT Gateway 생성

이제 서브넷을 생성 했으니 아래와 같이 코드를 작성하여 리소스를 생성합니다.

resource "aws_vpc" "main" {
  cidr_block = "10.100.0.0/16"

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

resource "aws_subnet" "public" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.100.1.0/24"
  map_public_ip_on_launch = true

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

resource "aws_subnet" "private" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.100.2.0/24"

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

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

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

resource "aws_route_table" "public" {
  vpc_id = aws_vpc.main.id

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

  tags = {
    Name = "public-rt"
  }
}

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

resource "aws_eip" "nat" {
  domain = "vpc"
}

resource "aws_nat_gateway" "main" {
  allocation_id = aws_eip.nat.id
  subnet_id     = aws_subnet.public.id

  tags = {
    Name = "main-nat"
  }
}

resource "aws_route_table" "private" {
  vpc_id = aws_vpc.main.id

  route {
    cidr_block = "0.0.0.0/0"
    nat_gateway_id = aws_nat_gateway.main.id
  }

  tags = {
    Name = "private-rt"
  }
}

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

output "vpc_id" {
  value = aws_vpc.main.id
}

output "public_subnet_id" {
  value = aws_subnet.public.id
}

output "private_subnet_id" {
  value = aws_subnet.private.id
}

output "internet_gateway_id" {
  value = aws_internet_gateway.main.id
}

output "nat_gateway_id" {
  value = aws_nat_gateway.main.id
}
  • 위 코드는 다음과 같은 리소스를 추가로 생성합니다

    인터넷 게이트웨이 (aws_internet_gateway) 생성

    퍼블릭 서브넷용 라우트 테이블 (aws_route_table), 인터넷 게이트웨이를 통해 인터넷 접근을 가능하게 설정

퍼블릭 서브넷에 라우트 테이블 연결 (aws_route_table_association)

NAT 게이트웨이 (aws_nat_gateway), 퍼블릭 서브넷에 연결된 탄력적 IP (aws_eip) 사용

프라이빗 서브넷용 라우트 테이블 (aws_route_table), NAT 게이트웨이를 통해 인터넷 접근을 가능하게 설정

프라이빗 서브넷에 라우트 테이블 연결 (aws_route_table_association)

terraform apply 를 실행하여 실제 리소스가 생성 됐는지 확인 합니다.

– Internet gateway 생성 확인
퍼블릭 서브넷용 라우트 테이블 (aws_route_table), 인터넷 게이트웨이를 통해 인터넷 접근을 가능하게 설정

– 퍼블릭 서브넷에 라우트 테이블 연결 (aws_route_table_association)
– NAT 게이트웨이 (aws_nat_gateway), 퍼블릭 서브넷에 연결된 탄력적 IP (aws_eip) 사용
– 프라이빗 서브넷용 라우트 테이블 (aws_route_table), NAT 게이트웨이를 통해 인터넷 접근을 가능하게 설정

– 프라이빗 서브넷에 라우트 테이블 연결 (aws_route_table_association)

5. 마무리
– DevOps에서 테라폼(Terraform) 사용 및 관리 가이드

위 예제 코드에서는 AWS VPC, 퍼블릭 서브넷, 프라이빗 서브넷, 인터넷 게이트웨이, NAT 게이트웨이를 테라폼을 사용해 생성하는 방법을 보여줍니다.

테라폼을 사용하면 인프라를 코드로 관리하여 효율적이고 일관된 인프라 배포가 가능합니다. 테라폼의 강력한 기능을 활용하여 인프라를 자동화하고, 코드 리뷰 및 CI/CD 파이프라인을 통해 변경 사항을 관리함으로써 안정적이고 재현 가능한 인프라 환경을 제공할 수 있습니다.

댓글 달기

이메일 주소는 공개되지 않습니다. 필수 항목은 *(으)로 표시합니다