Ubuntu에서 coredns pod 구동 에러조치
Ubuntu 환경에서 CoreDNS DNS Loop 해결
Kubernetes 클러스터 최초 구성한 뒤 CoreDNS Pod가 정상적으로 올라오지 않고 CrashLoopBackOff 상태가 반복되었다. 처음에는 CoreDNS 설정 문제로 생각했지만, 로그를 확인해 보니 Ubuntu의 systemd-resolved와 /etc/resolv.conf 연결 구조 때문에 발생한 DNS loop 문제였다.
증상
-
kube-system 네임스페이스의 CoreDNS Pod 상태를 확인했다.
$> kubectl get pod -n kube-system | egrep -vi 'run|com' NAMESPACE NAME READY STATUS RESTARTS kube-system coredns-699dd8795c-zfgmq 0/1 CrashLoopBackOff 401 kube-system coredns-699dd8795c-zlnbh 0/1 CrashLoopBackOff 400 -
두 CoreDNS Pod 모두 CrashLoopBackOff 상태였고 재시작 횟수도 계속 증가하고 있어 Pod 로그를 확인했다.
$> kubectl logs -n kube-system coredns-699dd8795c-zfgmq maxprocs: Leaving GOMAXPROCS=2: CPU quota undefined .:53 [INFO] plugin/reload: Running configuration SHA512 = 0fa0ebfa7231f5eabbc5c70e626899aee4ece58bf8505c05f52cebc6b43208d08777671d33649bcf0f0525d426f43c1ce4d371c2ab8a4502a39c65ac79d238db CoreDNS-1.12.4 linux/amd64, go1.25.0, f323295 [FATAL] plugin/loop: Loop (127.0.0.1:60545 -> :53) detected for zone "." -
핵심은 아래 로그였다.
[FATAL] plugin/loop: Loop (127.0.0.1:60545 -> :53) detected for zone "."- CoreDNS가 upstream DNS로 질의를 전달한 뒤, 해당 요청이 다시 CoreDNS로 돌아오는 DNS loop를 감지하고 종료한 것이다.
원인 확인
-
CoreDNS의 기본 설정은 외부 도메인 질의를 /etc/resolv.conf에 정의된 DNS 서버로 전달한다.
forward . /etc/resolv.conf -
따라서 CoreDNS가 실행되는 Kubernetes 노드의 /etc/resolv.conf를 확인했다.
$> cat /etc/resolv.conf # This is /run/systemd/resolve/stub-resolv.conf managed by man:systemd-resolved(8). # Do not edit. nameserver 127.0.0.53 options edns0 trust-ad search . -
Ubuntu에서는 기본적으로 systemd-resolved가 DNS를 관리하는데 /etc/resolv.conf는 일반 파일이 아니라 symbolic link이며, 기본 구성에서는 systemd-resolved의 stub resolver 파일을 바라본다.
$> ls -l /etc/resolv.conf /etc/resolv.conf -> ../run/systemd/resolve/stub-resolv.conf -
stub-resolv.conf에는 실제 사내 DNS나 외부 DNS IP가 아닌 local DNS stub resolver 주소가 설정된다.
nameserver 127.0.0.53 -
127.0.0.53은 Ubuntu 노드에서 동작하는 systemd-resolved의 local stub resolver 주소다.
- CoreDNS가 /etc/resolv.conf를 upstream DNS 설정으로 사용하면서 127.0.0.53으로 질의를 전달했고, 이 요청이 다시 CoreDNS로 돌아오면서 DNS loop가 발생했다.
- CoreDNS의 loop 플러그인은 무한 재귀를 방지하기 위해 loop를 감지하면 프로세스를 종료한다. 이 때문에 CoreDNS Pod가 반복 재시작되며 CrashLoopBackOff 상태가 되었다.
조치 방법
-
/etc/resolv.conf가 stub-resolv.conf가 아닌 실제 upstream DNS 정보가 포함된 파일을 바라보도록 변경했다.
$> sudo ln -snf /run/systemd/resolve/resolv.conf /etc/resolv.conf -
변경상태 확인
$> ls -l /etc/resolv.conf /etc/resolv.conf -> /run/systemd/resolve/resolv.conf- 이제 /etc/resolv.conf는 127.0.0.53만 포함하는 stub 파일이 아니라, systemd-resolved가 관리하는 실제 upstream DNS 서버 정보가 포함된 파일을 참조한다.
변경 후 확인
-
링크 변경 후 /etc/resolv.conf 내용을 확인한다.
cat /etc/resolv.conf nameserver 10.10.0.10 nameserver 10.10.0.11 -
CoreDNS Pod도 다시 생성한다.
$> kubectl -n kube-system rollout restart deployment/coredns -
CoreDNS Pod 상태를 확인한다.
$> kubectl -n kube-system get pod -l k8s-app=kube-dns NAME READY STATUS RESTARTS AGE coredns-7ffd757c96-75766 1/1 Running 2 (17m ago) 40m coredns-7ffd757c96-gzgzr 1/1 Running 2 (18m ago) 40m -
로그도 확인한다.
$> kubectl -n kube-system logs deployment/coredns --tail=100- 정상적으로 복구되면 plugin/loop 관련 FATAL 로그가 더 이상 출력되지 않고, CoreDNS Pod가 Running 상태가 된다.