Cloud/Kubernetes
CoreDNS
Jinseung's Blog
2026. 9. 9. 20:22
이번 블로그에서는 Kubernetes의 기본 DNS 서버인 CoreDNS의 개념에 대한 글을 작성해보겠습니다.
CoreDNS 개념
CoreDNS는 Kubernetes 클러스터의 기본 DNS 서버로, Service, Pod 이름을 클러스터 내부 IP로 변환(서비스 디스커버리)하고 클러스터 외부 도메인 질의는 상위(upstream) DNS로 포워딩하는 모듈형 DNS 애플리케이션입니다.
위치와 역할
- Kubernetes 1.13부터 kube-dns를 대체한 기본 클러스터 DNS
- kube-system 네임스페이스에 Deployment로 실행되고, 그 앞에 kube-dns라는 이름의 Service(ClusterIP)가 붙습니다. ( Service 이름이 kube-dns인 이유는 과거 호환성 때문입니다.)
- 클러스터의 모든 Pod는 이 DNS Service IP를 /etc/resolv.conf의 nameserver로 받아 사용합니다.
DNS 이름 규칙
- Service : <service-name>.<namespace>.svc.cluster.local
- 같은 네임스페이스면 <service-name> 만으로도 조회 가능합니다.
- Headless Service(clusterIP: None)는 A 레코드가 각 Pod IP로 반환됩니다.
- SRV 레코드로 포트 정보도 조회 가능: _<port-name>._<protocol>.<service>.<ns>.svc.cluster.local
- Pod : 기본은 IP 기반입니다. 10-244-1-5.<namespace>.pod.cluster.local 형태 (IP의 .을 -로 치환)
resolv.conf와 ndots
Pod 안 /etc/resolv.conf는 대략 이렇게 세팅되게 됩니다.
nameserver 10.96.0.10 # kube-dns Service IP
search <ns>.svc.cluster.local svc.cluster.local cluster.local
options ndots:5
ndots:5: 조회하려는 이름에 점(.)이 5개 미만이면 먼저 search 도메인들을 붙여서 순서대로 질의합니다. 그래서 google.com(점 1개) 같은 외부 도메인도 google.com.<ns>.svc.cluster.local 등을 먼저 시도해 불필요한 질의가 여러 번 발생할 수 있습니다 → DNS 성능 이슈의 흔한 원인이기도 합니다.
Corefile 설정 파일
CoreDNS는 플러그인 체인으로 동작하며, kube-system의 coredns ConfigMap에 담긴 Corefile로 설정합니다.
.:53 {
errors
health {
lameduck 5s
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
prometheus :9153
forward . /etc/resolv.conf {
max_concurrent 1000
}
cache 30
loop
reload
loadbalance
}
- .:53 : 모든 존(.)을 53 포트에서 처리한다는 서버 블록
- 위에서 아래로 플러그인이 체인처럼 엮여 질의를 처리
주요 플러그인
| kubernetes | 클러스터 도메인(cluster.local)의 Service/Pod 질의를 API 서버 정보로 응답. pods insecure/verified/disabled 옵션 |
| forward | 클러스터 도메인이 아닌 질의를 상위 DNS(기본 /etc/resolv.conf, 즉 노드 DNS)로 전달 |
| cache | 응답 캐싱(기본 TTL 30초)으로 상위 질의 부하 감소 |
| errors | 에러를 stdout으로 로깅 |
| health | :8080/health 헬스 엔드포인트 (livenessProbe용). lameduck은 종료 전 유예 시간 |
| ready | :8181 준비 상태(200 OK) 반환 (readinessProbe용) |
| prometheus | :9153/metrics로 메트릭 노출 |
| loop | DNS 포워딩 루프 감지 시 프로세스 종료로 무한루프 방지 |
| reload | Corefile 변경을 재시작 없이 자동 반영(약 2분 지연) |
| loadbalance | A/AAAA 레코드 순서를 라운드로빈으로 섞어 부하 분산 |
| fallthrough | 해당 플러그인이 처리 못한 질의를 다음 플러그인으로 넘김 |
관련 명령어
CoreDNS 리소스 확인 명령어
kubectl get deployment coredns -n kube-system
kubectl get svc kube-dns -n kube-system
kubectl get configmap coredns -n kube-system -o yaml
kubectl -n kube-system logs -l k8s-app=kube-dns
Pod 내부에서 DNS 해석 테스트
# 임시 디버그 Pod
kubectl run -it --rm dnsutils --image=registry.k8s.io/e2e-test-images/agnhost:2.39 -- sh
# 안에서
nslookup kubernetes.default # ClusterIP 반환되면 정상
nslookup my-svc.my-namespace.svc.cluster.local
cat /etc/resolv.conf # nameserver / search / ndots 확인
커스텀 스텁 도메인 추가 방법
consul.local 질의는 별도 DNS(10.150.0.1)로 보내고, 나머지 외부 질의는 특정 nameserver(172.16.0.1)로 포워딩 합니다.
.:53 {
errors
health
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
}
prometheus :9153
forward . 172.16.0.1
cache 30
loop
reload
loadbalance
}
consul.local:53 {
errors
cache 30
forward . 10.150.0.1
}
이것으로 Kubernetes의 기본 DNS 서버인 CoreDNS에 대한 글을 마치겠습니다. 감사합니다!