Terraform 실전 · 지우지 않고 소유를 내려놓기 · 이론
부수기와 내려놓기는 다른 일이다
한 줄 요약
설정에서 리소스 블록을 지우는 것은 "부숴라" 다. "이제 우리가 관리하지 않는다" 는 뜻은 removed 블록으로 따로 말해야 한다.
왜 이게 필요했나 — 지우기와 내려놓기가 같은 문장이었다
한 팀이 데이터베이스 세 대를 관리하다가 그중 하나를 다른 팀에 넘긴다고 하자. 코드에서 그 블록을 지우는 것이 자연스러워 보인다. 그리고 plan 을 돌리면 destroy 1 이 뜬다. 운영 중인 데이터베이스다.
예전에는 이 상황을 명령으로 풀었다. 상태에서 그 주소를 빼는 명령을 손으로 한 번 치고, 그다음에 코드를 지운다. 동작은 하지만 두 가지가 나쁘다. 첫째, 기록이 없다. 누가 언제 무엇을 상태에서 뺐는지 커밋에 남지 않는다. 둘째, 순서를 틀리면 끝난다. 코드를 먼저 지우고 apply 를 치면 그것으로 상황이 종료된다.
removed 블록은 이 일을 선언으로 옮긴 것이다. 코드에 적히니 리뷰를 받고, 커밋에 남고, 순서가 뒤집힐 여지가 없다.
어떻게 동작하나
# 1) 리소스 블록을 지운다# 2) 그 자리에 removed 블록을 둔다removed { from = local_file.legacy}계획을 돌리면 이렇게 나온다.
# local_file.legacy will be removed from the OpenTofu state# but will not be destroyedPlan: 0 to add, 0 to change, 0 to destroy.읽어야 할 곳이 두 군데다. 첫째, 동작을 가리키는 낱말이 destroy 가 아니다. 둘째, 그래서 Plan: 줄의 세 숫자가 모두 0 이다 — 실물에는 아무 일도 하지 않는다는 뜻이다.
판마다 받는 인자가 다르다. 이것이 이 모듈에서 꼭 가져가야 할 습관인데, removed 블록이 lifecycle 같은 하위 블록을 받는지는 쓰고 있는 판에 달려 있다. 문서 사이트는 기본으로 최신판을 보여 주므로, 문서에 있다고 해서 내 도구가 받는다는 보장이 없다. 확인하는 법은 간단하다 — 넣어 보고 plan 을 돌려 보면 도구가 직접 답한다. 실습 3단계에서 이 파드의 판이 무엇을 받고 무엇을 안 받는지 직접 물어 표로 적는다.
이름만 바꾸는 일은 moved 다. removed 와 헷갈리기 쉬운데 목적이 반대다. moved 는 "같은 객체인데 주소가 바뀌었다" 를 말해 상태의 항목을 새 주소로 옮긴다. 이것이 없으면 도구는 옛 이름이 사라지고 새 이름이 생긴 것으로 읽어 부수고 다시 만든다. 옮겼는지 다시 만들었는지는 식별자를 견주면 바로 안다.
하나만 다시 만들고 싶을 때는 -replace. 설정은 그대로 두고 "이 주소만 부수고 다시 만들어라" 를 계획에 넣는다. 예전에는 같은 일을 taint 로 했는데, 차이가 중요하다. taint 는 상태 파일을 먼저 고쳐 놓고 다음 계획이 그것을 읽게 한다. 표시해 둔 채 잊어버리면 엉뚱한 사람이 엉뚱한 때에 그 교체를 적용하게 된다. -replace 는 그 실행에만 적용되므로 흔적이 남지 않는다. 그래도 taint·untaint 를 알아 둬야 하는 이유는, 남이 표시해 둔 상태를 만났을 때 당황하지 않기 위해서다.
현장에서 만나는 모습
가장 흔한 사고는 removed 블록을 치우지 않고 남겨 두는 것이다. 일이 끝나면 그 블록은 죽은 코드인데, 죽은 채로 있다가 언젠가 그 주소의 리소스가 다시 필요해지는 날 되살아난다. "잊어라" 와 "만들어라" 가 같은 주소에 동시에 있으면 계획이 막힌다. 더 얄궂은 것은 이 오류가 설정 검증(validate)은 통과하고 계획에서만 난다는 점이다. 주소를 상태와 맞춰 보는 일은 계획 단계의 몫이기 때문이다. CI 가 validate 만 돌리고 있으면 이 문제를 못 잡는다.
두 번째는 조직 분할이다. 팀이 갈라질 때 한쪽 몫을 통째로 넘겨야 하는데, removed 의 from 에는 모듈 주소도 올 수 있어서 모듈 하나를 한꺼번에 내려놓을 수 있다. 다만 받는 쪽이 그 실물을 자기 상태로 가져가는 일은 별도 작업이고, 프로바이더가 그 리소스의 가져오기를 지원해야 한다 — 모든 리소스가 그렇지는 않다.
세 번째는 소유가 비어 있는 기간이다. 내려놓은 시점부터 받는 쪽이 가져갈 때까지 그 실물은 어느 코드도 관리하지 않는다. 그 사이에 아무도 그것을 건드리지 않게 하려면, 넘기는 작업을 문서와 일정으로 감싸야 한다. 도구가 해 줄 수 있는 일이 아니다.
네 번째는 되찾을 수 있는가다. 상태에서 뺀 것을 다시 코드로 관리하려면 가져오기(import)를 해야 하는데, 프로바이더가 그 리소스의 가져오기를 구현해 두지 않았으면 방법이 없다. 이 실습의 파일 리소스가 바로 그런 경우다. 그래서 내려놓기 전에 "이건 되돌릴 수 있는 결정인가" 를 한 번 확인해 두는 편이 안전하다 — 되돌릴 수 없다면 사본을 남기거나, 넘기는 쪽과 받는 쪽이 같은 시각에 작업해야 한다.
다음 실습에서 할 것
/root/tfa-removed 에서 넘겨받은 파일 하나를 removed 로 상태에서만 빼고 실물이 남는 것을 확인합니다. 이 판의 removed 가 무엇을 받는지 직접 물어 표로 적고, moved 로 이름을 바꿔 식별자가 유지되는 것을 1단계 사본과 견주고, 잊으라는 선언과 만들라는 선언이 겹쳤을 때의 오류를 받아 본 뒤, -replace 와 taint 로 하나만 다시 만들고, 마지막으로 모듈 하나를 통째로 내려놓습니다.