Infrastructure as Code · 드리프트와 임포트 · 실습
보안 규칙을 세 곳에 복붙했고, prod 한 곳을 빼먹었다
목표
이미 운영 중인 복붙 환경 둘을 moved 로 교체 없이 모듈 호출로 바꾸고, 모듈을 git 태그로 고정해 dev 만 새 버전을 쓰게 한 뒤, 변수 값이 들어오는 경로의 우선순위와 모듈 경계의 입력 검증을 확인합니다.
왜 중요한가
복붙한 환경은 한 곳을 고칠 때마다 나머지를 빼먹을 기회를 만듭니다. 그렇다고 이미 적용된 코드를 모듈로 옮기면서 리소스 주소가 바뀌면 도구는 그것을 지우고 다시 만들려 하므로, 리팩터링은 상태에 이동을 알리는 일과 함께 해야 합니다. 모듈에 버전이 없으면 모듈을 고친 순간 모든 환경이 같이 바뀌어 '관계없는 환경이 깨짐' 이 생기고, 값이 여러 경로로 들어오는 규칙을 모르면 실험하다 남긴 파일 하나가 운영 값을 조용히 바꿉니다.
단계
1. /root/iac-mod/dev/main.tf 와 /root/iac-mod/prod/main.tf 에 같은 모양의 리소스 둘을 두세요. local_file.config 는 out/app.conf 에 name=api, env=<환경>, replicas=<수> 세 줄(dev 1, prod 3), local_file.banner 는 out/banner.txt 에 api (<환경>) 한 줄입니다. 두 디렉터리 모두 init·apply 하세요.
2. /root/iac-mod/modules/web/main.tf 에 입력 env(문자열)·replicas(수), 같은 두 리소스, 출력 config_path 를 둔 모듈을 만드세요. dev 의 main.tf 는 replicas 변수(기본 1)를 두고 module "web" 을 source = "../modules/web" 로 부르며, moved 블록 두 개로 옛 주소를 module.web.local_file.config·module.web.local_file.banner 로 옮기세요. init 한 뒤 계획에 생성·삭제·교체가 없어야 하고, 그대로 apply 합니다.
3. /root/iac-mod/prod/main.tf 도 같은 모듈을 부르게 바꾸세요(replicas 기본 3, env prod, moved 두 개). 계획에 생성·삭제·교체가 없어야 하고 apply 합니다. 이제 규칙을 고칠 곳은 모듈 한 곳입니다.
4. /root/iac-mod/modules/web 을 git 저장소로 만들어 지금 내용을 커밋하고 태그 v1.0.0 을 붙이세요. dev·prod 의 source 를 git::file:///root/iac-mod/modules/web?ref=v1.0.0 로 바꾸고 tofu init -upgrade 한 뒤 두 계획이 모두 깨끗해야 합니다.
5. 모듈에 두 가지를 더해 커밋하고 태그 v2.0.0 을 붙이세요: config 내용 끝에 owner=platform 한 줄, 그리고 replicas 가 1 이상 10 이하인지 검사하는 validation. dev 만 ref=v2.0.0 으로 올려 init·apply 하고, prod 는 v1.0.0 에 남겨 계획이 깨끗해야 합니다.
6. dev 에서 replicas 값을 여러 경로로 넣어 보며 echo var.replicas | tofu console 로 실제 값을 확인하고 /root/iac-mod/precedence.txt 에 적으세요. 모든 경우에 환경 변수 TF_VAR_replicas=9 가 있습니다. env_only(파일 없음), with_tfvars(terraform.tfvars 에 2), with_auto(여기에 a.auto.tfvars 3·b.auto.tfvars 4 추가), with_var_file(여기에 -var-file=ops.tfvars, 값 6), with_var(-var-file=ops.tfvars -var replicas=5 순서), var_then_file(-var replicas=5 -var-file=ops.tfvars 순서) 여섯 줄을 이름=값 으로 씁니다. 끝나면 a·b.auto.tfvars 와 ops.tfvars 를 지우고 terraform.tfvars(2)만 남겨 apply 하세요.
7. dev 에서 tofu plan -var replicas=0 을 실행해 출력(오류 포함)을 /root/iac-mod/invalid.txt 에 저장하세요. 채점기는 dev 의 사본에서 0 과 11 이 거부되고, prod(v1.0.0, 검사 없음)에서는 0 이 통과하는지 확인합니다. dev 와 prod 의 계획은 깨끗하게 남겨 둡니다.
참고
- 파드에는 OpenTofu 1.9.0, local 프로바이더 미러, git 이 있어 인터넷 없이 돕니다. 모듈 저장소는
/root/iac-mod/modules/web의 로컬 git 저장소입니다. - 모듈의 source 나 ref 를 바꾸면
tofu init(버전을 올릴 때는-upgrade)을 다시 해야 합니다. - 이 파드의 git 에는 사용자 이름·이메일이 설정돼 있지 않습니다. 커밋할 때
git -c user.name=… -c user.email=… commit처럼 넘기세요. - 흔한 실수: 모듈 안에서 path.module 로 파일 경로를 잡아 moved 뒤에 교체가 붙는 것. 흔한 실수: 우선순위 실험 파일(*.auto.tfvars)을 남겨 두는 것.
- [Refactoring(moved)](https://opentofu.org/docs/language/modules/develop/refactoring/) · [Module Sources(git, ref)](https://opentofu.org/docs/language/modules/sources/) · [Input Variables(우선순위·validation)](https://opentofu.org/docs/language/values/variables/) · [Terraform: Input Variables](https://developer.hashicorp.com/terraform/language/values/variables)
단계 7개
- 복붙한 두 환경을 먼저 적용해 둔다
- dev 를 모듈 호출로 바꾸되 아무것도 다시 만들지 않는다
- prod 도 같은 모듈로 옮긴다
- 모듈에 버전을 붙이고 두 환경을 그 버전에 고정한다
- 새 버전은 dev 에서 먼저, prod 는 그대로
- 같은 변수에 값이 여러 곳에서 들어오면 누가 이기나
- 모듈 경계에서 잘못된 값을 막는다