[Terraform] Variable + foreach 사용법

# 0. 목적

  • 테라폼의 Variable 모듈을 사용하여 어떤 식으로 변수화를 진행할 수 있을지를 확인하고, 확장을 해본다.
  • Official AWS Provider를 사용하여 VPC & Public Subnet & Private Subnet을 순차적으로 올려보고, 변수화를 진행한다.
  • 확장 가능성을 확인해본다.
  • 여러개를 한번에 프로비저닝해본다.
  • 코드 위주로 작성한다.

진행 환경

  • MacOS M1 
  • terraform version: v1.5.7
  • aws provider: 5.17.0
  • AWS: 2.13.21
  • Python: 3.11.5
  • aws configure 미리 설정 후 진행(Access & Secret Key)

# 1. Variable 선언

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "5.17.0"
    }
  }
}
variable "user_title" {
  type    = string
  default = "cw2"
}
resource "aws_vpc" "vpc" {
  cidr_block           = "10.10.0.0/16"
  enable_dns_hostnames = true

  tags = {
    Name        = "${var.user_title}-vpc"
    Terraform   = "true"
    Environment = "dev"
  }
}

resource "aws_subnet" "public_sn1" {
  vpc_id                  = aws_vpc.vpc.id
  cidr_block              = "10.10.10.0/24"   
  availability_zone       = "ap-northeast-1a" 
  map_public_ip_on_launch = true              
  tags = {
    Name = "${var.user_title}-public-sn"
  }
}
resource "aws_subnet" "private_sn1" {
  vpc_id                  = aws_vpc.vpc.id
  cidr_block              = "10.10.11.0/24"   
  availability_zone       = "ap-northeast-1a" 
  map_public_ip_on_launch = false             
  tags = {
    Name = "${var.user_title}-private-sn1"
  }
}

위의 테라폼 코드를 통해서 cw2-vpc, cw2-public-sn, cw2-private-sn1 서브넷이 프로비저닝 된다.

"user_title"을 통해서 테라폼 변수를 선언하고, default 값으로 cw2 설정했다. 변수 타입은 문자열이므로 string.

이를 사용하기 위해서 terraform apply를 실행하면, 변수의 값은 default이 사용된다.


# 2. 사용법

단순히 기본 값으로 쓸거면, 변수화를 진행할 이유가 없다.

변수를 받아 동적으로 프로비저닝을 하기 위해선, terraform apply 시 아래와 같은 태그를 붙여 변수의 값을 지정할 수 있다.

terraform apply -var="[정의된 변수]=[사용자 입력 값]"

이를 적용해본 결과는 아래와 같다.

--auto-approve는 사용자의 입력(yes or no) 없이 apply를 실행시켜주는 옵션
중략 후 성공한 결과
프로비저닝된 VPC, Subnet 2개

kakao란 변수로 user_title 값을 설정했으므로 해당 부분이 적용되어 프로비저닝 되었음을 확인할 수 있다.

 


# 3. 활용하기

위의 사용법에서 조금 더 나아가 다른 부분까지 변수화를 진행해보자. 예를 들어, 서브넷의 가용 영역도 별도로 받고, VPC의 Network 영역을 받아서 Subnet에도 적용을 시켜본다.

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "5.17.0"
    }
  }
}

variable "user-title" {
  type    = string
  default = "cw2"
}

variable "vpc-cidr" {
  type    = string
  default = "10.10.0.0/16"
}

variable "subnet-az" {
  type    = string
  default = "a"
}

resource "aws_vpc" "vpc" {
  cidr_block           = var.vpc-cidr
  enable_dns_hostnames = true

  tags = {
    Name        = "${var.user-title}-vpc"
    Terraform   = "true"
    Environment = "dev"
  }
}

resource "aws_subnet" "public_sn1" {
  vpc_id                  = aws_vpc.vpc.id
  cidr_block              = "${substr(var.vpc-cidr, 0, 5)}.10.0/24"
  availability_zone       = "ap-northeast-1${var.subnet-az}"
  map_public_ip_on_launch = true
  tags = {
    Name = "${var.user-title}-public-sn1"
  }
}

resource "aws_subnet" "private_sn1" {
  vpc_id                  = aws_vpc.vpc.id
  cidr_block              = "${substr(var.vpc-cidr, 0, 5)}.11.0/24"         
  availability_zone       = "ap-northeast-1${var.subnet-az}" 
  map_public_ip_on_launch = false
  tags = {
    Name = "${var.user-title}-private-sn1"
  }
}

이번에는 총 3개의 변수를 사용했다. user-title, vpc-cidr, subnet-az

그리고 해당 변수들을 필요한 부분에 적용시켰고, subnet의 cidr_block의 경우는 테라폼 자체 함수를 통해서 문자열을 잘라 넣어서 네트워크 영역을 나눠 사용했다.

 

변수를 동적으로 적용하는 법은 아래와 같다.

terraform apply --auto-approve -var="user-title=test" \
-var="vpc-cidr=10.10.0.0/16" -var="subnet-az=d"

여기서는 output까지 지정해서 제대로 올라갔는지 확인을 했다(코드에선 빠졌음).
프로비저닝된 test 환경

이번에는 test라는 공통된 이름을 사용했고 cidr 및 Subnet의 가용 영역 또한 동적으로 설정했다.


# 4. 파일을 통해 변수 관리

테라폼에서는 파일을 통해 변수를 관리 및 사용하는 것이 가능하다.
terraform은 `.tfvars` 확장자 파일로 변수 값을 정의해놓을 수 있다.
즉, 코드를 다 짜놓으면 이 부분만 건드려서 프로비저닝 하는 것이 가능하다.

 

아래의 `terraform.tfvars`을 정의하고 이전에 사용했던 테라폼 코드를 동작시켜본다.

user-title = "s"
vpc-cidr = "10.11.0.0/16"
subnet-az = "c"
`terraform apply -var-file="terraform.tfvars"


# 5. 환경변수로 테라폼 변수 사용

테라폼에서는 환경변수를 통해 변수를 입력받을 수 있다.

이를 위해선 'TF_VAR_' 접두사를 붙여서 환경변수를 선언해야 한다.

Linux & MacOS의 경우 `export TF_VAR_example_var="사용자_지정_값"` 으로 환경변수 선언이 가능하다.

간단하게 사용 가능하다.


# 6. 한번에 여러 개 프로비저닝하기

테라폼과 aws Provider에서 이를 위해서 count 또는 for_each 를 사용할 수 있다. with variable

1. count 사용

variable "subnet_count" {
  type    = number
  default = 3
}

resource "aws_subnet" "example_subnet" {
  count = var.subnet_count

  vpc_id     = aws_vpc.nba-vpc.id
  cidr_block = "10.10.${count.index}.0/24"
}

-> main.tf

 

이렇게 subnet_count 변수의 값을 통해서 그 개수만큼의 서브넷을 생성할 수 있다. VPC의 CIDR이 10.10.*.*/16은 된다는 가정

이렇게 프로비저닝을 하면, subnet-0(10.10.0.0/24), subnet-1(10.10.1.0/24), subnet-2(10.10.2.0/24) 서브넷이 만들어진다.

2. for_each 사용

subnets = {
  subnet1 = {
    cidr_block = "10.10.1.0/24"
    name       = "Subnet 1"
  }
  subnet2 = {
    cidr_block = "10.10.2.0/24"
    name       = "Subnet 2"
  }
  subnet3 = {
    cidr_block = "10.10.3.0/24"
    name       = "Subnet 3"
  }
}

-> terraform.tfvars

resource "aws_subnet" "example_subnet" {
  for_each = var.subnets

  vpc_id     = aws_vpc.nba-vpc.id
  cidr_block = each.value.cidr_block

  tags = {
    Name = each.value.name
  }
}

-> main.tf

 

이렇게 사용하면 각각 subnet-1(10.10.1.0/24), subnet-2(10.10.2.0/24), subnet-23(10.10.3.0/24)으로 서브넷 3개가 생성된다.

3. EC2 + for_each

variable "ec2_instances" {
  type = map(object({
    instance_type = string
    ami           = string
  }))
  default = {
    instance1 = {
      instance_type = "t2.micro"
      ami           = "ami-0123456789abcdef0"
    }
    instance2 = {
      instance_type = "t2.small"
      ami           = "ami-0123456789abcdef1"
    }
    instance3 = {
      instance_type = "t2.medium"
      ami           = "ami-0123456789abcdef2"
    }
  }
}

resource "aws_instance" "example_instance" {
  for_each = var.ec2_instances

  ami           = each.value.ami
  instance_type = each.value.instance_type
}

이렇게 EC2를 띄울 때도 변수를 적용할 수 있다.

728x90
반응형