Kubernetes 클러스터에서 Pod와 Service가 서로를 찾는 방식과 CoreDNS, /etc/resolv.conf, ndots, Corefile, 그리고 DNS 문제를 디버깅하는 방법을 쉽게 설명합니다.
가입하기
앱 받기
가입하기

팔로우
6분 읽기
·
5일 전
71
공유
Kubernetes 클러스터 안에서 pod들이 서로를 어떻게 찾아가는지 궁금했던 적이 있나요? DNS를 처음부터 하나씩 풀어보겠습니다.
전체 크기로 이미지를 보려면 enter를 누르거나 클릭하세요

작성자 이미지
Kubernetes에는 정말 많은 구성 요소가 있습니다… 그런데도 somehow 모두가 서로를 잘 찾아갑니다. frontend pod는 backend service와 통신하고, backend는 database와 통신하며, 모든 것이 그냥 잘 돌아갑니다. 그런데 잠깐 멈춰서 이런 생각을 해본 적 있나요? pod는 실제로 트래픽을 어디로 보내야 하는지 어떻게 아는 걸까요?
답은 DNS입니다 — 정확히는 CoreDNS입니다. CoreDNS는 kube-system 네임스페이스에서 조용히 돌아가며, 모든 서비스 이름이 올바른 IP로 해석되도록 보장하는 숨은 주역입니다. 그리고 이게 내부적으로 어떻게 동작하는지 이해하고 나면, 무작위로 튀어나오는 “name resolution failed” 오류를 디버깅하는 일이 훨씬 쉬워집니다.
그럼 처음부터 차근차근 살펴봅시다.
CoreDNS는 유연한 플러그인 기반 DNS 서버이며, Kubernetes 1.13부터 기본 클러스터 DNS가 되었습니다. CoreDNS 이전에는 Kubernetes가 kube-dns를 사용했지만, 더 가볍고, 설정이 더 유연하며, 확장도 더 쉬워서 CoreDNS가 이를 대체했습니다.
CoreDNS를 Kubernetes 클러스터의 전화번호부라고 생각하면 쉽습니다. pod가 service와 통신하려고 할 때 IP 주소를 외우는 것이 아니라, CoreDNS에 “이봐, my-service가 어디 있지?”라고 묻고, CoreDNS가 올바른 IP를 돌려줍니다. 정말 그만큼 단순합니다.
CoreDNS는 보통 고가용성을 위해 두 개의 replica로 kube-system 네임스페이스 안의 Deployment로 실행됩니다. 또한 모든 pod가 DNS resolver로 사용하는 안정적인 ClusterIP를 가진 Service도 하나 두고 있는데, 보통 이름은 kube-dns입니다.
pod가 서비스 이름을 해석하려고 할 때 단계별로 어떤 일이 일어나는지 보겠습니다.
pod가 DNS 쿼리를 보냅니다 — 예를 들어 같은 네임스페이스에 있는 my-service에 도달하려고 한다고 해봅시다. 이 쿼리는 pod 내부의 /etc/resolv.conf에 설정된 DNS resolver로 전송됩니다.
resolver는 CoreDNS Service IP, 즉 kube-dns의 ClusterIP를 가리킵니다. 이 IP는 pod가 시작될 때 kubelet이 모든 pod의 /etc/resolv.conf에 자동으로 주입합니다.
CoreDNS는 쿼리를 받으면 이것이 내부 Kubernetes 이름인지 외부 도메인인지 확인합니다. 내부 이름이라면(예: my-service.default.svc.cluster.local), CoreDNS는 Kubernetes API를 사용해 Service를 조회하고 그 ClusterIP를 반환합니다.
쿼리가 외부 도메인(예: google.com)에 대한 것이라면, CoreDNS는 이를 upstream DNS 서버로 전달합니다 — 보통 클러스터 노드가 사용하도록 설정된 DNS입니다.
해석된 IP가 pod로 반환되고 연결이 성립됩니다. 이 모든 과정은 밀리초 단위로 일어납니다.
이 부분은 중요합니다. Kubernetes는 서비스에 대해 아주 명확한 DNS 네이밍 패턴을 따릅니다.
service-name.namespace.svc.cluster.local
하나씩 분해해 보겠습니다.
service-name — 생성한 Kubernetes Service의 이름입니다.
namespace — Service가 속한 네임스페이스입니다(default, kube-system 등).
svc — 이것이 Service 리소스라는 뜻입니다.
cluster.local — 기본 클러스터 도메인입니다(변경 가능하지만, 실제로는 거의 바꾸지 않습니다).
예를 들어 production 네임스페이스에 backend-api라는 서비스가 있다면, 전체 DNS 이름은 backend-api.production.svc.cluster.local이 됩니다. 그런데 여기서 재미있는 점이 있습니다. pod가 같은 네임스페이스에 있다면 그냥 backend-api만 사용해도 되고, 나머지는 Kubernetes가 알아서 처리해줍니다. 이 부분은 조금 뒤에서 더 설명하겠습니다.
마법이 시작되는 곳이 바로 여기입니다. 아무 pod에나 exec로 들어가서 /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 Service의 ClusterIP이며, 결국 CoreDNS pod들을 가리킵니다. 이 pod에서 발생하는 모든 DNS 쿼리는 먼저 여기로 갑니다.
search domains — Kubernetes가 짧은 이름 뒤에 붙이는 suffix들입니다. 그래서 my-service라고만 입력하면 Kubernetes는 먼저 my-service.default.svc.cluster.local을 시도하고, 그다음 my-service.svc.cluster.local, 이런 식으로 일치하는 항목을 찾을 때까지 계속 시도합니다. 이것이 같은 네임스페이스 안에서 짧은 이름을 사용할 수 있는 이유입니다!
이 작성자의 업데이트를 받으려면 무료로 Medium에 가입하세요.
구독
구독
더 빠른 로그인을 위해 나를 기억하기
ndots:5— 이게 은근히 중요한 부분입니다. resolver에게 “이 이름에 점이 5개보다 적으면, 절대 이름으로 취급하기 전에 먼저 search domain을 붙여서 시도하라”라고 알려줍니다. 그리고 바로 여기서 일이 흥미로워지기도 하고, 때로는 느려지기도 합니다. 이건 바로 다음에서 보겠습니다.
이건 Kubernetes DNS에서 가장 흔한 함정 중 하나인데, 대부분은 이런 일이 일어나고 있다는 사실조차 모릅니다.
ndots:5가 설정되어 있으면, pod가 api.stripe.com 같은 외부 도메인을 해석하려고 할 때(점이 2개뿐입니다), resolver는 이렇게 생각합니다. “흠, 점이 5개보다 적네, 그럼 먼저 search domain을 붙여서 시도해보자.” 그래서 실제 도메인을 시도하기도 전에 다음과 같은 쿼리들을 먼저 날립니다.
api.stripe.com.default.svc.cluster.local → NXDOMAIN
api.stripe.com.svc.cluster.local → NXDOMAIN
api.stripe.com.cluster.local → NXDOMAIN
api.stripe.com → 드디어 해석 성공! 이 말은 외부 연결 하나마다 불필요한 DNS 쿼리가 4번씩 발생한다는 뜻입니다. 이런 요청을 수백 개의 pod가 수천 번씩 만든다고 생각해 보세요. 그러면 DNS 병목이 생기는 건 순식간입니다.
어떻게 해결할까?
옵션 1: 앱 설정에서 외부 도메인 뒤에 trailing dot을 붙입니다(api.stripe.com.). 이 점은 resolver에게 이미 fully qualified domain name이므로 search domain을 건너뛰라고 알려줍니다.
**옵션 2:**pod spec의 dnsConfig에서 ndots 값을 더 낮게(예: 2) 설정합니다. 그러면 불필요한 조회를 줄이면서도 내부 서비스 디스커버리는 계속 정상적으로 동작합니다.
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에서 DNS 문제는 생각보다 훨씬 흔합니다. 문제 해결에 도움이 되는 빠른 명령 몇 가지를 소개합니다.
CoreDNS pod가 실행 중인지 확인:
여기서 핵심 플러그인들이 하는 일은 다음과 같습니다.
kubernetes— 이것이 핵심 플러그인으로, Kubernetes API를 감시하면서 클러스터 도메인(cluster.local) 내의 service/pod 이름을 해석합니다.
forward— 클러스터 도메인과 일치하지 않는 모든 항목은 upstream DNS 서버로 전달됩니다(대개 노드의 /etc/resolv.conf에 정의된 서버들).
cache — DNS 응답을 30초 동안 캐시하여 CoreDNS와 upstream 서버의 부하를 줄입니다.
health and ready— 상태 확인 endpoint를 노출하여 Kubernetes가 CoreDNS가 살아 있고 준비되었는지 알 수 있게 합니다.
loop — 무한 DNS 전달 루프를 감지하고, 그런 루프가 발견되면 CoreDNS를 종료합니다. 정말 생명줄 같은 기능입니다.
prometheus — Prometheus로 모니터링할 수 있도록 9153 포트에서 DNS 메트릭을 노출합니다.
DNS 문제 디버깅 — 빠른 명령들
kubectl get pods -n kube-system -l k8s-app=kube-dns pod 내부에서 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 만약 nslookup이 kubernetes service의 ClusterIP를 반환한다면 DNS는 정상적으로 동작하고 있는 것입니다. 반대로 timeout이 나거나 SERVFAIL을 반환한다면 뭔가 잘못된 것입니다 — 다음으로 CoreDNS pod 로그를 확인해 보세요.
CoreDNS 로그 확인:
kubectl logs -n kube-system -l k8s-app=kube-dns REFUSED, SERVFAIL, 또는 i/o timeout 같은 오류를 찾아보세요 — 이런 오류는 보통 upstream DNS 문제이거나, 53번 포트의 DNS 트래픽을 막는 network policy 문제를 가리킵니다.
기억하세요: Kubernetes에서 네트워킹이 고속도로라면, DNS는 GPS입니다. DNS가 없으면 아무것도 어디로 가야 할지 알 수 없습니다.
도움이 되었다면 clap을 눌러주시고
를 팔로우해 더 많은 Kubernetes 심화 글도 받아보세요. CoreDNS나 여러분이 겪었던 DNS 문제에 대해 질문이 있나요? 댓글로 남겨주세요 — 여러분의 생생한 경험담을 꼭 듣고 싶습니다!
다음에 또 만나요. happy resolving! 그리고 기억하세요 — pod들이 서로를 찾지 못한다면, 아마 DNS 문제일 가능성이 큽니다. 언제나 DNS죠.
71
71
팔로우
적은 노력으로 Kubernetes의 바다를 항해할 수 있도록 도와드리겠습니다
팔로우

응답 작성하기
취소
응답

작성 위치
작성자
## Kubernetes v1.36 — Sneak Peek ### Kubernetes v1.36이 곧 다가옵니다. 그리고 그 뒤에서 어떤 변화가 준비되고 있는지 소개합니다
Mar 9

작성 위치
작성자
Dec 29, 2025

작성 위치
작성자
## GKE에서 Workload Identity 이해하기 ### Workload Identity란 무엇일까?
Jul 8, 2024

작성 위치
작성자
## Kubernetes v1.35 — 설명 ### 긴 공백 끝에 Timbernetes에 대한 자세한 블로그를 가져왔습니다 🤓, 마음에 드셨으면 좋겠습니다
Dec 22, 2025

## 2026년에 DevOps 엔지니어가 되지 마세요! ### YAML 작성을 멈추세요. 파이프라인을 babysitting하는 것도 멈추세요. 게임의 판이 근본적으로 바뀌었습니다.
Mar 2
## Tesla가 얼마나 뒤처져 있는지 당신은 전혀 모릅니다 ### 도약의 순간은 이미 일어났습니다.
6일 전

작성 위치
작성자
Mar 12

작성 위치
작성자
## Kubernetes v1.36 — Sneak Peek ### Kubernetes v1.36이 곧 다가옵니다. 그리고 그 뒤에서 어떤 변화가 준비되고 있는지 소개합니다
Mar 9

작성 위치
작성자
5일 전

## AWS EKS 질문 — 프라이빗 IP에 배포된 노드들 ### 그래서 질문은 이것이었습니다:
Feb 9