
조건문 사용
CONDITION ? TRUEVAL : FALSEVAL
예시:
resource "aws_instance" "myinstance" {
count = "${var.env=="prod" ? 2 : 1}"
}
module "vpc-prod" {
source = "terraform-aws-modules/vpc/aws"
version = "5.19.0"
name = "vpc-prod"
cidr = "10.0.0.0/16"
azs = ["${var.AWS_REGION}a", "${var.AWS_REGION}b", "${var.AWS_REGION}c"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]
enable_nat_gateway = false
enable_vpn_gateway = false
tags = {
Terraform = "true"
Environment = "prod"
}
}
module "vpc-dev" {
source = "terraform-aws-modules/vpc/aws"
version = "5.19.0"
name = "vpc-dev"
cidr = "10.0.0.0/16"
azs = ["${var.AWS_REGION}a", "${var.AWS_REGION}b", "${var.AWS_REGION}c"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]
enable_nat_gateway = false
enable_vpn_gateway = false
tags = {
Terraform = "true"
Environment = "dev"
}
}
terraform-aws-modules/vpc/aws를 사용해서 모듈을 사용해 쉽게 VPC를 만들수 있다.data "aws_ami" "ubuntu" {
most_recent = true
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
owners = ["099720109477"] # Canonical
}
resource "aws_instance" "example" {
ami = data.aws_ami.ubuntu.id
instance_type = "t2.micro"
# the VPC subnet
subnet_id = var.ENV == "prod" ? module.vpc-prod.public_subnets[0] : module.vpc-dev.public_subnets[0]
# the security group
vpc_security_group_ids = [var.ENV == "prod" ? aws_security_group.allow-ssh-prod.id : aws_security_group.allow-ssh-dev.id]
# the public SSH key
key_name = aws_key_pair.mykeypair.key_name
}
subnet_id : 변수가 prod와 같아서 참이면 vpc-pro.public subnets 첫번째 값을 할당하고 거짓이면 vpc-dev.public_subnet 첫번째 값을 할당 vpc_security_group_ids : 변수 값에 따라 보안 정책 할당Terraform 리소스 built-in function 사용할 수 있도록 지원한다. index(list, elem), join(delim, list) 등등.. 이름을보면 용도를 대충 유추할 수 있는 빌트인함수들이다.
Terraform 0.12버전이후 부터 map,list 같은 함수는 가독성 때문에 없어지고 다른 형태의 쓰임새로 대체되었다.
Terraform console.exe 다운로드 후 console연결 이후 빌트인함수들을 사용
Terraform variable 은 아래와 같이 type이랑 default 변수에 값을 넣을 수 있다.
default가 없는 경우 terraform apply -var="map1={...}" 명령어 입력 또는 .tfvars 파일에 따로 설정해줘야 한다.
그래서 API Key, 프로젝트 별 고유이름 등 보안을 신경써야하는 경우 default를 생략하고 직접 입력한다.
vars.tf
variable "AWS_REGION" {
type = string
default = "eu-west-1"
}
variable "project_tags" {
type = map(string)
default = {
Component = "Frontend"
Environment = "Production"
}
}
ebs.tf
resource "aws_ebs_volume" "example" {
availability_zone = "eu-west-1a"
size = 8
tags = {for k, v in merge({ Name = "Myvolume" }, var.project_tags): k => lower(v)}
}
=> : HCL for문 화살표 연산자로 왼쪽의 값을 오른쪽의 형태로 변환해서 Mapping 하겠다는 의미: 기준 왼쪽 입력, 오른쪽 출력terraform plan 입력 출력 결과 일부
"Name"="myvolume" VALUE는 소문자로 치환 후 추가확인Terraform에서 dynamic 블록을 사용해 코드를 효율적으로 줄일 수 있다.
똑같은 설정을 여러 번 복사, 붙여넣기 하는 대신 리스트를 돌면서 자동으로 설정해주는 반복문을 사용할수있다.
사용예시1
resource "aws_security_group" "example" {
name = "example" # can use expressions here
dynamic "ingress" {
for_each = [22, 443]
content {
from_port = ingress.value
to_port = ingress.value
protocol = "tcp"
}
}
}
for_each 리스트에 있는 값이 content블록에 작성된 ingress.value 에 반복되어 설정된다.사용예시2
보통 값을 for_each에 직접 설정하기보다 별도 variable를 미리선언 후 KEY:VALUE형태로 사용한다.
variable "ports" {
type = map(list(string))
default = {
"22" = [ "127.0.0.1/32", "192.168.0.0/24" ]
"443" = [ "0.0.0.0/0" ]
}
}
resource "aws_security_group" "example" {
name = "example" # can use expressions here
dynamic "ingress" {
for_each = var.ports
content {
from_port = ingress.key
to_port = ingress.key
cidr_blocks = ingress.value
protocol = "tcp"
}
}
}
실무에서는 개발과 운영환경은 분리해서 terraform구조를 만들어서 관리한다. multiple AWS accounts으로 개발/운영 계정을 따로 관리하는게 가장 좋다.
하나의 계정만 사용이 가능하다면 위와 같은 구조에서 각각 다른 디렉터리에서 terraform apply 수행으로 변수값에 따라 인스턴스를 생성 조건을 다르게 할 수 있다.





Terraform은 provider dependency lockfile 을 0.14부터 사용한다. 해당 파일은 terraform init 할 때 terraform.lcok.hcl 명으로 생각성된다.
해당 파일에 providers와 modules의 버전이 기록되서 lockfile을 git에 commit해서 버전 관리를 해야하고 해당 파일 기준으로 롤백이나 자동화 운영을 할 수 있다. lockfile은 또한 체크섭을 따로 저장해서 아카이브를 다운로드를 받을 때 무결성을 확인할 수 있다.
Terraform에서 provider 정보를 변경하는 경우 Terraform lock파일이 업데이트된다.
terraform state 명령어로 state파일을 조작하는 방법
| 명령어 | Description |
|---|---|
| terraform state list | state 조회 |
| terraform state mv | 상태안에서 이동 또는 이름명 수정 |
| terraform state pull | output을 stdout하거나 현재 state를 pull |
| terraform state push | local file을 push해서 state를 덮어씀 |
| terraform state replace-provider | state 파일에 provider 정보를 교체 |
| terraform state rm | state로부터 item을 삭제 |
| terraform state show | state의 item 조회 |
State 조작할 때의 몇가지 use cases
terraoform state 파일을 좀 더 보기쉽게 커맨드를 사용할 수 있다.
먼저 terraform state list 입력 후 출력되는 파라미터를 terraform state show [parameter] 명령어로 조회 시 다른 리소스에서 사용할 수 있는 속성들을 얻을 수 있다.
만약 리소스 파라미터이름을 변경하고 (ex: "aws_ssm_parameter" "myparameter" -> "myparameter2") terraform apply 명령어를 실행하면 기존 myparameter는 삭제되고 myparameter2가 새로 생성된다.
terraform state mv aws_ssm_parameter.myparameter aws_ssm_parameter.myparameter2 명령어 입력하면 기존 오브젝트의 이름이 삭제없이 변경된다.
Packer는 AMI를 생성하는 도구인데 인스턴스에서 소프트웨어를 프로비저닝할때 이전에는 테라폼을 쉘 명령어와 셰프와 함께 사용했지만 Packer로 대체해서 사용이 가능하다.
Packer
Intergrating terraform and packer within your workflow
DevOps using terraform
