상태만 고치는 명령과 지우는 순서
한 줄 요약
계획은 코드와 상태, 상태와 실물이라는 두 비교를 함께 한다. 새로고침 계열 명령은 뒤쪽 비교만 떼어 내고, 파괴는 그 그래프를 거꾸로 걷는다.
왜 나눠야 했나
apply 한 번에는 사실 세 가지 일이 들어 있다. 실물을 읽어 상태를 최신으로 만들고, 그 상태를 코드와 견줘 할 일을 정하고, 정한 일을 실행한다. 대부분은 이 묶음이 편하다. 그런데 묶여 있어서 곤란한 경우가 있다.
첫째, 상태만 틀린 경우다. 누군가 콘솔에서 자원을 손으로 지웠거나 이름을 바꿨다고 하자. 코드는 멀쩡하고 실물도 (그 변경을 인정한다면) 멀쩡한데 상태만 옛말을 하고 있다. 이때 그냥 적용하면 도구는 없는 것을 새로 만들거나 있는 것을 덮어쓴다. 필요한 것은 "상태를 실물에 맞추기" 뿐이다.
둘째, 반대로 실물을 읽는 비용이 클 때가 있다. 자원이 수천 개인 저장소에서는 새로고침만 몇 분씩 걸린다. 급할 때 그 단계를 건너뛰고 계획을 뽑고 싶어진다.
그래서 두 비교를 따로 다루는 옵션이 생겼다.
본문의 설명대로 apply 를 일의 단위로 쪼갠 그림이다. 새로고침 전용 명령은 이 가운데 실물과 상태를 견주는 앞쪽만 떼어 낸다.
- 실물을 읽어 상태를 최신으로 만든다프로바이더 API 로 실제 자원을 조회한다. 누군가 콘솔에서 손으로 지운 것도 여기서 드러난다.
- 상태를 코드와 견줘 할 일을 정한다갱신된 상태와 코드를 비교해 계획을 만든다.
- 정한 일을 실행한다계획이 정한 대로 만들고, 고치고, 지운다.
여기서 구분할 것 새로고침 전용 계획은 코드를 아예 보지 않고 상태와 실물만 견준다. 여기서 적용하면 상태만 바뀌고 실물은 한 톨도 건드리지 않으며, 직전 상태는 백업 파일에 남는다.
잠깐, 예측해 보세요 새로고침 전용 계획의 출력에 local_file.conf has been deleted 가 떴다. 이 출력만 보고 코드와 실물이 일치한다고 말할 수 있을까?
설명 확인 · 채점 없는 자가 점검
말할 수 없다. 새로고침 전용 계획은 코드를 보지 않고 상태와 실물만 비교하므로 코드와의 차이는 이 출력에 담기지 않는다. 코드까지 반영한 결과는 보통 계획으로 따로 확인해야 한다.
어떻게 동작하나
새로고침 전용 계획은 코드를 아예 보지 않는다. 상태와 실물만 견주고, 상태를 어떻게 고칠지 보여 준다.
Note: Objects have changed outside of OpenTofu
# local_file.conf has been deleted
- resource "local_file" "conf" {
여기서 적용하면 상태만 바뀐다. 실물은 한 톨도 건드리지 않고, 직전 상태는 백업 파일에 남는다. 상태의 일련번호가 올라가고 사라진 항목이 상태에서 빠진다.
실물을 읽지 않는 계획은 정반대다. 상태에 적힌 값을 사실로 믿으므로, 밖에서 무엇이 바뀌었든 모른다.
No changes. Your infrastructure matches the configuration.
같은 순간에 그냥 계획을 돌리면 전혀 다른 말이 나온다. 없어진 것을 다시 만들고, 그 값을 참조하던 것까지 교체한다. 같은 코드, 같은 상태, 같은 순간인데 결론이 다르다 — 차이는 실물을 읽었느냐뿐이다. 그래서 속도를 위해 이 옵션을 쓴 계획으로 승인을 받으면 안 된다.
파괴 쪽으로 가 보자. 만들 때 도구는 의존 그래프를 따라 앞에서부터 만든다. 네트워크가 생겨야 데이터베이스가 생기고, 그래야 애플리케이션이 생긴다. 지울 때는 정확히 그 역순이어야 한다. 애플리케이션이 아직 데이터베이스를 가리키고 있는데 데이터베이스를 먼저 지우면, 남은 쪽이 없는 것을 가리키게 된다.
파괴 계획도 보통 계획처럼 파일로 저장할 수 있다. 되돌릴 수 없는 작업일수록 저장해 리뷰한 뒤 그 파일만 적용하는 편이 안전하다. 저장한 계획 파일은 기계가 읽을 형식으로도 볼 수 있어 무엇이 지워질지 목록으로 뽑아 승인에 붙일 수 있다.
대상을 좁히는 옵션은 다르다. 이것을 쓰면 도구가 평소 지켜 주던 전체 그래프의 일관성을 사람이 책임지겠다는 뜻이고, 그래서 경고가 붙는다.
Warning: Resource targeting is in effect
Warning: Applied changes may be incomplete
마지막으로, 다 지워도 상태 파일 자체는 사라지지 않는다. 항목 목록과 출력이 비고 일련번호가 올라갈 뿐, 그 상태의 혈통 번호는 그대로다. 같은 자리에서 다시 적용하면 같은 기록의 연장선으로 이어진다. 상태 파일을 지우는 것은 자원을 지우는 것과 전혀 다른 일이다 — 지우면 실물은 남고 기록만 사라져, 도구는 그것들을 모르는 것으로 취급하게 된다.
현장에서 만나는 모습
가장 비싼 사고는 상태만 어긋난 상황에서 그냥 적용해 버리는 것이다. 운영에서 누군가 손으로 고친 자원을 도구가 다시 만들고, 그 사이 트래픽이 끊긴다. 새로고침 전용 계획을 먼저 돌려 "코드가 아니라 상태 문제인가" 를 가르는 습관이 이 사고를 막는다.
두 번째는 빠른 계획의 함정이다. 대규모 저장소에서 새로고침을 끈 계획을 CI 에 넣어 두면 검토는 빨라지지만, 밖에서 생긴 변경은 승인 뒤에야 드러난다. 속도가 필요하면 적용 직전에 한 번 더, 실물을 읽는 계획을 돌리는 것이 타협점이다.
세 번째는 대상을 좁힌 적용이 습관이 되는 경우다. 급할 때 한 번 쓴 옵션이 팀의 기본 절차가 되면, 그래프 전체가 일관된 적이 없는 저장소가 된다. 쓴 뒤에는 반드시 좁히지 않은 계획을 한 번 돌려 깨끗한지 확인한다.
네 번째는 파괴를 명령 한 줄로 끝내는 관행이다. 지우는 일은 되돌릴 수 없는데, 대화형 확인만 한 번 거치고 끝내면 무엇이 지워졌는지 나중에 아무도 재구성하지 못한다. 계획을 파일로 저장해 기계가 읽을 형식으로 목록을 뽑아 두면, 승인 근거가 남고 사고가 났을 때 무엇을 복구해야 하는지가 한 번에 나온다. 파일로 저장한 계획을 적용하면 리뷰한 것과 실제 작업이 어긋날 여지도 없다.
누군가 콘솔에서 자원을 지운 직후에 같은 저장소로 계획을 두 번 뽑는다. conf 라는 이름은 본문 사례의 설명용 이름이다.
- 실물을 읽지 않는 계획 (-refresh=false)상태에 적힌 값을 사실로 믿는다. 밖에서 무엇이 바뀌었든 모르고 변경 없음이라고 말한다.
- 실물을 읽는 보통 계획없어진 것을 다시 만들고, 그 값을 참조하던 것까지 교체하겠다고 말한다.
여기서 구분할 것 차이는 실물을 읽었느냐뿐이다. 그래서 속도를 위해 읽기를 끈 계획으로 승인을 받으면 안 된다. 밖에서 생긴 변경이 승인 뒤에야 드러난다.
잠깐, 예측해 보세요 자원이 수천 개라 CI 의 계획을 -refresh=false 로 바꿔 몇 분을 아꼈다. 이 속도 이득과 안전을 함께 가져가려면 어떻게 해야 할까?
설명 확인 · 채점 없는 자가 점검
읽기를 끈 계획은 검토용으로만 쓰고 승인의 근거로 삼지 않는다. 본문이 제시한 타협점은 적용 직전에 한 번 더 실물을 읽는 계획을 돌리는 것이다.
다음 실습에서 할 것
여덟 단계를 돕니다. 기준선을 만들고, 도구를 거치지 않고 파일을 고친 뒤 새로고침 전용 계획을 뽑고, 실물을 읽지 않은 계획과 읽은 계획을 나란히 저장해 비교합니다. 이어서 새로고침만 적용해 상태의 일련번호와 항목 수가 어떻게 바뀌는지, 손으로 고친 파일은 그대로인지 확인합니다. 뒤쪽 네 단계에서는 세 단계 사슬을 만들어 파괴 계획을 파일로 저장하고, 그 파일을 적용해 지워지는 순서를 로그로 확인하고, 대상을 좁힌 파괴의 경고를 읽고, 마지막으로 다 지운 상태에 무엇이 남는지를 백업과 견줍니다.