⭐ 가시다(gasida) 님이 진행하는 Terraform T101 4기 실습 스터디 게시글입니다.
책 '테라폼으로 시작하는 IaC' 를 기준으로 정리하였습니다.
게시글 상 소스코드, 사진에서 **굵게** 혹은 '''코드쉘''' 에 대한 부분이 들어가있을수도 있습니다.
AWS 실습 환경설정
AWS CLI 설치 및 자격증명
- AWS default VPC 를 사용
- AWS IAM User 생성(권한수준: AdministratorAccess, 액세스 방식:CLI)
aws configure
#AWS Access Key ID [****************RGXL]:
#AWS Secret Access Key [****************n+SO]:
#Default region name [ap-northeast-2]:
#Default output format [json]:
Default VPC 존재 확인
aws ec2 describe-vpcs --filter 'Name=isDefault,Values=true' | jq '.Vpcs[0].VpcId'
(Default VPC가 없는 경우) Default VPC 생성
aws ec2 create-default-vpc
# default Subnet 생성
aws ec2 create-default-subnet --availability-zone ap-northeast-2a
aws ec2 create-default-subnet --availability-zone ap-northeast-2b
aws ec2 create-default-subnet --availability-zone ap-northeast-2c
aws ec2 create-default-subnet --availability-zone ap-northeast-2d
기본적인 테라폼 언어 구조
resource "{provider}"_"{type}" "{name}" {
#config
}
- provider: 공급자 이름
- type: 리소스의 유형
- name: 리소스 이름
- config: 한개 이상의 arguments
AWS EC2 배포 실습1 : 단순배포
터미널1
#Amazon Linux 2 최신 ami id 찾기
AL2ID=`aws ec2 describe-images --owners amazon --filters "Name=name,Values=amzn2-ami-hvm-2.0.*-x86_64-gp2" "Name=state,Values=available" --query 'Images|sort_by(@, &CreationDate)[-1].[ImageId]' --output text`
echo $AL2ID
#main.tf 설정
cat <<EOT > main.tf
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_instance" "example" {
ami = "$AL2ID"
instance_type = "t2.micro"
}
EOT
# [터미널1] EC2 생성 모니터링
export AWS_PAGER=""
while true; do aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output text ; echo "------------------------------" ; sleep 1; done
터미널2
#초기화
terramform init
#확인
ls -al
#실행계획 확인
terraform plan
#실행계획 실행
terraform apply #yes
#EC2 생성확인 (seoul region)
export AWS_PAGER=""
aws ec2 describe-instances --output table
배포완료!
AWS EC2 배포 실습2 : 업데이트
코드파일 변경
#main.tf
#tags 파일이 추가됨에 주의
cat <<EOT > main.tf
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_instance" "example" {
ami = "$AL2ID"
instance_type = "t2.micro"
tags = {
Name = "t101-study"
}
}
EOT
#배포 계획 확인
terraform plan
terraform plan
명령어는 배포계획을 설명해주며, 이때 추가되는 리소스, 변경되는 리소스, 제거되는 리소스를 요약하여 설명해준다.
#배포실행
terraform apply #yes
AWS EC2 배포 실습3 : 배포리소스 제거
#리소스 삭제
#방법1
terraform destroy #yes
#방법2
terraform destroy -auto-approve
terraform 주요 커맨드 실습
자주 사용하는 명령어 정리
terraform init
: 루트모듈(작업구성파일이 있는 디렉토리) 초기화
terraform validate
: 코드적인 문법의 유효성 검사
terraform plan
: 변경사항에 관한 실행계획생성
terraform apply
: 실행계획(plan) 에서 작성된 내용을 실제로 적용
terraform destroy
: 모든 리소스를 제거
실습 디렉토리, 파일 생성
mkdir 03.start
cd 03.start
#vi main.tf
resource "local_file" "abc" {
content = "abc!"
filename = "${path.module}/abc.txt"
}
EOF
#:wq!
terraform init
: init
되지 않은 상태에서 plan
실행
terraform plan
╷
│ Error: Inconsistent dependency lock file
│
│ The following dependency selections recorded in the lock file are inconsistent with the current configuration:
│ - provider registry.terraform.io/hashicorp/local: required by this configuration but no version is selected
│
│ To make the initial dependency selections that will initialize the dependency lock file, run:
│ terraform init
╵
terraform init
으로 초기화시켜주지않으면, plan, apply 등을 실행할 수 없다.
terraform validate: 파일 검증
main.tf수정
resource "local_file" "abc" {
content = "abc!"
# filename = "${path.module}/abc.txt"
}
terraform init #성공
terraform validate
╷
│ Error: Missing required argument
│
│ on main.tf line 1, in resource "local_file" "abc":
│ 1: resource "local_file" "abc" {
│
│ The argument "filename" is required, but no definition was found.
╵
- 필수 argument filename 을 설정해주지 않아서 생기는 에러.
- terraform init 은 성공적으로 진행, 그러나 코드검사에서 에러발견
main.tf수정
resource "local_file" "abc" {
content = "abc!"
filename = "${path.module}/abc.txt"
}
검증
#단순검정
terraform validate
#json 형태로 표시
terraform validate -json
#json 형태로 표시 + 색깔구분
terraform validate -json | jq
terraform plan: 실제로 테라폼으로 적용할 인프라의 변경 사항에 관한 실행계획을 생성.
terraform plan
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
+ create
Terraform will perform the following actions:
# local_file.abc will be created
+ resource "local_file" "abc" {
+ content = "abc!"
+ content_base64sha256 = (known after apply)
+ content_base64sha512 = (known after apply)
+ content_md5 = (known after apply)
+ content_sha1 = (known after apply)
+ content_sha256 = (known after apply)
+ content_sha512 = (known after apply)
+ directory_permission = "0777"
+ file_permission = "0777"
+ filename = "./abc.txt"
+ id = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you
run "terraform apply" now.
terraform apply: plan 으로 생성된 계획을 실행하는 옵션
terraform apply
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
+ create
Terraform will perform the following actions:
# local_file.abc will be created
+ resource "local_file" "abc" {
+ content = "abc!"
+ content_base64sha256 = (known after apply)
+ content_base64sha512 = (known after apply)
+ content_md5 = (known after apply)
+ content_sha1 = (known after apply)
+ content_sha256 = (known after apply)
+ content_sha512 = (known after apply)
+ directory_permission = "0777"
+ file_permission = "0777"
+ filename = "./abc.txt"
+ id = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: no #yes 를 입력하면 실행됨
Apply cancelled.
terraform plan -out={filename}
: plan결과를 파일형태로 생성
terraform plan -out=tfplan 15:20:43
Terraform used the selected providers to generate the following execution plan. Resource actions are
indicated with the following symbols:
+ create
Terraform will perform the following actions:
# local_file.abc will be created
+ resource "local_file" "abc" {
+ content = "abc!"
+ content_base64sha256 = (known after apply)
+ content_base64sha512 = (known after apply)
+ content_md5 = (known after apply)
+ content_sha1 = (known after apply)
+ content_sha256 = (known after apply)
+ content_sha512 = (known after apply)
+ directory_permission = "0777"
+ file_permission = "0777"
+ filename = "./abc.txt"
+ id = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
──────────────────────────────────────────────────────────────────────────────────────────────────────────
Saved the plan to: tfplan
To perform exactly these actions, run the following command to apply:
terraform apply "tfplan"
이미 생성된 plan 으로 바로 apply 가능(물어보지않는다)
terraform apply tfplan
local_file.abc: Creating...
local_file.abc: Creation complete after 0s [id=5678fb68a642f3c6c8004c1bdc21e7142087287b]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
확인
terraform state list
local_file.abc
main.tf파일 수정
resource "local_file" "abc" {
content = "abc!"
filename = "${path.module}/abc.txt"
}
resource "local_file" "dev" {
content = "def!"
filename = "${path.module}/def.txt"
}
적용
terraform apply
local_file.abc: Refreshing state... [id=5678fb68a642f3c6c8004c1bdc21e7142087287b]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# local_file.dev will be created
+ resource "local_file" "dev" {
+ content = "def!"
+ content_base64sha256 = (known after apply)
+ content_base64sha512 = (known after apply)
+ content_md5 = (known after apply)
+ content_sha1 = (known after apply)
+ content_sha256 = (known after apply)
+ content_sha512 = (known after apply)
+ directory_permission = "0777"
+ file_permission = "0777"
+ filename = "./def.txt"
+ id = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
local_file.dev: Creating...
local_file.dev: Creation complete after 0s [id=15f946cb27f0730866cefea4f0923248d9366cb0]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
main.tf파일수정
resource "local_file" "abc" {
content = "abc!"
filename = "${path.module}/abc.txt"
}
apply
terraform apply
local_file.abc: Refreshing state... [id=5678fb68a642f3c6c8004c1bdc21e7142087287b]
local_file.dev: Refreshing state... [id=15f946cb27f0730866cefea4f0923248d9366cb0]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
- destroy
Terraform will perform the following actions:
# local_file.dev will be destroyed
# (because local_file.dev is not in configuration)
- resource "local_file" "dev" {
- content = "def!" -> null
- content_base64sha256 = "Rm4skjSqJGFRkUFCflW7rNUZ4sAS3vzjWfrOjTwlDBU=" -> null
- content_base64sha512 = "JwN8zsR7XvAQZ9KkxokoJPkPZt5LElyjPuH0Pmhd82GIL/Zu3rZOHRacv8myxhbbZzpUahtQ6HDB0OMSiXedyA==" -> null
- content_md5 = "3f6d9022e2f7b9cf3995155f239cba7c" -> null
- content_sha1 = "15f946cb27f0730866cefea4f0923248d9366cb0" -> null
- content_sha256 = "466e2c9234aa2461519141427e55bbacd519e2c012defce359face8d3c250c15" -> null
- content_sha512 = "27037ccec47b5ef01067d2a4c6892824f90f66de4b125ca33ee1f43e685df361882ff66edeb64e1d169cbfc9b2c616db673a546a1b50e870c1d0e31289779dc8" -> null
- directory_permission = "0777" -> null
- file_permission = "0777" -> null
- filename = "./def.txt" -> null
- id = "15f946cb27f0730866cefea4f0923248d9366cb0" -> null
}
Plan: 0 to add, 0 to change, 1 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
local_file.dev: Destroying... [id=15f946cb27f0730866cefea4f0923248d9366cb0]
local_file.dev: Destruction complete after 0s
Apply complete! Resources: 0 added, 0 changed, 1 destroyed.
terraform 제거
terraform destroy
local_file.abc: Refreshing state... [id=5678fb68a642f3c6c8004c1bdc21e7142087287b]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
- destroy
Terraform will perform the following actions:
# local_file.abc will be destroyed
- resource "local_file" "abc" {
- content = "abc!" -> null
- content_base64sha256 = "U+Dv8yBGJvPiVspjZXLXzN+OtaGQyd76P6VnvGOGa3Y=" -> null
- content_base64sha512 = "J873Ugx5HyDEnYsjdX8iMBjn4I3gft82udsl3lNeWEoqwmNE3mvUZNNz4QRqQ3iaT5SW1y9p3e1Xn2txEBapKg==" -> null
- content_md5 = "4edb03f55c86d5e0a76f5627fa506bbf" -> null
- content_sha1 = "5678fb68a642f3c6c8004c1bdc21e7142087287b" -> null
- content_sha256 = "53e0eff3204626f3e256ca636572d7ccdf8eb5a190c9defa3fa567bc63866b76" -> null
- content_sha512 = "27cef7520c791f20c49d8b23757f223018e7e08de07edf36b9db25de535e584a2ac26344de6bd464d373e1046a43789a4f9496d72f69dded579f6b711016a92a" -> null
- directory_permission = "0777" -> null
- file_permission = "0777" -> null
- filename = "./abc.txt" -> null
- id = "5678fb68a642f3c6c8004c1bdc21e7142087287b" -> null
}
Plan: 0 to add, 0 to change, 1 to destroy.
Do you really want to destroy all resources?
Terraform will destroy all your managed infrastructure, as shown above.
There is no undo. Only 'yes' will be accepted to confirm.
Enter a value: yes
local_file.abc: Destroying... [id=5678fb68a642f3c6c8004c1bdc21e7142087287b]
local_file.abc: Destruction complete after 0s
Destroy complete! Resources: 1 destroyed.
AWS EC2 배포 실습4 : EC2+웹서버 설정
디렉토리 설정
mkdir t101-1week-web
cd t101-1week-web
#ubuntu 22.04 AMI ID 확인
aws ec2 describe-images --owners 099720109477 \
--filters "Name=name,Values=ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*" "Name=state,Values=available" \
--query 'Images|sort_by(@, &CreationDate)[-1].[ImageId, Name]' --output text
# 변수 지정
UBUNTUID=ami-0572f73f0a5650b33
코드파일 작성
cat <<EOT > main.tf
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_instance" "example" {
ami = "$UBUNTUID"
instance_type = "t2.micro"
user_data = <<-EOF
#!/bin/bash
echo "Hello, T101 Study" > index.html
nohup busybox httpd -f -p 8080 &
EOF
tags = {
Name = "terraform-Study-101"
}
}
EOT
배포 프로세스
terraform init
terraform plan
terraform apply -auto-approve #yes 입력을 받지 않고 바로 실행하는 명령어
웹서버 접속시도(다른터미널)
AWS 대시보드에서 EC2 퍼블릭IP 주소확인
#PIP={EC2공인IP}
PIP=3.38.169.81
while true; do curl --connect-timeout 1 http://$PIP:8080/ ; echo "------------------------------"; date; sleep 1; done
실행결과 : 웹서버에 접근 불가능
에러나는 이유: 보안그룹이 연동설정 되어있지 않기 때문
파일수정: main.tf
cat <<EOT > main.tf
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_instance" "example" {
ami = "$UBUNTUID"
instance_type = "t2.micro"
vpc_security_group_ids = [aws_security_group.instance.id]
user_data = <<-EOF
#!/bin/bash
echo "Hello, T101 Study" > index.html
nohup busybox httpd -f -p 8080 &
EOF
tags = {
Name = "Single-WebSrv"
}
}
resource "aws_security_group" "instance" {
name = var.security_group_name
ingress {
from_port = 8080
to_port = 8080
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
variable "security_group_name" {
description = "The name of the security group"
type = string
default = "terraform-example-instance"
}
output "public_ip" {
value = aws_instance.example.public_ip
description = "The public IP of the Instance"
}
EOT
실행결과
AWS EC2 배포 실습5 : EC2+웹서버 설정변경적용
목표 : 기존에 배포한 웹서버의 포트 8080 → 9090 으로 변경적용
파일수정:main.tf
cat <<EOT > main.tf
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_instance" "example" {
ami = "$UBUNTUID"
instance_type = "t2.micro"
vpc_security_group_ids = [aws_security_group.instance.id]
user_data = <<-EOF
#!/bin/bash
echo "Hello, T101 Study 9090" > index.html
nohup busybox httpd -f -p 9090 &
EOF
user_data_replace_on_change = true
tags = {
Name = "Single-WebSrv"
}
}
resource "aws_security_group" "instance" {
name = var.security_group_name
ingress {
from_port = 9090
to_port = 9090
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
variable "security_group_name" {
description = "The name of the security group"
type = string
default = "terraform-example-instance"
}
output "public_ip" {
value = aws_instance.example.public_ip
description = "The public IP of the Instance"
}
EOT
배포프로세스 실행
terraform plan
aws_security_group.instance: Refreshing state... [id=sg-0f8395cb6787e07ce]
aws_instance.example: Refreshing state... [id=i-0e04061ead82f60c1]
Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
~ update in-place
-/+ destroy and then create replacement
Terraform will perform the following actions:
# aws_instance.example must be replaced
-/+ resource "aws_instance" "example" {
~ arn = "arn:aws:ec2:ap-northeast-2:909418839780:instance/i-0e04061ead82f60c1" -> (known after apply)
~ associate_public_ip_address = true -> (known after apply)
~ availability_zone = "ap-northeast-2a" -> (known after apply)
~ cpu_core_count = 1 -> (known after apply)
~ cpu_threads_per_core = 1 -> (known after apply)
~ disable_api_stop = false -> (known after apply)
~ disable_api_termination = false -> (known after apply)
~ ebs_optimized = false -> (known after apply)
- hibernation = false -> null
+ host_id = (known after apply)
+ host_resource_group_arn = (known after apply)
+ iam_instance_profile = (known after apply)
~ id = "i-0e04061ead82f60c1" -> (known after apply)
~ instance_initiated_shutdown_behavior = "stop" -> (known after apply)
+ instance_lifecycle = (known after apply)
~ instance_state = "running" -> (known after apply)
~ ipv6_address_count = 0 -> (known after apply)
~ ipv6_addresses = [] -> (known after apply)
+ key_name = (known after apply)
~ monitoring = false -> (known after apply)
+ outpost_arn = (known after apply)
+ password_data = (known after apply)
+ placement_group = (known after apply)
~ placement_partition_number = 0 -> (known after apply)
~ primary_network_interface_id = "eni-084bca41a462c1390" -> (known after apply)
~ private_dns = "ip-172-31-3-189.ap-northeast-2.compute.internal" -> (known after apply)
~ private_ip = "172.31.3.189" -> (known after apply)
~ public_dns = "ec2-3-38-169-81.ap-northeast-2.compute.amazonaws.com" -> (known after apply)
~ public_ip = "3.38.169.81" -> (known after apply)
~ secondary_private_ips = [] -> (known after apply)
~ security_groups = [
- "terraform-example-instance",
] -> (known after apply)
+ spot_instance_request_id = (known after apply)
~ subnet_id = "subnet-0bfc43f4db5b0f497" -> (known after apply)
tags = {
"Name" = "Single-WebSrv"
}
~ tenancy = "default" -> (known after apply)
~ user_data = "d91ca31904077f0b641b5dd5a783401396ffbf3f" -> "efd980ae7b7a847bd5772af117f6a53cc7824934" # forces replacement
+ user_data_base64 = (known after apply)
~ user_data_replace_on_change = false -> true
# (6 unchanged attributes hidden)
- capacity_reservation_specification {
- capacity_reservation_preference = "open" -> null
}
- cpu_options {
- core_count = 1 -> null
- threads_per_core = 1 -> null
# (1 unchanged attribute hidden)
}
- credit_specification {
- cpu_credits = "standard" -> null
}
- enclave_options {
- enabled = false -> null
}
- maintenance_options {
- auto_recovery = "default" -> null
}
- metadata_options {
- http_endpoint = "enabled" -> null
- http_protocol_ipv6 = "disabled" -> null
- http_put_response_hop_limit = 1 -> null
- http_tokens = "optional" -> null
- instance_metadata_tags = "disabled" -> null
}
- private_dns_name_options {
- enable_resource_name_dns_a_record = false -> null
- enable_resource_name_dns_aaaa_record = false -> null
- hostname_type = "ip-name" -> null
}
- root_block_device {
- delete_on_termination = true -> null
- device_name = "/dev/sda1" -> null
- encrypted = false -> null
- iops = 100 -> null
- tags = {} -> null
- tags_all = {} -> null
- throughput = 0 -> null
- volume_id = "vol-0f64d298fd7e63793" -> null
- volume_size = 8 -> null
- volume_type = "gp2" -> null
# (1 unchanged attribute hidden)
}
}
# aws_security_group.instance will be updated in-place
~ resource "aws_security_group" "instance" {
id = "sg-0f8395cb6787e07ce"
~ ingress = [
- {
- cidr_blocks = [
- "0.0.0.0/0",
]
- from_port = 8080
- ipv6_cidr_blocks = []
- prefix_list_ids = []
- protocol = "tcp"
- security_groups = []
- self = false
- to_port = 8080
# (1 unchanged attribute hidden)
},
+ {
+ cidr_blocks = [
+ "0.0.0.0/0",
]
+ from_port = 9090
+ ipv6_cidr_blocks = []
+ prefix_list_ids = []
+ protocol = "tcp"
+ security_groups = []
+ self = false
+ to_port = 9090
# (1 unchanged attribute hidden)
},
]
name = "terraform-example-instance"
tags = {}
# (8 unchanged attributes hidden)
}
Plan: 1 to add, 1 to change, 1 to destroy.
Changes to Outputs:
~ public_ip = "3.38.169.81" -> (known after apply)
─────────────────────────────────────────────────────────────────────────
Note: You didn't use the -out option to save this plan, so Terraform
can't guarantee to take exactly these actions if you run "terraform
apply" now.
Plan에서 보이는 내용 중 중요한것 정보
1 to add, 1 to change, 1 to destroy
⇒ public_ip 값이 기존(3.38.169.81) 에서 다른ip로 변경될 수 있다는 정보를 알려줌
배포실행
terraform apply -auto-approve
기존배포
배포후
- 퍼블릭IP 가 3.39.249.59 로 변경됨!
배포된 내용 제거
terraform destroy
Terraform 구성요소
terraform block
테라폼 블록: 테라폼 구성을 명시하는 데 사용
- 테라폼 버전, 프로바이더 버전 과 같은 값들은 자동으로 설정되지만, 직접 명시할 경우 버전을 지정할 수 있다.
terraform {
required_version = "~> 1.3.0" # 테라폼 버전
required_providers { # 프로바이더 버전을 나열
random = {
version = ">= 3.0.0, < 3.1.0"
}
aws = {
version = "4.2.0"
}
}
cloud { # Cloud/Enterprise 같은 원격 실행을 위한 정보
organization = "<MY_ORG_NAME>"
workspaces {
name = "my-first-workspace"
}
}
backend "local" { # state를 보관하는 위치를 지정
path = "relative/path/to/terraform.tfstate"
}
}
terraform version
required_version
으로 테라폼 버전을 직접설정 가능
현재 버전정보 확인
terraform version
Terraform v1.8.5
on darwin_arm64
+ provider registry.terraform.io/hashicorp/local v2.5.1
main.tf파일수정
terraform {
required_version = "< 1.0.0"
}
resource "local_file" "abc" {
content = "abc!"
filename = "${path.module}/abc.txt"
}
terraform init: 버전충돌
terraform init
Initializing the backend...
╷
│ Error: Unsupported Terraform Core version
│
│ on main.tf line 2, in terraform:
│ 2: required_version = "< 1.0.0"
│
│ This configuration does not support Terraform version 1.8.5. To proceed, either choose another supported Terraform version or update this version
│ constraint. Version constraints are normally set for good reason, so updating the constraint may lead to other errors or unexpected behavior.
╵
main.tf파일수정
terraform {
required_version = ">= 1.0.0"
}
resource "local_file" "abc" {
content = "abc!"
filename = "${path.module}/abc.txt"
}
terraform init: 성공
terraform init
Initializing the backend...
Initializing provider plugins...
- Reusing previous version of hashicorp/local from the dependency lock file
- Using previously-installed hashicorp/local v2.5.1
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
Provider version
- 0.13. 이후 버전부터 provider version 을 terraform block 에서 required_providers 에 정의함
#e.g
**terraform** {
r**equired_providers** {
aws = {
source = "hashicorp/aws"
version = "~> 4.2.0"
}
azurerm = {
source = "hashicorp/azurerm"
version = ">= 2.99.0"
}
}
}
main.tf수정: 프로바이더 버전을 과하게 높게 설정
terraform {
required_version = ">= 1.0.0"
required_providers {
local = {
source = "hashicorp/local"
version = ">=10000.0.0"
}
}
}
resource "local_file" "abc" {
content = "123!"
filename = "${path.module}/abc.txt"
}
terraform init: 버전 충돌
terraform init
Initializing the backend...
Initializing provider plugins...
- Reusing previous version of hashicorp/local from the dependency lock file
╷
│ Error: Failed to query available provider packages
│
│ Could not retrieve the list of available versions for provider hashicorp/local: locked provider registry.terraform.io/hashicorp/local 2.5.1 does not
│ match configured version constraint >= 10000.0.0; must use terraform init -upgrade to allow selection of new versions
╵
main.tf수정: local provider 버전을 ≥2.0.0
terraform {
required_version = ">= 1.0.0"
required_providers {
local = {
source = "hashicorp/local"
version = ">= 2.0.0"
}
}
}
resource "local_file" "abc" {
content = "123!"
filename = "${path.module}/abc.txt"
}
terraform init
terraform init
Initializing the backend...
Initializing provider plugins...
- Reusing previous version of hashicorp/local from the dependency lock file
- Using previously-installed hashicorp/local v2.5.1
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
Cloud block
- Terraform Cloud, Enterprise 는 CLI,VCS,API 기반의 방식을 지원
- Cloud block 에 선언함
#e.g.
terraform {
**cloud** {
hostname = "[app.terraform.io](http://app.terraform.io/)"
organization = "my-org"
workspades = {
name = "my-app-prod"
}
}
}
Backend block
- Terraform 실행 시 저장되는 State(상태 파일)의 저장위치를 선언함.
- 하나의 백엔드만 허용함
- 외부에 백엔드 저장소를 사용하는것이 가능하며, 패스워드 또는 인증서 정보같은 민감데이터가 포함될 수 있으므로, State 접근 제어가 필요함
State 잠금동작
- default 활성화 backend value : local
- State를 로컬환경에 저장하고 관리하는 방식 으로 사용함
- local 이 아닌 백엔드 구성은 동시에 여러사용자가 접근가능한 방식을 사용함
.terraform.tfstate.lock.info
파일을 생성하여 파일을 잠금, 동시성 이슈를 해결함
Terraform Resource block
Resource Block: 선언된 항목을 생성하는 동작을 수행함
실습환경 설정
mkdir 03.end
cd 03.end
resource block 기본형
리소스 유형: 프로바이더이름_제공리소스유형
의 쌍으로 구성.
resource "<리소스 유형>" "<이름>" {
<인수> = <값>
}
Terraform 종속성
- 아무런 설정을 하지 않은경우 여러개의 리소스는 병렬로 실행되며
- 필요한 경우 암시적 종속성을 갖게 된다.
순서가 없는 main.tf
resource "local_file" "abc" {
content = "123!"
filename = "${path.module}/abc.txt"
}
resource "local_file" "def" {
content = "456!"
filename = "${path.module}/def.txt"
}
순서를 설정한 main.tf
- 암시적 종속성을 부여하여 설정
- def 리소스는 local_file.abc 의 content 값을 사용하기 때문에, abc리소스가 먼저 생성된다.
resource "local_file" "abc" {
content = "123!"
filename = "${path.module}/abc.txt"
}
resource "local_file" "def" {
content = local_file.abc.content # 123!
filename = "${path.module}/def.txt"
}
혹은 종속성을 명시하여 설정하여도 동일함
resource "local_file" "abc" {
content = "123!"
filename = "${path.module}/abc.txt"
}
resource "local_file" "def" {
depends_on = [
local_file.abc
]
content = "456!"
filename = "${path.module}/def.txt"
}