LabHub
배우기 러닝패스 코스

Terraform in Practice

Deleting It from Code Nearly Destroyed a Live Resource

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

리소스를 부수지 않고 상태에서만 빼는 removed 블록을 써 보고, 이 판의 removed 가 무엇을 받는지 도구에게 직접 물어 기록하고, moved 로 이름만 바꾸고, -replace 와 taint 로 하나만 다시 만든 뒤, 모듈 하나를 통째로 내려놓습니다.

왜 중요한가

인프라 코드를 오래 운영하면 코드와 실물의 소유 관계를 손대야 하는 날이 옵니다. 팀이 갈라지고, 다른 도구로 옮기고, 넘겨받은 것을 되돌려 줍니다. 그런데 설정에서 리소스 블록을 지우는 것은 도구에게 '부숴라' 로 읽힙니다 — 소유를 내려놓는다는 뜻이 아닙니다. 그래서 그 뜻을 따로 말하는 선언이 필요하고, 명령이 아니라 선언으로 하는 이유는 리뷰와 기록 때문입니다. 누가 언제 무엇을 상태에서 뺐는지가 커밋에 남습니다. 여기에 한 가지 함정이 더 있습니다 — 문서는 언제나 최신판을 설명하지만 여러분이 쓰는 판은 그보다 낮을 수 있습니다. removed 블록이 받는 인자가 판마다 다르다는 것을 알고, 문서가 아니라 손에 있는 도구에게 물어 확인하는 습관이 이 모듈에서 배울 두 번째 것입니다.

단계

  1. /root/tfa-removed/keep.tfrandom_pet.keep(length 2)과 그 이름을 out/keep.txt 에 쓰는 local_file.keep 을, /root/tfa-removed/legacy.tfout/legacy.txtlegacy service 한 줄을 쓰는 local_file.legacy 를 두고 init·apply 하세요. 그다음 상태 파일을 /root/tfa-removed/snapshots/before.tfstate 로 한 번만 복사합니다.
  2. /root/tfa-removed/legacy.tf 를 지우고 /root/tfa-removed/removed.tfremoved 블록으로 local_file.legacy 를 상태에서 빼겠다고 선언하세요. apply 전에 계획 출력을 /root/tfa-removed/removed-plan.txt 에 저장하고 apply 합니다. out/legacy.txt 는 그대로 남아 있어야 합니다.
  3. /root/tfa-removed/removed.tf 의 removed 블록 안에 lifecycle 블록(destroy = false) 를 잠깐 넣고 tofu plan 을 돌려 결과를 /root/tfa-removed/lifecycle-probe.txt 에 저장한 뒤 원래대로 되돌리세요. 그다음 /root/tfa-removed/removed-facts.tsv 에 세 줄을 탭 두 칸으로 적습니다 — tofu_version 은 이 파드의 코어 버전, removed_lifecyclesupported 또는 unsupported, removed_effectforget 또는 destroy.
  4. /root/tfa-removed/keep.tfrandom_pet.keeprandom_pet.app 으로 바꾸고(참조도 함께), /root/tfa-removed/moved.tfmoved 블록으로 옛 주소에서 새 주소로 옮긴다고 선언한 뒤 apply 하세요. 그다음 /root/tfa-removed/moved.tsvbefore(1단계 사본에 적힌 random_pet.keep 의 id)와 after(지금 상태의 random_pet.app 의 id) 두 줄을 탭 두 칸으로 적습니다. 두 값은 같아야 합니다.
  5. /root/tfa-removed/legacy.tf 를 잠깐 되살려(2단계와 같은 내용) tofu plan 을 돌리고, 출력을 /root/tfa-removed/conflict.txt 에 저장한 뒤 다시 그 파일을 지우세요. removed 블록은 그대로 둡니다. 마지막에 계획은 깨끗해야 합니다.
  6. 상태 파일을 /root/tfa-removed/snapshots/before-replace.tfstate 로 복사한 뒤 tofu apply -replace=random_pet.app -auto-approve 를 돌리세요. 그다음 /root/tfa-removed/replace.tsvbefore(사본의 id)와 after(지금 id) 두 줄을 탭 두 칸으로 적습니다. 두 값은 달라야 합니다.
  7. tofu taint random_pet.app 으로 표시한 뒤, 상태에 적힌 그 인스턴스의 상태 값을 /root/tfa-removed/taint-status.txt 에 한 줄로 저장하고 tofu plan 출력을 /root/tfa-removed/taint-plan.txt 에 저장하세요. 그다음 tofu untaint 로 되돌려 계획이 깨끗한 상태로 마칩니다.
  8. /root/tfa-removed/modules/archive/main.tfout/archive-1.txt·out/archive-2.txt 두 파일을 쓰는 모듈을 만들고 /root/tfa-removed/archive.tf 에서 module "archive" 로 부른 뒤 apply 하세요. 그다음 /root/tfa-removed/archive.tf 를 지우고 /root/tfa-removed/archive-removed.tfremoved 블록으로 module.archive 를 통째로 상태에서 빼세요. 계획 출력은 /root/tfa-removed/module-plan.txt 에 저장하고, 두 파일은 디스크에 남아야 합니다.

참고

넘겨받은 것까지 한 상태에 담는다

/root/tfa-removed/keep.tfrandom_pet.keep(length 2)과 그 이름을 out/keep.txt 에 쓰는 local_file.keep 을, /root/tfa-removed/legacy.tfout/legacy.txtlegacy service 한 줄을 쓰는 local_file.legacy 를 두고 init·apply 하세요. 그다음 상태 파일을 /root/tfa-removed/snapshots/before.tfstate 로 한 번만 복사합니다.

뒤 단계에서 '이 리소스가 다시 만들어졌는가, 그대로인가' 를 판단하려면 지금의 식별자를 어딘가 남겨 둬야 합니다. 사본은 처음 한 번만 뜨세요 — 나중에 덮어쓰면 비교할 원본이 사라집니다.

상태에서만 빼고 실물은 남긴다

/root/tfa-removed/legacy.tf 를 지우고 /root/tfa-removed/removed.tfremoved 블록으로 local_file.legacy 를 상태에서 빼겠다고 선언하세요. apply 전에 계획 출력을 /root/tfa-removed/removed-plan.txt 에 저장하고 apply 합니다. out/legacy.txt 는 그대로 남아 있어야 합니다.

설정에서 리소스 블록만 지우면 도구는 그것을 부수라는 뜻으로 읽습니다. removed 블록은 '이 주소를 상태에서 잊어라' 를 따로 말하는 선언입니다. 계획 출력에서 이 동작을 가리키는 낱말이 destroy 가 아니라는 점을 확인하세요.

이 판의 removed 가 무엇을 받는지 도구에게 묻는다

/root/tfa-removed/removed.tf 의 removed 블록 안에 lifecycle 블록(destroy = false) 를 잠깐 넣고 tofu plan 을 돌려 결과를 /root/tfa-removed/lifecycle-probe.txt 에 저장한 뒤 원래대로 되돌리세요. 그다음 /root/tfa-removed/removed-facts.tsv 에 세 줄을 탭 두 칸으로 적습니다 — tofu_version 은 이 파드의 코어 버전, removed_lifecyclesupported 또는 unsupported, removed_effectforget 또는 destroy.

문서는 언제나 최신판을 설명합니다. 지금 손에 있는 판이 무엇을 받는지는 도구에게 물어야 알 수 있고, 그 답을 적어 두는 것이 팀의 시간을 아낍니다. 효과는 2단계의 계획 출력이 이미 말해 주고 있습니다.

이름만 바꾼다 — 같은 것을 다시 만들지 않고

/root/tfa-removed/keep.tfrandom_pet.keeprandom_pet.app 으로 바꾸고(참조도 함께), /root/tfa-removed/moved.tfmoved 블록으로 옛 주소에서 새 주소로 옮긴다고 선언한 뒤 apply 하세요. 그다음 /root/tfa-removed/moved.tsvbefore(1단계 사본에 적힌 random_pet.keep 의 id)와 after(지금 상태의 random_pet.app 의 id) 두 줄을 탭 두 칸으로 적습니다. 두 값은 같아야 합니다.

moved 블록이 없으면 도구는 '옛 이름이 사라지고 새 이름이 생겼다' 로 읽어 부수고 다시 만듭니다. moved 는 같은 객체의 주소만 바뀌었다고 알려 주는 선언이라, 식별자가 그대로 유지됩니다. 그것이 정말 그런지 1단계 사본과 견줘 확인하세요.

잊으라고 해 놓고 다시 선언하면

/root/tfa-removed/legacy.tf 를 잠깐 되살려(2단계와 같은 내용) tofu plan 을 돌리고, 출력을 /root/tfa-removed/conflict.txt 에 저장한 뒤 다시 그 파일을 지우세요. removed 블록은 그대로 둡니다. 마지막에 계획은 깨끗해야 합니다.

잊으라는 선언과 만들라는 선언이 같은 주소에 동시에 있으면 도구는 무엇을 해야 할지 알 수 없습니다. 이 오류는 tofu validate 는 통과하고 plan 에서만 납니다 — 왜 그런지 생각해 보세요(주소 해석은 설정 검증이 아니라 계획 단계의 일입니다).

하나만 다시 만든다

상태 파일을 /root/tfa-removed/snapshots/before-replace.tfstate 로 복사한 뒤 tofu apply -replace=random_pet.app -auto-approve 를 돌리세요. 그다음 /root/tfa-removed/replace.tsvbefore(사본의 id)와 after(지금 id) 두 줄을 탭 두 칸으로 적습니다. 두 값은 달라야 합니다.

-replace 는 설정을 바꾸지 않고 '이것만 부수고 다시 만들어라' 를 계획에 넣습니다. 프로바이더가 이상해졌을 때나, 설정에 드러나지 않는 부팅 상태를 초기화할 때 씁니다. 이 리소스에 의존하는 것이 함께 다시 만들어지는지도 계획에서 보세요.

손으로 표시했다가 되돌린다

tofu taint random_pet.app 으로 표시한 뒤, 상태에 적힌 그 인스턴스의 상태 값을 /root/tfa-removed/taint-status.txt 에 한 줄로 저장하고 tofu plan 출력을 /root/tfa-removed/taint-plan.txt 에 저장하세요. 그다음 tofu untaint 로 되돌려 계획이 깨끗한 상태로 마칩니다.

표시는 인프라를 건드리지 않고 상태 파일에만 적힙니다 — 다음 계획이 그것을 읽어 교체를 넣습니다. jq 로 그 인스턴스의 status 를 보세요. 오늘은 같은 일을 -replace 로 더 안전하게 할 수 있지만(상태를 미리 바꾸지 않으므로), 이 명령이 무엇을 하는지는 알아야 남이 표시해 둔 것을 만났을 때 당황하지 않습니다.

모듈 하나를 통째로 내려놓는다

/root/tfa-removed/modules/archive/main.tfout/archive-1.txt·out/archive-2.txt 두 파일을 쓰는 모듈을 만들고 /root/tfa-removed/archive.tf 에서 module "archive" 로 부른 뒤 apply 하세요. 그다음 /root/tfa-removed/archive.tf 를 지우고 /root/tfa-removed/archive-removed.tfremoved 블록으로 module.archive 를 통째로 상태에서 빼세요. 계획 출력은 /root/tfa-removed/module-plan.txt 에 저장하고, 두 파일은 디스크에 남아야 합니다.

removed 의 from 에는 리소스 주소뿐 아니라 모듈 주소도 올 수 있고, 그러면 그 모듈 안의 것이 한꺼번에 상태에서 빠집니다. 조직을 나눌 때 한 팀의 몫을 통째로 넘기는 작업이 이 모양입니다. 모듈 안에서 파일 경로를 잡을 때는 루트 기준 경로를 쓰는 편이 헷갈리지 않습니다.