이름 해석 실패는 메시지만으로 원인을 좁힐 수 있다. 애플리케이션이 뱉는 문구와 실제 원인의 대응은 다음과 같다.
| 메시지 | 뜻 |
|---|---|
Name or service not known / Could not resolve host |
리졸버가 이름을 풀지 못함. DNS 서버 미도달이거나 레코드 없음 |
NXDOMAIN |
DNS 서버가 "그런 이름 없다"고 명확히 응답 |
SERVFAIL |
DNS 서버가 응답은 했지만 처리 실패. 상위 위임 · DNSSEC · 포워더 문제 |
DNS request timed out |
질의에 응답이 없음. 방화벽 · 서버 다운 · 경로 문제 |
Connection refused(53) |
서버는 살아 있으나 DNS 서비스가 그 주소에서 듣고 있지 않음 |
파이썬의 NameResolutionError, 자바의 UnknownHostException, MLflow 의 Max retries exceeded ... Failed to resolve 는 모두 첫 줄과 같은 부류다. 애플리케이션 문제가 아니라 그 호스트의 리졸버 문제다.
# 1) 리졸버가 누구를 보고 있는지
cat /etc/resolv.conf
resolvectl status # systemd-resolved 를 쓰는 배포판
# 2) 이름이 실제로 풀리는지. 서버를 지정해 캐시와 순서를 배제한다
dig +short <이름>
dig @<DNS서버IP> <이름>
# 3) 서버까지 UDP 53 이 열려 있는지
dig @<DNS서버IP> <이름> +tcp
nc -vzu <DNS서버IP> 53
# 4) 이름은 풀리는데 접속만 안 되면 DNS 문제가 아니다
getent hosts <이름>
curl -sv --connect-timeout 5 http://<이름>/ 2>&1 | head
getent hosts 는 /etc/hosts 와 nsswitch.conf 경로를 그대로 타므로 애플리케이션이 보는 결과에 가장 가깝다. 반대로 dig · nslookup 은 DNS 서버에만 묻는다. hosts 파일에 넣은 이름은 dig 에 나오지 않는 것이 정상이며, 이 차이를 모르면 "hosts 에 넣었는데 왜 안 되냐"로 헤매게 된다.
DNS request timed out.
timeout was 2 seconds.
DNS request timed out.
timeout was 2 seconds.
(그 뒤 정상 응답)
앞쪽 DNS 서버가 응답하지 않고 뒤쪽 서버가 답하는 상태다. 조회 자체는 성공하지만 매번 기본 타임아웃만큼 지연되므로 접속이 느려진다.
/etc/resolv.conf 를 직접 고치지 말고 NetworkManager 프로파일에서 바꾼다. 재부팅이나 DHCP 갱신 때 덮어써진다.# /etc/resolv.conf
options timeout:1 attempts:2 rotate
첫 서버가 IPv6 주소인데 IPv6 경로가 없을 때도 같은 증상이 난다. dig @<각 서버> 로 어느 쪽이 죽었는지 먼저 특정한다.
레코드를 고쳤는데 옛 값이 계속 나오면 TTL 이 남아 있는 것이다. 각 계층의 캐시를 지운다.
# systemd-resolved
resolvectl flush-caches
# dnsmasq / nscd / unbound
systemctl restart dnsmasq
nscd -i hosts
unbound-control flush <이름>
# BIND 재귀 서버
rndc flushname <이름>
브라우저는 자체 DNS 캐시를 따로 들고 있다. 서버에서 지워도 브라우저만 옛 값을 쓰는 경우가 있다.
지운 뒤에도 옛 값이 나오면 상위 재귀 서버(사내 포워더 · ISP)의 캐시가 남은 것이므로 TTL 만큼 기다린다. 레코드 변경을 예고할 수 있으면 미리 TTL 을 낮춰 두는 것이 정석이다.
컨테이너는 호스트의 /etc/resolv.conf 를 그대로 쓰지 않는다. 도커는 기본 브리지에서 자체 리졸버(127.0.0.11)를 넣고, 쿠버네티스는 클러스터 DNS 를 넣는다. 호스트에서는 되는데 컨테이너에서 안 되면 이 차이를 먼저 본다. 쿠버네티스 쪽 진단은 CoreDNS 레코드 추가와 클러스터 DNS 확인 에 정리했다.
사내망 전용 이름을 컨테이너에서 못 찾는 경우는 대부분 search 도메인이 빠진 것이다. 짧은 이름 대신 FQDN 을 쓰거나 컨테이너에 리졸버 설정을 명시한다.
이름은 풀리는데 접속이 안 되면 그때부터는 경로 · 포트 문제다.
Connection timed out : 방화벽 · 보안그룹에서 막힘. 패킷이 버려진다.Connection refused : 도달은 했으나 그 포트에서 듣는 프로세스가 없다.No route to host : 라우팅 또는 ARP 단계에서 끊김.이 구분은 포트 열림 확인 - closed 와 filtered 와 tcpdump 로 포트 도달 여부 확인 에 자세히 있다.