쿠버네티스 DNS의 비밀 - CoreDNS가 서비스를 찾는 진짜 방법

|Platform Decision|10분 읽기

쿠버네티스에서 파드들은 어떻게 서로를 찾을까요?

쿠버네티스 클러스터에서 개발하시다 보면, 신기한 일을 많이 보게 되죠. 프론트엔드 파드가 백엔드 서비스와 멀쩡히 통신하고, 백엔드는 또 데이터베이스와 자연스럽게 연결되고... 모든 게 마법처럼 돌아가더라고요.

그런데 한 번쯤 궁금하지 않으셨나요? 파드들이 도대체 어떻게 서로의 위치를 찾아내는 걸까요? IP 주소를 외우고 다니는 것도 아닌데 말이에요.

정답은 바로 DNS, 더 정확히는 CoreDNS입니다. 오늘은 이 숨은 일꾼이 어떻게 우리 클러스터를 돌려주는지, 그리고 가끔 느려지는 DNS 문제는 어떻게 해결하는지 차근차근 알아보겠습니다.

CoreDNS, 쿠버네티스의 전화번호부

CoreDNS는 2018년부터 쿠버네티스 1.13 버전의 기본 DNS 서버로 자리잡았어요. 그 전에는 kube-dns를 썼는데, CoreDNS가 더 가볍고 설정도 편해서 완전히 대체했죠.

CoreDNS를 쿠버네티스 클러스터의 전화번호부라고 생각하시면 딱 맞아요. 파드가 "내가 연결하려는 서비스가 어디 있지?"라고 물으면, CoreDNS가 "여기 IP 주소야!"하고 알려주는 거죠.

보통 CoreDNS는 이렇게 구성되어 있어요:

  • kube-system 네임스페이스에서 Deployment로 실행
  • 고가용성을 위해 보통 2개 복제본으로 운영
  • kube-dns라는 이름의 Service로 안정적인 ClusterIP 제공

모든 파드가 이 ClusterIP를 DNS 서버로 사용하게 됩니다.

파드 안에서 DNS 조회가 일어나는 과정

실제로 파드가 서비스 이름을 찾을 때 어떤 일이 벌어지는지 단계별로 살펴볼까요?

1단계: DNS 쿼리 발생 파드가 같은 네임스페이스의 my-service에 접근하려고 합니다. 이때 파드 내부의 /etc/resolv.conf에 설정된 DNS 서버로 쿼리를 보내죠.

2단계: CoreDNS로 전달 kubelet이 파드를 시작할 때 자동으로 /etc/resolv.conf에 kube-dns 서비스 IP를 넣어줍니다. 그래서 모든 DNS 쿼리가 CoreDNS로 가게 되어요.

3단계: 내부 vs 외부 판단 CoreDNS가 쿼리를 받으면 이게 쿠버네티스 내부 이름인지, 아니면 외부 도메인인지 판단합니다.

  • 내부 이름 (예: my-service.default.svc.cluster.local)이면 → Kubernetes API로 서비스 조회 후 ClusterIP 반환
  • 외부 도메인 (예: google.com)이면 → 상위 DNS 서버로 전달

4단계: IP 주소 반환 해결된 IP 주소가 파드로 돌아가고, 파드는 이 IP로 연결을 시작합니다. 이 모든 과정이 보통 몇 밀리초 안에 끝나요.

쿠버네티스 DNS 이름 규칙 - 이것만 알면 끝

쿠버네티스에서 서비스 이름은 아주 체계적인 패턴을 따릅니다:

서비스이름.네임스페이스.svc.cluster.local

각 부분을 자세히 살펴보면:

  • 서비스이름: 여러분이 만든 Service 리소스의 이름
  • 네임스페이스: 서비스가 속한 네임스페이스 (default, production 등)
  • svc: 이게 서비스 리소스라는 표시
  • cluster.local: 클러스터 기본 도메인 (거의 바꾸지 않아요)

예를 들어 production 네임스페이스에 backend-api 서비스가 있다면:

backend-api.production.svc.cluster.local

하지만 여기서 꿀팁! 같은 네임스페이스 안에서는 그냥 backend-api만 써도 됩니다. 쿠버네티스가 알아서 나머지를 붙여주거든요.

/etc/resolv.conf 파일의 비밀

아무 파드에 들어가서 /etc/resolv.conf를 열어보시면 이런 내용이 보일 거예요:

nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5

각 줄이 하는 일을 알아볼까요?

nameserver 10.96.0.10

  • kube-dns 서비스의 ClusterIP
  • 모든 DNS 쿼리가 여기로 먼저 갑니다

search 도메인들

  • 짧은 이름을 입력했을 때 자동으로 붙여줄 접미사들
  • my-service라고 치면 my-service.default.svc.cluster.localmy-service.svc.cluster.local 순으로 시도
  • 이게 있어서 같은 네임스페이스에서는 짧은 이름만 써도 되는 거예요

ndots:5

  • 여기서부터 이야기가 복잡해집니다... 다음 섹션에서 자세히 다뤄볼게요

ndots 문제 - DNS가 느려지는 진짜 이유

이 부분이 정말 중요한데, 많은 분들이 모르고 계시는 함정이에요.

ndots:5 설정은 "이름에 점이 5개 미만이면 절대 이름으로 보지 말고 search 도메인을 먼저 시도해봐"라는 뜻입니다.

문제는 외부 API를 호출할 때 생겨요. 예를 들어 api.stripe.com (점 2개)을 호출한다면:

  1. api.stripe.com.default.svc.cluster.local → 없음 (NXDOMAIN)
  2. api.stripe.com.svc.cluster.local → 없음 (NXDOMAIN)
  3. api.stripe.com.cluster.local → 없음 (NXDOMAIN)
  4. api.stripe.com → 드디어 성공!

외부 API 호출 하나당 불필요한 DNS 쿼리가 3번씩 더 발생하는 거죠. 파드가 많고 외부 호출이 많으면 DNS 병목이 생길 수밖에 없어요.

해결 방법은?

방법 1: 도메인 끝에 점 붙이기

// 이렇게 하지 말고
fetch('https://api.stripe.com/charges')

// 이렇게 하세요
fetch('https://api.stripe.com./charges')

마지막 점이 "이미 완전한 도메인 이름이야"라고 알려주는 거예요.

방법 2: ndots 값 조정 Pod spec에서 dnsConfig로 ndots를 더 낮게 설정할 수 있습니다:

apiVersion: v1
kind: Pod
spec:
  dnsConfig:
    options:
    - name: ndots
      value: "2"

CoreDNS 설정 파일 들여다보기

CoreDNS는 Corefile이라는 설정 파일로 동작을 제어해요. kube-system 네임스페이스의 coredns ConfigMap에 들어있죠:

kubectl get configmap coredns -n kube-system -o yaml

전형적인 Corefile 내용:

.:53 {
    errors
    health
    ready
    kubernetes cluster.local in-addr.arpa ip6.arpa {
        pods insecure
        fallthrough in-addr.arpa ip6.arpa
    }
    prometheus :9153
    forward . /etc/resolv.conf
    cache 30
    loop
    reload
    loadbalance
}

주요 플러그인들이 하는 일:

  • kubernetes: 쿠버네티스 API 모니터링하며 클러스터 내부 이름 해석
  • forward: 클러스터 외부 도메인을 상위 DNS 서버로 전달
  • cache: DNS 응답을 30초간 캐싱해서 성능 향상
  • health/ready: 쿠버네티스 헬스체크용 엔드포인트
  • prometheus: 9153 포트에서 모니터링 메트릭 제공

DNS 문제 해결하기 - 실전 명령어

DNS 문제가 생겼을 때 유용한 명령어들을 정리해드릴게요.

1. CoreDNS 파드 상태 확인

kubectl get pods -n kube-system -l k8s-app=kube-dns

2. DNS 테스트용 파드로 직접 확인

kubectl run dnsutils --image=registry.k8s.io/e2e-test-images/jessie-dnsutils:1.3 --restart=Never -- sleep 3600
kubectl exec -it dnsutils -- nslookup kubernetes.default

정상이면 kubernetes 서비스의 ClusterIP가 나와야 해요. 타임아웃이나 SERVFAIL이 뜨면 문제가 있는 거죠.

3. CoreDNS 로그 확인

kubectl logs -n kube-system -l k8s-app=kube-dns

REFUSED, SERVFAIL, I/O timeout 같은 에러를 찾아보세요. 보통 상위 DNS 서버 문제나 네트워크 정책으로 53번 포트가 막힌 경우가 많아요.

마무리하며

쿠버네티스에서 네트워킹이 고속도로라면, DNS는 내비게이션 같은 존재예요. 아무리 좋은 고속도로가 있어도 길을 모르면 소용없잖아요.

CoreDNS의 동작 원리를 이해하고 나니까, "왜 가끔 외부 API 호출이 느려지지?" 같은 궁금증도 해결되시죠? ndots 설정만 제대로 해줘도 DNS 성능이 확실히 좋아집니다.

다음에는 쿠버네티스 네트워킹의 다른 부분도 다뤄보겠습니다. 혹시 궁금한 점이 있으시면 댓글로 남겨주세요!

도움이 되셨다면 주변 개발자분들께도 공유해주시고, 구독과 좋아요도 부탁드려요! 💪

파트너스 활동으로 일정 수수료를 제공받을 수 있습니다.

#쿠버네티스#CoreDNS#DNS#네트워킹#DevOps