출력 output
출력 값은 주로 테라폼 코드의 프로비저닝 수행 후의 결과 속성 값을 확인하는 용도로 사용된다.
또한 프로그래밍 언어에서 코드 내 요소 간에 제한된 노출을 지원하듯, 테라폼 모듈 간, 워크스페이스 간 데이터 접근 요소로도 활용할 수 있다.
예를 들면 자바의 getter와 비슷한 역할이다. 출력 값의 용도는 다음과 같이 정의할 수 있다.
- 루트 모듈에서 사용자가 확인하고자 하는 특정 속성 출력
- 자식 모듈의 특정 값을 정의하고 루트 모듈에서 결과를 참조
- 서로 다른 루트 모듈의 결과를 원격으로 읽기 위한 접근 요소
output "instance_ip_addr" {
value = "http://10.1.1"
}
main.tf파일 내용
(참고) 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
...
Changes to Outputs:
+ file_abspath = "/Users/gasida/Downloads/workspaces/3.8/abc.txt"
+ file_id = (known after apply)
#
terraform apply -auto-approve
...
Outputs:
file_abspath = "/Users/gasida/Downloads/workspaces/3.8/abc.txt"
file_id = "6367c48dd193d56ea7b0baad25b19455e529f5ee"
# graph 확인 > graph.dot 파일 선택 후 오른쪽 상단 DOT 클릭
terraform graph > graph.dot
# 파일 경로 비교 확인
terraform state list
terraform state show local_file.abc
echo "local_file.abc" | terraform console
echo "local_file.abc.filename" | terraform console
terraform output -raw file_abspath ; echo
(추가) abs 함수: 숫저의 절대값 반화, 음수면 양수로 - 링크, abspath 함수
반복문
list 형태의 값 목록이나 Key-Value 형태의 문자열 집합인 데이터가 있는 경우 동일한 내용에 대해 테라폼 구성 정의를 반복적으로 하지 않고 관리할 수 있다.
count : 반복문, 정수 값만큼 리소스나 모듈을 생성 - Blog
- 리소스 또는 모듈 블록에 count 값이 정수인 인수가 포함된 경우 선언된 정수 값만큼 리소스나 모듈을 생성하게 된다.
- count에서 생성되는 참조값은 count.index이며, 반복하는 경우 0부터 1씩 증가해 인덱스가 부여된다.
- main.tf 파일
resource "local_file" "abc" {
count = 5
content = "abc"
filename = "${path.module}/abc.txt"
}
output "filecontent" {
value = local_file.abc.*.content
}
output "fileid" {
value = local_file.abc.*.id
}
output "filename" {
value = local_file.abc.*.filename
}
실행 후 확인 : 5개의 파일이 생성되어야 하지만 파일명이 동일하여 결과적으로 하나의 파일만 존재 ← count 사용 시 주의
#
terraform init && terraform apply -auto-approve
terraform state list
echo "local_file.abc" | terraform console
echo "local_file.abc[0]" | terraform console
echo "local_file.abc[4]" | terraform console
terraform state show 'local_file.abc[0]'
terraform state show 'local_file.abc[4]'
ls *.txt
#
terraform output
terraform output filename
terraform output fileid
terraform output filecontent
파일 수정
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 apply -auto-approve
terraform state list
ls *.txt
echo "local_file.abc" | terraform console
echo "local_file.abc[0].content" | terraform console
echo "local_file.abc[4].content" | terraform console
terraform state show 'local_file.abc[0]'
terraform state show 'local_file.abc[4]'
#
terraform output
terraform output filename
terraform output fileid
terraform output filecontent
# graph 확인 > graph.dot 파일 선택 후 오른쪽 상단 DOT 클릭
terraform graph > graph.dot
때때로 여러 리소스나 모듈의 count로 지정되는 수량이 동일해야 하는 상황이 있다. 이 경우 count에 부여되는 정수 값을 외부 변수에 식별되도록 구성할 수 있다.
main.tf 파일 수정 : 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"
}
확인
#
terraform apply -auto-approve
terraform state list
ls *.txt
diff abc-a.txt abc-b.txt
diff abc-a.txt def-c.txt
cat abc-a.txt abc-b.txt abc-c.txt
cat def-a.txt def-b.txt def-c.txt
echo "local_file.abc" | terraform console
echo "local_file.abc[0].content" | terraform console
echo "local_file.abc[2].content" | terraform console
terraform state show 'local_file.abc[0]'
terraform state show 'local_file.abc[2]'
# graph 확인 > graph.dot 파일 선택 후 오른쪽 상단 DOT 클릭
terraform graph > graph.dot
[스터디 전용/실습3] 반복문
실습1 : IAM 사용자 3명 생성
사용자 1명 생성 코드
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_iam_user" "example" {
name = "neo"
}
범용 프로그래밍 언어 for 반복문 사용 ⇒ 테라폼은 for 반복문 또는 언어에 내장된 절차 논리가 없어서 아래 구문 동작 불가능
# This is just pseudo code. It won't actually work in Terraform.
for (i = 0; i < 3; i++) {
resource "aws_iam_user" "example" {
name = "neo"
}
}
테라폼에서 count 를 사용하여 3명 IAM 사용자 생성 → 3명의 IAM 사용자 이름 중복으로 오류 발생 ⇒ for 반복문의 인덱스를 사용하여 각 사용자에게 고유한 이름 지정 가능
resource "aws_iam_user" "example" {
count = 3
name = "neo"
}
iam.tf
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_iam_user" "myiam" {
count = 3
name = "myuser.${count.index}"
}
iam.tf : 아래 처럼 count.index 를 사용하여 반복문 안에 있는 각각의 반복 ieration 을 가리키는 인덱스를 얻을 수 있음
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_iam_user" "myiam" {
count = 3
name = "myuser.${count.index}"
}
#
terraform init && terraform plan
...
# aws_iam_user.myiam[0] will be created
# aws_iam_user.myiam[1] will be created
# aws_iam_user.myiam[2] will be created
# apply
terraform apply -auto-approve
# 확인
terraform state list
aws_iam_user.myiam[0]
aws_iam_user.myiam[1]
aws_iam_user.myiam[2]
echo "aws_iam_user.myiam" | terraform console
echo "aws_iam_user.myiam[0]" | terraform console
terraform state show 'aws_iam_user.myiam[0]'
terraform state show 'aws_iam_user.myiam[2]'
aws iam list-users | jq
...
count 입력 변수를 통해 IAM 사용자 생성
touch variables.tf
variable "user_names" {
description = "Create IAM users with these names"
type = list(string)
default = ["gasida", "akbun", "hyungwook"]
}
- 테라폼에서 count 와 함께 배열 조회 구문과 length 함수를 사용해서 사용자들 생성 가능
- 배열 조회 구문 Array lookup syntax
- ARRAY[<INDEX>]
- 예를 들어 다음은 var.user_names 의 인덱스 1에서 요소를 찾는 방법
- var.user_names[1]
- length (내장) 함수 built-on function
- length(<ARRAY>)
- 주어진 ARRAY 의 항목 수를 반환하는 함수. 문자열 및 맵을 대상으로도 동작
- 배열 조회 구문 Array lookup syntax
- iam.tf : 코드 내용 수정
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_iam_user" "myiam" {
count = length(var.user_names)
name = var.user_names[count.index]
}
init & plan : 리소스에 count 사용한 후에는 하나의 리소스가 아니라 리소스의 배열이 됩니다.
- aws_iam_user.myiam 은 이제 IAM 사용자의 배열이므로 표준 구문을 사용하여 해당 리소스인 <PROVIDER>_<TYPE>.<NAME>.<ATTRIBUTE> 에서 속성을 읽은 대신 배열에서 인덱스를 지정해서 IAM 사용자를 명시해야합니다.
- <PROVIDER>_<TYPE>.<NAME>[INDEX].ATTRIBUTE
- IAM 사용자 한명의 ARN과 사용자 전체의 ARN 을 출력 변수 outputs 으로 제공
- output.tf : IAM 사용자 전체의 ARN을 원하면 인덱스 대신 스플랫 splat 연산자인 * 를 사용
output "first_arn" {
value = aws_iam_user.myiam[0].arn
description = "The ARN for the first user"
}
output "all_arns" {
value = aws_iam_user.myiam[*].arn
description = "The ARNs for all users"
}
#
terraform apply -auto-approve
terraform state list
terraform output
terraform output first_arn
terraform output -raw first_arn
terraform output all_arns
terraform output -raw all_arns
count 제약사항 - 인라인 블록 반복 X, 배열 중간 값을 변경할 때 의도하지 않은 결과 발생
- [실습X] 전체 리소스를 반복할 수는 있지만 리소스 내에서 인라인 블록을 반복할 수는 없습니다.
- 예를 들어 아래 ASG 리소스에 태그 설정 방법에서 생각해보자
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
}
}
- 각각의 tag 를 사용하려면 key, value, propagate_at_launch 에 대한 값으로 새 인라인 블록을 만들어야 합니다.
- 따라서 count 매개변수를 사용해서 이러한 태그를 반복하고 동적인 인라인 tag 블록을 생성하려고 시도할 수도 있지만, 인라인 블록 내에서는 count 사용은 지원하지 않습니다.
2. [실습] 배열 중간 값을 변경할 때 의도하지 않은 결과 발생
실습을 위해 다시 IAM 사용자 생성
variables.tf : IAM 사용자 생성 목록
variable "user_names" {
description = "Create IAM users with these names"
type = list(string)
default = ["gasida", "akbun", "hyungwook"]
}
variables.tf : 중간에 있는 akbun 을 제거하고 plan & apply
variable "user_names" {
description = "Create IAM users with these names"
type = list(string)
default = ["gasida", "hyungwook"]
}
# plan : 출력 내용 확인!
terraform plan
...
~ update in-place
- destroy
- 배열의 중간에 항목을 제거하면 모든 항목이 1칸씩 앞으로 당겨짐.
- 테라폼이 인덱스 번호를 리소스 식별자로 보기 때문에 ‘인덱스 1에서는 계정 생성, 인덱스2에서는 계정 삭제한다’라고 해석합니다.
- 즉 count 사용 시 목록 중간 항목을 제거하면 테라폼은 해당 항목 뒤에 있는 모든 리소스를 삭제한 다음 해당 리소스를 처음부터 다시 만듬.
[악분님 작성 count 실습] 따라하기 👍🏻👍🏻 - Link Blog Github
악분님이 테라폼 반복문 관련 내용(count, for_each, for expression 등)이해를 위한 좋은 실습을 정리해주셨습니다
코드 가져오기
git clone https://github.com/sungwook-practice/t101-study.git
cd t101-study/count_vs_foreach
cat Readme.md
tree -L 1
실습 환경 배포 : AWS VPC 생성
cd template
ls
cat terraform.tfvars
terraform init && terraform plan && terraform apply -auto-approve
terraform state list
**[시나리오 1**] - aws_subnet
- AWS VPC Subnet 테라폼 코드 작성
- 요구사항 : subnet cidr를 변수로 입력
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
tags = {
Name = "terraform VPC"
}
}
resource "aws_subnet" "main" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
tags = {
Name = "Main"
}
}
변수 처리 + 실습 편리를 위해 output 추가
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
tags = {
Name = "terraform VPC"
}
}
resource "aws_subnet" "main" {
vpc_id = aws_vpc.main.id
cidr_block = var.subnet_cidr
}
output "myvpc_id" {
value = aws_vpc.main.id
}
2. variables.tf 수정
variable "vpc_cidr" {
type = string
}
variable "subnet_cidr" {
type = string
}
3. terraform.tfvars 수정
vpc_cidr = "192.168.0.0/16"
subnet_cidr = "192.168.1.0/24"
4.배포 실행
# 배포 실행
terraform plan && terraform apply -auto-approve
# 실행 결과 확인
terraform state list
terraform output myvpc_id
# 신규 생성한 VPC 내에 서브넷 확인
aws ec2 describe-subnets --filters "Name=vpc-id,Values=$(terraform output -raw myvpc_id)" --output table
aws ec2 describe-subnets --filters "Name=vpc-id,Values=$(terraform output -raw myvpc_id)" --query "Subnets[*].{ID:SubnetId,CIDR:CidrBlock,AZ:AvailabilityZone}"
aws ec2 describe-subnets --filters "Name=vpc-id,Values=$(terraform output -raw myvpc_id)" --query "Subnets[*].{ID:SubnetId,CIDR:CidrBlock,AZ:AvailabilityZone}" --output text
5. 다음 실습을 위해 생성한 리소스 삭제
terraform destroy -auto-approve
[시나리오 2] - index element length
- subnet 1개밖에 못만드나요?…
- 요구사항 : subnet cidr 변수 값을 여러 개 입력받도록 해주세요 → count 사용!
index element length function 공식 문제 예제 따라해보기
terraform console
-----------------
> index(["a", "b", "c"], "b")
1
> element(["a", "b", "c"], 1)
"b"
> element(["a", "b", "c"], 3)
"a"
> length([])
0
> length(["a", "b"])
2
> length({"a" = "b"})
1
> length("hello")
5
> exit
-----------------
1. variables.tf 수정
variable "vpc_cidr" {
type = string
}
variable "subnet_cidr" {
type = list(string)
}
2.terraform.tfvars 수정
vpc_cidr = "192.168.0.0/16"
subnet_cidr = ["192.168.1.0/24", "192.168.2.0/24"]
3.main.tf 수정
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
tags = {
Name = "terraform VPC"
}
}
resource "aws_subnet" "main" {
count = length(var.subnet_cidr)
vpc_id = aws_vpc.main.id
cidr_block = element(var.subnet_cidr, count.index)
}
output "myvpc_id" {
value = aws_vpc.main.id
}
4.배포 실행
# 신규 터미널 : 모니터링
while true; do aws ec2 describe-subnets --filters --query "Subnets[*].{ID:SubnetId,CIDR:CidrBlock,AZ:AvailabilityZone}" --output text; echo; time; sleep 1; done
# 배포 실행
terraform plan && terraform apply -auto-approve
# 실행 결과 확인
terraform state list
# 신규 생성한 VPC 내에 서브넷 확인
aws ec2 describe-subnets --filters "Name=vpc-id,Values=$(terraform output -raw myvpc_id)" --output table
aws ec2 describe-subnets --filters "Name=vpc-id,Values=$(terraform output -raw myvpc_id)" --query "Subnets[*].{ID:SubnetId,CIDR:CidrBlock,AZ:AvailabilityZone}"
# Tip. 코드 중 동작 결과를 눈으로 직접 확인해보기
terraform console
--------------------
> length(var.subnet_cidr)
2
> aws_vpc.main.id
"vpc-0c01f6cdbf3c9ad7a"
> exit
--------------------
5. 다음 실습을 위해 생성한 리소스 삭제
terraform destroy -auto-approve
[시나리오 3] - aws_subnet-arg_az (AZ for the subnet)
- 감사, 그런데~
- 요구사항 : 서브넷이 배치되는 AZ 설정이 필요. AZ는 변수로 입력해주세요
1.variables.tf 수정
variable "vpc_cidr" {
type = string
}
variable "subnet_cidr" {
type = list(string)
}
variable "subnet_az" {
type = list(string)
}
2.terraform.tfvars 수정
vpc_cidr = "192.168.0.0/16"
subnet_cidr = ["192.168.1.0/24", "192.168.2.0/24"]
subnet_az = ["ap-northeast-2a", "ap-northeast-2c"]
3.main.tf 수정
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
tags = {
Name = "terraform VPC"
}
}
resource "aws_subnet" "main" {
count = length(var.subnet_cidr)
vpc_id = aws_vpc.main.id
cidr_block = element(var.subnet_cidr, count.index)
availability_zone = element(var.subnet_az, count.index)
}
output "myvpc_id" {
value = aws_vpc.main.id
}
4.배포 실행
# 신규 터미널 : 모니터링
while true; do aws ec2 describe-subnets --filters --query "Subnets[*].{ID:SubnetId,CIDR:CidrBlock,AZ:AvailabilityZone}" --output text; echo; time; sleep 1; done
# 배포 실행
terraform plan && terraform apply -auto-approve
# 실행 결과 확인
terraform state list
echo "aws_subnet.main[0].availability_zone" | terraform console
echo "aws_subnet.main[1].availability_zone" | terraform console
echo "aws_subnet.main[0].tags_all" | terraform console
echo "aws_subnet.main[1].tags_all" | terraform console
# 신규 생성한 VPC 내에 서브넷 확인
aws ec2 describe-subnets --filters "Name=vpc-id,Values=$(terraform output -raw myvpc_id)" --output table
aws ec2 describe-subnets --filters "Name=vpc-id,Values=$(terraform output -raw myvpc_id)" --query "Subnets[*].{ID:SubnetId,CIDR:CidrBlock,AZ:AvailabilityZone}"
aws ec2 describe-subnets --filters "Name=vpc-id,Values=$(terraform output -raw myvpc_id)" --query "Subnets[*].{ID:SubnetId,CIDR:CidrBlock,AZ:AvailabilityZone,Name:Tags[?Key=='Name']|[0].Value}" --output table
5.다음 실습을 위해 생성한 리소스 삭제
terraform destroy -auto-approve
[시나리오 4] - aws_subnet-arg_tags (A map of tags assigned to the resource) map
- subnet이 여러개인데 구분할 수 없을까요?
- 요구사항 : subnet tag 설정이 필요해요
1.main.tf 1차 수정(vpc tags 복붙) → 실행 후 확인
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
tags = {
Name = "terraform VPC"
}
}
resource "aws_subnet" "main" {
count = length(var.subnet_cidr)
vpc_id = aws_vpc.main.id
cidr_block = element(var.subnet_cidr, count.index)
availability_zone = element(var.subnet_az, count.index)
tags = {
Name = "terraform VPC"
}
}
output "myvpc_id" {
value = aws_vpc.main.id
}
실행 후 확인
# 신규 터미널 : 모니터링
while true; do aws ec2 describe-subnets --filters --query "Subnets[*].{ID:SubnetId,CIDR:CidrBlock,AZ:AvailabilityZone,Name:Tags[?Key=='Name']|[0].Value}" --output text; echo; time; sleep 1; done
# 배포 실행
terraform plan && terraform apply -auto-approve
# 실행 결과 확인
terraform state list
echo "aws_subnet.main[0].tags_all" | terraform console
echo "aws_subnet.main[1].tags_all" | terraform console
aws ec2 describe-subnets --filters "Name=vpc-id,Values=$(terraform output -raw myvpc_id)" --query "Subnets[*].{ID:SubnetId,CIDR:CidrBlock,AZ:AvailabilityZone,Name:Tags[?Key=='Name']|[0].Value}" --output table
2.main.tf 2차 수정(count index 활용) → 실행 후 확인
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
tags = {
Name = "terraform VPC"
}
}
resource "aws_subnet" "main" {
count = length(var.subnet_cidr)
vpc_id = aws_vpc.main.id
cidr_block = element(var.subnet_cidr, count.index)
availability_zone = element(var.subnet_az, count.index)
tags = {
Name = "terraform VPC-${count.index}"
}
}
output "myvpc_id" {
value = aws_vpc.main.id
}
[시나리오 5] - map
- tag에 인덱스번호 말고 고유하게 이름을 설정할 수 없을까요?
- 요구사항 : subnet tag 를 설정하는 변수 생성
1.variables.tf 수정
variable "vpc_cidr" {
type = string
}
variable "subnet_cidr" {
type = list(string)
}
variable "subnet_az" {
type = list(string)
}
variable "subnet_tag" {
type = list(map(string))
}
2.terraform.tfvars 수정 : main 에 tag 내용을 복붙 후 수정
vpc_cidr = "192.168.0.0/16"
subnet_cidr = ["192.168.1.0/24", "192.168.2.0/24"]
subnet_az = ["ap-northeast-2a", "ap-northeast-2c"]
subnet_tag = [
{
Name = "public-subnet"
Environment = "dev"
},
{
Name = "private-subnet"
Environment = "dev"
}
]
3.main.tf 수정
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
tags = {
Name = "terraform VPC"
}
}
resource "aws_subnet" "main" {
count = length(var.subnet_cidr)
vpc_id = aws_vpc.main.id
cidr_block = element(var.subnet_cidr, count.index)
availability_zone = element(var.subnet_az, count.index)
tags = element(var.subnet_tag, count.index)
}
output "myvpc_id" {
value = aws_vpc.main.id
}
4.배포 실행
# 신규 터미널 : 모니터링
while true; do aws ec2 describe-subnets --filters --query "Subnets[*].{ID:SubnetId,CIDR:CidrBlock,AZ:AvailabilityZone}" --output text; echo; time; sleep 1; done
# 배포 실행
terraform plan && terraform apply -auto-approve
# 실행 결과 확인
terraform state list
echo "aws_subnet.main[0].tags_all" | terraform console
echo "aws_subnet.main[1].tags_all" | terraform console
# 신규 생성한 VPC 내에 서브넷 확인
aws ec2 describe-subnets --filters "Name=vpc-id,Values=$(terraform output -raw myvpc_id)" --query "Subnets[*].{ID:SubnetId,CIDR:CidrBlock,AZ:AvailabilityZone,Name:Tags[*]|[*].Value}" --output table
aws ec2 describe-subnets --filters "Name=vpc-id,Values=$(terraform output -raw myvpc_id)" --query "Subnets[*].{ID:SubnetId,CIDR:CidrBlock,AZ:AvailabilityZone,Name:Tags[*]|[*].Value}" --output text
[시나리오 6] (리팩토링) - map list_object
- subnet 추가할 때마다 변수 전부 일일이 입력해야 되나요? 불편한데…
(휴먼에러도 나고 있네요) - 요구사항 : subnet 설정 변수를 한 변수로 설정하도록 리팩토링
1.variables.tf 수정
variable "vpc_cidr" {
type = string
}
variable "subnets" {
type = list(object({
cidr = string
az = string
tags = map(string)
}))
}
2.terraform.tfvars 수정
vpc_cidr = "192.168.0.0/16"
subnets = [
{
cidr = "192.168.1.0/24",
az = "ap-northeast-2a",
tags = {
Name = "public-subnet"
Environment = "dev"
}
},
{
cidr = "192.168.2.0/24",
az = "ap-northeast-2c",
tags = {
Name = "private-subnet"
Environment = "dev"
}
}
]
3.main.tf 수정 → 실행
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
tags = {
Name = "terraform VPC"
}
}
resource "aws_subnet" "main" {
count = length(var.subnet_cidr)
vpc_id = aws_vpc.main.id
cidr_block = var.subnets[count.index].cidr
availability_zone = var.subnets[count.index].az
tags = var.subnets[count.index].tags
}
output "myvpc_id" {
value = aws_vpc.main.id
}
실행 → 에러 발생
main.tf 수정
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
tags = {
Name = "terraform VPC"
}
}
resource "aws_subnet" "main" {
count = length(var.subnets)
vpc_id = aws_vpc.main.id
cidr_block = var.subnets[count.index].cidr
availability_zone = var.subnets[count.index].az
tags = var.subnets[count.index].tags
}
output "myvpc_id" {
value = aws_vpc.main.id
}
배포 실행
# 신규 터미널 : 모니터링
while true; do aws ec2 describe-subnets --filters --query "Subnets[*].{ID:SubnetId,CIDR:CidrBlock,AZ:AvailabilityZone}" --output text; echo; time; sleep 1; done
# 배포 실행
terraform plan && terraform apply -auto-approve
# 실행 결과 확인
terraform state list
echo "aws_subnet.main[0].tags_all" | terraform console
echo "aws_subnet.main[1].tags_all" | terraform console
# 신규 생성한 VPC 내에 서브넷 확인
aws ec2 describe-subnets --filters "Name=vpc-id,Values=$(terraform output -raw myvpc_id)" --query "Subnets[*].{ID:SubnetId,CIDR:CidrBlock,AZ:AvailabilityZone,Name:Tags[*]|[*].Value}" --output table
aws ec2 describe-subnets --filters "Name=vpc-id,Values=$(terraform output -raw myvpc_id)" --query "Subnets[*].{ID:SubnetId,CIDR:CidrBlock,AZ:AvailabilityZone,Name:Tags[*]|[*].Value}" --output text
terraform destroy -auto-approve
[시나리오 7] 장애 상황 재현 - Docs
- 테라폼 변수에서 안쓰는 subnet을 삭제한 후, 테라폼을 실행하니 EC2 instance가 교체되었어요. EC2 내에 작업한 내용이 다 사라졌는데…
- 요구사항 : 오류 확인 후 코드 수정
1.실습 환경 배포
# 코드 파일 확인
cd ..
cd step5_count_invalid_example
ls
실습 편리를 위해 main.tf 하단에 output 추가
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
tags = {
Name = "terraform VPC"
}
}
resource "aws_subnet" "main" {
count = length(var.subnets)
vpc_id = aws_vpc.main.id
cidr_block = var.subnets[count.index].cidr
availability_zone = var.subnets[count.index].az
tags = var.subnets[count.index].tags
}
resource "aws_instance" "server" {
ami = "ami-0e8bd0820b6e1360b"
instance_type = "t4g.nano"
subnet_id = aws_subnet.main[1].id
# index 접근 방법 오류 해결 코드
# subnet_id = index(aws_subnet.main.*.cidr_block, "192.168.2.0/24")
tags = {
Name = "Terraform demo"
}
}
output "myvpc_id" {
value = aws_vpc.main.id
}
배포 실행
# 신규 터미널 : 모니터링
aws ec2 describe-instances --query "Reservations[*].Instances[*].{PrivateIP:PrivateIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --output text
while true; do aws ec2 describe-instances --query "Reservations[*].Instances[*].{PrivateIP:PrivateIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --output text; echo; aws ec2 describe-subnets --query "Subnets[*].{ID:SubnetId,CIDR:CidrBlock,AZ:AvailabilityZone,Name:Tags[*]|[*].Value}" --output text; echo; time; sleep 1; done
# 배포 실행
terraform init && terraform plan && terraform apply -auto-approve
# 실행 결과 확인
terraform state list
aws ec2 describe-instances --query "Reservations[*].Instances[*].{PrivateIP:PrivateIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --output table
aws ec2 describe-subnets --filters "Name=vpc-id,Values=$(terraform output -raw myvpc_id)" --query "Subnets[*].{ID:SubnetId,CIDR:CidrBlock,AZ:AvailabilityZone,Name:Tags[*]|[*].Value}" --output table
2.[장애 재현] terraform.tfvars 수정 : 아래 부분 주석 처리
vpc_cidr = "192.168.0.0/16"
subnets = [
# (유투브 7번째 시나리오) terrafprm apply 이 후, 첫 번째 요소를 주석하세요
# {
# cidr = "192.168.1.0/24",
# az = "ap-northeast-2a",
# tags = {
# Name = "public-subnet"
# Environment = "dev"
# }
# },
# (유투브 8번째 시나리오) terrafprm apply 이 후, 주석을 해제하고 terraform apply해보세요
# {
# cidr = "192.168.5.0/24",
# az = "ap-northeast-2a",
# tags = {
# Name = "public-subnet"
# Environment = "dev"
# }
# },
{
cidr = "192.168.2.0/24",
az = "ap-northeast-2a",
tags = {
Name = "private-subnet"
Environment = "dev"
}
},
...
실행 후 인스턴스 삭제..
4.원인 : 반복문을 index로 접근했기 때문에 - Docs
(아래 그림은 출처 - 악분)
리소스 삭제
terraform destroy -auto-approve
'study > T101 4기' 카테고리의 다른 글
T101 4기 3주차 두번째 (0) | 2024.06.29 |
---|---|
T101 4기 3주차 첫번째 (0) | 2024.06.29 |
T101 4기 2주차 첫번째 (0) | 2024.06.22 |
T101 4기 1주차 세번째 (0) | 2024.06.15 |
T101 4기 1주차 두번째 (0) | 2024.06.15 |