Service DNS 액세스 진단

KubernetesBeginner
지금 연습하기

소개

이전 실습에서는 Service 가 Pod 에 클러스터 내부의 안정적인 진입점을 제공하는 방법을 살펴보았습니다. Kubernetes 는 각 Service 에 DNS 이름도 부여합니다. 동일한 네임스페이스에 있는 Pod 는 일반적으로 짧은 Service 이름을 사용할 수 있지만, 다른 네임스페이스에 있는 Pod 는 Service 의 네임스페이스가 포함된 더 긴 이름을 사용해야 하는 경우가 많습니다.

이번 실습에서는 웹 Service 를 생성하고, 동일 네임스페이스 내 DNS 액세스를 테스트하며, 네임스페이스 간 단축 이름 사용 실패를 재현하고, Service FQDN 을 사용하여 요청을 수정합니다. 또한 DNS 문제가 Service, 엔드포인트, 혹은 CoreDNS 중 어디에서 발생하는지 진단하는 데 도움이 되는 객체들을 검사합니다.

웹 Service 준비

이 단계에서는 이후 DNS 테스트에서 확인할 대상 Service 를 생성합니다. 이번 실습의 핵심은 DNS 명명 규칙이므로 워크로드는 간단하게 구성합니다.

/home/labex/project에서 시작합니다:

mkdir -p /home/labex/project
cd /home/labex/project

Kubernetes API 서버에 연결할 수 있는지 확인합니다. VM 이 막 시작되어 노드가 아직 준비되지 않았다면 몇 초 기다린 후 명령어를 다시 실행하세요.

kubectl get nodes --request-timeout=5s

예상 출력:

NAME         STATUS   ROLES           AGE   VERSION
labex-v135   Ready    control-plane   ...   v1.35...

클러스터 네트워킹이 준비될 때까지 기다립니다. 이 실습은 Pod 간 트래픽을 전송하므로 DNS 액세스 테스트를 수행하기 전에 Pod 네트워킹이 정상 상태여야 합니다.

kubectl wait --namespace kube-system --for=condition=Ready pod -l k8s-app=calico-node --timeout=120s

예상 출력:

pod/calico-node-... condition met

ckad-prep-dns라는 네임스페이스를 생성하고 현재 네임스페이스로 설정합니다:

kubectl create namespace ckad-prep-dns
kubectl config set-context --current --namespace=ckad-prep-dns

Deployment 를 생성하고 dns-web이라는 이름의 Service 로 노출합니다:

kubectl create deployment dns-web --image=nginx:1.25 --port=80
kubectl expose deployment dns-web --port=80 --target-port=80

웹 Pod 가 사용 가능해질 때까지 기다립니다:

kubectl rollout status deployment/dns-web --timeout=120s

Service 와 해당 EndpointSlice 를 검사합니다. Service 는 안정적인 DNS 대상이며, EndpointSlice 는 Service 가 선택한 현재 백엔드 Pod 주소를 보여줍니다.

kubectl get service dns-web
kubectl get endpointslice -l kubernetes.io/service-name=dns-web

예상 출력:

NAME      TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
dns-web   ClusterIP   ...          <none>        80/TCP    ...

NAME          ADDRESSTYPE   PORTS   ENDPOINTS   AGE
dns-web-...   IPv4          80      ...         ...

동일 네임스페이스에서 Service 확인

이 단계에서는 Service 와 동일한 네임스페이스에 클라이언트 Pod 를 생성하고 짧은 Service 이름을 사용합니다. 이는 가장 기본적인 Service DNS 사례입니다.

실행 상태를 유지하는 클라이언트 Pod 를 생성합니다:

kubectl run same-ns-client --image=busybox:1.36 --restart=Never --command -- sleep 3600

클라이언트 Pod 가 준비될 때까지 기다립니다:

kubectl wait --for=condition=Ready pod/same-ns-client --timeout=120s

예상 출력:

pod/same-ns-client condition met

클라이언트 Pod 내부에서 nslookup을 사용하여 짧은 Service 이름인 dns-web을 확인합니다. 클라이언트 Pod 와 Service 가 동일한 네임스페이스에 있으므로 짧은 이름이 작동합니다. BusyBox 의 nslookup은 다른 검색 접미사에 대해 추가적인 NXDOMAIN 라인을 출력하고 올바른 주소를 표시한 후 0 이 아닌 종료 코드를 반환할 수 있으므로, 명령어에 || true를 추가했습니다. Name 및 Address 라인을 확인하세요.

kubectl exec same-ns-client -- sh -c 'nslookup dns-web || true'

예상 출력:

Name:      dns-web.ckad-prep-dns.svc.cluster.local
Address: ...

이제 Service 의 짧은 이름으로 HTTP 요청을 보냅니다:

kubectl exec same-ns-client -- wget -qO- http://dns-web | grep '<title>Welcome to nginx'

예상 출력:

<title>Welcome to nginx!</title>

네임스페이스 간 단축 이름 실패 진단

이 단계에서는 다른 네임스페이스에 클라이언트 Pod 를 생성하여 흔히 발생하는 DNS 실수를 재현합니다. 짧은 Service 이름은 먼저 클라이언트 Pod 의 네임스페이스를 기준으로 확인되므로, 클라이언트가 다른 네임스페이스에서 실행될 때는 dns-web이 ckad-prep-dns 네임스페이스의 Service 를 찾지 못합니다.

두 번째 네임스페이스와 클라이언트 Pod 를 생성합니다:

kubectl create namespace ckad-prep-dns-client
kubectl run remote-client --namespace ckad-prep-dns-client --image=busybox:1.36 --restart=Never --command -- sleep 3600
kubectl wait --namespace ckad-prep-dns-client --for=condition=Ready pod/remote-client --timeout=120s

예상 출력:

namespace/ckad-prep-dns-client created
pod/remote-client created
pod/remote-client condition met

원격 네임스페이스에서 짧은 이름을 확인해 봅니다. 이 실패는 예상된 결과이므로 || true를 사용하여 실습을 계속 진행합니다.

kubectl exec --namespace ckad-prep-dns-client remote-client -- nslookup dns-web || true

예상 출력 (실패 메시지):

** server can't find dns-web...

이제 정규화된 Service 이름 (FQDN) 을 확인합니다. 전체 패턴은 <service>.<namespace>.svc.cluster.local입니다.

kubectl exec --namespace ckad-prep-dns-client remote-client -- nslookup dns-web.ckad-prep-dns.svc.cluster.local

예상 출력:

Name:      dns-web.ckad-prep-dns.svc.cluster.local
Address 1: ...

HTTP 액세스에도 동일한 정규화된 이름을 사용합니다:

kubectl exec --namespace ckad-prep-dns-client remote-client -- wget -qO- http://dns-web.ckad-prep-dns.svc.cluster.local | grep '<title>Welcome to nginx'

예상 출력:

<title>Welcome to nginx!</title>

DNS 문제 해결 경로 확인

이 단계에서는 DNS 명명 문제와 Service 또는 백엔드 문제를 구분하는 데 도움이 되는 객체들을 검사합니다. 실무적인 문제 해결 순서는 다음과 같습니다: Service 이름과 네임스페이스 확인, 엔드포인트 존재 여부 확인, CoreDNS 가용성 확인.

먼저, 실제 네임스페이스에서 Service 를 검사합니다:

kubectl get service dns-web --namespace ckad-prep-dns

예상 출력:

NAME      TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
dns-web   ClusterIP   ...          <none>        80/TCP    ...

다음으로, EndpointSlice 를 검사합니다. DNS 는 확인되지만 HTTP 트래픽이 실패한다면, 엔드포인트가 누락된 경우가 많습니다.

kubectl get endpointslice --namespace ckad-prep-dns -l kubernetes.io/service-name=dns-web

예상 출력 (최소 하나의 엔드포인트 포함):

NAME          ADDRESSTYPE   PORTS   ENDPOINTS   AGE
dns-web-...   IPv4          80      ...         ...

CoreDNS Pod 를 확인합니다. CoreDNS 는 Pod 의 DNS 쿼리에 응답하는 클러스터 DNS 서비스입니다.

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

예상 출력 (Running 상태의 CoreDNS Pod):

NAME                       READY   STATUS    RESTARTS   AGE
coredns-...                1/1     Running   ...        ...

마지막으로, 원격 클라이언트의 DNS 검색 설정을 검사합니다. search 라인은 전체 이름을 사용하기 전에 왜 짧은 이름 dns-web이 클라이언트 네임스페이스에서 먼저 검색되었는지 설명해 줍니다.

kubectl exec --namespace ckad-prep-dns-client remote-client -- cat /etc/resolv.conf

예상 출력 (검색 경로):

search ckad-prep-dns-client.svc.cluster.local svc.cluster.local cluster.local
nameserver ...

요약

초보자도 이해하기 쉬운 순서로 Kubernetes Service DNS 액세스를 진단하는 방법을 실습했습니다. Service 를 생성하고, 동일 네임스페이스 클라이언트가 짧은 Service 이름을 사용할 수 있음을 확인했으며, 네임스페이스 간 단축 이름 실패를 재현하고, 전체 Service DNS 이름으로 수정했습니다. 또한 Service, EndpointSlice, CoreDNS Pod 및 클라이언트 DNS 검색 경로를 검사하여 DNS 액세스 문제가 어디에서 발생하는지 파악하는 방법을 배웠습니다.