안녕하세요 늑대양 입니다
Terraform 관련 기초 스터디(Terraform 101 Study)를 참여하게 되어 해당 내용들을 주차별로 정리하고자 합니다.
해당 스터디는 CloudNet@ 팀의 Gasida 님이 호스트를 맡아 주셨으며,
https://gasidaseo.notion.site/CloudNet-Blog-c9dfa44a27ff431dafdd2edacc8a1863
CloudNet@ Blog | Notion
CloudNet@ 팀에서 Cloud Infra & Network 기술에 대한 정보를 공유하는 블로그 입니다.
gasidaseo.notion.site
스터디 메인 교재는 "테라폼으로 시작하는 IaC" 도서를 기준으로 진행 됩니다.
https://www.yes24.com/Product/Goods/119179333
테라폼으로 시작하는 IaC - 예스24
“현업에서 요구하는 진짜 IaC 사용법”테라폼으로 배우는 인프라 운영의 모든 것IaC는 효율적인 데브옵스와 클라우드 자동화 구축을 위해 꼭 필요한 기술로 각광받고 있다. 그중에서도 테라폼
www.yes24.com
아래의 내용은 4주차 - Provider & State 내용을 다루고 있습니다.
4주차 - Provider & State
Provider:
Provider 소개
https://registry.terraform.io/browse/providers
Terraform Registry
registry.terraform.io
https://developer.hashicorp.com/terraform/language/providers
Providers - Configuration Language | Terraform | HashiCorp Developer
An overview of how to install and use providers, Terraform plugins that interact with services, cloud providers, and other APIs.
developer.hashicorp.com
- 테라폼은 terraform 바이너리 파일을 시작으로 로컬 환경에나 배포 서버와 같은 원격 환경에서 원하는 대상을 호출하는 방식으로 실행
- 이때 ‘원하는 대상’은 호출하는 방식이 서로 다르지만 대상의 공급자, 즉 프로바이더가 제공하는 API를 호출해 상호작용
- 여기서 테라폼이 대상과의 상호작용을 할 수 있도록 하는 것이 ‘프로바이더’
- 각 프로바이더의 API구현은 서로 다르지만 테라폼의 고유 문법으로 동일한 동작을 수행하도록 구현되어 있음
- 프로바이더는 플러그인 형태로 테라폼에 결합되어 대상이 되는 클라우드, SaaS, 기타 서비스 API를 사용해 동작을 수행
- 각 프로바이더는 테라폼이 관리하는 리소스 유형과 데이터 소스를 사용할 수 있도록 연결
- 즉, 테라폼은 프로바이더 없이는 어떤 종류의 인프라와 서비스도 관리할 수 없다는 의미
- 대부분의 프로바이더는 대상 인프라 환경이나 서비스 환경에 대한 리소스를 관리하므로, 프로바이더를 구성할 때는 대상과의 연결과 인증에*(예. AWS 자격증명 등)* 필요한 정보가 제공되어야 함
- 각 프로바이더는 테라폼 실행 파일과는 별도로 자체 관리되고 게시되며, 테라폼 레지스트리 사이트에서 주요 프로바이더와 관련 문서를 확인 가능
4.1 Provider 구성
테라폼 레지스트리의 프로바이더 목록에는 유지 보수 및 게시에 대한 권한에 따라 티어 정보가 제공
https://registry.terraform.io/browse/providers
Terraform Registry
registry.terraform.io
- 지정하는 프로바이더의 요구사항을 정의:
- 레지스트리의 Overview 항목 오른쪽에 있는 [USE PROVIDER] 클릭해 현재 버전의 정의 방법을 확인
- AWS Provider 예시:
Terraform Registry
registry.terraform.io
로컬 이름과 프로바이더 지정
- terraform 블록의 required_providers 블록 내에 <로컬 이름> = { } 으로 여러 개의 프로바이더를 정의 가능
- 여기서 사용되는 로컬 이름은 테라폼 모듈 내에서 고유해야 함
- 로컬 이름과 리소스 접두사는 독립적으로 선언되며, 각 프로바이더의 소스 경로가 지정되면 프로바이더의 고유 접두사가 제공
- 만약 동일한 접두사를 사용하는 프로바이더가 선언되는 경우 로컬 이름을 달리해 관련 리소스에서 어떤 프로바이더를 사용하는지 명시적으로 지정 가능
- 예를 들어, 다음의 main.tf에서처럼 동일한 http 이름을 사용하는 다수의 프로바이더가 있는 경우 각 프로바이더에 고유한 이름을 부여하고 리소스와 데이터 소스에 어떤 프로바이더를 사용할지 provider 인수에 명시하며 동일한 source에 대해 다수의 정의는 불가능
- 동일한 http 접두사를 사용하는 다수의 프로바이더 사용 정의 예시
terraform {
required_providers {
architech-http = {
source = "architect-team/http"
version = "~> 3.0"
}
http = {
source = "hashicorp/http"
}
aws-http = {
source = "terraform-aws-modules/http"
}
}
}
data "http" "example" {
provider = aws-http
url = "https://checkpoint-api.hashicorp.com/v1/check/terraform"
request_headers = {
Accept = "application/json"
}
}
단일 프로바이더의 다중 정의
- 동일한 프로바이더를 사용하지만 다른 조건을 갖는 경우, 사용되는 리소스마다 별도로 선언된 프로바이더를 지정해야 하는 경우가 있다.
- 예를 들면, AWS 프로바이더를 사용하는데 서로 다른 권한의 IAM을 갖는 Access ID 또는 대상 리전을 지정해야 하는 경우
- 이때는 프로바이더 선언에서 alias를 명시하고 사용하는 리소스와 데이터 소스에서는 provider 메타인수를 사용해 특정 프로바이더를 지정 가능
- provider 메타인수에 지정되지 않은 경우 alias가 없는 프로바이더가 기본 프로바이더로 동작
# main.tf
provider "aws" {
region = "ap-southeast-1"
}
provider "aws" {
alias = "seoul"
region = "ap-northeast-2"
}
resource "aws_instance" "app_server1" {
ami = "ami-06b79cf2aee0d5c92"
instance_type = "t2.micro"
}
resource "aws_instance" "app_server2" {
provider = aws.seoul
ami = "ami-0ea4d4b8dc1e46212"
instance_type = "t2.micro"
}
# 배포 실행
terraform init && terraform plan
terraform apply -auto-approve
# 확인
terraform state list
echo "aws_instance.app_server1.public_ip" | terraform console
echo "aws_instance.app_server2.public_ip" | terraform console
aws ec2 describe-instances --filters Name=instance-state-name,Values=running --output table
aws ec2 describe-instances --filters Name=instance-state-name,Values=running --output table --region ap-southeast-1
# 삭제
terraform destroy -auto-approve
프로바이더 요구사항 정의
- 테라폼 실행 시 요구되는 프로바이더 요구사항은 terraform 블록의 required_providers 블록에 여러 개를 정의 가능
- source에는 프로바이더 다운로드 경로를 지정하고 version은 버전 제약을 명시
- 프로바이더 요구사항 정의 블록
terraform {
required_providers {
<프로바이더 로컬 이름> = {
source = [<호스트 주소>/]<네임스페이스>/<유형>
version = <버전 제약>
}
...
}
}
- 호스트 주소 : 프로바이더를 배포하는 주소로서 기본값은 registry.terraform.io
- 네임스페이스 : 지정된 레지스트리 내에서 구분하는 네임스페이스로, 공개된 레지스트리 및 Terraform Cloud의 비공개 레지스트리의 프로바이더를 게시하는 조직을 의미
- 유형 : 프로바이더에서 관리되는 플랫폼이나 서비스 이름으로 일반적으로 접두사와 일치하나 일부 예외가 있을 수 있음
- 프로바이더는 기능이나 조건이 시간이 지남에 따라 변경될 수 있다. 이 같은 변경에 특정 버전을 명시하거나 버전 호환성을 정의할 때, version에 명시할 수 있다. 이 값이 생략되는 경우 terraform init을 하는 당시의 가장 최신 버전으로 선택된다. 버전 상세 내용은 3.3장 버전 설정 확인
프로바이더 설치
- 테라폼을 실행하기 전 terraform init 명령을 통해 정의된 프로바이더를 다운로드, 복사, 캐시에서 읽어옴
- 항상 지정된 구성에 대해 동일한 프로바이더를 설치하도록 하려면 테라폼 구성에 사용되는 프로바이더에 대해 명시적으로 terraform 블록에 정의하거나 .terraform.lock.hcl 잠금 파일을 코드 저장소에 공유하는 방안이 요구
- 2장에서 살펴본 것처럼 required_providers에 지정된 프로바이더가 있는 경우 코드상 구성에서 사용 여부에 관계없이 프로바이더를 다운로드하게 되고, required_providers에 지정하지 않더라고 테라폼 구성 코드사에서 사용된 프로바이더를 테라폼에서 추론해 최신 버전의 프로바이더를 다운로드
프로바이더 간 전환 여부
- 클라우드를 대상으로 테라폼을 사용하는 경우 다른 클라우드 프로바이더로 전환이 가능할까? ⇒ 불가능하다!
- 테라폼은 인프라에 대한 단일 프로비저닝 도구로 사용되지만 대상이 되는 환경은 서로 다른 API로 구현된 프로바이더가 제공
4.2 Provider 에코시스템
테라폼의 에코시스템은 사용자가 사용하는 방식과 구조에 테라폼을 적용할 수 있도록 설계
- 에코시스템을 위한 테라폼 통합은 워크플로 파트너와 인프라 파트너로 나눔
- 워크플로 파트너는 테라폼 실행 및 Terraform Cloud/Enterprise와 연계하여 동작하는 기능을 제공하는 항목으로 구성
- 대표적으로 테라폼 구성을 관리하기 위한 VCS를 제공하는 깃허브, 깃랩, 비트버킷, 애저 데브옵스가 이 항목에 해당
- 프로바이더의 경우 인프라 파트너로 해당
- 인프라 파트너는 사용자가 테라폼으로 대상 플랫폼의 API로 상호작용 가능한 리소스를 관리
- 인프라 파트너의 분류와 프로바이더 대상은 아래와 같음
퍼블릭 클라우드
- IaaS, SaaS 및 PaaS를 포함한 다양한 서비스를 제공하는 대규모 글로벌 클라우드 제공
컨테이너 오케스트레이션
- 컨테이너 프로비저닝 및 배포를 지원
IaaS(Infrastructure-as-a-Service)
- 스토리지, 네트워킹 및 가상화와 같은 솔루션을 제공하는 인프라 및 IaaS 제공
보안 및 인증
- 인증 및 보안 모니터링 플랫폼
자산 관리
- 소프트웨어 라이선스, 하드웨어 자산 및 클라우드 리소스를 비롯한 주요 조직 및 IT 리소스의 자산 관리를 제공
CI/CD
- 지속적인 통합 및 지속적인 제공/배포
로깅 및 모니터링
- 로거, 측정 도구 및 모니터링 서비스와 같은 서비스를 구성하고 관리하는 기능
유틸리티
- 임의 값 생성, 파일 생성, http 상호 작용 및 시간 기반 리소스와 같은 도우미 기능
클라우드 자동화
- 구성 관리와 같은 전문화된 클라우드 인프라 자동화 관리 기능
데이터 관리
- 데이터 센터 스토리지, 백업 및 복구 솔루션
네트워킹
- 라우팅, 스위칭, 방화벽 및 SD-WAN 솔루션과 같은 네트워크별 하드웨어 및 가상화된 제품과 통합
VCS(버전 제어 시스템)
- Terraform 내에서 VCS(버전 제어 시스템) 프로젝트, 팀 및 리포지토리에 중점
통신 및 메시징
- 통신, 이메일 및 메시징 플랫폼과 통합
데이터베이스
- 데이터베이스 리소스를 프로비저닝 및 구성하는 기능
PaaS(Platform-as-a-Service)
- 다양한 하드웨어, 소프트웨어 및 애플리케이션 개발 도구를 제공하는 플랫폼 및 PaaS
웹 서비스
- 웹 호스팅, 웹 성능, CDN 및 DNS 서비스
- 퍼블릭 클라우드(Iaas, Paas) 프로바이더 + 프라이빗 클라우드/VM
- 컨테이너 오케스트레이터
- SaaS 서비스
- 기타 솔루션
4.3 Provider 경험해보기
[AWS] 실습. 2개의 리전에 Ubuntu EC2 배포:
2가지 주의 사항
- Warning 1 : Multiregion is hard 프로덕션 수준의 멀티 리전은 어려움
- Active-Active 멀티 리전 서비스를 위해서 ‘지역간 지연 시간, 고유 ID, 최종 일관성’ 등 여러가지 고려사항이 많아서 쉽지 않음
- Warning 2 : Use aliases sparingly Alias 를 빈번하게 사용하지 말자
- 별칭을 사용하여 두 리전에 배포하는 단일 테라폼 모듈은 한 리전이 다운 시, plan 과 apply 시도가 실패
- 프로덕션 환경은 멀티 리전의 별칭을 사용하는 것보다는, 3장에서 설명한 것 처럼 환경을 완전히 격리 필요
- 이를 통해 영향도를 최소화 가능
#provider_data.tf
provider "aws" {
region = "ap-northeast-2"
alias = "region_1"
}
provider "aws" {
region = "ap-southeast-1"
alias = "region_2"
}
data "aws_region" "region_1" {
provider = aws.region_1
}
data "aws_region" "region_2" {
provider = aws.region_2
}
data "aws_ami" "ubuntu_region_1" {
provider = aws.region_1
most_recent = true
owners = ["099720109477"] # Canonical
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
}
}
data "aws_ami" "ubuntu_region_2" {
provider = aws.region_2
most_recent = true
owners = ["099720109477"] # Canonical
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
}
}
# ec2.tf
resource "aws_instance" "region_1" {
provider = aws.region_1
ami = data.aws_ami.ubuntu_region_1.id
instance_type = "t2.micro"
}
resource "aws_instance" "region_2" {
provider = aws.region_2
ami = data.aws_ami.ubuntu_region_2.id
instance_type = "t2.micro"
}
# 실행
# [터미널1] ap-northeast-2
while true; do aws ec2 describe-instances --region ap-northeast-2 --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] ap-southeast-1
while true; do aws ec2 describe-instances --region ap-southeast-1 --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
# init & plan & apply
terraform init && terraform plan && terraform apply -auto-approve
terraform state list
# 확인
aws ec2 describe-instances --region ap-northeast-2 --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output text
aws ec2 describe-instances --region ap-southeast-1 --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output text
# 삭제
terraform destroy -auto-approve
State:
https://developer.hashicorp.com/terraform/language/state
State | Terraform | HashiCorp Developer
An introduction to state, information that Terraform uses to map resources to a configuration, track metadata, and improve performance.
developer.hashicorp.com
5.1 State의 목적과 의미
상태 파일 확인 실습.
# 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
# 상태 파일 확인(VSCODE) : JSON 형식
ls
cat terraform.tfstate | jq
...
"serial": 1,
...
# 아래 정보는 terraform.tfstate 정보를 통해 출력
terraform state list
terraform state show aws_vpc.myvpc
# vpc.tf 파일 수정
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_vpc" "myvpc" {
cidr_block = "10.10.0.0/16"
tags = {
Name = "tf-state"
}
}
# 배포 : plan 시 tfstate 상태와 코드 내용을 비교해서 검토
terraform plan && terraform apply -auto-approve
# 상태 파일 비교 : 백업 파일 생성됨
ls terraform.tfstate*
terraform.tfstate terraform.tfstate.backup
diff terraform.tfstate terraform.tfstate.backup
< "serial": 3,
---
> "serial": 1,
...
# 확인 후 삭제
terraform destroy -auto-approve
- 상태 파일은 배포할 때마다 변경되는 프라이빗 API private API로, 오직 테라폼 내부에서 사용하기 위한 것
- 테라폼 상태 파일을 직접 편집하거나 직접 읽는 코드로 작성해서는 안됨
팀 단위에서 테라폼 운영 시, 문제점
- 상태 파일을 저장하는 공유 스토리지 Shared storage for state files
- 각 팀원이 동일한 테라폼 상태 파일 사용을 위해서, 공유 위치에 저장이 필요
- 상태 파일 잠금 Locking state files
- 잠금 기능 없이 두 팀원이 동시에 테라폼 실행 시 여러 테라폼 프로세스가 상태 파일을 동시에 업데이트하여 충돌 가능(경쟁 상태 race condition)
- 상태 파일 격리 Isolating state files
- 예를 들면 테스트 dev 와 검증 stage 과 상용 prodction 각 환경에 대한 격리가 필요
상태 파일 공유로 버전 관리 시스템 비추천
- 수동 오류 Manual error
- 테라폼을 실행하기 전에 최신 변경 사항을 가져오거나 실행하고 나서 push 하는 것을 잊기 쉽습니다(?).
- 팀의 누군가가 이전 버전의 상태 파일로 테라폼을 실행하고, 그 결과 실수로 이전 버전으로 롤백하거나 이전에 배포된 인프라를 복제하는 문제가 발생 할 수 있음.
- 잠금 Locking
- 대부분의 버전 관리 시스템은 여러 명의 팀 구성원이 동시에 하나의 상태 파일에 terraform apply 명령을 실행하지 못하게 하는 잠금 기능이 제공되지 않음.
- 시크릿 Secrets
- 테라폼 상태 파일의 모든 데이터는 평문으로 저장됨. 민감 정보가 노출될 위험.
지원되는 원격 백엔드
AWS S3, Azure Blob Storage, Google Cloud Storage, Consul, Postgres database, k8s secret 등 - 링크
- 수동 오류 해결: plan/apply 실행 시 마다 해당 백엔드에서 파일을 자동을 로드, apply 후 상태 파일을 백엔드에 자동 저장
- 잠금: apply 실행 시 테라폼은 자동으로 잠금을 활성화, -lock-timout=<TIME> 로 대기 시간 설정 지정 가능
- 시크릿: 대부분 원격 백엔드는 기본적으로 데이터를 보내거나 상태 파일을 저장할 때 암호화하는 기능을 지원
5.2 State 동기화
테라폼 구성 파일은 기존 State와 구성을 비교해 실행 계획에서 생성, 수정, 삭제 여부를 결정
State 유형 별 실습:
유형 1: 신규 리소스 정의 → Apply ⇒ 리소스 생성
# main.tf
locals {
name = "mytest"
}
resource "aws_iam_user" "myiamuser1" {
name = "${local.name}1"
}
resource "aws_iam_user" "myiamuser2" {
name = "${local.name}2"
}
#
terraform init && terraform apply -auto-approve
terraform state list
terraform state show aws_iam_user.myiamuser1
#
ls *.tfstate
cat terraform.tfstate | jq
# 아래 실행 시 어떻게 되나? 테라폼은 멱등성 한가?
terraform apply -auto-approve
ls *.tfstate
# iam 사용자 리스트 확인
aws iam list-users | jq
유형 2: 신제 리소스 수동 제거 → Apply ⇒ 리소스 생성
# 실제 리소스 수동 제거
aws iam delete-user --user-name mytest1
aws iam delete-user --user-name mytest2
aws iam list-users | jq
terraform state list
# 아래 명령어 실행 결과 차이는?
terraform plan
terraform plan -refresh=false
cat terraform.tfstate | jq .serial
#
terraform apply -auto-approve
terraform state list
cat terraform.tfstate | jq .serial
# iam 사용자 리스트 확인
aws iam list-users | jq
유형 3: Apply → Apply ← 코드, State, 형상 모두 일치한 경우
#
terraform apply -auto-approve
cat terraform.tfstate | jq .serial
terraform apply -auto-approve
cat terraform.tfstate | jq .serial
terraform apply -auto-approve
cat terraform.tfstate | jq .serial
유형 4: 코드에서 일부 리소스 삭제 → Apply
# main.tf 수정
locals {
name = "mytest"
}
resource "aws_iam_user" "myiamuser1" {
name = "${local.name}1"
}
#
terraform apply -auto-approve
terraform state list
terraform state show aws_iam_user.myiamuser1
#
ls *.tfstate
cat terraform.tfstate | jq
# iam 사용자 리스트 확인
aws iam list-users | jq
유형 5: 실수로 tfstate 파일 삭제 → plan/apply ← 책에는 없는 내용
# 실수로 tfstate 파일 삭제
terraform state list
aws_iam_user.myiamuser1
rm -rf terraform.tfstate*
#
terraform plan
aws iam list-users | jq
terraform plan -refresh=false
#
terraform apply -auto-approve
terraform state list
cat terraform.tfstate | jq
# iam 사용자 리스트 확인
aws iam list-users | jq
# 위 상황에서 복구? 하는 방법은? import 등 방법이 가능
유형 6: 실수로 tfstate 파일 삭제 시 → import 로 tfstate 파일 복구
https://developer.hashicorp.com/terraform/cli/import
Import | Terraform | HashiCorp Developer
Terraform can import and manage existing infrastructure. This can help you transition your infrastructure to Terraform.
developer.hashicorp.com
https://developer.hashicorp.com/terraform/tutorials/state/state-import
Import Terraform configuration | Terraform | HashiCorp Developer
Use configuration to import existing infrastructure into Terraform. Review important considerations when bringing infrastructure under Terraform management.
developer.hashicorp.com
# iam 사용자 리스트 확인
aws iam list-users | jq
# import 도움말 : 빨간색 설명 출력...
terraform import
# ADDR은 리소스주소 , ID는
# terraform [global options] import [options] ADDR ID
terraform import aws_iam_user.myiamuser1 mytest1
aws_iam_user.myiamuser1: Importing from ID "mytest1"...
aws_iam_user.myiamuser1: Import prepared!
Prepared aws_iam_user for import
aws_iam_user.myiamuser1: Refreshing state... [id=mytest1]
Import successful!
The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
#
terraform state list
cat terraform.tfstate | jq
terraform apply -auto-approve
# 확인 후 리소스 삭제
terraform destroy -auto-approve
5.3 Terraform Backend: AWS S3 + DynamoDB
https://developer.hashicorp.com/terraform/language/settings/backends/s3
Backend Type: s3 | Terraform | HashiCorp Developer
Terraform can store state remotely in S3 and lock that state with DynamoDB.
developer.hashicorp.com
실습.
https://malwareanalysis.tistory.com/633#8.-state-%EB%B0%B1%EC%97%94%EB%93%9C
테라폼 t102 스터디 - state
안녕하세요. 이 글은 테라폼 스터디에서 공부한 state를 정리했습니다. 영상: https://youtu.be/E2n3bZrzpKE 1. state란? 테라폼은 대상에 배포한 결과를 state로 관리합니다. 또한, 테라폼 실행 작업(생성/수
malwareanalysis.tistory.com
# [사전 준비 1] 리모트 공용 저장소 AWS S3 생성
#
git clone https://github.com/sungwook-practice/t101-study.git example
cd example/state/step3_remote_backend/s3_backend
tree
# VSCODE에서 코드 파일들 확인 : main.tf, variables.tf , terraform.tfvars
## S3 버킷에 버저닝 활성화 <- 권장 옵션 설정
# terraform.tfvars 파일 내용 수정 : 각자 자신의 '닉네임' 추가하여 S3 버킷 이름 작성
bucket_name = "<닉네임>-hello-t1014-remote-backend"
bucket_name = "wolf-sheep-hello-t1014-remote-backend"
# 생성
terraform init && terraform apply -auto-approve
# 확인
terraform state list
aws s3 ls
# 2. 테라폼 자원 배포 시 ‘리모트 백엔드 저장소’ 설정 사용
# VSCODE에서 provider.tf 코드 확인
cd ../vpc
ls
cat provider.tf
# VSCODE에서 provider.tf 수정
...
backend "s3" {
#bucket = "<닉네임>-hello-t1014-remote-backend"
bucket = "wolf-sheep-hello-t1014-remote-backend"
key = "terraform/state-test/terraform.tfstate"
region = "ap-northeast-2"
#dynamodb_table = "terraform-lock" 주석처리
}
...
# 테라폼 초기화
terraform init
Initializing the backend...
Successfully configured the backend "s3"! Terraform will automatically
use this backend unless the backend configuration changes.
...
# tfstate 파일 로컬 확인
terraform apply -auto-approve
terraform state list
ls
# AWS S3 버킷 내에 tfstate 파일 확인
MYBUCKET=gasida-hello-t1014-remote-backend
aws s3 ls s3://$MYBUCKET --recursive --human-readable --summarize
# 3. Locking 을 위한 DynamoDB 활용을 위해 DynamoDB 생성
# - 테라폼에서 DynamoDB 잠금을 사용하기 위해서는 LockID 라는 기본 키가 있는 테이블을 생성해야됨
# VSCODE에서 provider.tf 코드 확인
cd ../dynamodb
ls
cat main.tf
# 생성
terraform init && terraform apply -auto-approve
# 확인
terraform state list
terraform state show aws_dynamodb_table.terraform_state_lock
# DynamoDB 테이블 생성 확인
aws dynamodb list-tables --output text
TABLENAMES terraform-lock
aws dynamodb describe-table --table-name terraform-lock | jq
aws dynamodb describe-table --table-name terraform-lock --output table
# 4. 2번 테라폼 자원 배포에 백엔드 설정 수정 및 적용
# VSCODE에서 provider.tf 코드 확인
cd ../vpc
cat provider.tf
# VSCODE에서 provider.tf 수정 : dynamodb_table = "terraform-lock" 주석 제거
...
backend "s3" {
bucket = "wolf-sheep-hello-t1014-remote-backend"
key = "terraform/state-test/terraform.tfstate"
region = "ap-northeast-2"
dynamodb_table = "terraform-lock"
}
...
# backend설정이 달라졌으므로 terraform init 으로 적용
# Reconfigure a backend, and attempt to migrate any existing state.
terraform init -migrate-state
# 5. VPC tag 수정 후 apply 와서 Locking 확인
# main.tf 수정 : '2' 추가
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
tags = {
Name = "terraform VPC 2"
}
}
# apply 후 DynamoDB 테이블 확인
terraform apply
...
Enter a value: <입력하지 않고 대기>
# 아래 LockID 정보 확인 후 apply
# apply 완료 후 다시 DynamoDB 테이블 확인 : item 없음 확인
# 6. S3 버저닝 정보 확인
# main.tf 수정 : '3' 추가
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
tags = {
Name = "terraform VPC 3"
}
}
# apply
terraform apply -auto-approve
# S3 버킷에 파일 확인
aws s3 ls s3://$MYBUCKET --recursive --human-readable --summarize
# 버저닝된 파일 확인
aws s3api list-object-versions --bucket $MYBUCKET | egrep "Key|VersionId|LastModified"
"Key": "dev/terraform.tfstate",
"VersionId": "oyo59fIIQ239_tVTY88upFoVgnp630BC",
"LastModified": "2022-10-23T08:54:04+00:00",
"Key": "dev/terraform.tfstate",
"VersionId": "vlOO1wCPEy3mzAOB7W76171u_i3WSG8r",
"LastModified": "2022-10-23T08:53:04+00:00",
"Key": "dev/terraform.tfstate",
"VersionId": "ukF5F_CMKQhoF_jDGftbsMO0eNIGLmDV",
"LastModified": "2022-10-23T08:51:55+00:00",
# 7. 실습 리소스 삭제
# 테라폼 배포 리소스 삭제 : 현재 vpc 디렉터리
terraform destroy -auto-approve
# DynamoDB 삭제
cd ../dynamodb
terraform destroy -auto-approve
# S3 삭제
cd ../s3_backend
terraform destroy -auto-approve
# S3 버킷에 객체 삭제
aws s3 rm s3://$MYBUCKET --recursive
# S3 버킷에 버저닝 객체 삭제
aws s3api delete-objects \
--bucket $MYBUCKET \
--delete "$(aws s3api list-object-versions \
--bucket "$MYBUCKET" \
--output=json \
--query='{Objects: Versions[].{Key:Key,VersionId:VersionId}}')"
# S3 버킷에 삭제마커 삭제
aws s3api delete-objects --bucket $MYBUCKET \
--delete "$(aws s3api list-object-versions --bucket "$MYBUCKET" \
--query='{Objects: DeleteMarkers[].{Key:Key,VersionId:VersionId}}')"
# S3 삭제
terraform destroy -auto-approve
테라폼 백엔드 단점
- 테라폼의 backend 블록에는 변수나 참조를 사용 할 수 없음
- 그 결과 S3 버킷 이름, 리전, DynamoDB 테이블 이름을 모두 테라폼 모듈에 수동으로 복사붙여녛어야 함
- 심지어 key 값은 중복되면 안되며 고유하게 넣어야함
- partial configuration 을 통해 일부 매개 변수를 전달해서 사용 할 수 있음
- 다만, 이 경우에도 모듈마다 서로 다른 key 값을 설정해야 하기 때문에 key 매개 변수는 테라폼 코드에 있어야함
- 부분적으로 구성한 것들을 모두 결합하려면 -backend-config 인수와 함께 terraform init 명령을 실행
terraform init -backend-config=backend.hcl
- 위의 단점을 보완해주는 오픈 소스 테라그런트(Terragrunt)가 있음
https://terragrunt.gruntwork.io/
Terragrunt | Terraform wrapper
Terragrunt is a thin wrapper for Terraform that provides extra tools for keeping your Terraform configurations DRY, working with multiple Terraform modules, and managing remote state.
terragrunt.gruntwork.io
5.4 Workspace
워크스페이스는 상태 관리의 '단위' 로 이해 가능
한 프로젝트 내에서 여러 개의 .tf 파일을 가진 디렉토리가 여러 워크스페이스로 동작 가능
https://developer.hashicorp.com/terraform/language/state/workspaces
State: Workspaces | Terraform | HashiCorp Developer
Workspaces allow the use of multiple states with a single configuration directory.
developer.hashicorp.com
- 작업 공간을 통한 격리 Isolation via workspaces
- 동일한 구성에서 빠르고 격리된 테스트 환경에 유용
- 파일 레이아웃을 이용한 격리 Isolation via file layout
- 보다 강력하게 분리해야 하는 운영 환경에 적합
- 테라폼 프로젝트의 파일 레이아웃 설명
- 각 테라폼 구성 파일을 분리된 폴더에 넣기. (예. stage , prod)
- 각 환경에 서로 다른 백엔드 구성. (예. S3 버킷 백엔드의 AWS 계정을 분리)
최상위 폴더
- stage : 테스트 환경과 같은 사전 프로덕션 워크로드 workload 환경
- prod : 사용자용 맵 같은 프로덕션 워크로드 환경
- mgmt : 베스천 호스트 Bastion Host, 젠킨스 Jenkins 와 같은 데브옵스 도구 환경
- global : S3, IAM과 같이 모든 환경에서 사용되는 리소스를 배치
각 환경별 구성 요소
- vpc : 해당 환경을 위한 네트워크 토폴로지
- services : 해당 환경에서 서비스되는 애플리케이션, 각 앱은 자체 폴더에 위치하여 다른 앱과 분리
- data-storage : 해당 환경 별 데이터 저장소. 각 데이터 저장소 역시 자체 폴더에 위치하여 다른 데이터 저장소와 분리
명명 규칙 naming conventions (예시)
- variables.tf : 입력 변수
- outputs.tf : 출력 변수
- main-xxx.tf : 리소스 → 개별 테라폼 파일 규모가 커지면 특정 기능을 기준으로 별도 파일로 분리 (ex. main-iam.tf, main-s3.tf 등) 혹은 모듈 단위로 나눔
- dependencies.tf : 데이터 소스
- providers.tf : 공급자
Tip 1. terraform-workspace-prompt
https://github.com/amatellanes/terraform-workspace-prompt
GitHub - amatellanes/terraform-workspace-prompt: Terraform workspace in your prompt.
Terraform workspace in your prompt. Contribute to amatellanes/terraform-workspace-prompt development by creating an account on GitHub.
github.com
Tip 2. Terraform workspace CLI
https://developer.hashicorp.com/terraform/cli/workspaces
Managing Workspaces - Terraform CLI | Terraform | HashiCorp Developer
Commands to list, select, create, and output workspaces. Workspaces help manage different groups of resources with one configuration.
developer.hashicorp.com
지금까지 Terraform 101 Study 4주차 내용이었습니다.
테라폼을 학습하시는 분들에게 도움이 되었으면 좋을 것 같습니다 🙏
긴 글 읽어주셔서 감사드립니다.
좋은 주말 보내세요!
감사합니다😊
'Terraform' 카테고리의 다른 글
Terraform 101 Study - 6주차 (0) | 2024.07.27 |
---|---|
Terraform 101 Study - 5주차 (0) | 2024.07.12 |
Terraform 101 Study - 3주차 (0) | 2024.06.30 |
Terraform 101 Study - 2주차 (0) | 2024.06.23 |
Terraform 101 Study - 1주차 (0) | 2024.06.16 |