서버에서 ping 8.8.8.8은 되는데 ping google.com은 실패합니다. 네트워크는 살아 있는데 배포 스크립트는 저장소 도메인을 찾지 못해 중단됩니다.
이 상황에서 봐야 할 곳은 애플리케이션 로그가 아니라 이름 해석 경로입니다. /etc/resolv.conf와 resolver 설정을 확인해야 합니다.
DNS 질의 실패와 /etc/resolv.conf 설정
인프라 운영 중 가장 황당한 순간 중 하나가 있습니다. ping 8.8.8.8은 잘 되는데 ping google.com은 안 되는 상황입니다. 네트워크는 분명 살아있는데 도메인으로는 아무것도 안 됩니다. 이 문제의 원인은 거의 항상 /etc/resolv.conf 하나입니다. 이 챕터에서는 DNS 클라이언트 설정 파일인 resolv.conf를 완전히 이해하고, 빠르게 수정하는 방법을 배웁니다.
resolv.conf 구조 이해
- 1/etc/resolv.conf 파일 구조와 nameserver, search, domain, options 지시어를 이해할 수 있다
- 2IP ping은 되는데 도메인 ping이 안 될 때 DNS 문제를 진단할 수 있다
- 3NetworkManager와 systemd-resolved가 resolv.conf를 덮어쓰는 원인을 설명할 수 있다
- 4nmcli / systemd-resolved / Netplan으로 DNS를 영구 설정할 수 있다
- 5재부팅 후 resolv.conf가 초기화되는 문제를 해결할 수 있다
- 6Docker·Kubernetes 환경에서 컨테이너 DNS 실패 원인을 파악하고 대처할 수 있다
cat /etc/resolv.confls -la /etc/resolv.confnslookup google.comsystemctl is-active systemd-resolved/etc/resolv.conf — DNS 클라이언트 설정 파일 해부
서버에서 curl api.internal이 안 됩니다. ping api.internal도 "Name or service not known"입니다. 외부 IP로는 되는데 내부 도메인만 안 됩니다. 이런 상황에서 /etc/resolv.conf를 보면 내부 DNS 서버 주소가 없거나 잘못된 서버를 바라보고 있습니다. DNS 클라이언트 설정 파일의 구조를 모르면 어디를 어떻게 고쳐야 하는지 알 수 없습니다.
확대
resolv.conf란
/etc/resolv.conf는 리눅스/유닉스 시스템에서 DNS 해석(Resolver) 동작을 설정하는 파일입니다. 프로그램이 google.com 같은 도메인 이름을 IP로 변환할 때 이 파일을 참조합니다.
resolv.conf가 사용되는 시점:
curl google.com
→ curl이 OS에 "google.com의 IP 알려줘" 요청
→ OS 리졸버가 /etc/resolv.conf 읽음
→ nameserver로 지정된 DNS 서버에 질의
→ IP 응답 받아서 curl에 전달
→ curl이 해당 IP로 HTTP 요청
resolv.conf 파일 구조
실제 파일 내용을 보면 지시어 구조를 바로 파악할 수 있습니다.
# 실습 디렉토리 준비
mkdir -p /tmp/networking/part2/exam_7 && cd /tmp/networking/part2/exam_7
cat /etc/resolv.conf
- nameserver—현재 서버가 어떤 DNS 서버에 질의하는지 확인합니다
- 심볼릭 링크—/etc/resolv.conf가 systemd-resolved 또는 NetworkManager에 의해 관리되는지 봅니다
- IP vs 도메인—IP 통신 성공과 DNS 실패를 분리해 원인을 좁힙니다
전형적인 내용:
# DNS 서버 IP (최대 3개, 위에서 아래 순서로 시도)
nameserver 8.8.8.8
nameserver 8.8.4.4
nameserver 1.1.1.1
# 검색 도메인 (짧은 호스트명 자동 보완)
search example.com internal.company.com
# 현재 도메인 (일반적으로 search와 유사한 역할)
domain example.com
# 추가 옵션
options ndots:5 timeout:2 attempts:3
각 지시어 상세 설명
nameserver
DNS 질의를 보낼 서버 IP를 지정합니다. 최대 3개까지 설정하며 위에서 아래 순서로 시도합니다.
nameserver 8.8.8.8
역할: DNS 질의를 보낼 서버 IP 지정
규칙:
- 최대 3개까지 설정 가능
- 첫 번째 서버가 응답 없을 때 두 번째 시도
- IPv4 또는 IPv6 주소 사용 가능
search
짧은 호스트명 입력 시 자동으로 도메인을 붙여 완전한 FQDN으로 만드는 검색 도메인을 지정합니다.
search example.com internal.company.com
역할: 짧은 호스트명 → FQDN 자동 변환
예시:
ping web01
→ web01.example.com 시도
→ web01.internal.company.com 시도
실무 활용:
쿠버네티스: search default.svc.cluster.local svc.cluster.local cluster.local
→ ping my-service 입력 시 my-service.default.svc.cluster.local로 질의
domain
시스템의 기본 도메인을 설정합니다. search와 함께 선언되면 마지막에 선언된 것이 적용됩니다.
domain example.com
역할: 시스템의 기본 도메인 설정
search와의 차이: search는 여러 도메인 지정 가능, domain은 하나만
참고: search와 domain이 둘 다 있으면 마지막에 선언된 것이 적용
options ndots
도메인 이름의 점(.) 개수가 ndots 값보다 작으면 search 도메인을 먼저 시도합니다. 쿠버네티스 환경에서는 기본값 5를 자주 만납니다.
options ndots:5
역할: 도메인 이름에 점(.)이 몇 개 미만이면 search 도메인 먼저 시도
기본값: 1
쿠버네티스 기본값: 5
예시 (ndots:2 설정 시):
nslookup google.com → 점이 1개, ndots:2보다 작음
→ google.com.example.com 먼저 시도 (search 도메인 붙임)
→ 실패하면 google.com 시도
/etc/nsswitch.conf와의 관계
resolv.conf는 DNS 질의 자체를 설정하지만, OS가 이름 해석에 어떤 방법을 어떤 순서로 사용할지는 /etc/nsswitch.conf가 결정합니다.
grep hosts /etc/nsswitch.conf
# hosts: files dns myhostname
이 한 줄이 이름 해석 순서를 정합니다.
files—/etc/hosts를 먼저 확인dns— 그다음/etc/resolv.conf의 nameserver로 DNS 질의myhostname— 마지막으로 자기 호스트명 해석
/etc/hosts에 항목이 있으면 DNS보다 먼저 사용됩니다.
이름 하나를 조회할 때 resolv.conf가 개입하는 순서 — nsswitch부터 응답까지
nameserver 한 줄만 맞으면 될 것 같지만, 실제 한 번의 이름 조회는 nsswitch 순서 판정 → /etc/hosts 확인 → resolv.conf의 nameserver·search·options 적용이라는 여러 단계를 거칩니다. 이 순서를 알면 "IP는 되는데 도메인만 안 되는" 경우가 어느 단계에서 끊긴 것인지, "가끔 정확히 5초 지연"이 어디서 새는지를 짚을 수 있습니다.
[앱] getaddrinfo("web01") — 이름 하나 조회
│
① nsswitch.conf의 hosts 행이 순서 결정
│ hosts: files dns → /etc/hosts 먼저, 없으면 DNS
│
② /etc/hosts 조회 (files)
│ 매칭 있으면 즉시 반환 (DNS로 안 감)
│
③ resolv.conf 로드 — nameserver·search·options 읽기
│
④ ndots 판정 (options ndots:N)
│ 이름의 점(.) 개수 < N → search 도메인부터 붙여 시도
│
⑤ search 도메인 하나씩 붙여 nameserver에 질의
│ web01.example.com → ... → 마지막에 절대 이름
│ 첫 nameserver 무응답이면 timeout 후 다음 nameserver로
│
⑥ 응답(A/AAAA) 수신 → IP 반환
▼
[앱] 받은 IP로 실제 연결
각 단계에서 무슨 일이 일어나고, 막히면 어떤 증상인가:
| 단계 | 하는 일 | 여기서 막히면 |
|---|---|---|
| ① nsswitch 순서 | hosts: 행이 files(hosts 파일)·dns의 사용 순서를 정함 | dns가 빠져 있으면 resolv.conf가 멀쩡해도 DNS 질의 자체를 안 함 |
| ② /etc/hosts | files 단계에서 로컬 고정 매핑을 먼저 조회 | 잘못된 고정 항목 → DNS를 보기 전에 엉뚱한 IP로 감 (nslookup은 정상인데 앱만 이상) |
| ③ resolv.conf 로드 | nameserver·search·options를 읽어 이후 질의 방식을 결정 | nameserver 비었음·틀림 → Name or service not known / SERVFAIL |
| ④ ndots 판정 | 이름의 점 개수가 ndots보다 작으면 search부터 붙임 | 쿠버네티스 기본 ndots:5 → 외부 도메인도 search 확장 폭증 → 조회 수·지연이 몇 배 |
| ⑤ nameserver 순차 시도 | search 후보를 위 nameserver부터 순서대로 질의, 무응답이면 timeout 후 다음 서버 | 1순위 nameserver 죽음 → options timeout(기본 5초)만큼 멈췄다 폴백 → "가끔 정확히 5초" |
| ⑥ 응답 반환 | 받은 A/AAAA 레코드의 IP를 앱에 돌려줌 | 응답 유실(병렬 A/AAAA 경쟁 등) → timeout 후 재시도로 지연 |
즉 resolv.conf는 단순히 'DNS 서버 IP를 적는 곳'이 아니라 한 번의 조회가 몇 번의 질의로 불어나고 어디서 지연되는지를 결정하는 지점 입니다. 그래서 IP는 되는데 도메인만 안 되면 ③(nameserver)을, 사내 도메인만 실패하면 ⑤의 search·nameserver 우선순위를, 외부 도메인이 유독 느리면 ④(ndots 확장)를, 가끔 정확히 5초 걸리면 ⑤의 timeout 폴백을 의심합니다. cat /etc/resolv.conf로 이 네 필드(nameserver·search·options·ndots)를 먼저 읽는 것이 DNS 진단의 출발점입니다.
NetworkManager와 resolv.conf — 덮어쓰기 문제의 원인
/etc/resolv.conf를 직접 수정해서 DNS 서버를 바꿨습니다. 그런데 다음 날 아침에 보면 원래대로 돌아가 있습니다. 다시 수정하면 또 바뀝니다. NetworkManager나 systemd-resolved가 자동으로 덮어쓰기 때문인데, 이 구조를 모르면 같은 작업을 계속 반복하게 됩니다.
확대
문제의 핵심
현대 리눅스(Ubuntu 18.04+, RHEL 7+)에서는 /etc/resolv.conf를 직접 수정해도 재부팅이나 네트워크 재연결 시 원래대로 돌아갑니다. 이는 NetworkManager 또는 systemd-resolved가 자동으로 관리하기 때문입니다.
resolv.conf 관리 주체 확인:
# resolv.conf가 심볼릭 링크인지 확인
ls -la /etc/resolv.conf
# Ubuntu 20.04+ (systemd-resolved 사용):
# /etc/resolv.conf -> ../run/systemd/resolve/stub-resolv.conf
# → 심볼릭 링크! 직접 수정해도 재부팅 시 덮어써짐
# 일반 파일인 경우:
# -rw-r--r-- 1 root root 89 ...
# → NetworkManager가 관리하거나, 수동 설정
resolv.conf 관리 구조
어떤 프로세스가 resolv.conf를 관리하는지에 따라 영구 설정 방법이 달라집니다.
확대
관리 주체 확인 방법
아래 순서로 확인하면 어떤 프로세스가 resolv.conf를 관리하는지 파악할 수 있습니다.
# systemd-resolved 실행 중인지 확인
systemctl is-active systemd-resolved
# active → systemd-resolved 사용
# NetworkManager 실행 중인지 확인
systemctl is-active NetworkManager
# active → NetworkManager 사용
# resolv.conf 내용으로 판단
head -3 /etc/resolv.conf
# "# Generated by NetworkManager" → NetworkManager 관리
# "# This is /run/systemd/resolve/stub-resolv.conf" → systemd-resolved 관리
# 주석 없음 → 수동 관리 가능성
실습 — DNS 문제 진단과 수정
가장 먼저 IP ping과 도메인 ping을 비교하여 DNS 문제임을 확인합니다.
# 1단계: 네트워크 연결 확인 (IP 주소로)
ping -c 2 8.8.8.8
# 성공하면 → L3 네트워크는 정상
# 2단계: 도메인 ping 시도
ping -c 2 google.com
# 실패 시 오류 메시지 확인:
# ping: google.com: Name or service not known → DNS 해석 실패
# ping: google.com: Temporary failure in name resolution → DNS 서버 응답 없음
# 3단계: resolv.conf 현재 내용 확인
cat /etc/resolv.conf
# nameserver 없거나 잘못된 IP → 원인 발견!
# 4단계: 직접 DNS 질의 테스트
nslookup google.com
# Server: 127.0.0.1 (DNS 서버)
# ** server can't find google.com: SERVFAIL → DNS 서버 문제
nslookup google.com 8.8.8.8
# 성공 시 → DNS 서버 자체는 살아있음, resolv.conf 설정 문제
# 5단계: dig으로 상세 진단
dig google.com
dig @8.8.8.8 google.com # 특정 DNS 서버에 직접 질의
진단 결과 해석:
nslookup google.com → 실패
nslookup google.com 8.8.8.8 → 성공
→ resolv.conf의 nameserver 설정 문제
nslookup google.com → 실패
nslookup google.com 8.8.8.8 → 실패
→ 네트워크에서 DNS 포트(53) 차단 가능성
또는 DNS 서버 자체 문제
ping 8.8.8.8 → 실패
→ 기본 네트워크 연결 문제 (DNS와 무관)
시스템이 관리하는 상황에서 resolv.conf를 직접 수정하는 임시 방법입니다.
이 명령은 시스템 설정 파일을 변경합니다. 기존 파일 백업과 적용 후 검증 방법을 준비하지 않으면 재부팅이나 서비스 재시작 때 장애가 반복될 수 있습니다.
# 현재 resolv.conf 내용 확인
cat /etc/resolv.conf
# resolv.conf가 심볼릭 링크인지 확인
ls -la /etc/resolv.conf
# lrwxrwxrwx → 심볼릭 링크 (systemd-resolved 사용)
# -rw-r--r-- → 일반 파일 (직접 수정 가능)
# 방법 A: 일반 파일인 경우 — 직접 수정
sudo tee /etc/resolv.conf << 'EOF'
nameserver 8.8.8.8
nameserver 8.8.4.4
nameserver 1.1.1.1
search example.com
EOF
# 방법 B: 심볼릭 링크인 경우 — chattr로 덮어쓰기 방지 후 수정
# (임시 방편으로 권장되지 않음)
sudo rm /etc/resolv.conf
sudo tee /etc/resolv.conf << 'EOF'
nameserver 8.8.8.8
nameserver 8.8.4.4
EOF
sudo chattr +i /etc/resolv.conf # 수정 불가 속성 설정 (임시)
# 나중에 해제: sudo chattr -i /etc/resolv.conf
# 즉시 테스트
ping -c 2 google.com
nslookup google.com
주의: 이 방법은 재부팅이나 NetworkManager 재시작 시 다시 초기화될 수 있습니다. 영구 설정은 다음 단계를 따르세요.
재부팅 후에도 유지되는 영구 DNS 설정 방법입니다.
방법 1: nmcli로 NetworkManager 연결 프로파일 수정
NetworkManager가 관리하는 환경에서는 연결 프로파일에 DNS를 설정해야 재부팅 후에도 유지됩니다.
# 현재 활성 연결 이름 확인
nmcli con show --active
# NAME UUID TYPE DEVICE
# ens3 12345678-1234-1234-1234-123456789012 ethernet ens3
# DNS 서버 설정 (연결 이름으로)
sudo nmcli con mod "ens3" ipv4.dns "8.8.8.8 8.8.4.4"
# DHCP로 받아온 DNS 무시 설정 (선택)
sudo nmcli con mod "ens3" ipv4.ignore-auto-dns yes
# 변경 사항 적용
sudo nmcli con up "ens3"
# 확인
nmcli con show "ens3" | grep ipv4.dns
# ipv4.dns: 8.8.8.8,8.8.4.4
# resolv.conf 확인 (NetworkManager가 업데이트해야 함)
cat /etc/resolv.conf
방법 2: NetworkManager conf.d 파일로 글로벌 설정
연결별 설정 대신 모든 연결에 공통으로 적용될 DNS를 conf.d에 설정합니다.
이 명령은 실행 중인 서비스 상태를 바꿔 순간적인 중단이나 설정 반영 실패를 만들 수 있습니다. 운영 트래픽 영향과 재시작 후 확인 명령을 먼저 준비하세요.
# 모든 연결에 적용되는 DNS 설정
sudo tee /etc/NetworkManager/conf.d/dns-servers.conf << 'EOF'
[global-dns-domain-*]
servers=8.8.8.8,8.8.4.4,1.1.1.1
EOF
sudo systemctl restart NetworkManager
cat /etc/resolv.conf
방법 3: systemd-resolved 설정 (Ubuntu 18.04+)
systemd-resolved가 관리하는 환경에서는 /etc/systemd/resolved.conf에 DNS를 설정합니다.
이 명령은 실행 중인 서비스 상태를 바꿔 순간적인 중단이나 설정 반영 실패를 만들 수 있습니다. 운영 트래픽 영향과 재시작 후 확인 명령을 먼저 준비하세요.
# /etc/systemd/resolved.conf 편집
sudo tee /etc/systemd/resolved.conf << 'EOF'
[Resolve]
DNS=8.8.8.8 8.8.4.4
FallbackDNS=1.1.1.1 9.9.9.9
Domains=~.
DNSSEC=no
DNSOverTLS=no
Cache=yes
EOF
# systemd-resolved 재시작
sudo systemctl restart systemd-resolved
# 현재 DNS 상태 확인
resolvectl status
# Global
# DNS Servers: 8.8.8.8 8.8.4.4
# Fallback DNS Servers: 1.1.1.1 9.9.9.9
# 테스트
resolvectl query google.com
방법 4: Netplan에서 DNS 설정 (Ubuntu Server)
Ubuntu Server에서 networkd가 렌더러일 때는 Netplan YAML로 DNS를 설정하고 netplan apply로 반영합니다.
이 명령은 시스템 설정 파일을 변경합니다. 기존 파일 백업과 적용 후 검증 방법을 준비하지 않으면 재부팅이나 서비스 재시작 때 장애가 반복될 수 있습니다.
# /etc/netplan/01-netcfg.yaml 편집
sudo tee /etc/netplan/01-netcfg.yaml << 'EOF'
network:
version: 2
renderer: networkd
ethernets:
ens3:
dhcp4: true
nameservers:
addresses: [8.8.8.8, 8.8.4.4, 1.1.1.1]
search: [example.com]
EOF
sudo netplan apply
# 확인
cat /etc/resolv.conf
resolvectl status
트러블슈팅
증상
수동으로 /etc/resolv.conf를 수정하고 DNS가 잘 되다가, 서버를 재부팅하면 다시 빈 파일이나 엉뚱한 내용으로 돌아옵니다.
# 수정 후 잘 됨
cat /etc/resolv.conf
# nameserver 8.8.8.8 ← 내가 설정한 내용
# 재부팅 후
cat /etc/resolv.conf
# # Generated by NetworkManager
# search . ← 초기화됨!
# nameserver 192.168.1.1 ← DHCP 서버가 준 DNS로 덮어써짐
ping google.com
# ping: google.com: Name or service not known
원인 파악
# 1. resolv.conf 관리 주체 확인
ls -la /etc/resolv.conf
# 2. NetworkManager가 관리 중인지 확인
cat /etc/resolv.conf | head -2
# "# Generated by NetworkManager" → NetworkManager가 덮어씀
# 3. DHCP 서버가 DNS를 보내주는지 확인
sudo journalctl -u NetworkManager | grep -i dns | tail -20
# "policy: set 'ens3' (ens3) as default for IPv4 routing and DNS"
# "dhcp4: option domain_name_servers => '192.168.1.1'" ← DHCP DNS 수신
해결 — NetworkManager에서 영구 설정
이 명령은 실행 중인 서비스 상태를 바꿔 순간적인 중단이나 설정 반영 실패를 만들 수 있습니다. 운영 트래픽 영향과 재시작 후 확인 명령을 먼저 준비하세요.
# 방법 1: nmcli로 DHCP DNS 무시하고 수동 DNS 설정
CONN=$(nmcli -t -f NAME con show --active | head -1)
echo "활성 연결: $CONN"
sudo nmcli con mod "$CONN" ipv4.dns "8.8.8.8 8.8.4.4"
sudo nmcli con mod "$CONN" ipv4.ignore-auto-dns yes
sudo nmcli con up "$CONN"
# 방법 2: 연결 설정 파일 직접 수정 (RHEL/CentOS)
ls /etc/sysconfig/network-scripts/
# ifcfg-ens3 → 해당 파일 편집
sudo tee -a /etc/sysconfig/network-scripts/ifcfg-ens3 << 'EOF'
DNS1=8.8.8.8
DNS2=8.8.4.4
PEERDNS=no
EOF
sudo systemctl restart NetworkManager
검증
# 재부팅 후에도 설정 유지 확인
sudo reboot
# 재접속 후
cat /etc/resolv.conf
# nameserver 8.8.8.8
# nameserver 8.8.4.4
ping google.com
# 성공!
증상
호스트에서는 DNS가 잘 되는데, Docker 컨테이너 안에서 DNS 해석이 실패합니다.
# 호스트에서는 잘 됨
ping google.com
# 정상
# 컨테이너 안에서는 실패
docker run --rm alpine ping google.com
# ping: bad address 'google.com'
docker run --rm alpine cat /etc/resolv.conf
# nameserver 127.0.0.11 ← Docker 내부 DNS
원인
Docker는 컨테이너의 /etc/resolv.conf를 자동 생성합니다. 호스트의 /etc/resolv.conf에 nameserver 127.0.0.53(systemd-resolved 스텁)이 있으면, Docker가 이를 컨테이너에 그대로 복사하여 컨테이너 내부에서 127.0.0.53에 접근 시 실패합니다.
# 문제 확인
cat /etc/resolv.conf
# nameserver 127.0.0.53 ← 호스트 루프백, 컨테이너에서 접근 불가!
# Docker daemon.json에서 DNS 설정 없는지 확인
cat /etc/docker/daemon.json
# {} 또는 파일 없음 → DNS 설정 없음
해결
이 명령은 실행 중인 서비스 상태를 바꿔 순간적인 중단이나 설정 반영 실패를 만들 수 있습니다. 운영 트래픽 영향과 재시작 후 확인 명령을 먼저 준비하세요.
# 방법 1: Docker daemon.json에 DNS 설정
sudo tee /etc/docker/daemon.json << 'EOF'
{
"dns": ["8.8.8.8", "8.8.4.4"],
"dns-search": []
}
EOF
sudo systemctl restart docker
# 테스트
docker run --rm alpine ping -c 2 google.com
# 방법 2: 컨테이너 실행 시 DNS 지정
docker run --rm --dns 8.8.8.8 alpine ping -c 2 google.com
# 방법 3: systemd-resolved 링크를 실제 파일로 변경
# (호스트 resolv.conf에서 127.0.0.53 제거)
sudo resolvectl dns ens3 8.8.8.8 8.8.4.4
sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf
# /run/systemd/resolve/resolv.conf는 실제 DNS IP를 포함
쿠버네티스 CoreDNS 문제:
# Pod에서 DNS 실패 시 CoreDNS 상태 확인
kubectl get pods -n kube-system | grep coredns
kubectl logs -n kube-system coredns-xxxxx
# Node의 resolv.conf 확인 (CoreDNS 설정에 영향)
# 각 노드에서:
cat /etc/resolv.conf
심화 — resolver가 조용히 만드는 비용: search 확장과 병렬 A/AAAA
심화: nameserver 한 줄 뒤에 숨은 비용 — 질의 폭증과 병렬 질의 유실
nameserver 한 줄만 맞으면 될 것 같지만, 정작 부하와 지연은 리졸버가 '한 번의 조회'를 뒤에서 여러 질의로 바꾸는 데서 나옵니다. resolv.conf의 search·options가 그 뒷면입니다.
- search 도메인 확장과 ndots:
options ndots:N은 '이름의 점(.) 개수가 N 미만이면 search 도메인을 먼저 붙여 시도하라'는 뜻입니다. 쿠버네티스 기본값 ndots:5에서는api.example.com(점 2개)조차 search 접미사(svc.cluster.local등 45개)를 하나씩 다 붙여 NXDOMAIN을 받은 뒤에야 절대 이름을 질의합니다. 외부 도메인 한 번 부르는데 DNS 왕복이 56배로 늘어 지연·부하가 커집니다. 이름 끝에 점을 붙여 FQDN(api.example.com.)으로 쓰거나 ndots를 낮추면 이 확장을 건너뜁니다. - 병렬 A/AAAA 질의: glibc 리졸버는 IPv4(A)와 IPv6(AAAA)를 같은 소켓·같은 소스 포트로 거의 동시에 보냅니다. 여기에 NAT/conntrack이 끼면 두 질의의 conntrack 항목이 5-튜플 경쟁을 일으켜 한쪽 응답이 드롭될 수 있고, 리졸버는 잃은 응답을
options timeout(기본 5초)만큼 기다렸다 재시도합니다 — '가끔 정확히 5초 지연되는 DNS'의 정체입니다. - 그래서 '가끔 느린 DNS'는 nameserver가 틀린 게 아니다: (a) search 확장으로 질의 수가 폭증했거나 (b) 병렬 질의 중 하나가 유실돼 timeout을 기다리는 경우입니다.
options single-request(-reopen),timeout/attempts축소, ndots 조정, FQDN 사용이 이때 쓰는 도구입니다.
즉 resolv.conf는 'DNS 서버 IP를 적는 곳'을 넘어, 조회가 몇 배로 늘어나고 어디서 5초가 새는지를 결정하는 튜닝 지점입니다.
상황: 앱이 외부·내부 호스트명을 부를 때 대개 수 ms인데, 간헐적으로 정확히 5초 걸린 뒤 성공합니다. 5초라는 딱 떨어지는 숫자가 반복되고, nameserver와 레코드는 모두 정상이라 원인을 잡기 어렵습니다.
원인: glibc 리졸버가 A와 AAAA 질의를 같은 소스 포트로 동시에 UDP로 보내는데, NAT(conntrack) 경로에서 두 질의의 conntrack 항목이 경쟁하며 한쪽 응답이 드롭됩니다. 리졸버는 잃은 응답을 resolv.conf의 options timeout(기본 5초)만큼 기다렸다 재시도해 성공하므로, 지연이 '정확히 5초'로 반복됩니다.
진단: cat /etc/resolv.conf의 options timeout 값이 5인지(지연 시간과 일치) 확인하고, 앱이 A와 AAAA를 함께 조회하는지 봅니다. dig는 기본이 A만 보내 재현이 안 될 수 있으니, 실제 앱 경로로 재현합니다. 노드의 conntrack insert_failed 카운터(conntrack -S)가 증가하는지도 확인합니다.
해결: resolv.conf options에 single-request-reopen을 추가해 A/AAAA를 별도 소켓·포트로 보내 경쟁을 없앱니다(single-request도 유사). timeout을 1로 낮추면 지연 폭 자체가 줄어듭니다. IPv6를 쓰지 않는 환경이면 불필요한 AAAA 조회를 줄이는 것도 근본 완화책입니다(DNS 동작 과정과 A, CNAME, TXT 레코드 분석의 질의 흐름과 함께 이해).
실무 맥락
DNS 장애가 전체 서비스를 멈추는 이유
DNS는 모든 서비스가 의존하는 인프라의 기반입니다. DNS가 느리거나 실패하면 예상치 못한 방식으로 장애가 연쇄됩니다.
DNS 장애 연쇄 효과 예시:
1. resolv.conf DNS 서버 다운 또는 네트워크 단절
↓
2. 애플리케이션이 DB 호스트명을 IP로 변환 실패
↓
3. DB 연결 타임아웃 (30초 기다리다 실패)
↓
4. 웹 요청 처리 지연/실패
↓
5. 사용자에게 503 Service Unavailable
실제 사례: DNS 서버 1개만 설정 → 해당 DNS 서버 재부팅 시
모든 서비스가 30초씩 지연 후 연결 실패
예방책: DNS 서버를 2~3개 지정하고 타임아웃을 단축하면 단일 장애점을 제거할 수 있습니다.
# resolv.conf에 DNS 서버를 항상 2~3개 설정
nameserver 10.0.0.1 # 내부 DNS (주)
nameserver 10.0.0.2 # 내부 DNS (보조)
nameserver 8.8.8.8 # 외부 DNS (최후 수단)
options timeout:1 attempts:2
# timeout: 응답 대기 시간(초), 기본 5초
# attempts: 재시도 횟수, 기본 2회
# → 내부 DNS 응답 없으면 1초 후 다음 서버 시도
빠른 DNS 진단 명령어 모음
DNS 문제가 의심될 때 아래 순서로 확인하면 대부분 원인을 5분 안에 파악할 수 있습니다.
이 명령은 실행 중인 서비스 상태를 바꿔 순간적인 중단이나 설정 반영 실패를 만들 수 있습니다. 운영 트래픽 영향과 재시작 후 확인 명령을 먼저 준비하세요.
# 현재 DNS 설정 한눈에 보기
resolvectl status 2>/dev/null || cat /etc/resolv.conf
# DNS 서버별 응답 시간 테스트
for dns in 8.8.8.8 8.8.4.4 1.1.1.1; do
echo -n "$dns: "
time nslookup google.com $dns > /dev/null 2>&1
done
# DNS 캐시 플러시 (이상한 결과 나올 때)
sudo systemd-resolve --flush-caches
# 또는
sudo resolvectl flush-caches
# 또는 NetworkManager 재시작
sudo systemctl restart NetworkManager
# 특정 도메인 DNS 추적
dig +trace google.com
# 루트 DNS → TLD DNS → 권한 DNS 전체 과정 보기
클라우드 환경에서의 DNS 특이점
클라우드 환경은 각 공급자가 제공하는 메타데이터 DNS 서버를 사용합니다. 온프레미스와 주소 체계가 다르므로 혼동하지 않도록 주의합니다.
AWS EC2:
- DHCP로 169.254.169.253 DNS 서버 자동 설정
- VPC DNS: 10.0.0.2 (VPC 기본 게이트웨이 +2 주소)
- Route 53 Resolver로 내부 도메인 해석
GCP GCE:
- 169.254.169.254 메타데이터 서버가 DNS 역할
- 내부 도메인: *.internal
Azure:
- 168.63.129.16 Azure DNS
클라우드에서 resolv.conf 직접 수정은 위험: cloud-init이 부팅 시 파일을 덮어쓰기 때문에 수동 수정은 재부팅 후 사라집니다.
# AWS EC2에서 resolv.conf 수정 시 주의
# cloud-init이 재부팅 시 resolv.conf를 원복할 수 있음
# AWS 권장 방법: DHCP 옵션 세트에서 DNS 서버 변경
# Console → VPC → DHCP option sets → DNS servers 수정
현업 팁 — 서버 프로비저닝 시 DNS 검증 자동화
서버를 새로 프로비저닝한 직후 DNS가 올바르게 동작하는지 확인하는 간단한 스크립트입니다. CI/CD 파이프라인의 헬스체크나 Ansible 후처리 단계에 넣어 쓸 수 있습니다.
# 서버 배포 후 DNS 검증 스크립트
#!/bin/bash
check_dns() {
local domain="${1:-google.com}"
local dns_server="${2}"
if [ -n "$dns_server" ]; then
result=$(nslookup "$domain" "$dns_server" 2>&1)
else
result=$(nslookup "$domain" 2>&1)
fi
if echo "$result" | grep -q "Address:"; then
echo "✓ DNS 해석 성공: $domain"
return 0
else
echo "✗ DNS 해석 실패: $domain"
echo " 오류: $result"
return 1
fi
}
# 인터넷 도메인 확인
check_dns google.com
# 내부 도메인 확인
check_dns internal.company.com 10.0.0.1
# 역방향 DNS 확인
nslookup 8.8.8.8
정리
/etc/resolv.conf 핵심 지시어
nameserver: DNS 서버 IP (최대 3개, 순서대로 시도)search: 짧은 호스트명에 자동으로 붙는 도메인domain: 시스템 기본 도메인options: timeout, attempts, ndots 등 세부 설정
DNS 문제 진단 흐름
ping 8.8.8.8성공 → 네트워크 정상ping google.com실패 → DNS 문제nslookup google.com실패 +nslookup google.com 8.8.8.8성공 → resolv.conf nameserver 설정 문제
cat /etc/resolv.conf로 nameserver 확인 및 수정
영구 설정 방법
- nmcli:
nmcli con mod <이름> ipv4.dns "8.8.8.8 8.8.4.4" - systemd-resolved:
/etc/systemd/resolved.conf - Netplan:
/etc/netplan/*.yaml의 nameservers - 재부팅 후 초기화되면 → NetworkManager/cloud-init 덮어쓰기가 원인
재부팅 후 초기화 문제 해결
ls -la /etc/resolv.conf→ 심볼릭 링크 확인cat /etc/resolv.conf상단 주석 → 관리 주체 확인nmcli con mod + ipv4.ignore-auto-dns yes→ 영구 해결
명령어·단축키 빠른 참조
이 모듈에서 다룬 DNS 진단·설정 명령을 실전 옵션과 함께 모았습니다. "예" 열의 조합을 그대로 써도 됩니다.
| 명령어/단축키 | 용도 | 자주 쓰는 예 |
|---|---|---|
cat /etc/resolv.conf | 현재 nameserver·search·options 확인 | 가장 먼저 — nameserver가 비었/틀렸는지 |
ls -la /etc/resolv.conf | 관리 주체(심볼릭 링크) 판별 | 링크면 systemd-resolved가 덮어씀 |
ping (IP vs 도메인) | DNS 문제 vs 네트워크 문제 분리 | ping -c2 8.8.8.8 성공 + ping -c2 google.com 실패 = DNS |
nslookup <도메인> <서버> | 특정 DNS 서버로 직접 질의 | nslookup google.com 8.8.8.8 (성공=resolv.conf 문제) |
dig | 질의 상세·특정 서버 지정 | dig @8.8.8.8 google.com |
dig +trace | 루트→TLD→권한 위임 경로 추적 | dig +trace google.com (SERVFAIL 원인) |
nmcli con mod ... ipv4.dns | 재부팅 후에도 유지되는 영구 DNS | sudo nmcli con mod "ens3" ipv4.dns "8.8.8.8 8.8.4.4" |
nmcli con mod ... ipv4.ignore-auto-dns | DHCP가 준 DNS 무시 | sudo nmcli con mod "ens3" ipv4.ignore-auto-dns yes |
resolvectl status | systemd-resolved DNS 상태 확인 | 적용된 nameserver·fallback 확인 |
resolvectl flush-caches | DNS 캐시 플러시 | 이상한 해석 결과 나올 때 |
grep hosts /etc/nsswitch.conf | 이름 해석 순서(files/dns) 확인 | /etc/hosts가 DNS보다 우선하는지 |
netplan apply | Netplan YAML DNS 반영(Ubuntu Server) | sudo netplan apply 후 resolvectl status |
관련 모듈로 더 깊이:
- DNS 동작 과정과 A, CNAME, TXT 레코드 분석 — A/CNAME/TXT 레코드와 DNS 질의 과정의 근본 원리
- nmcli와 ifconfig로 네트워크 인터페이스 완벽 제어 — nmcli로 DNS를 영구 설정하고 재부팅 초기화를 막는 법
- ping과 ICMP 프로토콜을 이용한 초동 경로 진단 — IP ping은 되는데 도메인 ping이 안 되는 증상의 구분
다음 모듈에서는 서비스가 127.0.0.1에만 바인딩되어 외부에서 연결이 안 되는 상황을 진단하고, bind-address 설정으로 해결하는 방법을 다룹니다.