네트워크 트러블슈팅 · /etc/hosts 와 이름 해석 순서 · 이론
/etc/hosts 는 무엇이고 언제 이기나
한 줄 요약
/etc/hosts 는 DNS 보다 먼저 보는 로컬 이름표이고, dig 는 그 파일을 전혀 보지 않는다. 이 한 문장이 수많은 미궁의 출구다.
왜 이게 필요했나
이런 신고가 온다. "DNS 는 정상인 것 같은데 애플리케이션만 옛 서버로 붙습니다."
확인해 보면 정말로 dig api.internal 은 새 IP 를 돌려준다. 그런데 애플리케이션은 계속 옛 IP 로 간다. 여기서 DNS 서버를 뒤지기 시작하면 하루가 간다.
범인은 보통 /etc/hosts 다. 누군가 지난주에 디버깅하면서 임시로 넣어 둔 줄이 남아 있는 것이다. 그리고 이 사고는 DNS 오류의 얼굴로 나타나지 않는다. 이름은 멀쩡히 풀리니까. 증상은 connection refused 나 timeout 으로 나타나고, 그래서 아무도 DNS 쪽을 의심하지 않는다.
어떻게 동작하나
먼저 파일 형식이다. 한 줄은 IP + 정규 이름 + 별칭들 이다.
127.0.0.1 localhost127.0.1.1 myserver::1 localhost ip6-localhost ip6-loopback10.0.1.50 api.internal.mycompany.com api-internal192.168.1.100 db-master.mycompany.com- 두 번째 필드가 정규 이름(canonical name), 세 번째부터가 별칭이다. 별칭으로도 똑같이 해석된다.
- IPv4 와 IPv6 를 각각 따로 적는다.
::1줄이 빠져 있으면 IPv6 로 붙는 애플리케이션이 이름을 못 찾는다. - 와일드카드도 CNAME 도 없다.
*.labhub.local같은 표기는 그냥 문자열이며 아무 이름도 매칭하지 않는다. 이름 하나에 줄 하나가 원칙이다. - 같은 이름을 여러 IP 에 적을 수는 있다. 이때
getent ahosts가 여러 줄을 돌려주고 애플리케이션은 위에서부터 시도한다.
그다음이 순서를 정하는 파일, /etc/nsswitch.conf 다.
grep '^hosts' /etc/nsswitch.conf# hosts: files dns myhostname# hosts: files mdns4_minimal [NOTFOUND=return] dns myhostname# hosts: files resolve [!UNAVAIL=return] dns myhostname토큰의 뜻은 이렇다.
| 토큰 | 무엇을 보나 |
| --- | --- |
| files | /etc/hosts |
| dns | /etc/resolv.conf 의 nameserver 로 직접 질의 |
| resolve | D-Bus 로 systemd-resolved 에 질의 |
| myhostname | 자기 호스트 이름과 로컬 인터페이스 주소 |
| mdns4_minimal | .local 이름을 mDNS 로 해석 |
대괄호 안의 것은 동작 규칙이다. [NOTFOUND=return] 은 앞 모듈이 "그런 이름 없음"이라고 답하면 거기서 멈추라는 뜻이다. 뒤에 있는 dns 까지 가지 않는다.
그래서 사내 도메인을 .local 로 지은 조직이 이 함정에 걸린다. mdns4_minimal [NOTFOUND=return] 이 .local 이름을 가로채고 실패하면 그 자리에서 끝나므로 DNS 로 넘어가지 않는다. 그런데 dig 는 nsswitch 를 보지 않으므로 정상 응답을 돌려준다. dig 는 되는데 애플리케이션만 실패한다.
여기서 이 코스에서 가장 중요한 문장이 나온다.
> dig 는 DNS 서버의 답을 보여 주고, getent 는 애플리케이션이 받을 답을 보여 준다. 두 결과가 다르면 그 차이가 곧 원인의 위치다.
dig, nslookup, host 는 전부 DNS 프로토콜 전용 도구다. /etc/hosts 도, nsswitch 도, systemd-resolved 의 링크별 설정도 보지 않는다. resolv.conf 에서 nameserver 주소만 가져다가 UDP 53 으로 질의를 던진다. 애플리케이션 경로를 재현하는 도구는 getent hosts / getent ahosts / resolvectl query 뿐이다.
현장에서 만나는 모습
hosts 로 임시 우회를 하고 지우지 않는다. 장애 대응 중 "일단 hosts 에 박아서 넘기자" 는 흔한 판단이고 대개 옳다. 문제는 그 줄이 3개월 뒤에도 남아 있다는 것이다. 그래서 hosts 를 손댈 때는 반드시 주석에 날짜와 이유와 담당자를 적는 규칙을 두는 팀이 많다.
컨테이너 이미지에 hosts 가 구워져 있다. 빌드 시점에 넣은 항목이 이미지에 남아 모든 환경에서 같은 IP 를 가리킨다. 스테이징에서 프로덕션 DB 로 붙는 사고가 이렇게 난다.
다음 실습에서 할 것
/etc/hosts 에 직접 항목을 넣고 getent 로 확인한 뒤, 망가진 hosts 파일 픽스처를 감사해 문제 줄을 찾아낸다. 그리고 규칙을 만족하는 최종본을 제출한다.