영향 Pod의 resolv.conf와 ndots·dnsPolicy, namespace별 Service 이름, kube-dns Service·EndpointSlice·CoreDNS, NetworkPolicy의 UDP/TCP 53을 순서대로 확인해 DNS 장애 범위를 안전하게 분리합니다.
Kubernetes DNS failureCoreDNS SERVFAILkube-dns timeoutService DNS NXDOMAINPod resolv.conf ndotsNetworkPolicy DNS UDP TCP 53ClusterFirstWithHostNet
NetworkPolicy를 실제로 집행하는 CNI, 영향 Pod selector와 kube-dns Pod selector를 확인하지 못했다면 egress policy를 변경하지 않습니다.
CoreDNS ConfigMap·로그에 내부 도메인이나 고객 식별자가 포함될 경우 원문 외부 공유를 중단하고 0600 증거·마스킹을 사용합니다.
kubelet resolvConf 또는 node resolver 변경이 필요하면 임의 재시작하지 않고 node drain·가용성·롤백 계획을 가진 cluster 담당자에게 이관합니다.
ROLLBACK
복구 기준
NetworkPolicy 변경은 변경 전 정책 목록과 GitOps revision을 기준으로 되돌리고 이번에 생성한 정확한 policy만 소유자 승인 후 제거합니다. CoreDNS 변경은 검증된 last-known-good manifest를 server-side dry-run·diff 후 적용합니다. node resolvConf 변경은 node drain과 kubelet 운영 절차로 이전 설정을 복원하며, CoreDNS Pod를 반복 재시작하는 방식은 rollback으로 사용하지 않습니다.
짧은 이름·namespace-qualified FQDN·외부 이름 비교 결과와 Service·kube-dns EndpointSlice
CoreDNS Pod readiness·제한 로그·Corefile checksum·RBAC, 영향 workload의 NetworkPolicy selector와 UDP/TCP 53 diff
변경 manifest revision·승인자·적용 시각과 변경 전후 동일 Pod DNS 응답
2026년 9월 4일 기준 PostgreSQL·Kubernetes·OpenSSL·NGINX·Certbot 공식 문서를 대조했습니다. 진단은 읽기 전용 명령과 최소 권한 계정으로 시작하고, 취소·세션 종료·설정 적용·reload는 대상·영향·복구 경로를 기록해 담당자가 승인한 경우에만 실행합니다. <...> 자리표시자는 검토된 리터럴 값으로 직접 치환하며 외부 입력으로 shell 명령을 조립하지 않습니다.
BEFORE YOU START
이런 증상에서 시작합니다
Pod에서 kubernetes.default 또는 같은 namespace Service 이름이 해석되지 않음
짧은 이름은 실패하지만 namespace-qualified 또는 끝에 점을 붙인 FQDN은 성공함
외부 도메인만 SERVFAIL·timeout이고 cluster.local 이름은 정상임
default-deny egress 적용 뒤 DNS가 UDP timeout 또는 TCP fallback 실패함
CHECK THE BRANCH
놓치기 쉬운 원인 분기
01
짧은 이름만 실패하는 경우
Pod namespace, search 목록과 ndots를 먼저 봅니다. 다른 namespace의 Service는 최소 service.namespace로 조회하고, FQDN 끝의 점은 search suffix 확장을 피하는 비교 기준입니다.
02
cluster.local 전체가 실패하는 경우
Pod resolv.conf의 nameserver, kube-dns Service와 EndpointSlice, CoreDNS Pod readiness·로그·RBAC 순서로 확인합니다. CoreDNS부터 재시작해 증거를 지우지 않습니다.
03
외부 이름만 실패하는 경우
CoreDNS Corefile의 forward 대상과 node resolv.conf, systemd-resolved stub loop를 확인합니다. kubelet resolvConf 변경은 node 전체 Pod에 영향을 주므로 즉시 수정하지 않습니다.
04
특정 workload·namespace만 실패하는 경우
Pod dnsPolicy·dnsConfig, hostNetwork와 NetworkPolicy 선택자를 비교합니다. egress 격리 시 DNS에 UDP와 TCP 53이 모두 필요합니다. Service ClusterIP가 endpoint Pod IP 또는 node-local 주소로 변환되는 지점은 CNI·kube-proxy·NodeLocal DNSCache 구현에 따라 달라 podSelector 규칙이 실제 DNS 경로와 맞는지 canary에서 검증해야 합니다.
FOLLOW THE FLOW
순서대로 확인하기
1
조회시스템을 변경하지 않는 확인 단계
cluster context와 영향 Pod DNS 관찰
운영 context와 namespace를 먼저 고정합니다. Pod에 진단 도구가 없다면 임의 이미지를 배포하지 말고 승인된 진단 Pod 또는 기존 workload에서 읽기 전용 명령을 실행합니다.
context·권한 확인
kubectl config current-context
kubectl auth can-i get pods -n <APP_NAMESPACE>
kubectl auth can-i get services -n kube-system
kubectl auth can-i get endpointslices.discovery.k8s.io -n kube-system
Pod DNS 정책·node
kubectl -n <APP_NAMESPACE> get pod <AFFECTED_POD> -o jsonpath='{.metadata.namespace}{"\t"}{.spec.nodeName}{"\t"}{.spec.hostNetwork}{"\t"}{.spec.dnsPolicy}{"\n"}{.spec.dnsConfig}{"\n"}'
query log plugin이 켜졌다면 내부 도메인·Pod IP가 노출될 수 있어 외부 공유 전에 마스킹합니다.
결과 읽기
Service가 없으면 이름 정의 문제, kube-dns endpoint가 없으면 addon readiness 문제, cluster FQDN은 되고 외부만 실패하면 upstream forward 문제, 특정 namespace만 실패하면 dnsPolicy·NetworkPolicy 문제일 가능성이 큽니다.
다음 판단
Corefile·RBAC·NetworkPolicy·node resolver를 변경 없이 확인합니다.
3
주의서버 부하나 권한을 고려할 단계
CoreDNS·RBAC·NetworkPolicy·node resolver 확인
ConfigMap과 policy는 읽기만 하고 secret은 조회하지 않습니다. CoreDNS query logging은 트래픽과 내부 이름을 늘릴 수 있으므로 장애 중 즉시 켜지 않습니다.
정책은 영향 Pod만 선택하고 UDP 53과 TCP 53을 모두 허용하는지 검토합니다. kube-dns podSelector만 가정하지 말고 Pod resolv.conf의 ClusterIP·node-local 주소와 CNI의 Service DNAT·NetworkPolicy 적용 지점을 공식 구현 문서로 확인합니다. 전체 egress 허용으로 우회하지 않습니다.
영향 Pod가 배치된 node에서만 실행합니다. systemd-resolved 환경의 stub 파일과 실제 /run/systemd/resolve/resolv.conf를 혼동하지 않습니다.
결과 읽기
Corefile forward 대상이 loop를 만들거나, EndpointSlice watch 권한이 없거나, default-deny가 TCP/UDP 53을 막거나, kubelet이 잘못된 node resolv.conf를 전달하는지 분리합니다.
다음 판단
원인이 확인된 분기의 검토된 manifest 하나만 적용합니다.
4
변경데이터·서비스 상태가 달라질 수 있는 단계
승인된 DNS egress 또는 CoreDNS 설정 한 가지 적용
NetworkPolicy와 CoreDNS를 동시에 바꾸지 않습니다. DNS egress 변경은 먼저 격리된 canary Pod selector에만 적용하고 UDP·TCP 53과 실제 Service 이름을 검증한 뒤 확장합니다. diff·server dry-run·소유자 승인·last-known-good manifest가 준비된 분기만 적용합니다. kubelet resolver 수정은 node drain과 재기동 계획이 필요한 별도 작업입니다.
변경 단계입니다. 실행 전 대상 이름과 경로, 서비스 중단 영향, 복구 방법을 다시 확인하세요.
Corefile에 reload plugin이 있으면 ConfigMap 변화를 감지할 수 있습니다. 임의 rollout restart로 증거를 지우지 않습니다.
결과 읽기
canary에서 podSelector 기반 규칙이 실패하면 Service ClusterIP→endpoint DNAT 또는 NodeLocal DNSCache 경로와 CNI 정책 적용 지점이 예상과 다른 것입니다. production에 확장하지 않습니다. CoreDNS 설정 적용 후 cluster-wide 응답이 회복하면 Corefile·upstream 원인입니다. rollout status만으로 DNS 성공을 판단하지 않습니다.
다음 판단
같은 영향 Pod에서 네 가지 이름 범위를 재검증하고 회귀 시 last-known-good manifest로 되돌립니다.
5
변경데이터·서비스 상태가 달라질 수 있는 단계
Pod별 DNS 재검증과 manifest 롤백
변경 전과 동일 Pod·동일 이름으로 확인하고 CoreDNS endpoint·로그 오류도 함께 봅니다. 새 Pod만 정상이라면 기존 Pod의 dnsConfig 차이와 node별 문제를 계속 조사합니다.
변경 단계입니다. 실행 전 대상 이름과 경로, 서비스 중단 영향, 복구 방법을 다시 확인하세요.
이번 변경이 CoreDNS였고 last-known-good manifest의 소유자·revision을 확인한 경우에만 실행합니다.
결과 읽기
짧은 이름, namespace-qualified FQDN, cluster 기본 Service와 외부 이름이 의도한 범위에서 모두 성공하고 CoreDNS SERVFAIL·timeout이 정상 기준으로 돌아와야 합니다.
다음 판단
NetworkPolicy는 이전 정책 집합을 적용하고 이번에 새로 만든 정확한 resource만 소유자 승인 후 제거합니다. CoreDNS는 last-known-good manifest로 원복합니다. node resolvConf는 구성 관리의 이전 값과 drain 절차로만 되돌립니다.