1. 데이터 소스
Terraform 코드에서 외부 리소스의 정보를 가져와서 사용할 수 있게 해주는 구성 요소입니다.
- 외부 리소스 참조: 데이터 소스를 사용하여 외부 인프라의 정보를 읽어올 수 있습니다. 예를 들어, 이미 존재하는 AWS VPC, 서브넷, 또는 보안 그룹의 정보를 가져와서 사용할 수 있습니다.
- 동적 설정: 데이터 소스에서 가져온 값을 바탕으로 동적으로 설정을 조정할 수 있습니다. 예를 들어, 최신 AMI ID를 가져와서 EC2 인스턴스를 생성할 때 사용할 수 있습니다.
- 구성 파일 간의 의존성 관리: 서로 다른 테라폼 구성 파일 간에 데이터 소스를 통해 의존성을 관리할 수 있습니다. 다른 모듈에서 생성한 리소스의 정보를 데이터 소스를 통해 가져와서 사용할 수 있습니다
데이터 소스 구성
데이터 소스 선언은 data 블록을 사용하여 데이터 소스를 선언합니다.
# 데이터 소스 선언
data "<리소스 유형>" "<이름>" {
<인수> = <값>
}
데이터 소스 속성 참조
데이터 소스 참조는 선언된 데이터 소스를 다른 리소스에서 참조할 때는 data. <provider>\_<resource>. <name>. <attribute>
형식을 사용합니다.
AWS aws_availability_zones(가용영역) 가져오기
사용 가능한 가용역 목록을 가져와서 데이터 소스로 선언하고 확인할 수 있습니다.
main.tf 작성
data "aws_availability_zones" "seoul" {
state = "available"
}
데이터 소스 참조 확인
terraform init -upgrade && terraform plan && terraform apply -auto-approve
terraform state list
terraform state show data.aws_availability_zones.seoul
# data.aws_availability_zones.seoul:
data "aws_availability_zones" "seoul" {
group_names = [
"ap-northeast-2",
]
id = "ap-northeast-2"
names = [
"ap-northeast-2a",
"ap-northeast-2b",
"ap-northeast-2c",
"ap-northeast-2d",
]
state = "available"
zone_ids = [
"apne2-az1",
"apne2-az2",
"apne2-az3",
"apne2-az4",
]
}
# 테라폼 콘솔 : 데이터 소스 참조 확인
terraform console
> data.aws_availability_zones.seoul.id
"ap-northeast-2"
> data.aws_availability_zones.seoul.names
tolist([
"ap-northeast-2a",
"ap-northeast-2b",
"ap-northeast-2c",
"ap-northeast-2d",
])
> data.aws_availability_zones.seoul.names[1]
"ap-northeast-2b"
# Tip. terraform console 값 echo로 확인
echo "data.aws_availability_zones.seoul" | terraform console
echo "data.aws_availability_zones.seoul.names" | terraform console
echo "data.aws_availability_zones.seoul.names[0]" | terraform console
2. 입력 변수(Variable)
Terraform 구성에서 값의 변수를 정의하여 코드의 유연성과 재사용성을 높이는 데 사용됩니다. 입력 변수를 사용하면 동일한 코드를 다양한 환경에서 쉽게 재사용할 수 있습니다
변수 선언 방식
변수는 variable 블록을 사용하여 선언됩니다
# variable 선언
variable "<이름>" {
<인수> = <값>
}
# variable 예시
variable "image_id" {
type = string
}
변의 정의 시 사용 가능한 메타인수는 다음과 같습니다.
- default : 변수 값을 전달하는 여러 가지 방법을 지정하지 않으면 기본값이 전달됨, 기본값이 없으면 대화식으로 사용자에게 변수에 대한 정보를 물어봄
- type : 변수에 허용되는 값 유형 정의, string number bool list map set object tuple와 유형을 지정하지 않으면 any 유형으로 간주
- description : 입력 변수의 설명
- validation : 변수 선언의 제약조건을 추가해 유효성 검사 규칙을 정의
- sensitive : 민감한 변수 값임을 알리고 테라폼의 출력문에서 값 노출을 제한 (암호 등 민감 데이터의 경우)
- nullable : 변수에 값이 없어도 됨을 지정
source, version, providers, count, for\_each, lifecycle, depends\_on, locals
의 키워드는 테라폼 예약 변수 이름으로 사용 불가능 합니다.
변수 유형
Terraform은 기본 데이터 유형과 복합 데이터 유형을 제공합니다. 각 유형은 특정한 용도와 특성을 가지며, 변수 선언 시 type 속성을 사용하여 명시할 수 있습니다.
- 기본 유형
- string : 글자 유형
- number : 숫자 유형
- bool : true 또는 false
- any : 명시적으로 모든 유형이 허용됨을 표시
- 집합 유형
- list (<유형>): 인덱스 기반 집합
- map (<유형>): 값 = 속성 기반 집합이며 키값 기준 정렬
- set (<유형>): 값 기반 집합이며 정렬 키값 기준 정렬
- object ({<인수 이름>=<유형>, …})
- tuple ([<유형>, …])
입력 변수 사용 예시
variable "string" {
type = string
description = "var String"
default = "myString"
}
variable "number" {
type = number
default = 123
}
variable "boolean" {
default = true
}
variable "list" {
default = [
"google",
"vmware",
"amazon",
"microsoft"
]
}
output "list_index_0" {
value = var.list.0
}
output "list_all" {
value = [
for name in var.list : upper(name)
]
}
variable "map" { # Sorting
default = {
aws = "amazon",
azure = "microsoft",
gcp = "google"
}
}
variable "set" { # Sorting
type = set(string)
default = [
"google",
"vmware",
"amazon",
"microsoft"
]
}
variable "object" {
type = object({ name = string, age = number })
default = {
name = "abc"
age = 12
}
}
variable "tuple" {
type = tuple([string, number, bool])
default = ["abc", 123, true]
}
variable "ingress_rules" { # optional ( >= terraform 1.3.0)
type = list(object({
port = number,
description = optional(string),
protocol = optional(string, "tcp"),
}))
default = [
{ port = 80, description = "web" },
{ port = 53, protocol = "udp" }]
}
#
terraform init && terraform plan && terraform apply -auto-approve
terraform state list
#
terraform output
list_all = [
"GOOGLE",
"VMWARE",
"AMAZON",
"MICROSOFT",
]
list_index_0 = "google"
유효성 검사
Terraform 변수 유효성 검사는 입력 변수의 값이 특정 조건을 만족하는지 확인하여 잘못된 구성이 적용되지 않도록 방지하는 데 사용됩니다.
유효성 검사 구성
- 유효성 검사 블록: validation 블록을 사용하여 유효성 검사를 정의합니다.
- 조건: condition 속성을 사용하여 유효성 검사를 위한 논리 조건을 정의합니다.
- 오류 메시지: error_message 속성을 사용하여 유효성 검사 실패 시 표시할 사용자 정의 오류 메시지를 지정합니다.
유효성 검사 예시
main.tf 작성
variable "name" {
type = string
validation {
condition = length(var.name) <= 10
error_message = "The 'name' value must be 10 characters or less."
}
}
terraform 실행
terraform init -upgrade && terraform apply -auto-approve
var.name
Enter a value: wer
No changes. Your infrastructure matches the configuration.
Terraform has compared your real infrastructure against your configuration and found no
differences, so no changes are needed.
민감한 변수 취급
민감 변수(Sensitive Variables)는 보안상 중요한 정보를 보호하기 위해 사용됩니다. 비밀번호, API 키, 비밀 키 등과 같은 민감한 데이터를 다룰 때 유용합니다.
main.tf 파일 작성
variable "jsp_password" {
default = "password"
sensitive = true
}
resource "local_file" "abc" {
content = var.my_password
filename = "${path.module}/abc.txt"
}
실행 및 확인
# 출력부분에 내용 안보임!
terraform apply -auto-approve
terraform state show local_file.abc
echo "local_file.abc.content" | terraform console
# local_file.abc will be created
+ resource "local_file" "abc" {
+ content = (sensitive value)
+ content_base64sha256 = (known after apply)
+ content_base64sha512 = (known after apply)
...
}
# 결과물 파일 확인
cat abc.txt ; echo
# terraform.tfstate 파일 확인 : VSCODE에서 terraform.tfstate 클릭 후 확인
cat terraform.tfstate | grep '"content":'
"content": "password",
변수 우선순위
테라폼은 선언되는 방식에 따라 변수의 우선순위가 있으므로, 이를 적절히 사용해 로컬 환경과 빌드 서버 환경에서의 정의를 다르게 하거나, 프로비저닝 파이프라인을 구성하는 경우 외부 값을 변수에 지정할 수 있습니다.
숫자가 작을수록 우선순위가 낮습니다.
우선순위 수준 1 : 실행 후 입력
# 실행
terraform apply -auto-approve
var.my_var
Enter a value: var1
...
# 확인
terraform state show local_file.abc
cat abc.txt ; echo
우선순위 수준 2 : variable 블록의 default 값
variable "my_var" {
default = "var2"
}
resource "local_file" "abc" {
content = var.my_var
filename = "${path.module}/abc.txt"
}
# 실행
terraform apply -auto-approve
# 확인
terraform state show local_file.abc
cat abc.txt ; echo
우선순위 수준 3 : 환경 변수 (TF_VAR 변수 이름)
시스템 환경 변수의 접두사에 TF_VAR_ 가 포함되면 그 뒤의 문자열을 변수 이름으로 인식합니다.
# Linux/macOS
export TF_VAR_my_var=var3
terraform apply -auto-approve
# 확인
cat abc.txt ; echo
우선순위 수준 4 : terraform.tfvars에 정의된 변수 선언
루트 모듈의 main.tf 파일과 같은 위치에 terraform.tfvars 파일을 생성해 변수에 대한 값을 추가하고 앞서 선언한 변수 선언과 비교해 우선순위를 확인합니다.
#
echo 'my_var="var4"' > terraform.tfvars
cat terraform.tfvars
#
terraform apply -auto-approve
# 확인
cat abc.txt ; echo
우선순위 수준 5 : *. auto.tfvars에 정의된 변수 선언
# a.auto.tfvars 파일 생성
echo 'my_var="var5_a"' > a.auto.tfvars
ls *.tfvars
#
terraform apply -auto-approve
# 확인
cat abc.txt ; echo
# b.auto.tfvars 파일 생성
echo 'my_var="var5_b"' > b.auto.tfvars
ls *.tfvars
#
terraform apply -auto-approve
# 확인
cat abc.txt ; echo
우선순위 수준 6 : *. auto.tfvars.json에 정의된 변수 선언
*. auto.tfvars와 같이 파일명의 정렬에 따라 우선순위가 적용됩니다.
# a.auto.tfvars.json 파일 생성
cat <<EOF > a.auto.tfvars.json
{
"my_var" : "var6_a"
}
EOF
ls *.tfvars ; ls *.json
#
terraform apply -auto-approve
# 확인
cat abc.txt ; echo
# c.auto.tfvars.json 파일 생성
cat <<EOF > c.auto.tfvars.json
{
"my_var" : "var6_c"
}
EOF
ls *.tfvars ; ls *.json
#
terraform apply -auto-approve
# 확인
cat abc.txt ; echo
[우선순위 수준 7] CLI 실행 시 -var 인수에 지정 또는 -var-file로 파일 지정
여러 인수가 선언되는 경우 나중에 선언된 변수의 우선순위가 높습니다.
#
terraform apply -auto-approve -var=my_var=var7
cat abc.txt ; echo
#
terraform apply -auto-approve -var=my_var=var7 -var=my_var=var8
cat abc.txt ; echo
*. tfvars와 같은 형식의 내용의 파일이라면 -var-file로 지정할 수 있습니다.
# var9.txt 파일 생성
echo 'my_var="var9"' > var9.txt
#
terraform apply -auto-approve -var=my_var=var7 -var-file="var9.txt"
cat abc.txt ; echo
3. 지역 값(Local)
local (지역 값)은 외부에서 입력되지 않고, 코드 내에서만 가공되어 동작하는 값을 선언하는 로컬 변수입니다.
- ‘local’은 입력 변수와 달리 선언된 모듈 내에서만 접근 가능하고, 변수처럼 실행 시에 입력받을 수 없습니다.
- 값이나 표현식을 반복적으로 사용할 수 있는 편의를 제공하지만, 빈번하게 여러 곳에서 사용되는 경우 실제 값에 대한 추적이 어려워져 유지 관리 측면에서 부담이 발생할 수 있으므로 주의해야 합니다.
local 선언
- locals 블록으로 시작합니다. 선언되는 인수에 표현되는 값은 상수만이 아닌 리소스의 속성, 변수의 값들도 조합해 정의할 수 있습니다.
- 동일한 tf 파일 내에서 여러 번 선언하는 것도 가능하고 여러 파일에 걸쳐 만드는 것도 가능합니다.
- 다만 locals에 선언한 로컬 변수 이름은 전체 루트 모듈 내에서 유일해야 합니다.
variable "prefix" {
default = "hello"
}
locals {
name = "terraform"
content = "${var.prefix} ${local.name}"
my_info = {
age = 20
region = "KR"
}
my_nums = [1, 2, 3, 4, 5]
}
locals {
content = "content2" # 중복 선언되었으므로 오류가 발생한다.
}
local 참조
- 선언된 local 값은 local. <이름>으로 참조할 수 있다.
- 테라폼 구성 파일을 여러 개 생성해 작업하는 경우 서로 다른 파일에 선언되어 있더라도 다른 파일에서 참조할 수 있다.
main.tf 파일 작성
variable "prefix" {
default = "hello"
}
locals {
name = "terraform"
}
resource "local_file" "abc" {
content = local.content
filename = "${path.module}/abc.txt"
}
sub.tf 파일 작성
locals {
content = "${var.prefix} ${local.name}"
}
실행 및 확인
terraform init -upgrade
terraform apply -auto-approve
terraform state list
terraform state show local_file.abc
4. 출력(output)
출력 값은 주로 테라폼 코드의 프로비저닝 수행 후의 결과 속성 값을 확인하는 용도로 사용됩니다.
output 선언
모듈 내에서 생성되는 속성 값들은 outout 블록에 정의합니다.
output "instance_ip_addr" {
value = "http://${aws_instance.server.private_ip}"
}
output 활용
abspath 함수는 파일 시스템 경로를 포함하는 문자열을 가져와 절대 경로로 변환하는 함수입니다.
resource "local_file" "abc" {
content = "abc123"
filename = "${path.module}/abc.txt"
}
output "file_id" {
value = local_file.abc.id
}
output "file_abspath" {
value = abspath(local_file.abc.filename)
}
plan 실행 시, 이미 정해진 속성은 출력을 예측하지만 아직 생성되지 않은 file_id 값은 값의 경우는 결과 예측을 할 수 없습니다.
# plan 실행 시, 이미 정해진 속성은 출력을 예측하지만
terraform init && terraform plan
...
Plan: 1 to add, 0 to change, 0 to destroy.
Changes to Outputs:
+ file_abspath = "/Users/spjang/terraform/3.8/abc.txt"
+ file_id = (known after apply)
5. 반복문
테라폼 반복문은 리소스를 반복적으로 생성하거나 변수의 값들을 반복 처리하는 데 사용됩니다. 반복문을 사용하면 코드의 간결성과 효율성을 높일 수 있습니다.
count
- count 메타 인수는 리소스 블록 내에서 정의되며, 생성할 리소스의 개수를 지정합니다.
- 각 리소스 인스턴스는 count.index 변수를 통해 고유한 인덱스를 갖습니다.
count 반복문을 이용해서 로컬파일을 생성합니다.
# main.tf
resource "local_file" "abc" {
count = 5
content = "This is filename abc${count.index}.txt"
filename = "${path.module}/abc${count.index}.txt"
}
output "fileid" {
value = local_file.abc.*.id
}
output "filename" {
value = local_file.abc.*.filename
}
output "filecontent" {
value = local_file.abc.*.content
}
# 실행 및 확인
terraform init && terraform apply -auto-approve
terraform state list
#
echo "local_file.abc" | terraform console
ls *.txt
abc0.txt abc1.txt abc2.txt abc3.txt abc4.txt
terraform output filename
[
"./abc0.txt",
"./abc1.txt",
"./abc2.txt",
"./abc3.txt",
"./abc4.txt",
]
count에 부여되는 정수 값을 외부 변수에 식별되도록 구성할 수 있습니다.
- length 함수 사용하여 count로 지정되는 수량을 동일하게 구성합니다.
- list 형태의 배열을 활용한 반복문 동작 구성합니다.
variable "names" {
type = list(string)
default = ["a", "b", "c"]
}
resource "local_file" "abc" {
count = length(var.names)
content = "abc"
# 변수 인덱스에 직접 접근
filename = "${path.module}/abc-${var.names[count.index]}.txt"
}
resource "local_file" "def" {
count = length(var.names)
content = local_file.abc[count.index].content
# element function 활용
filename = "${path.module}/def-${element(var.names, count.index)}.txt"
}
count 제약 사항
1. 전체 리소스를 반복할 수는 있지만 리소스 내에서 태그와 같은 인라인 블록을 반복할 수는 없습니다.
- 각각의 tag를 사용하려면 key, value, propagate_at_launch에 대한 값으로 새 인라인 블록을 만들어야 합니다.
- 따라서 count 매개변수를 사용해서 이러한 태그를 반복하고 동적인 인라인 tag 블록을 생성하려고 시도할 수도 있지만, 인라인 블록 내에서는 count 사용은 지원하지 않습니다.
resource "aws_autoscaling_group" "example" {
launch_configuration = aws_launch_configuration.example.name
vpc_zone_identifier = data.aws_subnets.default.ids
target_group_arns = [aws_lb_target_group.asg.arn]
health_check_type = "ELB"
min_size = var.min_size
max_size = var.max_size
tag {
key = "Name"
value = var.cluster_name
propagate_at_launch = true
}
}
2. 배열 중간 값을 변경할 때, 의도하지 않은 결과 발생합니다.
- 배열의 중간에 항목을 제거하면 모든 항목이 1칸씩 앞으로 당겨집니다.
- 테라폼이 인덱스 번호를 리소스 식별자로 보기 때문에 ‘인덱스 1에서는 계정 생성, 인덱스 2에서는 계정 삭제한다’라고 해석합니다.
- 즉 count 사용 시 목록 중간 항목을 제거하면 테라폼은 해당 항목 뒤에 있는 모든 리소스를 삭제한 다음 해당 리소스를 처음부터 다시 만듭니다.
# 변경 전
variable "user_names" {
description = "Create IAM users with these names"
type = list(string)
default = ["userA", "userB", "userC"]
}
# 변경 후
variable "user_names" {
description = "Create IAM users with these names"
type = list(string)
default = ["userA", "userC"]
}
terraform apply -auto-approve
...
│ Error: updating IAM User (userB): operation error IAM: UpdateUser, https response error StatusCode: 409, RequestID: a655d2bb-65fd-43f4-aec3-3b3486c43275, EntityAlreadyExists: User with name userC already exists.
│
│ with aws_iam_user.jspiam[1],
│ on iam.tf line 5, in resource "aws_iam_user" "jspiam":
│ 5: resource "aws_iam_user" "jspiam" {
count 인수를 사용할 때, 외부 변수가 목록(list) 타입이라면 중간에 값이 삭제되면 인덱스가 줄어들어 의도했던 특정 위치의 리소스만 삭제되는 것이 아니라 이후의 모든 리소스가 삭제되고 다시 생성될 수 있다는 점에 유의해야 합니다.
'Automation > Terraform' 카테고리의 다른 글
테라폼으로 AWS EKS 배포 - T101 7주차 (0) | 2024.07.27 |
---|---|
Terraform Module & Runner - T101 5주차 (2) | 2024.07.14 |
Terraform Provider & State - T101 4주차 (0) | 2024.07.06 |
Terraform 기본사용 3 - T101 3주차 (0) | 2024.06.29 |
Terraform 기본사용 1 - T101 1주차 (0) | 2024.06.16 |