Terraform 도입기 (3): 기존 인프라 옮기기
콘솔로 만든 인프라를 3주에 걸쳐 Terraform으로 가져오면서 정한 규칙들. 고치지 않고 먼저 옮긴다는 것, 그리고 옮기고 나서야 보인 것들.
시리즈 · Terraform 도입기3 / 5
저장소를 만들고 3주쯤은 거의 옮기는 일만 했다. 운영 중인 리소스를 대상으로 하는 작업이라 속도보다는 사고를 안 내는 게 먼저였다.
옮기는 PR에서는 아무것도 고치지 않는다
기존 인프라를 코드로 옮기다 보면 고치고 싶은 게 계속 보인다. 설명 없는 보안 그룹 규칙, 규칙 없이 지은 이름, 쓰는지 안 쓰는지 모를 리소스. 손이 근질거리는데, 참기로 했다.
완료 기준은 단순하게 잡았다. 리소스를 가져온 다음 plan을 돌려서 No changes가 나오면 끝이다. 코드와 실제 인프라가 정확히 같다는 뜻이니까.
옮기는 일과 고치는 일을 한 번에 하면 plan에 변경이 떴을 때 그게 내가 의도한 수정인지 잘못 옮겨 적은 것인지 구분이 안 된다. 운영 서버를 놓고 그 구분을 잃고 싶지 않았다. 일단 있는 그대로 담고, 고치는 건 다음 PR에서 리뷰를 받으면서 한다.
초안은 도구, 정리는 사람
양이 많아서 손으로 다 옮겨 적을 수는 없었다. 기존 리소스를 Terraform 코드로 뽑아 주는 Terraformer를 썼다.
다만 뽑혀 나온 코드를 그대로 쓰지는 않았다. 리소스 이름이 기계적으로 붙어 있고, 숫자가 전부 문자열이고, 리소스끼리의 참조는 죄다 하드코딩된 ID다. 그래서 값만 거기서 가져오고 구조는 2편에서 정한 모양으로 다시 짰다. 그러고 나서 plan이 깨끗해질 때까지 맞췄다.
초기에 옮긴 파일에는 지금도 그 흔적이 있다. 포트 번호가 "22"처럼 문자열로 적혀 있다든가. 동작에 차이가 없어서 그냥 뒀다. 보기 좋으라고 운영 리소스의 코드를 건드릴 이유는 없다.
순서
덜 아픈 것부터, 그리고 다른 것에 기대지 않는 것부터 했다.
맨 처음에 한 건 사실 마이그레이션이 아니었다. 개발 환경에 VPC를 새로 만들고 CI 서버를 올렸다. 없어져도 괜찮은 곳에서 구조와 모듈을 먼저 써 본 것이다. 2편에서 말한 구조 변경이 이 단계에서 나왔다. 운영 리소스를 다 옮긴 뒤에 깨달았다면 꽤 괴로웠을 것이다.
그다음은 IAM, 보안 그룹, VPC와 라우팅·게이트웨이·VPN, RDS, EC2, 로드 밸런서 순이었다. 위에서 아래로 의존이 흐르는 순서와 같다. 양으로는 보안 그룹이 제일 많았고, 잘못됐을 때 영향이 제일 넓은 건 네트워크 쪽이었다.
plan에 뜨는 건 전부 진짜여야 한다
보안 그룹 모듈에 사소한 장치를 하나 넣었다. IP 목록을 받으면 정렬해서 쓴다.
사람이 IP를 추가할 때 목록 맨 위에 넣든 맨 아래에 넣든 결과가 같아야 한다고 생각했다. 순서만 바뀌었는데 plan에 변경이라고 뜨면, 리뷰하는 사람이 진짜 변경과 가짜 변경을 골라내야 한다. 그런 일이 몇 번 반복되면 사람들은 plan을 대충 넘기기 시작한다. plan을 믿을 수 있어야 리뷰가 의미가 있다.
비슷한 이유로 기존 보안 그룹의 이름과 설명은 규칙에 안 맞아도 그대로 뒀다. 이 두 값은 바꾸면 리소스가 새로 만들어진다. 이름 규칙은 바꿔도 안전한 태그에만 적용했다.
실수로 지우지 않게
Terraform은 코드에서 블록을 지우면 리소스를 지운다. 솔직히 콘솔보다 실수로 뭔가를 날리기 쉬운 도구다. 그래서 데이터가 들어 있는 것들에는 AWS 쪽 보호 장치를 코드로 걸어 뒀다. 서버에는 종료 방지, 디스크에는 서버가 사라져도 남도록, DB에는 삭제 방지.
이러면 누가 실수로 블록을 지운 PR이 머지돼도 apply 단계에서 AWS가 거절한다. 정말 지워야 할 때는 보호를 끄는 PR을 먼저 올리고 삭제 PR을 따로 올려야 한다. 귀찮은데, 귀찮으라고 한 것이다. 삭제가 리뷰를 두 번 거치게 된다.
옮기고 나서야 보인 것들
마이그레이션에서 제일 큰 수확은 옮긴 다음에 나왔다. 콘솔에서는 화면 여러 개를 오가야 알 수 있던 것들이 파일 하나에 모이니까 그냥 보였다.
같은 IP가 보안 그룹마다 다른 이름으로 적혀 있었다. 필요 이상으로 넓은 대역에 열려 있는 규칙이 있었다. 그리고 이름은 private인데 라우팅은 인터넷 게이트웨이를 향하는 서브넷이 있었다. 콘솔에서는 서브넷 화면과 라우팅 테이블 화면이 따로라서 눈에 안 띄었던 것이다.
마지막 건 넉 달 뒤에 정리를 시작했는데, 그때 커밋 메시지가 create: (진짜) private subnet 생성이다. 지금 봐도 좀 웃기다.
이런 것들은 옮기는 동안에는 건드리지 않고 적어만 뒀다. 그 뒤로 PR 하나에 하나씩 고쳤다. 넓은 대역은 실제로 접근하는 서버 주소로 좁히고, 같은 VPC 안의 서버끼리는 IP 대신 보안 그룹 자체를 출발지로 지정하는 식으로 바꿨다. 네트워크는 격리된 서브넷을 새로 만들고, NAT를 붙이고, 기존 경로를 걷어 내는 순서로 몇 달에 걸쳐 나눠서 했다. 한 단계를 적용하고 한동안 지켜본 다음에 다음 단계로 갔다.
급하게 하지 않아도 됐던 건 이미 코드에 다 올라와 있었기 때문이다. 뭐가 남았는지 알고 있으면 천천히 해도 불안하지 않다.
다음 글은 마이그레이션이 끝난 뒤 여러 사람이 같이 일하는 방식을 만든 이야기다.