CoreDNS 는 플러그인을 순서대로 엮어 동작하는 DNS 서버이며 Kubernetes 의 클러스터 DNS 기본 구현체다. 설정 파일은 Corefile 하나이고, 쿠버네티스에서는 kube-system 네임스페이스의 coredns ConfigMap 이 그 파일을 담는다.
클러스터 밖의 이름 몇 개를 고정하는 것이 목적이면 hosts 플러그인이 가장 간단하다. 영역 전체를 책임져야 하면 file 플러그인으로 존 파일을 읽힌다.
. {
hosts {
192.168.1.100 example.local
192.168.1.101 db.local
fallthrough
}
forward . 8.8.8.8 8.8.4.4
log
}
fallthrough 가 핵심이다. 이 지시어가 없으면 hosts 블록에 없는 이름은 뒤 플러그인(forward)으로 넘어가지 않고 NXDOMAIN 이 되어 클러스터 전체 이름 해석이 끊긴다.
hosts 는 /etc/hosts 형식의 외부 파일도 읽는다. hosts /etc/coredns/custom.hosts example.local { ... } 처럼 파일 경로와 담당 영역을 함께 적는다.
example.com:53 {
file /etc/coredns/db.example.com
log
errors
}
존 파일 형식은 BIND 와 같다. 작성 규칙은 DNS 레코드 종류와 존 파일 작성 을 따르고, 고칠 때마다 SOA serial 을 올린다.
특정 도메인만 다른 DNS 서버로 넘기려면 forward 를 영역별로 둔다.
internal.example.com:53 {
forward . 10.0.0.53
cache 30
}
# 현재 Corefile 확인
kubectl -n kube-system get configmap coredns -o yaml
# 편집
kubectl -n kube-system edit configmap coredns
기본 Corefile 의 kubernetes 플러그인 블록 뒤, forward . /etc/resolv.conf 앞에 hosts 블록을 넣는다. 순서가 중요하다. forward 뒤에 두면 도달하지 않는다.
Corefile: |
.:53 {
errors
health
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
hosts {
192.168.1.100 example.local
fallthrough
}
prometheus :9153
forward . /etc/resolv.conf
cache 30
loop
reload
loadbalance
}
ConfigMap 이 바뀌면 reload 플러그인이 약 30초 안에 알아서 다시 읽는다. 즉시 반영하려면 파드를 다시 띄운다.
kubectl -n kube-system rollout restart deployment coredns
kubectl delete pod -l k8s-app=kube-dns 로도 되지만, rollout restart 가 순차 교체라 조회가 끊기지 않는다.
ConfigMap 을 sed 로 조립해 kubectl patch 하는 한 줄 명령은 줄바꿈과 따옴표가 쉽게 깨진다. 실수하면 클러스터 DNS 가 통째로 멈추므로 편집 후 문법을 확인하고 적용하는 편이 안전하다.
파드 안에서 curl: Could not resolve host 가 나오면 아래 순서로 좁힌다.
# 1) 리졸버 설정. nameserver 가 kube-dns 서비스 IP 인지
kubectl exec -it <pod> -- cat /etc/resolv.conf
# 2) CoreDNS 파드와 서비스 엔드포인트
kubectl -n kube-system get pod -l k8s-app=kube-dns
kubectl -n kube-system get endpoints kube-dns
# 3) 클러스터 내부 이름과 외부 이름을 나눠서 질의
kubectl run dnstest --rm -it --image=busybox:1.36 --restart=Never -- \
nslookup my-svc.default.svc.cluster.local
# 4) CoreDNS 로그
kubectl -n kube-system logs -l k8s-app=kube-dns --tail=100
내부 이름은 되는데 외부 이름만 안 되면 CoreDNS 의 forward 대상(노드의 /etc/resolv.conf)이 응답하지 않는 것이다. 둘 다 안 되면 CoreDNS 파드나 kube-dns 서비스 엔드포인트를 먼저 본다.
/etc/resolv.conf 의 options ndots:5 때문에 점이 5개 미만인 이름은 search 도메인을 먼저 붙여 질의한다. 외부 FQDN 조회가 느리면 이름 끝에 점을 붙여(example.com.) 절대 이름으로 만들거나, 파드에 dnsConfig 로 ndots 를 낮춘다.
NetworkPolicy 를 쓰는 네임스페이스라면 kube-dns 로 나가는 UDP · TCP 53 egress 를 허용했는지 확인한다. DNS 만 막혀 "네트워크는 되는데 이름만 안 되는" 증상이 된다.