周五晚上手动改的规则,周一的 apply 想把它删掉
한국어 원문으로 표시합니다.
목표
코드 밖에서 생긴 변경을 plan -refresh-only 로 따로 읽고, 그대로 적용하면 사라질 것을 계획 JSON 에서 찾은 뒤, 흡수·되돌림·제외 세 가지 해소를 직접 하고 매일 돌릴 감지 스크립트를 만듭니다.
왜 중요한가
선언형 도구는 코드를 진실로 삼으므로 콘솔에서 고친 옳은 수정도 다음 적용에서 되돌립니다. 그래서 드리프트를 발견하면 먼저 무엇이 사라질지 읽고, 흡수할지 되돌릴지를 사람이 정해야 합니다. ignore_changes 는 모든 드리프트를 숨겨 주는 스위치가 아니고, 프로바이더가 읽지 않는 속성의 변경은 계획에 아예 나타나지 않습니다. 이 한계를 알아야 감지 결과가 비었을 때 '일치한다' 와 '안 보인다' 를 구분할 수 있습니다.
단계
/root/iac-drift/main.tf에rules변수(기본값["allow 443"]), 규칙마다 한 줄씩out/firewall.rules에 쓰는local_file.fw,out/motd.txt에maintenance window: sun 02:00한 줄을 쓰는local_file.motd를 두고 init·apply 하세요.- 장애 대응 중 누군가
/root/iac-drift/out/firewall.rules끝에allow 8443한 줄을 손으로 더했습니다(직접 더하세요). 코드는 건드리지 않고tofu plan -refresh-only로 밖에서 생긴 변경만 본 출력을/root/iac-drift/drift.txt에 저장하세요. - 코드를 바꾸지 말고
tofu plan -out=/root/iac-drift/monday.tfplan으로 계획을 저장하세요(적용하지 않음). 그 계획이firewall.rules에 쓸 내용과 지금 파일을 비교해, 적용하면 사라질 줄만/root/iac-drift/lost.txt에 적으세요. - 긴급 수정이 옳았다고 판단했습니다.
rules기본값을["allow 443", "allow 8443"]로 바꾸고 apply 하세요. 그 뒤firewall.rules는 두 줄이고 계획은 깨끗해야 합니다. - 이번에는 누군가
out/motd.txt를maintenance window: none으로 바꿨습니다(직접 바꾸세요). 이건 잘못된 변경입니다. 되돌리기 전에tofu plan -refresh-only출력을/root/iac-drift/revert-drift.txt에 저장하고, 코드는 그대로 둔 채 apply 해 공지를 코드의 내용으로 되돌리세요. main.tf에out/cache.conf에cache v1을 쓰고lifecycle { ignore_changes = [content] }가 걸린local_file.cache를 더해 apply 하세요. (가) 파일을 손으로cache tampered로 바꾼 뒤tofu plan출력을/root/iac-drift/ignore.txt에 저장하고 apply 로 되돌립니다. (나) 코드의 내용을cache v2로 바꾸고 계획이 깨끗한지 봅니다(적용하지 않음). (다)chmod 600 out/firewall.rules뒤tofu plan -detailed-exitcode의 종료 코드를/root/iac-drift/perm.txt에perm=<코드>로 적으세요./root/iac-drift/detect.sh <작업디렉터리>를 만드세요.plan -refresh-only를 계획 파일로 저장해 밖에서 바뀐 리소스의 주소를 모아, 드리프트가 없으면OK와 0, 있으면DRIFT <주소들(공백 구분, 정렬)>한 줄과 2, 실패하면ERROR와 1 로 끝냅니다. 작업 디렉터리에 파일을 남기지 않습니다. 채점기는/root/iac-drift의 사본에서 파일을 바꿔 가며 확인합니다.
참고
- 파드에는 OpenTofu 1.9.0 과 local 프로바이더 미러가 있어 인터넷 없이 돕니다.
- local_file 은 내용이 기록과 다르면 파일을 '삭제됨' 으로 보고하고 다시 만드는 계획을 세웁니다(이 파드에서 실측). 클라우드 리소스의 프로바이더는 보통 속성 단위 차이(~ 수정)로 보고하므로 화면 모양은 다르지만, 흡수·되돌림·제외의 판단은 같습니다.
- 밖에서 생긴 변경만 보기:
tofu plan -refresh-only, 그것을 상태에만 받아들이기:tofu apply -refresh-only. - 흔한 실수: 드리프트를 보자마자 apply 해 옳은 긴급 수정을 지우는 것. 흔한 실수: ignore_changes 를 걸었으니 감지에서 빠진다고 믿는 것.
- tofu plan (-refresh-only) · tofu refresh · lifecycle (ignore_changes) · JSON Output Format (resource_drift)
기준선: 방화벽 규칙과 공지를 코드로 적용한다
/root/iac-drift/main.tf 에 rules 변수(기본값 ["allow 443"]), 규칙마다 한 줄씩 out/firewall.rules 에 쓰는 local_file.fw, out/motd.txt 에 maintenance window: sun 02:00 한 줄을 쓰는 local_file.motd 를 두고 init·apply 하세요.
for 식으로 규칙마다 줄바꿈을 붙이고 join 으로 이어 붙이면 됩니다. 적용 뒤 계획이 비어 있어야 기준선입니다.
금요일 밤의 긴급 수정을 계획에서 본다
장애 대응 중 누군가 /root/iac-drift/out/firewall.rules 끝에 allow 8443 한 줄을 손으로 더했습니다(직접 더하세요). 코드는 건드리지 않고 tofu plan -refresh-only 로 밖에서 생긴 변경만 본 출력을 /root/iac-drift/drift.txt 에 저장하세요.
-refresh-only 는 코드의 변경을 계획하지 않고 실제와 상태의 차이만 보여 줍니다. local_file 프로바이더는 파일 내용이 기록과 다르면 그 파일을 '삭제됐다' 고 보고합니다 — 속성 하나가 바뀐 것으로 보이지 않는다는 점을 출력에서 확인하세요.
월요일에 그냥 apply 하면 무엇이 사라지나
코드를 바꾸지 말고 tofu plan -out=/root/iac-drift/monday.tfplan 으로 계획을 저장하세요(적용하지 않음). 그 계획이 firewall.rules 에 쓸 내용과 지금 파일을 비교해, 적용하면 사라질 줄만 /root/iac-drift/lost.txt 에 적으세요.
계획 JSON 의 resource_changes 에서 local_file.fw 의 change.after.content 가 적용 뒤 파일 내용입니다. 지금 파일에만 있는 줄이 사라질 줄입니다. comm 이나 grep -vxF -f 로 줄 단위 차이를 구할 수 있습니다.
옳은 수정이었다 — 코드로 흡수한다
긴급 수정이 옳았다고 판단했습니다. rules 기본값을 ["allow 443", "allow 8443"] 로 바꾸고 apply 하세요. 그 뒤 firewall.rules 는 두 줄이고 계획은 깨끗해야 합니다.
흡수는 코드를 현실에 맞추는 것입니다. 이 프로바이더는 파일을 '삭제됨' 으로 보았기 때문에, 코드를 고친 뒤의 계획도 수정이 아니라 생성으로 나옵니다 — 쓰는 내용이 지금 파일과 같으니 결과는 같습니다.
잘못된 수정이었다 — 코드대로 되돌린다
이번에는 누군가 out/motd.txt 를 maintenance window: none 으로 바꿨습니다(직접 바꾸세요). 이건 잘못된 변경입니다. 되돌리기 전에 tofu plan -refresh-only 출력을 /root/iac-drift/revert-drift.txt 에 저장하고, 코드는 그대로 둔 채 apply 해 공지를 코드의 내용으로 되돌리세요.
되돌림은 현실을 코드에 맞추는 것입니다. 되돌리기 전에 왜 그런 변경이 있었는지 확인하는 것이 절차의 일부입니다 — 여기서는 drift 출력을 남기는 것으로 그 흔적을 남깁니다.
ignore_changes 가 막는 것과 못 막는 것, 아예 안 보이는 것
main.tf 에 out/cache.conf 에 cache v1 을 쓰고 lifecycle { ignore_changes = [content] } 가 걸린 local_file.cache 를 더해 apply 하세요. (가) 파일을 손으로 cache tampered 로 바꾼 뒤 tofu plan 출력을 /root/iac-drift/ignore.txt 에 저장하고 apply 로 되돌립니다. (나) 코드의 내용을 cache v2 로 바꾸고 계획이 깨끗한지 봅니다(적용하지 않음). (다) chmod 600 out/firewall.rules 뒤 tofu plan -detailed-exitcode 의 종료 코드를 /root/iac-drift/perm.txt 에 perm=<코드> 로 적으세요.
ignore_changes 는 '설정에 적힌 값이 바뀌어도 수정 계획을 세우지 마라' 는 뜻입니다. 프로바이더가 실물을 읽다가 없어졌다고 판단하는 것은 막지 못합니다. 그리고 프로바이더가 읽지 않는 속성의 변경은 드리프트로 잡히지 않습니다.
매일 아침 도는 드리프트 감지
/root/iac-drift/detect.sh <작업디렉터리> 를 만드세요. plan -refresh-only 를 계획 파일로 저장해 밖에서 바뀐 리소스의 주소를 모아, 드리프트가 없으면 OK 와 0, 있으면 DRIFT <주소들(공백 구분, 정렬)> 한 줄과 2, 실패하면 ERROR 와 1 로 끝냅니다. 작업 디렉터리에 파일을 남기지 않습니다. 채점기는 /root/iac-drift 의 사본에서 파일을 바꿔 가며 확인합니다.
계획 JSON 에는 resource_changes 말고도 resource_drift 가 있습니다 — 밖에서 생긴 변경이 거기에 따로 담깁니다. -detailed-exitcode 는 -refresh-only 와 함께 쓸 수 있습니다.