백엔드 블록
- 백엔드 블록의 구성은 테라폼 실행 시 저장되는 **State(상태 파일)**의 저장 위치를 선언한다.
- 주의할 점은 하나의 백엔드만 허용한다는 점이다.
- 테라폼은 State의 데이터를 사용해 코드로 관리된 리소스를 탐색하고 추적한다.
- 작업자 간의 협업을 고려한다면 테라폼으로 생성한 리소스의 상태 저장 파일을 공유할 수 있는 외부 백엔드 저장소가 필요하다.
- 그리고 State에는 외부로 노출되면 안 되는 패스워드 또는 인증서 정보 같은 민감한 데이터들이 포함될 수 있으므로 State의 접근 제어가 필요하다.
State 잠금 동작
- 기본적으로 활성화되는 백엔드는 local이다.
- 상태를 작업자의 로컬 환경에 저장하고 관리하는 방식이다.
- 이 밖의 다른 백엔드 구성은 동시에 여러 작업자가 접근해 사용할 수 있도록 공유 스토리지 같은 개념을 갖는다.
- 공유되는 백엔드에 State가 관리되면 테라폼이 실행되는 동안 .terraform.tfstate.lock.info 파일이 생성되면서 해당 State를 동시에 사용하지 못하도록 잠금 처리를 한다.
- 파일 생성을 확인하고 싶다면 terraform apply를 실행하고 생성되는 잠금 파일을 확인해보자. 잠금 파일 내의 정보는 다음과 같다.
ID: 30773305-a78d-49f1-8f3f-5604d742b66f
Operation: OperationTypeApply # 어떤 동작으로 인해 해당 잠금 파일이 생성되었는지 명기
Info:
Who: gasida@seojonghoui-MacBookPro.local # 작업자 정보
Version: 1.5.1 # 실행한 테라폼 버전
Created: 2023-06-28 12:23:59.113608 +0000 UTC
Path: state/terraform.tfstate # 잠긴 state 파일의 위치
- 잠금 파일이 테라폼 실행에 어떤 영향을 주는지 확인해보자.
- 코드 파일 수정 : content 내용을 수정, 문서 서식
resource "local_file" "abc" {
content = "123456!"
filename = "${path.module}/abc.txt"
}
# 터미널1
terraform apply
...
Enter a value: 대기
# 터미널2
terraform apply
...
ls -a
파일 하나가 생성되면서
아래 처럼 오류가 발생한다.
백엔드 설정 변경
- 현재 State 파일 정보 확인
ls terraform.tfstate*
terraform.tfstate terraform.tfstate.backup
# 리소스 확인
terraform state list
# State 파일 정보 확인
cat terraform.tfstate
- 백엔드가 설정되면 다시 init 명령을 수행해 State의 위치를 재설정해야 한다.
- 백엔드 블록에 local을 정의해 terraform init을 수행해본다.
# init 시 백엔드 변경에 따른 마이그레이션 안내
terraform init
...
Enter a value: yes
...
#
ls terraform.tfstate*
tree state
cat state/terraform.tfstate | jq
cat state/terraform.tfstate | jq -r .serial
#
terraform apply -auto-approve
코드수정
terraform {
backend "local" {
path = "state/terraform.tfstate"
}
}
resource "local_file" "abc" {
content = "123456789!"
filename = "${path.module}/abc.txt"
}
apply
#
terraform plan
terraform apply -auto-approve
#
cat abc.txt
ls terraform.tfstate*
tree state
cat state/terraform.tfstate | jq
cat state/terraform.tfstate | jq -r .serial # 예시)현재: 10
cat state/terraform.tfstate.backup | jq -r .serial # 예시)백업: 7
# 이전 사용 state 파일 삭제 후 확인
rm -rf terraform.tfstate*
ls -al
#
terraform plan
terraform apply -auto-approve
cat abc.txt
확인
- 리소스
- 리소스 구성 resource
- 실습을 위해서 03.end 디렉터리를 신규 생성 후 열기 → main.tf 파일 생성
cd ..
rm -rf 03.start
mkdir 03.end
cd 03.end
touch main.tf
- 리소스 블록은 resource로 시작한다. 이후 리소스 블록이 생성할 ‘리소스 유형’을 정의한다.
- 리소스 선언 : 리소스 유형(프로바이더이름_제공리소스유형), 동일한 유형에 대한 식별자 역할로 고유한 이름, 구성 인수들이 이름 뒤에 중괄호 내에 선언됨
resource "<리소스 유형>" "<이름>" {
<인수> = <값>
}
resource "local_file" "abc" {
content = "123"
filename = "${path.module}/abc.txt"
}
리소스에서 사용되는 유형들은 프로바이더에 종속성을 갖는다. 특정 프로바이더의 유형만 추가해도 init 수행 시 해당 프로바이더를 설치한다.
# main.tf
resource "local_file" "abc" {
content = "123"
filename = "${path.module}/abc.txt"
}
resource "aws_instance" "web" {
ami = "ami-a1b2c3d4"
instance_type = "t2.micro"
}
init
# init 시 프로바이더 선언 없이도 리소스 추가로 자동 인식된 프로바이더 요구사항과 초기화
terraform init
tree .terraform
확인
- 리소스 동작 보조 추가 메타인수를 정의 할 수 있다 → 뒤에서 자세히 설명
- depends_on : 종속성을 선언하며, 선언된 구성요소와의 생성 시점에 대해 정의
- count : 선언된 개수에 따라 여러 리소스를 생성
- for_each : map 또는 set 타입의 데이터 배열의 값을 기준으로 여러 리소스를 생성
- provider : 동일한 프로바이더가 다수 정의되어 있는 경우 지정
- lifecycle : 리소스의 수명주기 관리
- provisioner : 리소스 생성 후 추가 작업 정의
- timeouts : 프로바이더에서 정의한 일부 리소스 유형에서는 create, update, delete에 대한 허용 시간 정의 가능
- 종속성
- 테라폼 종속성은 resource, module 선언으로 프로비저인되는 각 요소의 생성 순서를 구분짓는다.
- 기본적으로 다른 리소스에서 값을 참조해 불러올 경우 생성 선후 관계에 따라 작업자가 의도하지는 않았지만 자동으로 연관 관계가 정의되는 암시적 종속성을 갖게 되고, 강제로 리소스 간 명시적 종속성을 부여할 경우에는 메타인수인 depends_on을 활용한다. [참고: Docs]
- 코드 파일 수정
resource "local_file" "abc" {
content = "123!"
filename = "${path.module}/abc.txt"
}
resource "local_file" "def" {
content = "456!"
filename = "${path.module}/def.txt"
}
- apply 실행 : 서로 선후 관계가 없는 동일한 수준으로, 병렬(동시) 실행
- VS Code 확장 graphviz 설치
# 모니터링 : 신규 터미널
cd 03.end
watch -d ls -l
# apply
terraform apply -auto-approve
...
Plan: 2 to add, 0 to change, 0 to destroy.
local_file.def: Creating...
local_file.abc: Creating...
local_file.abc: Creation complete after 0s [id=5f30576af23a25b7f44fa7f5fdf70325ee389155]
local_file.def: Creation complete after 0s [id=b9fbde4d33ab9c450a7ce303fb4788c9d2db9aed]
# 리소스 확인
ls *.txt
terraform state list
local_file.abc
local_file.def
# graph 확인 > graph-1.dot 파일 선택 후 오른쪽 상단 DOT 클릭
terraform graph
terraform graph > graph-1.dot
# 모든 리소스 제거
terraform destroy -auto-approve
ls *.txt
terraform state list
병렬로 실행된 것을 볼 수 있습니다. (의존 관계가 없음)
리소스 참조값을 설정해 두 개의 리소스 간 암시적 종속성 부여
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"
}
종속성 확인
리소스의 속성을 주입하지 않아도 두 리소스 간에 종속성이 필요한 경우에, depends_on 선언으로 적용 가능
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"
}
#
terraform destroy -auto-approve
terraform apply -auto-approve
...
# graph 확인 > graph-3.dot 파일 선택 후 오른쪽 상단 DOT 클릭
terraform graph
terraform graph > graph-3.dot
결과는 위에 그림과 같습니다.
리소스 속성 참조
- 리소스 구성에서 참조 가능한 값은 인수와 속성이다
- 인수 : 리소스 생성 시 사용자가 선언하는 값
- 속성 : 사용자가 설정하는 것은 불가능하지만 리소스 생성 이후 획득 가능한 리소스 고유 값
- 리소스 인수의 선언과 참조 가능한 인수 및 속성 패턴
# Terraform Code
resource "<리소스 유형>" "<이름>" {
<인수> = <값>
}
# 리소스 참조
<리소스 유형>.<이름>.<인수>
<리소스 유형>.<이름>.<속성>
아래 코드는 쿠버네티스 프로바이더의 Namespace 리소스를 생성하고 이후 Secret을 해당 Namespace에 생성하는 종속성을 리소스 인수 값 값으로 생성하는 예이다. Namespace의 이름만 변경해도, 해당 Namespace를 참조하는 모든 리소스가 업데이트되어 영향을 받는다.
resource "kubernetes_namespace" "example" {
metadata {
annotations = {
name = "example-annotation"
}
name = "terraform-example-namespace"
}
}
resource "kubernetes_secret" "example" {
metadata {
namespace = kubernetes_namespace.example.metadata.0.name # namespace 리소스 인수 참조
name = "terraform-example"
}
data = {
password = "P4ssw0rd"
}
}
- 리소스가 생성될 때, 사용자가 입력한 ‘인수’를 받아 실제 리소스가 생성되면 일부 리소스는 자동으로 기본값이나 추가되는 ‘속성’이 부여된다.
- 각 리소스마다 문서를 확인해보면 인수는 Arguments로 표현되어 있으며, 리소스 생성 후 추가되는 속성 값으로 Attributes에 안내되어 있다 - 링크
- 리소스 속성을 참조하는 다른 리소스 또는 구성요소에서는 생성 후의 속성 값들도 인수로 가져올 수 있다.
수명주기
create_before_destroy (bool): 리소스 수정 시 신규 리소스를 우선 생성하고 기존 리소스를 삭제
- 예를 들어 image 변경 되는 경우 해당 VM 리소스를 삭제하고 다시 생성
- 테라폼의 기본 수명주기는 삭제 후 생성이기 때문에 작업자가 의도적으로 수정된 리소스를 먼저 생성하기를 원할 수 있다.
- 이 경우 create_before_destroy 가 true로 선언되면 의도한 생성을 실행한 후 삭제로 동작한다.
- 하지만 생성되는 리소스가 기존 리소스로 인해 생성이 실패되거나 삭제 시 함께 삭제될 수 있으니 주의해야 한다.
- 잘못된 사례 1 : 리소스의 명시적 구분이 사용자가 지정한 특정 이름이나 ID인 경우 기존 리소스에 할당되어 있기 때문에 생성 실패
- 잘못된 사례 2 : 생성 후 삭제 시 동일한 리소스에 대한 삭제 명령이 수행되어 리소스가 모두 삭제
prevent_destroy (bool): 해당 리소스를 삭제 Destroy 하려 할 때 명시적으로 거부
resource "local_file" "abc" {
content = "lifecycle - step 3"
filename = "${path.module}/abc.txt"
lifecycle {
prevent_destroy = true
}
}
apply 시 에러 발생
수정수 apply
resource "local_file" "abc" {
content = "lifecycle - step 3"
filename = "${path.module}/abc.txt"
}
ignore_changes (list): 리소스 요소에 선언된 인수의 변경 사항을 테라폼 실행 시 무시
- ignore_changes 리소스 요소의 인수를 지정해 수정 계획에 변경 사항이 반영되지 않도록 하는 것이다.
resource "local_file" "abc" {
content = "lifecycle - step 4"
filename = "${path.module}/abc.txt"
lifecycle {
ignore_changes = []
}
}
수정 후 다시 apply
resource "local_file" "abc" {
content = "lifecycle - step 5"
filename = "${path.module}/abc.txt"
lifecycle {
ignore_changes = [
content
]
}
}
ignore를 적용하면 파일이 수정 되지 않습니다.
precondition: 리소스 요소에 선언해 인수의 조건을 검증
- 리소스 생성 이전에 입력된 인수 값을 검증하는 데 사용해 프로비저닝 이전에 미리 약속된 값 이외의 값 또는 필수로 명시해야 하는 인수 값을 검증할 수 있다.
variable "file_name" {
default = "step0.txt"
}
resource "local_file" "abc" {
content = "lifecycle - step 6"
filename = "${path.module}/${var.file_name}"
lifecycle {
precondition {
condition = var.file_name == "step6.txt"
error_message = "file name is not \"step6.txt\""
}
}
}
실행하면 되지 않습니다.
- precondition은 프로비저닝해야 하는 클라우드 인프라의 VM을 생성할 때 내부적으로 검증된 이미지 아이디를 사용하는지 등과 같은 구성을 미리 확인하고 사전에 잘못된 프로비저닝을 실행할 수 없도록 구성할 수 있다.
파일 수정 후 apply
resource "local_file" "abc" {
content = ""
filename = "${path.module}/step7.txt"
lifecycle {
postcondition {
condition = self.content != ""
error_message = "content cannot empty"
}
}
}
output "step7_content" {
value = local_file.abc.id
}
그래도 실행이 안된다 -> postcondition 조건에 맞지 않아 에러 발생
다시 수정
resource "local_file" "abc" {
content = "step7 file ok"
filename = "${path.module}/step7.txt"
lifecycle {
postcondition {
condition = self.content != ""
error_message = "content cannot empty"
}
}
}
output "step7_content" {
value = local_file.abc.id
}
확인
- 종속성을 갖는 여러 리소스를 구성하는 경우, 리소스의 데이터가 다른 리소스 생성 시 활용될 때 원하는 속성이 정의되어야 하는 경우를 확인할 수 있다.
- 특히, 프로비저닝 이후에 생성되는 속성 값이 있으므로 영향을 받는 다른 리소스가 생성되기 전에 예상되지 않은 프로비저닝 작업을 방지할 수 있다.
'study > T101 4기' 카테고리의 다른 글
T101 4기 3주차 첫번째 (0) | 2024.06.29 |
---|---|
T101 4기 2주차 두번째 (0) | 2024.06.22 |
T101 4기 2주차 첫번째 (0) | 2024.06.22 |
T101 4기 1주차 두번째 (0) | 2024.06.15 |
T101 4기 1주차 첫번째 (0) | 2024.06.15 |