LabHub
배우기 러닝패스 코스

Kubernetes Networking — On a Real Cluster

Actually Dig Into Cluster DNS

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

이 실습은 진짜 쿠버네티스에서 돕니다

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. webSRV 레코드를 조회해 /root/k8sdns/srv.txt 에 저장하세요.
  7. lowdots 라는 파드를 dnsConfigndots: 1 을 주어 띄우고, 4번의 curl 과 같은 도구로 질의 수를 다시 세어 /root/k8sdns/fixed.txt 에 저장하세요(queries= 줄 포함). 3회 이하여야 합니다. 도구를 바꾸면 비교가 성립하지 않습니다.
  8. /root/k8sdns/report.mddns_ip=, queries_before=, queries_after= 세 줄과 함께 ndots 가 왜 문제였는지, 그리고 nslookup 으로 재면 왜 문제가 보이지 않는지를 적으세요.

참고

CoreDNS 는 어디에 있는가

CoreDNS 가 어디에 있고 무엇을 하는지 확인해 /root/k8sdns/coredns.txt 에 저장하세요. kube-dns 서비스의 ClusterIP 와 Corefile 전문이 들어가야 합니다.

kube-dns 라는 이름의 서비스를 kube-system 에서 찾고, coredns ConfigMap 의 Corefile 을 함께 담습니다. 이름이 CoreDNS 인데 서비스 이름이 kube-dns 인 것은 예전 구현의 이름을 그대로 물려받았기 때문입니다.

파드는 무엇을 보고 이름을 찾는가

파드 안의 /etc/resolv.conf 를 그대로 /root/k8sdns/resolv.txt 에 저장하세요. nameserver·search·options 세 줄이 모두 있어야 합니다.

파드 하나를 띄워 그 안의 /etc/resolv.conf 를 그대로 읽습니다. VM 자신의 resolv.conf 가 아니라 파드 안의 것이어야 합니다 — 둘은 완전히 다릅니다.

서비스 이름이 주소가 되는 순간

web 이라는 Deployment(레플리카 2, nginx:1.27-alpine, 포트 이름 http)와 같은 이름의 Service 를 만들고, 긴 이름과 짧은 이름 둘 다 조회해 /root/k8sdns/svc-a.txt 에 저장하세요. 같은 ClusterIP 가 나와야 합니다.

Deployment 와 Service 를 만든 뒤, 같은 네임스페이스의 파드에서 webweb.default.svc.cluster.local 을 각각 조회합니다. 짧은 이름이 되는 이유는 search 도메인 덕분입니다.

이름 하나에 질의 몇 번인가

CoreDNS 의 Corefile 에 log 플러그인을 켜고, example.com두 가지 도구로 각각 조회해 CoreDNS 로그의 질의 수를 세어 /root/k8sdns/ndots.txt 에 저장하세요. queries_nslookup=queries_getaddrinfo= 두 줄로 시작하고 그 아래에 로그를 붙입니다.

Corefile 에 log 를 한 줄 넣고 CoreDNS 를 재시작한 뒤, 파드에서 example.com 을 한 번만 조회하고 로그를 셉니다. 끝에 점을 붙이면(example.com.) 검색 도메인을 건너뛰므로 붙이지 마세요.

헤드리스는 무엇을 돌려주는가

web-h 라는 헤드리스 Service(clusterIP: None)를 만들고 조회 결과를 /root/k8sdns/headless.txt 에 저장하세요. 파드 IP 들이 그대로 나와야 합니다.

clusterIP: None 인 서비스를 만들고 조회합니다. 평범한 서비스와 달리 주소가 여러 개 나옵니다.

포트 번호를 이름으로 찾는다

webSRV 레코드를 조회해 /root/k8sdns/srv.txt 에 저장하세요.

SRV 이름은 _<포트이름>._tcp.<서비스>.<네임스페이스>.svc.cluster.local 입니다. 3단계에서 포트에 http 라는 이름을 붙여 두었습니다.

ndots 를 낮춰 고친다

lowdots 라는 파드를 dnsConfigndots: 1 을 주어 띄우고, 4번의 curl 과 같은 도구로 질의 수를 다시 세어 /root/k8sdns/fixed.txt 에 저장하세요(queries= 줄 포함). 3회 이하여야 합니다. 도구를 바꾸면 비교가 성립하지 않습니다.

파드 스펙의 dnsConfig.options{name: ndots, value: "1"} 을 넣습니다. 그러면 점이 하나만 있어도 검색 도메인을 거치지 않습니다.

무엇을 배웠나

/root/k8sdns/report.mddns_ip=, queries_before=, queries_after= 세 줄과 함께 ndots 가 왜 문제였는지, 그리고 nslookup 으로 재면 왜 문제가 보이지 않는지를 적으세요.

dns_ip=, queries_before=, queries_after= 세 줄과 함께, ndots 가 왜 문제였는지를 본문에 적습니다.