안 쓰는 프록시 서버를 정리하면서 EC2 인스턴스를 지우고 Route 53 의 CNAME 레코드까지 함께 지웠다. 며칠 뒤에 확인하다가 그 이름을 부르는 코드가 여전히 성공하고 있는 것을 발견했다.
Table of contents
Open Table of contents
배경 — 죽은 주소를 부르는데 성공하는 작업
코드에는 지운 proxy.internal.example.com 이 하드코딩돼 있었고 상품 생성과 수정 경로에서 그것을 부르고 있었다. 내 작업용 장비에서 dig 로 조회해 보니 NXDOMAIN 이었다.
그런데 channel_jobs 에는 최근 하루 동안 실패 없이 성공만 쌓여 있었다. 코드가 죽은 주소를 부르는데도 성공한다는 것은 앞뒤가 맞지 않는 상태였다.
원인 — 내가 본 곳과 서버가 보는 곳
여기서 모순처럼 보이는 것이 실은 내 전제가 틀렸다는 신호에 가까웠다. 내가 확인한 것은 작업용 장비에서 공개 이름 서버에 물었을 때의 결과뿐이었다.
운영 서버가 그 이름을 어떻게 푸는지는 아직 보지 않은 것이고 이름 해석 경로는 공개 존과 사설 존과 /etc/hosts 와 서비스 디스커버리로 여럿이다. AWS 공식 문서대로 사설 호스팅 영역은 VPC 안에서의 질의에만 답하는 별도 컨테이너라 지운 것은 공개 쪽 CNAME 하나였고 사설 쪽 A 레코드는 그대로 살아 있었다.
주의 — 세 단으로 쌓인 추론
내가 실제로 한 것은 삭제이고 결론 낸 것은 그 코드 경로가 죽었다는 것이었다. 그 삭제와 결론 사이에는 검증이라고 할 만한 것이 하나도 없었다.
지웠으니 해석이 안 되고 해석이 안 되니 호출이 실패하고 실패하니 그 코드는 죽었다는 세 단의 추론이 쌓여 있었다. 실제 관측은 첫 단뿐이었고 그 뒤의 세 단계는 전부 추론이었다.
검증 — 두 가지를 실측한 결과
두 가지 방법이 있었는데 로컬 dig 결과를 믿고 지운 대로 두는 것과 운영 서버에 들어가 직접 확인하는 것이다. 뒤쪽을 골랐다. 이유는 앞뒤가 안 맞는 관측은 내 전제가 틀렸다는 신호라서다. 대신 운영 서버 접속 승인을 받느라 반나절이 드는 것을 감수했다. getent hosts 로 그 이름을 풀어 보니 10.0. 대역 사설 주소로 해석됐다. 최근 작업의 성공과 실패도 GROUP BY DATE(created_at), result 로 세어 보니 계속 성공만 쌓이고 있었다.
둘 다 봐야 하는데 이름이 풀려도 그 끝의 서버가 죽었을 수 있고 작업이 성공해도 다른 경로일 수 있기 때문이다. 두 관측이 같은 방향을 가리키고 나서야 그 경로가 살아 있다는 것이 확정됐다.
조치 — 클래스 하나에 여러 경로
같은 ChannelClient 의 다른 메서드들도 죽었는지 확인해 봤는데 그쪽은 외부 인터페이스에 직결이라 이 프록시와 무관했다. 클래스가 하나라고 해서 거기서 나가는 경로도 하나인 것은 아니었다.
남은 정리 작업의 순서도 바꿔서 코드에서 부르는 곳을 찾고 운영 서버에서 해석되는지 보고 어디서 해석되는지 확인하고 최근 작업의 성패를 본 뒤에 지우기로 했다. 전에는 공개 이름 서버에 없으면 죽은 것으로 봤다.
정리
- 이름 해석 경로는 공개 존 하나가 아니다
- 내 환경에서 안 풀린다고 운영에서도 안 풀리는 것이 아니다
- 삭제는 관측이고 그 코드가 죽었다는 것은 추론이다
- 추론이 몇 단 쌓였는지를 세어 보면 검증 지점이 드러난다
- 운영 서버의 해석 결과와 최근 작업 성패를 둘 다 본다
- 이름이 풀려도 끝의 서버가 죽었을 수 있다
- 클래스가 하나여도 메서드마다 다른 곳을 부를 수 있다
- 앞뒤가 안 맞는 관측은 내 전제가 틀렸다는 신호다