이전 작성 글: Terraform 이란?
# 기본 문법
<BLOCK TYPE> "<BLOCK LABEL>" "<BLOCK LABEL>" {
# Block body
<IDENTIFIER> = <EXPRESSIONS> # Argument
}
# 문법 예시
resource "aws_vpc" "main" {
cidr_block = var.base_cidr_block
}
key-value
형식으로 들어갈 수 있게 됨terraform
∙ provider
∙ resource
∙ data
∙ module
∙ local
∙ variable
∙ output
_
∙ -
이렇게 4가지Tip! HCL 에서 지향하는 Style Convention
Terraform Configuration Syntax
Terraform
은 명령어를 통해 자동으로 포멧팅 가능
- 명령어:
terraform fmt -diff
- Indent 는 tab 이 아닌 two space
- Block 내에 여러 arguments 를 정의할 때는 = 을 기준으로 key와 value를 정의
- Resource 를 정의할 때는 meta-argument 들이 있는데 count ∙ for each 는 머리 부분에 위치하는 것을 선호하고 lifecycle 이나 depends on 은 하단부에 위치하는 것을 선호
.tf
파일을 작성하게 되는데 tf
파일은 HCL 문법을 따르지만 .json
확장자를 이용하여 json
으로도 이용 가능Terraform
으로 init ∙ plan ∙ apply 명령을 하게 되면 현재 사용자의 디렉토리 상에서 .tf
파일과 .tf.json
파일을 찾게 되는데 하위 디렉토리에 대해서는 탐색을 하지 않음tf
파일을 작성할 때는 인코딩을 항상 UTF-8 로 설정해야 함tf
파일을 가지고 있는 디렉토리를 Module 이라고 부름# 구조 예시
|-- terraform
| |-- a
| |-- b
| |-- c
terraform
디렉토리에 a
∙b
∙c
모듈 디렉토리가 있고 c
모듈이 a
∙b
모듈을 가져다 쓴다고 했을 때 c
위치에서 terraform apply 를 수행하면 c
라는 워크스페이스는 Root Module 이 되고 c
가 사용하는 a
∙b
모듈은 Child Module 이 됨c
에서 terraform apply 하는 것이 아니라 a
에서 terraform apply 를 한다면 a
가 Root Modul 이 됨# 예시
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_iam_user" "user_1" {
name = "user-1"
}
resource "aws_iam_user" "user_2" {
name = "user-2"
}
resource "aws_iam_user" "user_1" {
name = "user-2"
}
output "user_arns" {
value = [
aws_iam_user.user_1.arn,
aws_iam_user.user_2.arn,
aws_iam_user.user_3.arn,
]
}
count.index
를 사용하여 인덱스 정보를 가져 올 수 있음resource
∙ module
∙ data
에서 사용 가능# count 적용
resource "aws_iam_user" "count" {
count = 3 # meta-argument
name = "count-user-${count.index}"
}
output "count_user_arns" {
value = aws_iam_user.count.*.arn
}
toset
을 사용each
∙ key
∙ each.value
로 데이터에 접근 할 수 있음# set 적용
resource "aws_iam_user" "for_each_set" {
for_each = toset([
"for-each-set-user-1",
"for-each-set-user-2",
"for-each-set-user-3",
])
name = each.key
}
output "for_each_set_user_arns" {
value = values(aws_iam_user.for_each_set).*.arn
}
each.key
∙ each.value
값이 생성되어서 활용 가능# map 적용
resource "aws_iam_user" "for_each_map" {
for_each = {
cab = {
level = "low"
manager = "man1"
}
bob = {
level = "mid"
manager = "man2"
}
louis = {
level = "high"
manager = "man2"
}
}
name = each.key
tags = each.value
}
data
∙ resource
∙ module
에서만 사용 가능한 표현식# 기본 문법
[for <ITEM> in <LIST> : <OUTPUT>]
[for k, v in var.map : length(k) + length(v)]
# 문법 예시
variable "names" {
description = "A list of names"
type = list(string)
default = ["gasida", "akbun", "fullmoon"]
}
output "upper_names" {
value = [for name in var.names : upper(name)]
}
# 기본 문법
condition ? true_val : false_val
# 문법 예시
resource "aws_iam_user_policy_attachment" "gurumee_cloudwatch_full_access" {
count = var.give_gurumee_cloudwatch_full_access ? 1 : 0
user = aws_iam_user.example.0.name
policy_arn = aws_iam_policy.cloudwatch_full_access.arn
}
resource "aws_iam_user_policy_attachment" "gurumee_cloudwatch_read_only" {
count = var.give_gurumee_cloudwatch_full_access ? 0 : 1
user = aws_iam_user.example.0.name
policy_arn = aws_iam_policy.cloudwatch_read_only.arn
}
# 기본 문법
%{ if <CONDITION> }<TRUEVAL>%{ else }<FALSEVAL>%{ endif }
# 문법 예시
variable "names" {
description = "Names to render"
type = list(string)
default = ["gasida", "akbun", "fullmoon"]
}
output "for_directive" {
value = "%{ for name in var.names }\${name}, %{ endfor }"
}
output "for_directive_index" {
value = "%{ for i, name in var.names }(\${i}) \${name}, %{ endfor }"
}
output "for_directive_index_if" {
value = <<EOF
%{ for i, name in var.names }
\${name}%{ if i < length(var.names) - 1 }, %{ endif }
%{ endfor }
EOF
}
Outputs:
for_directive = "gasida, akbun, fullmoon, "
for_directive_index = "(0) gasida, (1) akbun, (2) fullmoon, "
for_directive_index_if = <<EOT
gasida,
akbun,
fullmoon
Tip! 추가 내용
# 기본 문법
module "<NAME>" {
source = "<MODULE_PATH>"
cluster_name = "cluster-a"
}
# 문법 예시
resource "aws_security_group" "elb-sg" {
name = "${var.cluster_name}-elb-sg"
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
var.cluster_name
과 같이 모듈을 사용하는 곳에서 설정한 변수를 받아와 리소스를 생성할 수 있음# 문법 예시
variable "cluster_name" {
default = "cluster_default"
}
# 문법 예시
output "elb_sg_name" {
value = aws_secruity_group.elb-sg.name
}
module.<MODULE_NAME>.elb_sg_name
으로 output 을 받아올 수 있음