쿠버네티스 네트워크 — 진짜 클러스터에서 · 이름이 풀리는 경로 · 실습
클러스터 DNS 를 실제로 캐본다
이 실습은 진짜 쿠버네티스에서 돕니다
VM 안에 k3s 한 대가 실제로 떠 있습니다. CoreDNS 가 진짜로 돌고, 질의를
로그로 남기며, 파드는 실제 컨테이너입니다. 그래서 "이름을 하나 찾는 데 질의가
몇 번 나가는가" 같은 것을 세어 볼 수 있습니다.
처음 뜨는 데 2분쯤 걸립니다. VM 이 부팅하고 k3s 를 설치하기 때문입니다.
목표
파드가 이름을 찾는 경로를 처음부터 끝까지 따라가고, ndots:5 가 만드는
숨은 비용을 직접 세어 확인한 뒤 dnsConfig 로 고칩니다.
왜 중요한가
클러스터에서 "느리다" 는 신고의 상당수가 DNS 입니다. 그런데 애플리케이션
지표에는 잘 잡히지 않습니다. 요청 하나가 이름 하나를 찾는 데 질의를 다섯 번
날리고 그중 넷이 NXDOMAIN 이어도, 애플리케이션 입장에서는 그냥 "조금 느린
요청" 입니다. CoreDNS 의 부하는 조용히 올라가고, 어느 날 파드 수가 늘면
그때 터집니다.
원인은 resolv.conf 한 줄입니다. ndots:5 는 **점이 5개 미만인 이름은
먼저 검색 도메인을 붙여 시도하라**는 뜻입니다. example.com 은 점이 하나라example.com.default.svc.cluster.local 부터 물어보게 됩니다. 클러스터 안
이름을 짧게 쓰라고 있는 편의가, 밖으로 나가는 이름에는 그대로 비용이 됩니다.
단계
1. CoreDNS 가 어디에 있고 무엇을 하는지 확인해 /root/k8sdns/coredns.txt 에 저장하세요. kube-dns 서비스의 ClusterIP 와 Corefile 전문이 들어가야 합니다.
2. 파드 안의 /etc/resolv.conf 를 그대로 /root/k8sdns/resolv.txt 에 저장하세요. nameserver·search·options 세 줄이 모두 있어야 합니다.
3. web 이라는 Deployment(레플리카 2, nginx:1.27-alpine, 포트 이름 http)와 같은 이름의 Service 를 만들고, 긴 이름과 짧은 이름 둘 다 조회해 /root/k8sdns/svc-a.txt 에 저장하세요. 같은 ClusterIP 가 나와야 합니다.
4. CoreDNS 의 Corefile 에 log 플러그인을 켜고, example.com 을 두 가지 도구로 각각 조회해 CoreDNS 로그의 질의 수를 세어 /root/k8sdns/ndots.txt 에 저장하세요. queries_nslookup= 과 queries_getaddrinfo= 두 줄로 시작하고 그 아래에 로그를 붙입니다.
- busybox 의
nslookup한 번 curl한 번 (curlimages/curl:8.10.1)
두 숫자가 크게 다릅니다. 왜 다른지가 이 단계의 핵심입니다.
5. web-h 라는 헤드리스 Service(clusterIP: None)를 만들고 조회 결과를 /root/k8sdns/headless.txt 에 저장하세요. 파드 IP 들이 그대로 나와야 합니다.
6. web 의 SRV 레코드를 조회해 /root/k8sdns/srv.txt 에 저장하세요.
7. lowdots 라는 파드를 dnsConfig 로 ndots: 1 을 주어 띄우고, 4번의 curl 과 같은 도구로 질의 수를 다시 세어 /root/k8sdns/fixed.txt 에 저장하세요(queries= 줄 포함). 3회 이하여야 합니다. 도구를 바꾸면 비교가 성립하지 않습니다.
8. /root/k8sdns/report.md 에 dns_ip=, queries_before=, queries_after= 세 줄과 함께 ndots 가 왜 문제였는지, 그리고 nslookup 으로 재면 왜 문제가 보이지 않는지를 적으세요.
참고
- 조회 도구는 파드 안에서 씁니다.
kubectl run q --rm -it --image=busybox:1.36 --restart=Never -- nslookup <이름>이 가장 간단합니다. - Corefile 은
kubectl -n kube-system get cm coredns -o yaml로 봅니다. 고칠 때는kubectl -n kube-system edit cm coredns뒤에kubectl -n kube-system rollout restart deploy coredns를 하세요. - 로그는
kubectl -n kube-system logs deploy/coredns로 봅니다. 세기 전에 로그를 한 번 비우고 싶으면 CoreDNS 를 재시작하면 됩니다. - SRV 이름은
_<포트이름>._<프로토콜>.<서비스>.<네임스페이스>.svc.cluster.local입니다. 포트에 이름이 없으면 SRV 가 만들어지지 않습니다. - 4번의 두 숫자가 다른 이유: busybox 의
nslookup은 DNS 프로토콜을 직접 말하므로search와ndots를 읽지 않습니다. 평범한 애플리케이션은getaddrinfo를 부르고, 그쪽은 resolv.conf 를 그대로 따르며 A 와 AAAA 를 각각 묻습니다. - 로그를 셀 때는 세기 직전에 CoreDNS 를 재시작하세요. 재시작이 곧 로그를 비우는 방법이고, 그래야 앞 단계의 질의가 섞이지 않습니다.
- 흔한 실수 1: 이름 끝에 점을 붙이는 것(
example.com.). 절대 이름이라 검색 도메인을 건너뛰어 배우려던 것이 사라집니다. - 흔한 실수 2: 5번에서
clusterIP: None을 빼는 것. 그러면 평범한 서비스라 ClusterIP 하나만 돌아옵니다.
단계 8개
- CoreDNS 는 어디에 있는가
- 파드는 무엇을 보고 이름을 찾는가
- 서비스 이름이 주소가 되는 순간
- 이름 하나에 질의 몇 번인가
- 헤드리스는 무엇을 돌려주는가
- 포트 번호를 이름으로 찾는다
- ndots 를 낮춰 고친다
- 무엇을 배웠나