티스토리 뷰
[IaC] 기본 사용법( data source, input variables, local, output, loop)
Hayley Shim 2023. 10. 28. 18:01안녕하세요. 최근 도서 “테라폼으로 시작하는 IaC” 의 내용을 기준으로 스터디한 내용을 정리했습니다. 지난 [IaC] IaC/테라폼 이해, 기본 명령 사용법 내용에 이어 해당 글에서는 기본 사용법(data source, input variables, local, output, loop)에 대해 알아보겠습니다.
2.기본 명령어
1. data source : 테라폼으로 정의되지 않은 외부 리소스 또는 저장된 정보를 테라폼 내에서 참조할 때 사용
- 데이터 소스 블록은 data로 시작하고 이후 ‘데이터 소스 유형’을 정의 (Resource 블록 정의와 유사)
사용 예)
data "local_file" "foo" {
filename = "${path.module}/foo.bar"
}
resource "aws_s3_object" "shared_zip" {
bucket = "my-bucket"
key = "my-key"
content = data.local_file.foo.content
}
데이터 소스를 정의할 때 사용 가능한 메타인수
- depends_on : 종속성을 선언하며, 선언된 구성요소와의 생성 시점에 대해 정의
- count : 선언된 개수에 따라 여러 리소스를 생성
- for_each : map 또는 set 타입의 데이터 배열의 값을 기준으로 여러 리소스를 생성
- lifecycle : 리소스의 수명주기 관리
실습 확인
# 실습을 위해 3.5 디렉터리를 신규 생성
$ mkdir 3.5 && cd 3.5
# 실습 확인을 위해서 abc.txt 파일 생성
$ echo "t101 study - 2week" > abc.txt
$ terraform init && terraform plan && terraform apply -auto-approve
$ terraform state list# 테라폼 콘솔 : 데이터 소스 참조 확인
$ echo "data.local_file.abc" | terraform console
데이터 소스 속성 참조
- 데이터 소스로 읽은 대상을 참조하는 방식은 리소스와 구별되게 data가 앞에 붙는다. 속성 값은 다음과 같이 접근할 수 있다.
# Terraform Code
data "<리소스 유형>" "<이름>" {
<인수> = <값>
}
# 데이터 소스 참조
data.<리소스 유형>.<이름>.<속성>
- 코드 예시 : 데이터 소스를 활용해 AWS 가용영역 인수를 정의하고 리전 내에서 사용 가능한 가용영역 목록 가져와서 사용하는 방법
# Declare the data source
data "aws_availability_zones" "available" {
state = "available"
}
resource "aws_subnet" "primary" {
availability_zone = data.aws_availability_zones.available.names[0]
# e.g. ap-northeast-2a
}
resource "aws_subnet" "secondary" {
availability_zone = data.aws_availability_zones.available.names[1]
# e.g. ap-northeast-2b
}
- 해당 문서에서 데이터 소스로 가져오기 위한 조건인 인수는 Argument로 표현되어 있고, 가져온 데이터 소스의 내용은 Attributes에 안내되어 있다
- main.tf 파일 코드 수정
resource "local_file" "abc" {
content = "123!"
filename = "${path.module}/abc.txt"
}
data "local_file" "abc" {
filename = local_file.abc.filename
}
resource "local_file" "def" {
content = data.local_file.abc.content
filename = "${path.module}/def.txt"
}
$ terraform apply -auto-approve
$ terraform state list
# 파일 확인
$ ls *.txt
diff abc.txt def.txt
# graph 확인
$ terraform graph > graph.dot
# 테라폼 콘솔 : 데이터 소스 참조 확인
$ terraform console
>
data.local_file.abc.content
...
exit
ls -l

2. input variables
- 입력 변수는 인프라를 구성하는 데 필요한 속성 값을 정의해 코드의 변경 없이 여러 인프라를 생성하는 데 목적
- 변수는 variable로 시작되는 블록으로 구성됨. 변수 블록 뒤의 이름 값은 동일 모듈 내 모든 변수 선언에서 고유해야 하며, 이 이름으로 다른 코드 내에서 참조됨
# variable 블록 선언의 예
variable "<이름>" {
<인수> = <값>
}
variable "image_id" {
type = string
}
- 테라폼 예약 변수 이름으로 사용 불가능한이름 : source, version, providers, count, for_each, lifecycle, depends_on, locals
변수 정의 시 사용 가능한 메타인수
- default : 변수 값을 전달하는 여러 가지 방법을 지정하지 않으면 기본값이 전달됨, 기본값이 없으면 대화식으로 사용자에게 변수에 대한 정보를 물어봄
- type : 변수에 허용되는 값 유형 정의, string number bool list map set object tuple 와 유형을 지정하지 않으면 any 유형으로 간주
- description : 입력 변수의 설명
- validation : 변수 선언의 제약조건을 추가해 유효성 검사 규칙을 정의 — 링크
- sensitive : 민감한 변수 값임을 알리고 테라폼의 출력문에서 값 노출을 제한 (암호 등 민감 데이터의 경우) — 링크
- nullable : 변수에 값이 없어도 됨을 지정
변수 유형
1)기본 유형
- string : 글자 유형
- number : 숫자 유형
- bool : true 또는 false
- any : 명시적으로 모든 유형이 허용됨을 표시
2)집합 유형
- list (<유형>): 인덱스 기반 집합
- map (<유형>): 값 = 속성 기반 집합이며 키값 기준 정렬
- set (<유형>): 값 기반 집합이며 정렬 키값 기준 정렬
- object ({<인수 이름>=<유형>, …})
- tuple ([<유형>, …])
list와 set은 선언하는 형태가 비슷하지만 참조 방식이 인덱스와 키로 각각 차이가 있고, map와 set의 경우 선언된 값이 정렬되는 특징을 가진다.
입력 변수 사용 예시
- 전달할 값이 number 인지 확인하는 입력 변수의 예
variable "number_example" {
description = "An example of a number variable in Terraform"
type = number
default = 42
}
2. 전달할 값이 list 인지 확인하는 입력 변수의 예
variable "list_example" {
description = "An example of a list in Terraform"
type = list
default = ["a", "b", "c"]
}
3. 조건 결합 사용 가능. 다음은 리스트의 모든 항목이 number 인 list 의 예
variable "list_numeric_example" {
description = "An example of a numeric list in Terraform"
type = list(number)
default = [1, 2, 3]
}
4.다음은 모든 값이 string 인 map 의 예
variable "map_example" {
description = "An example of a map in Terraform"
type = map(string)
default = {
key1 = "value1"
key2 = "value2"
key3 = "value3"
}
}
5. 다음은 object 또는 tuple 제약 조건을 사용하여 보다 복잡한 구조적 유형(structural type) 작성 가능
variable "object_example" {
description = "An example of a structural type in Terraform"
type = object({
name = string
age = number
tags = list(string)
enabled = bool
})
default = {
name = "value1"
age = 42
tags = ["a", "b", "c"]
enabled = true
}
}
변수 유형별 선언 방식의 예시 — main.tf 파일
# 실습을 위해 3.6 디렉터리를 신규 생성 후 열기
$ cd .. && rm -rf 3.5
$ mkdir 3.6 && cd 3.6
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"
유효성 검사 : 입력되는 변수 타입 지정 이외, 사용자 지정 유효성 검사가 가능
- 변수 블록 내에 validation 블록에서 조건인 condition에 지정되는 규칙이 true 또는 false를 반환해야 하며, error_message는 condition 값의 결과가 false 인 경우 출력되는 메시지를 정의
- regex 함수는 대상의 문자열에 정규식을 적용하고 일치하는 문자열을 반환하는데, 여기에 can 함수를 함께 사용하면 정규식에 일치하지 않는 경우의 오류를 검출
- validation 블록은 중복으로 선언할 수 있음
- variable 유효성 검사의 예 — main.tf 코드 파일 내용 수정
variable "image_id" {
type = string
description = "The id of the machine image (AMI) to use for the server."
validation {
condition = length(var.image_id) > 4
error_message = "The image_id value must exceed 4."
}
validation {
# regex(...) fails if it cannot find a match
condition = can(regex("^ami-", var.image_id))
error_message = "The image_id value must starting with \"ami-\"."
}
}
확인
#
terraform apply -auto-approve
var.image_id
The id of the machine image (AMI) to use for the server.
Enter a value: ami
...
#
terraform apply -auto-approve
var.image_id
The id of the machine image (AMI) to use for the server.
Enter a value: ami-
...
#
terraform apply -auto-approve
var.image_id
The id of the machine image (AMI) to use for the server.
Enter a value: ami-12345678
...
변수 참조 : variable은 코드 내에서 var.<이름>으로 참조된다.
main.tf 코드 파일 내용 수정
variable "my_password" {}
resource "local_file" "abc" {
content = var.my_password
filename = "${path.module}/abc.txt"
}
# 실행
terraform init -upgrade
terraform apply -auto-approve
var.my_password
Enter a value: qwe123
...
# 확인
terraform state list
terraform state show local_file.abc
cat abc.txt ; echo
# 해당 파일에 다른 내용으로 변경해보기
terraform apply -auto-approve
var.my_password
Enter a value: t101mypss
...
# 확인
cat abc.txt ; echo
민감한 변수 취급 : 입력 변수의 민감 여부 선언 가능
main.tf 코드 파일 내용 수정
- 기본값 추가로 입력 항목은 발생하지 않지만, 출력에서 참조되는 변수 값이(sensitive)로 감춰지는 것을 확인 할 수 있다
variable "my_password" {
default = "password"
sensitive = true
}
resource "local_file" "abc" {
content = var.my_password
filename = "${path.module}/abc.txt"
}
확인 : 민감한 변수로 지정해도 terraform.tfstate 파일에는 결과물이 평문으로 기록되므로 State 파일의 보안에 유의해야 한다. [참고 — Docs]
# 출력부분에 내용 안보임!
terraform apply -auto-approve
terraform state show local_file.abc
# 결과물 파일 확인
cat abc.txt ; echo
# terraform.tfstate 파일 확인
cat terraform.tfstate | grep '"content":'
"content": "password",
변수 입력 방식과 우선순위
- variable의 목적은 코드 내용을 수정하지 않고 테라폼의 모듈적 특성을 통해 입력되는 변수로 재사용성을 높이는 데 있다.
- 특히 입력 변수라는 명칭에 맞게 사용자는 프로비저닝 실행 시에 원하는 값으로 변수에 정의할 수 있다.
- 선언되는 방식에 따라 변수의 우선순위가 있으므로, 이를 적절히 사용해 로컬 환경과 빌드 서버 환경에서의 정의를 다르게 하거나, 프로비저닝 파이프라인을 구성하는 경우 외부 값을 변수에 지정할 수 있다.
- main.tf 코드 파일 내용 수정
variable "my_var" {}
resource "local_file" "abc" {
content = var.my_var
filename = "${path.module}/abc.txt"
}
- [우선순위 수준]의 숫자가 작을수록 우선순위도 낮다.

[실습1] VPC + 보안그룹 + EC2 배포
- 실습내용:default VPC 대신 VPC를 직접 만들고 해당 VPC 내에 EC2 1대를배포
vpc.tf 배포
# 신규 디렉토리 생성
mkdir my-vpc-ec2
cd my-vpc-ec2
# vpc.tf 파일 생성
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_vpc" "myvpc" {
cidr_block = "10.10.0.0/16"
tags = {
Name = "t101-study"
}
}
# 배포
terraform init && terraform plan && terraform apply -auto-approve
terraform state list
terraform state show aws_vpc.myvpc
# VPC 확인
export AWS_PASER=""
aws ec2 describe-vpcs | jq
aws ec2 describe-vpcs --filter 'Name=isDefault,Values=false" | jq
aws ec2 describe-vpcs --filter 'Name=isDefault,Values=false' --output yaml
# AWS 관리콘솔에서 VPC 생성 정보 확인 : DNS 옵션값확인
#VPC.tf 내용수정: VPC DNS옵션 수정
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_vpc" "myvpc" {
cidr_block = "10.10.0.0/16"
enable_dns_support = true
enable_dns_hostnames = true
tags= {
Name ="t101-study"
}
}
# 배포
terraform plan && terraformapply -auto-approve
# VPC.tf 내용수정: 서브넷 2개 생성 추가
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_vpc" "myvpc" {
cidr_block = "10.10.0.0/16"
enable_dns_support = true
enable_dns_hostnames = true
tags = {
Name = "t101-study"
}
}
resource "aws_subnet" '"mysubnet2" {
vpc_id = aws_vpc.myvpc.id
cidr_block = "10.10.2.0/24"
availability_zone ="ap-northeast-2c"
tags = {
Name = "t101-subnet2"
}
}
output "aws_vpc_id" {
value = aws_vpc.myvpc.id
}
# 배포
terraform plan && terraform apply -auto-approve
terraform state list
terraform state show aws_subnet.mysubnet1
terraform output
terraform output aws_vpc_id
terraform output -raw aws_vpc_id
#VPC.tf 내용수정 : IGW 로 전달하는 디폴트 라우팅 정보 추가
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_vpc" "myvpc" {
cidr_block = "10.10.0.0/16"
enable_dns_support = true
enable_dns_hostnames = true
tags = {
Name = "t101-study"
}
}
resource "aws_subnet" "mysubnet1" {
vpc_id = aws_vpc.myvpc.id
cidr_block = "10.10.1.0/24"
availability_zone = "ap-northeast-2a"
tags = {
Name = "t101-subnet1"
}
}
resource "aws_subnet" "mysubnet2" {
vpc_id = aws_vpc.myvpc.id
cidr_block = "10.10.2.0/24"
availability_zone = "ap-northeast-2c"
tags = {
Name = "t101-subnet2"
}
}
resource "aws_internet_gateway" "myigw" {
vpc_id = aws_vpc.myvpc.id
tags = {
Name = "t101-igw"
}
}
resource "aws_route_table" "myrt" {
vpc_id = aws_vpc.myvpc.id
tags = {
Name = "t101-rt"
}
}
resource "aws_route_table_association" "myrtassociation1" {
subnet_id = aws_subnet.mysubnet1.id
route_table_id = aws_route_table.myrt.id
}
resource "aws_route_table_association" "myrtassociation2" {
subnet_id = aws_subnet.mysubnet2.id
route_table_id = aws_route_table.myrt.id
}
resource "aws_route" "mydefaultroute" {
route_table_id = aws_route_table.myrt.id
destination_cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.myigw.id
}
output "aws_vpc_id" {
value = aws_vpc.myvpc.id
}
# 배포
terraform plan && terraform apply -auto-approve
terraform state list
aws_internet_gateway.myigw
aws_route.mydefaultroute
aws_route_table.**myrt
aws_route_table_association.myrtassociation1
aws_route_table_association.myrtassociation2
aws_subnet.mysubnet1
aws_subnet.mysubnet2
aws_vpc.myvpc
terraform state show aws_route.mydefaultroute
# graph 확인 > graph.dot 파일 선택 후 오른쪽 상단 DOT 클릭
terraform graph > graph.dot
# 라우팅 테이블 확인
#aws ec2 describe-route-tables --filters 'Name=tag:Name,Values=t101-rt' --query 'RouteTables[].Associations[].SubnetId'
aws ec2 describe-route-tables --filters 'Name=tag:Name,Values=**t101-rt**' --output table
sg.tf 배포
# sg.tf 파일 생성 : 보안그룹 생성
resource "aws_security_group" "mysg" {
vpc_id = aws_vpc.myvpc.id
name = "T101 SG"
description = "T101 Study SG"
}
resource "aws_security_group_rule" "mysginbound" {
type = "ingress"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
security_group_id = aws_security_group.mysg.id
}
resource "aws_security_group_rule" "mysgoutbound" {
type = "egress"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
security_group_id = aws_security_group.mysg.id
}
# 보안그룹 배포
ls *.tf
terraform plan && terraform apply -auto-approve
terraform state list
aws_security_group.mysg
aws_security_group_rule.mysginbound
aws_security_group_rule.mysgoutbound
...
terraform state show aws_security_group.mysg
terraform state show aws_security_group_rule.mysginbound
# graph 확인 > graph.dot 파일 선택 후 오른쪽 상단 DOT 클릭
terraform graph > graph.dot
ec2.tf 파일 생성 : EC2 생성
data "aws_ami" "my_amazonlinux2" {
most_recent = true
filter {
name = "owner-alias"
values = ["amazon"]
}
filter {
name = "name"
values = ["amzn2-ami-hvm-*-x86_64-ebs"]
}
owners = ["amazon"]
}
resource "aws_instance" "myec2" {
depends_on = [
aws_internet_gateway.myigw
]
ami = data.aws_ami.my_amazonlinux2.id
associate_public_ip_address = true
instance_type = "t2.micro"
vpc_security_group_ids = ["${aws_security_group.mysg.id}"]
subnet_id = aws_subnet.mysubnet1.id
user_data = <<-EOF
#!/bin/bash
wget https://busybox.net/downloads/binaries/1.31.0-defconfig-multiarch-musl/busybox-x86_64
mv busybox-x86_64 busybox
chmod +x busybox
RZAZ=$(curl http://169.254.169.254/latest/meta-data/placement/availability-zone-id)
IID=$(curl 169.254.169.254/latest/meta-data/instance-id)
LIP=$(curl 169.254.169.254/latest/meta-data/local-ipv4)
echo "<h1>RegionAz($RZAZ) : Instance ID($IID) : Private IP($LIP) : Web Server</h1>" > index.html
nohup ./busybox httpd -f -p 80 &
EOF
user_data_replace_on_change = true
tags = {
Name = "t101-myec2"
}
}
output "myec2_public_ip" {
value = aws_instance.myec2.public_ip
description = "The public IP of the Instance"
}
배포 후 EC2 확인
ls *.tf
terraform plan && terraform apply -auto-approve
terraform state list
data.aws_ami.my_amazonlinux2
aws_instance.myec2
...
terraform state show data.aws_ami.my_amazonlinux2
terraform state show aws_instance.myec2
# 데이터소스 값 확인
terraform console
>
data.aws_ami.my_amazonlinux2.id
"ami-01c81850a6167bb81"
data.aws_ami.my_amazonlinux2.image_id
data.aws_ami.my_amazonlinux2.name
data.aws_ami.my_amazonlinux2.owners
data.aws_ami.my_amazonlinux2.platform_details
data.aws_ami.my_amazonlinux2.hypervisor
data.aws_ami.my_amazonlinux2.architecture
exit
# graph 확인 > graph.dot 파일 선택 후 오른쪽 상단 DOT 클릭
terraform graph > graph.dot
# 출력된 EC2 퍼블릭IP로 cul 접속 확인
terraform output -raw myec2_public_ip
13.29.103.4
MYIP=$(terraform output -raw myec2_public_ip)
while true; do curl --connect-timeout 1 http://$MYIP/ ; echo "------------------------------"; date; sleep 1; done
삭제
terraform destroy -auto-approve
3.local
- 코드 내에서 사용자가 지정한 값 또는 속성 값을 가공해 참조 가능한 local (지역 값)은 외부에서 입력되지 않고, 코드 내에서만 가공되어 동작하는 값을 선언
- local은 입력 변수와 달리 선언된 모듈 내에서만 접근 가능하고, 변수처럼 실행 시에 입력받을 수 없다
- 로컬은 사용자가 테라폼 코드를 구현할 때 값이나 표현식을 반복적으로 사용할 수 있는 편의를 제공
- 빈번하게 여러 곳에서 사용되는 경우 실제 값에 대한 추적이 어려워져 유지 관리 측면에서 부담이 발생할 수 있으므로 주의
local 선언
- 로컬이 선언되는 블록은 locals로 시작한다. 선언되는 인수에 표현되는 값은 상수만이 아닌 리소스의 속성, 변수의 값들도 조합해 정의할 수 있다.
- 동일한 tf 파일 내에서 여러 번 선언하는 것도 가능하고 여러 파일에 걸쳐 만드는 것도 가능하다.
- 다만 lcoals에 선언한 로컬 변수 이름은 전체 루트 모듈 내에서 유일해야 한다.
- 정의되는 속성 값은 지정된 값의 형태에 따라 다양한 유형으로 정의할 수 있다.
- main.tf 파일 : local 값 선언 방식의 예
# 실습을 위해 3.7 디렉토리를 생성하고 main.tf 파일을 생성
$ cd .. && rm -rf 3.6
$ mkdir 3.7 && cd 3.7
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" # 중복 선언되었으므로 오류가 발생한다.
}
실행
$ terraform init
main.tf 파일 수정
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]
}
#
$ terraform init
$ terraform apply -auto-approve
# 실제로 사용한 리소스가 없음
$ terraform state list
# 출력이 없다.
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}"
}
실행 : main.tf의 content 내용 값으로 local.content를 참조하며, 해당 값은 다른 테라폼 구성 파일에 있지만 실행 시점에는 마치 하나의 구성 파일 처럼 올바로 표기되는 것을 확인할 수 있다.
#
ls *.tf
terraform init -upgrade
terraform apply -auto-approve
terraform state list
terraform state show local_file.abc
# graph 확인 > graph.dot 파일 선택 후 오른쪽 상단 DOT 클릭
terraform graph > graph.dot
#
cat abc.txt ; echo
이 예제에서는 서로 다른 테라폼 구성 파일에서도 로컬 값을 참조할 수 있다는 가능성을 확인할 수 있지만, 관리 측면에서는 서로 참조하는 로컬값이 파편화되어 유지 보수가 어려워질 수 있으므로 주의가 필요하다.
[실습2] IAM User 생성
iam user 생성
mkdir local-test && cd local-test
# iamuser.tf 파일 생성
provider "aws" {
region = "ap-northeast-2"
}
locals {
name = "mytest"
team = {
group = "dev"
}
}
resource "aws_iam_user" "myiamuser1" {
name = "${local.name}1"
tags = local.team
}
resource "aws_iam_user" "myiamuser2" {
name = "${local.name}2"
tags = local.team
}
# 콘솔에서 IAM User 확인
terraform init && terraform apply -auto-approve
terraform state list
terraform state show aws_iam_user.myiamuser1
# graph 확인 > graph.dot 파일 선택 후 오른쪽 상단 DOT 클릭
terraform graph > graph.dot
# iam 사용자 리스트 확인
aws iam list-users | jq
# 삭제
terraform destroy -auto-approve
4.output
출력 값은 주로 테라폼 코드의 프로비저닝 수행 후의 결과 속성 값을 확인하는 용도로 사용된다.
또한 프로그래밍 언어에서 코드 내 요소 간에 제한된 노출을 지원하듯, 테라폼 모듈 간, 워크스페이스 간 데이터 접근 요소로도 활용할 수 있다.
예를 들면 자바의 getter와 비슷한 역할이다. 출력 값의 용도는 다음과 같이 정의할 수 있다.
- 루트 모듈에서 사용자가 확인하고자 하는 특정 속성 출력
- 자식 모듈의 특정 값을 정의하고 루트 모듈에서 결과를 참조
- 서로 다른 루트 모듈의 결과를 원격으로 읽기 위한 접근 요소
output 선언
- 모듈 내에서 생성되는 속성 값들은 output 블록에 정의된다
output "instance_ip_addr" {
value = "http://${aws_instance.server.private_ip}"
}
출력되는 값은 value의 값이며 테라폼이 제공하는 조합과 프로그래밍적인 기능들에 의해 원하는 값을 출력할 수 있다.
주의할 점은 output 결과에서 리소스 생성 후 결정되는 속성 값은 프로비저닝이 완료되어야 최종적으로 결과를 확인할 수 있고 terraform plan 단계에서는 적용될 값이 출력하지 않는다는 것이다.
변수 정의 시 사용 가능한 메타인수는 다음과 같다.
- description : 출력 값 설명
- sensitive : 민감한 출력 값임을 알리고 테라폼의 출력문에서 값 노출을 제한
- depends_on : value에 담길 값이 특정 구성에 종속성이 있는 경우 생성되는 순서를 임의로 조정
- precondition : 출력 전에 지정된 조건을 검증
output 활용
# 실습을 위해 3.8 디렉토리를 생성하고 main.tf 파일을 생성
$ cd .. && rm -rf 3.7
$ mkdir 3.8 && cd 3.8
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"
#
terraform state list
terraform output
- 추가) abs 함수: 숫자의 절대값 반환, 음수면 양수로 — 링크, abapath 함수
5. loop
list 형태의 값 목록이나 Key-Value 형태의 문자열 집합인 데이터가 있는 경우 동일한 내용에 대해 테라폼 구성 정의를 반복적으로 하지 않고 관리할 수 있다.
- count : 반복문, 정수 값만큼 리소스나 모듈을 생성
- 리소스 또는 모듈 블록에 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[0]" | terraform console
ls *.txt
terraform output
# terraform output filename
# terraform output fileid
# terraform output filecontent
- main.tf 파일 수정 : count.index 값 추가
resource "local_file" "abc" {
count = 5
content = "abc${count.index}"
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[0]" | terraform console
ls *.txt
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"
}
- 실행 후 확인 : local_file.abc와 local_file.def는 var.name에 선언되는 값에 영향을 받아 동일한 갯수만큼 생성하게 된다.
- local_file.def의 경우 local_file.abc와 개수가 같아야 content에 선언되는 인수 값에 오류가 없을 것이므로 서로 참조되는 리소스와 모듈의 반복정의에 대한 공통의 영향을 주는 변수로 관리할 수 있다.
#
terraform apply -auto-approve
terraform state list
ls *.txt
diff abc-a.txt abc-b.txt
diff abc-a.txt def-c.txt
echo "local_file.abc[0]" | terraform console
echo "local_file.def[0]" | terraform console
terraform output
# terraform output filename
# terraform output fileid
# terraform output filecontent
# graph 확인 > graph.dot 파일 선택 후 오른쪽 상단 DOT 클릭
terraform graph > graph.dot
- count로 생성되는 리소스의 경우 <리소스 타입>.<이름>[<인덱스 번호>], 모듈의 경우 module.<모듈 이름>[<인덱스 번호>]로 해당 리소스의 값을 참조한다.
- 단, 모듈 내에 count 적용이 불가능한 선언이 있으므로 주의해야 한다.
- 예를 들어 provider 블록 선언부가 포함되어 있는 경우에는 count 적용이 불가능하다 → provider 분리
- 또한 외부 변수가 list 타입인 경우 중간에 값이 삭제되면 인덱스가 줄어들어 의도했던 중간 값에 대한 리소스만 삭제되는 것이 아니라 이후의 정의된 리소스들도 삭제되고 재생성된다. → 아래 실습으로 확인
main.tf 파일 수정 : list 형태의 값 변경
```bash
variable "names" {
type = list(string)
default = **["a", "c"]** # index 1자리의 b를 삭제
}
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 plan
ls -l *.txt
terraform apply -auto-approve
#
terraform state list
ls *.txt
- 배열의 중간에 항목을 제거하면 모든 항목이 1칸씩 앞으로 당겨짐.
- 테라폼이 인덱스 번호를 리소스 식별자로 보기 때문에 ‘인덱스 1에서는 계정 생성, 인덱스2에서는 계정 삭제한다’라고 해석합니다.
- 즉 count 사용 시 목록 중간 항목을 제거하면 테라폼은 해당 항목 뒤에 있는 모든 리소스를 삭제한 다음 해당 리소스를 처음부터 다시 만듬
2. for_each : 반복문, 선언된 key 값 개수만큼 리소스를 생성
- 리소스 또는 모듈 블록에서 for_each에 입력된 데이터 형태가 map 또는 set이면, 선언된 key 값 개수만큼 리소스를 생성하게 된다.
- main.tf 파일 수정 : for_each 값이 있는 반복문 동작 확인
resource "local_file" "abc" {
for_each = {
a = "content a"
b = "content b"
}
content = each.value
filename = "${path.module}/${each.key}.txt"
}
- 실행 후 확인
#
terraform apply -auto-approve
terraform state list
ls *.txt
cat a.txt ;echo
cat b.txt ;echo
echo 'local_file.abc["a"]' | terraform console
- or_each가 설정된 블록에서는 each 속성을 사용해 구성을 수정할 수 있다
- each.key : 이 인스턴스에 해당하는 map 타입의 key 값
- each.value : 이 인스턴스에 해당하는 map의 value 값
- 생성되는 리소스의 경우 <리소스 타입>.<이름>[<key>], 모듈의 경우 module.<모듈 이름>[<key>]로 해당 리소스의 값을 참조한다.
- 이 참조 방식을 통해 리소스 간 종속성을 정의하기도 하고 변수로 다른 리소스에서 사용하거나 출력을 위한 결과 값으로 사용한다.
- main.tf 파일 수정 : local_file.abc는 변수의 map 형태의 값을 참조, local_file.def의 경우 local_file.abc 도한 결과가 map으로 반환되므로 다시 for_each 구문을 사용할 수 있다
variable "names" {
default = {
a = "content a"
b = "content b"
c = "content c"
}
}
resource "local_file" "abc" {
for_each = var.names
content = each.value
filename = "${path.module}/abc-${each.key}.txt"
}
resource "local_file" "def" {
for_each = local_file.abc
content = each.value.content
filename = "${path.module}/def-${each.key}.txt"
}
- 실행 후 확인
#
terraform apply -auto-approve
terraform state list
ls *.txt
- key 값은 count의 index와는 달리 고유하므로 중간에 값을 삭제한 후 다시 적용해도 삭제한 값에 대해서만 리소스를 삭제한다.
- main.tf 파일 수정 : count 경우와 유사하게 중간 값을 삭제 후 확인
variable "names" {
default = {
a = "content a"
c = "content c"
}
}
resource "local_file" "abc" {
for_each = var.names
content = each.value
filename = "${path.module}/abc-${each.key}.txt"
}
resource "local_file" "def" {
for_each = local_file.abc
content = each.value.content
filename = "${path.module}/def-${each.key}.txt"
}
- 실행 후 확인
#
terraform apply -auto-approve
terraform state list
ls *.txt
3. for : 복합 형식 값의 형태를 변환하는 데 사용 ← for_each와 다름
- 예를 들어 list 값의 포맷을 변경하거나 특정 접두사 prefix를 추가할 수도 있고, output에 원하는 형태로 반복적인 결과를 표현할 수 도 있다.
- list 타입의 경우 값 또는 인덱스와 값을 반환
- map 타입의 경우 키 또는 키와 값에 대해 반환
- set 타입의 경우 키 값에 대해 반환
- main.tf 파일 수정 : list의 내용을 담는 리소스를 생성, var.name의 내용이 결과 파일에 content로 기록됨
variable "names" {
default = ["a", "b", "c"]
}
resource "local_file" "abc" {
content = jsonencode(var.names) # 결과 : ["a", "b", "c"]
filename = "${path.module}/abc.txt"
- 실행 후 확인 : jsonencode Function — 링크
terraform apply -auto-approve
terraform state list
ls *.txt
cat abc.txt ;echo
echo "local_file.abc" | terraform console
# 참고 jsonencode Function
echo 'jsonencode({"hello"="world"})' | terraform console
for 구문을 사용하는 몇 가지 규칙은 다음과 같다
- list 유형의 경우 반환 받는 값이 하나로 되어 있으면 값을, 두 개의 경우 앞의 인수가 인덱스를 반환하고 뒤의 인수가 값을 반환
- 관용적으로 인덱스는 i, 값은 v로 표현
- map 유형의 경우 반환 받는 값이 하나로 되어 있으면 키를, 두 개의 경우 앞의 인수가 키를 반환하고 뒤의 인수가 값을 반환
- 관용적으로 키는 k, 값은 v로 표현
- 결과 값은 for 문을 묶는 기호가 **[ ]**인 경우 tuple로 반환되고 **{ }**인 경우 object 형태로 반환
- object 형태의 경우 키와 값에 대한 쌍은 ⇒ 기호로 구분
- { } 형식을 사용해 object 형태로 결과를 반환하는 경우 키 값은 고유해야 하므로 값 뒤에 그룹화 모드 심볼(…)를 붙여서 키의 중복을 방지(SQL의 group by 문 또는 Java의 MultiValueMap과 같은 개념)
- if 구문을 추가해 조건 부여 가능
main.tf 파일 수정 : list 유형에 대한 for 구문 처리의 몇 가지 예를 확인
variable "names" {
type = list(string)
default = ["a", "b"]
}
output "A_upper_value" {
value = [for v in var.names : upper(v)]
}
output "B_index_and_value" {
value = [for i, v in var.names : "${i} is ${v}"]
}
output "C_make_object" {
value = { for v in var.names : v => upper(v) }
}
output "D_with_filter" {
value = [for v in var.names : upper(v) if v != "a"]
}
실행 후 확인
#
terraform apply -auto-approve
terraform state list
#
terraform output
terraform output A_upper_value
terraform output D_with_filter
#
terraform console
>
-----------------
var.names
[for v in var.names : upper(v)]
[for i, v in var.names : "${i} is ${v}"]
{ for v in var.names : v => upper(v) }
[for v in var.names : upper(v) if v != "a"]
exit
-----------------
main.tf 파일 수정 : map 유형에 대한 for 구문 처리의 몇 가지 예를 확인
variable "members" {
type = map(object({
role = string
}))
default = {
ab = { role = "member", group = "dev" }
cd = { role = "admin", group = "dev" }
ef = { role = "member", group = "ops" }
}
}
output "A_to_tupple" {
value = [for k, v in var.members : "${k} is ${v.role}"]
}
output "B_get_only_role" {
value = {
for name, user in var.members : name => user.role
if user.role == "admin"
}
}
output "C_group" {
value = {
for name, user in var.members : user.role => name...
}
}
실행 후 확인
#
terraform apply -auto-approve
terraform state list
#
terraform output
terraform output A_upper_value
#
terraform console
>
-----------------
var.members
[for k, v in var.members : "${k} is ${v.role}"]
{for name, user in var.members : name => user.role}
{for name, user in var.members : name => user.role if user.role == "admin"}
{for name, user in var.members : user.role => name...}
exit
-----------------
4. dynamic : 리소스 내부 속성 블록을 동적인 블록으로 생성
- count 나 for_each 구문을 사용한 리소스 전체를 여러 개 생성하는 것 이외도 리소스 내에 선언되는 구성 블록을 다중으로 작성해야 하는 경우가 있다.
- 예를 들면 AWS Security Group 리소스 구성에 ingress, egress 요소가 리소스 선언 내부에서 블록 형태로 여러 번 정의되는 경우다.
resource "aws_security_group" "example" {
name = "example-security-group"
description = "Example security group"
vpc_id. = aws_vpc.main.id
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
ipv6_cidr_blocks = ["::/0"]
}
}
- 리소스 내의 블록 속성(Attributes as Blocks)은 리소스 자체의 반복 선언이 아닌 내부 속성 요소 중 블록으로 표현되는 부분에 대해서만 반복 구문을 사용해야 하므로, 이때 dynamic 블록을 사용해 동적인 블록을 생성 할 수 있다.
- dynamic 블록을 작성하려면, 기존 블록의 속성 이름을 dynamic 블록의 이름으로 선언하고 기존 블록 속성에 정의되는 내용을 content 블록에 작성한다.
- 반복 선언에 사용되는 반복문 구문은 for_each를 사용한다. 기존 for_each 적용 시 each 속성에 key, value가 적용되었다면 dynamic에서는 dynamic에 지정한 이름에 대해 속성이 부여된다.
- dynamic 블록 활용 예
main.tf 파일 수정 : archive 프로바이더(링크)의 archive_file에 source 블록 선언을 반복 — 링크
data "archive_file" "dotfiles" {
type = "zip"
output_path = "${path.module}/dotfiles.zip"
source {
content = "hello a"
filename = "${path.module}/a.txt"
}
source {
content = "hello b"
filename = "${path.module}/b.txt"
}
source {
content = "hello c"
filename = "${path.module}/c.txt"
}
}
실행 후 확인
#
terraform init -upgrade
terraform apply -auto-approve
terraform state list
terraform state show data.archive_file.dotfiles
ls *.zip
unzip dotfiles.zip
ls *.txt
cat a.txt ; echo
main.tf 파일 수정 : 리소스 내에 반복 선언 구성을 dynamic 블록으로 재구성
variable "names" {
default = {
a = "hello a"
b = "hello b"
c = "hello c"
}
}
data "archive_file" "dotfiles" {
type = "zip"
output_path = "${path.module}/dotfiles.zip"
dynamic "source" {
for_each = var.names
content {
content = source.value
filename = "${path.module}/${source.key}.txt"
}
}
}
실행 후 확인 : 동일한 결과가 기대되어 변경 사항이 없다!
#
terraform apply -auto-approve
terraform state list
terraform state show data.archive_file.dotfiles
ls *.zip
[실습3] 반복문
# IAM 사용자 3명 생성
# 사용자 1명 생성 코드
provider "aws" {
region = "us-east-2"
}
resource "aws_iam_user" "example" {
name = "neo"
}
# 테라폼은 for 반복문 또는 언어에 내장된 절차 논리가 없다
# 테라폼에서 count 를 사용하여 3명 IAM 사용자 생성
# → 3명의 IAM 사용자 이름 중복으로 오류 발생
# ⇒ for 반복문의 인덱스를 사용하여 각 사용자에게 고유한 이름 지정 가능
resource "aws_iam_user" "example" {
count = 3
name = "neo"
}
# iam.tf
# count.index 를 사용하여 반복문 안에 있는 각각의 반복 ieration 을 가리키는 인덱스를 얻을 수 있음
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_iam_user" "myiam" {
count = 3
name = "myuser.${count.index}"
}
# init & plan 실행 및 apply
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]
aws iam list-users | jq
...
#
terraform console
>
-----------------
aws_iam_user.myiam
aws_iam_user.myiam[0]
aws_iam_user.myiam[1].name
exit
-----------------
# 삭제
terraform destroy -auto-approve
aws iam list-users | jq
# count 입력 변수를 통해 IAM 사용자 생성
# 입력 변수 코드 생성 variables.tf
variable "user_names" {
description = "Create IAM users with these names"
type = list(string)
default = ["gasida", "akbun", "ssoon"]
}
# 테라폼에서 count 와 함께 배열 조회 구문과 length 함수를 사용해서 사용자들 생성 가능
# 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 사용한 후에는 하나의 리소스가 아니라 리소스의 배열이 됨
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
# output.tf
# IAM 사용자 전체의 ARN을 원하면 인덱스 대신 스플랫 splat 연산자인 * 를 사용
terraform apply -auto-approve
terraform state list
terraform output
terraform output all_arns
# 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
}
}
# 위 ASG 리소스 태그 설정 방법에서 각각의 tag 를 사용하려면
# key, value, propagate_at_launch 에 대한 값으로 새 인라인 블록을 만들어야 함
# 배열 중간 값을 변경할 때 발생
#실습을 위해 다시 IAM 사용자 생성
terraform apply -auto-approve
# variables.tf : IAM 사용자 생성 목록에서 생각
variable "user_names" {
description = "Create IAM users with these names"
type = list(string)
default = ["**gasida**", "**akbun**", "**ssoon**"]
}
# variables.tf : 중간에 있는 akbun 을 제거하고 plan & apply
variable "user_names" {
description = "Create IAM users with these names"
type = list(string)
default = ["gasida", "ssoon"]
}
# plan : 출력 내용 확인!
terraform plan
...
~ update in-place
- destroy
# 배열의 중간에 항목을 제거하면 모든 항목이 1칸씩 앞으로 당겨짐
# 즉 count 사용 시 목록 중간 항목을 제거하면
# 테라폼은 해당 항목 뒤에 있는 모든 리소스를 삭제한 다음 해당 리소스를 처음부터 다시 만듬
# 삭제
terraform destroy -auto-approve
aws iam list-users | jq
# for_each 표현식을 사용하면
# 리스트 lists, 집합 sets, 맵 maps 를 사용하여
# 전체 리소스의 여러 복사본 또는 리소스 내 인라인 블록의 여러 복사본, 모듈의 복사본을 생성 할 수 있음
# 먼저 for_each 를 사용하여 리소스의 여러 복사본을 만드는 구문
resource "<PROVIDER>_<TYPE>" "<NAME>" {
for_each = <COLLECTION>
[CONFIG ...]
}
# COLLECTION은 루프를 처리할 집합 sets 또는 맵 maps
# 리소스에 for_each 를 사용할 때에는 리스트는 지원하지 않음
# CONFIG 는 해당 리소스와 관련된 하나 이상의 인수로 구성되는데
# CONFIG 내에서 each.key 또는 each.value 를 사용하여
# COLLECTION 에서 현재 항목의 키와 값에 접근할 수 있음
# for_each 를 사용하여 3명의 IAM 사용자를 생성하는 방법
# var.user_names 리스트를 집합(set)으로 변환하기 위해 toset 사용.
# for_each 는 리소스에 사용될 때는 집합과 맵만 지원.
# for_each 가 이 집합을 반복하면 each.value 에서 각 사용자 이름을 사용할 수 있음
# iam.tf : 일반적으로는 each.key 는 키/값 쌍 맵에서만 사용가능하지만
# 사용자 이름은 each.key 에서도 사용할 수 있음
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_iam_user" "myiam" {
for_each = toset(var.user_names)
name = each.value
}
# variables.tf
variable "user_names" {
description = "Create IAM users with these names"
type = list(string)
default = ["gasida", "akbun", "ssoon"]
}
# for_each 를 사용한 후에는 하나의 리소스 또는 count 를 사용한 것과 같은
# 리소스 배열이 되는 것이 아니라 리소스 맵 list into a set 이 됨
# outputs.tf : 이 의미를 확인하려면 원래의 outputs 을 제거하고 새로운 all_users 출력 변수를 추가
output "all_users" {
value = aws_iam_user.myiam
}
# plan & apply
terraform plan && terraform apply -auto-approve
# 확인
terraform state list
terraform output
# for_each 를 사용해 리소스를 맵으로 처리하면 컬렉션 중간의 항목도 안전하게 제거할 수 있어서,
# count 로 리소스를 배열 처리보다 이점이 큼
# variables.tf
variable "user_names" {
description = "Create IAM users with these names"
type = list(string)
default = ["gasida", "ssoon"]
}
# plan & apply
terraform plan
terraform apply -auto-approve
terraform state list
# 삭제
terraform destroy -auto-approve
aws iam list-users | jq
위 내용 외에 도서 ‘Terraform: Up & Running(By Yevgeniy Brikman)’ 를 기준으로 작성된 지난 블로그 글을 참고하여 테라폼 학습에 도움되시길 바랍니다.
[IaC] Terraform tips & tricks — Loops & Conditions
[IaC] Managing Secrets with Terraform
[IaC] Production-grade Terraform code
[IaC] GKE configuration deep dive
[IaC] Working with Multiple Providers
blog migration project
written in 2023.9.9
https://medium.com/techblog-hayleyshim/iac-%EA%B8%B0%EB%B3%B8-%EC%82%AC%EC%9A%A9%EB%B2%95-data-source-input-variables-local-output-loop-eb8e0a85d1be
'Programming > IaC' 카테고리의 다른 글
[IaC] State & 모듈 (0) | 2023.10.28 |
---|---|
[IaC] 기본 사용법( condition, function, provisioner, null_resource와 terraform_data, moved block, cli를 위한 시스템 환경 변수) & 프로바이더 (0) | 2023.10.28 |
[IaC] IaC/테라폼 이해, 기본 명령 사용법( command, HCL, block, resource) (0) | 2023.10.28 |
[IaC] Working with Multiple Providers (0) | 2023.10.28 |
[IaC] GKE configuration deep dive (0) | 2023.10.28 |
- Total
- Today
- Yesterday
- 혼공챌린지
- operator
- 도서
- cloud
- security
- S3
- SDWAN
- controltower
- VPN
- terraform
- AI
- PYTHON
- handson
- 국제 개발 협력
- 혼공단
- EKS
- 파이썬
- k8s cni
- GCP
- gcp serverless
- k8s
- NW
- k8s calico
- AWS
- IaC
- OS
- 혼공파
- NFT
- GKE
- cni
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |