Terraform Study - w02

wdb·2023년 7월 15일

도전과제

01. 가용영역 리스트

소스코드

리전 내의 가용영역 목록을 가져오기 위해 Data Sources를 이용하였습니다. Data Sources는 테라폼 외부에서 정의된 정보를 가져오기 위해 사용합니다.

# availiability_zone.tf

data "aws_availability_zones" "available_azs" {
  state = "available"
}

Data Sources를 사용하기 위해서는 데이터 블록을 정의합니다. aws_availiability_zones는 AWS의 가용영역을 가져오는 속성입니다. state = "available"인 사용가능한 가용영역을 가져올 수 있도록 하는 인자입니다. 이 때 리전은 provider.tf 파일의 provider 블록에서 정의된 리전 정보를 이용합니다.

# output.tf

output "az_list" {
  value = data.aws_availability_zones.available_azs.names
}

output을 이용하여 데이터 블록에서 가져온 가용영역 정보를 출력해보겠습니다. tf apply 명령어를 입력하여 테라폼 상태를 업데이트하면 output이 아래와 같이 출력됩니다.

provider.tf에 정의한 서울 리전(ap-northeast-2)에서 사용가능한 가용영역의 목록이 출력된 것을 확인하였습니다.

이제 VPC를 만들겠습니다.

# vpc.tf

resource "aws_vpc" "vpc" {
  cidr_block = var.vpc_cidr

  enable_dns_support   = true
  enable_dns_hostnames = true

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

일반적으로 VPC를 만들 땐 DNS 옵션을 활성화하여 VPC 내부에 생성된 서비스의 DNS를 이용할 수 있도록 합니다. CIDR 블록은 variable.tf에서 지정한 값을 사용합니다.

다음으로 서브넷을 만들을 만듭니다. 출력된 가용영역에 서브넷을 한 개씩 만드려고 합니다.

# subnet.tf

resource "aws_subnet" "public_subnet" {
  vpc_id            = aws_vpc.vpc.id
  count             = length(data.aws_availability_zones.available_azs.names)
  cidr_block        = element(var.public_subnet_cidrs, count.index)
  availability_zone = data.aws_availability_zones.available_azs.names[count.index]

  tags = {
    Name = "${var.prefix}-public-subnet-${substr(data.aws_availability_zones.available_azs.names[count.index], -1, 0)}"
  }
}

VPC의 id를 vpc.tf에서 생성했던 vpc의 id로 설정합니다. count를 사용하여 생성할 서브넷의 수를 설정하는데, 이 때 불러왔던 가용영역의 수를 length 함수로 구합니다. count의 index를 활용하여 가용영역 리스트에서 필요한 값을 넣습니다.

02. 리소스 유형 / 이름 구분

소스코드

테라폼에서 리소스 유형이란 프로바이더에서 가져올 리소스의 종류입니다. 리소스 블록에서 aws_vpc라고 선언한다면, AWS의 VPC 리소스에 대해서 생성한다는 의미입니다. 하나의 테라폼 프로젝트에서 여러 개의 VPC 리소스를 만드는 경우도 있을 것입니다. 이때 각 VPC를 구분하려면 고유한 이름이 필요합니다. 리소스 블록에서는 리소스 유형 다음에 리소스 이름을 정의하여 테라폼 프로젝트 안에서 해당 리소스를 고유하게 구분할 수 있게 합니다.

# availiability_zone.tf

data "aws_availability_zones" "my_azs" {
  state = "available"

  filter {
    name   = "opt-in-status"
    values = ["opt-in-not-required"]
  }
}

위의 코드에서 'aws_availability_zones'와 같은 리소스 유형은 같은 리소스 종류를 정의한다면 항상 동일합니다. 하지만 'my_azs'와 같은 리소스 이름은 테라폼 프로젝트 안에서 상이해야 합니다.

03. 입력변수

소스코드

variable.tf에서 변수를 정의할 때 default라는 인수를 사용할 수 있습니다. default는 사용자가 변수 값을 별도로 입력하지 않았을 경우, 기본적으로 설정할 값을 정의하는 역할을 합니다. 만약 변수에 default 값을 정하지 않고, tfvars 파일에도 변수의 값을 입력하지 않았다면, CLI에서 입력변수로 해당 변수값을 설정해야 합니다.
provider를 설정하기 위해 아래와 같이 변수를 정의하였습니다.

# variable.tf

variable "account_profile" {}
variable "region" {}
variable "prefix" {}
...

tfvars 파일에 account_profile과 region 값만 설정하였습니다.

# terraform.tfvars

###########################################
################ Default ##################
###########################################

account_profile = "wdb"
region          = "ap-northeast-2"

terraform plan 명령어를 입력했을 때, variable.tf에서 선언은 했지만 tfvars 파일에서 값이 설정되지 않은 var.prefix는 입력변수가 되어서 CLI에서 입력을 해주어야 하는 값이 된 것을 확인할 수 있습니다.

04. 로컬변수

소스코드

로컬변수는 테라폼 프로젝트 내에서 사용되는 변수로, 주로 별도의 연산이 필요한 값들을 설정할 때 사용합니다.

# terraform.tfvars

###########################################
################## VPC ####################
###########################################

vpc_cidr            = "10.100.0.0/16"
public_subnet_cidrs = ["10.100.0.0/24", "10.100.1.0/24", "10.100.2.0/24", "10.100.3.0/24"]
availability_zones = ["a", "c"]

VPC와 서브넷을 만들기 위해 tfvars 파일에 변수값을 설정하였습니다. 서브넷은 가용영역 ap-northeast-2a와 ap-northeast-2c에만 생성하려 합니다. 편의를 위해 가용영역을 설정하는 availability_zones 변수값을 a와 c로만 입력하였습니다.
프로바이더에서 정의한 리전과 availability_zones에 설정된 a변수값만으로 ap-northeast-2a와 같은 가용영역 코드를 완성하려 합니다.

# local.tf

locals {
  az_names = formatlist("${var.region}%s", var.availability_zones)
}

local.tf에서 formatlist 함수를 이용하해 리전 코드와 availability_zones 변수를 결합한 가용영역 코드를 만들었습니다. formatlist 함수는 문자열 리스트를 인자로 받아 특정 문자열과 결합한 문자열의 목록을 반환합니다.

# subnet.tf

resource "aws_subnet" "public_subnet" {
  vpc_id            = aws_vpc.vpc.id
  count             = local.az_count
  cidr_block        = element(var.public_subnet_cidrs, count.index)
  availability_zone = local.az_names[count.index]
...
}

서브넷을 생성할 때 로컬의 az_names를 통해 결합된 가용영역 코드를 가져와 이용합니다.

05. 반복문

소스코드

terraform의 반복문 중 for_each를 이용하여 서브넷을 생성해보았습니다. 두 개의 서브넷을 만드려 합니다.

# terraform.tfvars

...
public_subnet = {
 sub-1 = {
   az   = "a"
   cidr = "10.100.0.0/24"
 }
 sub-2 = {
   az   = "c"
   cidr = "10.100.1.0/24"
 }
}

tfvars 파일에 key-value 형식인 map 형식으로 서브넷의 가용영역(az)와 CIDR 블록 값을 설정해주었습니다.

# subnet.tf

resource "aws_subnet" "public_subnet" {
  for_each = var.public_subnet

  vpc_id            = aws_vpc.vpc.id
  cidr_block        = each.value["cidr"]
  availability_zone = "${var.region}${each.value["az"]}"

  tags = {
    Name = "${var.prefix}-public-subnet-${each.value["az"]}"
  }
}

서브넷 리소스 블록에서 for_each에 map 형식으로 정의한 변수 public_subnet을 대입해줍니다. for_each에 설정된 변수는 each라는 개체에서 key와 value 속성을 이용하여 값을 가져올 수 있습니다.
each에서 key는 'sub_1'입니다. each.value에서 sub_1에서 정의된 map 형식의 값입니다. each.value 역시 map 형식이라 인덱싱을 하여 접근해야 합니다. Each.value(sub_1)에서 cidr라는 키에 설정된 값을 가져오기 위해 each.value["cidr"]를 사용합니다. 첫 번째 서브넷에 가용영역으로 설정된 값을 가져오기 위해서는 each.value["az"]를 이용하면 됩니다.
for_each를 이용하면 보다 직관적으로 같은 유형의 리소스 값을 설정하는 것이 가능해집니다.

0개의 댓글