Dev / App

K8s Network - CoreDNS 내부 & 외부 통신 구조

K8s Network

6 min read
K8s Network - CoreDNS 내부 & 외부 통신 구조

CoreDNS

CoreDNS는 K8s 클러스터에서 DNS resolve 역할을 수행할 수 있는 DNS 서버입니다. Pod, Service의 도메인을 관리하고, 외부 도메인에 대한 서버 연결이 필요한 경우 통로로 사용됩니다.

kubectl get pod,svc,ep -n kube-system -l k8s-app=kube-dns -o wide

파드가 생성 시, Default로 DNS 질의를 사용하면, kube-dns 서비스를 기본으로 찾습니다. 실제 파드 생성 후, /etc/resolv.conf 파일 확인 시, kube-dns의 ClusterIP가 nameserver로 설정되어 있습니다.

Pod, Service의 DNS

Pod 및 Service는 CoreDNS를 통해서 도메인 접근이 가능하다고 했었습니다.
이 말을 바꿔 말하면, pod 및 Service에 할당된 IP는 가변하기에, DNS를 통해서 endpoint를 설정한다면, 불편함을 해결할 수 있습니다.

Pod 및 Service의 DNS는 아래와 같은 규칙으로 생성됩니다.

•	Pod Domain: <Pod IP>.<namespace>.pod.cluster.local
•	Service Domain: <Service Name>.<namespace>.svc.cluster.local

DNS 통신 확인

실습 파드 생성

코드 보기
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: nginx
  name: nginx
spec:
  nodeName: minjun-worker1
  containers:
  - image: nginx
    name: nginx
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: null
  labels:
    app: nginx
  name: nginx
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    run: nginx
  type: ClusterIP
---
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: netshoot
  name: netshoot
spec:
  nodeName: minjun-worker2
  containers:
  - image: nicolaka/netshoot
    name: netshoot
    args: ["sleep", "infinty"]
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
    
kubectl exec -it netshoot -- zsh
curl nginx.default.svc.cluster.local
curl nginx.default
curl nginx

ClusterIP를 모르는 상태에서, DNS만으로도 통신이 됨을 확인 가능합니다.

DNS만으로 어떻게 통신이 가능한가?
-> CoreDNS가 nginx라는 Service 이름을 DNS로 resolve하기 때문입니다.

<통신 과정>

  1. netshoot pod에서 curl
  2. CoreDNS가 Service name: nginx의 도메인에 대해서 ClusterIP로 변환(resolve)

예를 들어, curl http://nginx 인 경우 아래와 같은 순서로 조회하며, 조회된 DNS 명이 ClusterIP로 resolve됩니다.
- 1. nginx.default.svc.cluster.local
- 2. nginx.svc.cluster.local
- 3. nginx.cluster.local

  1. Service name: nginx라는 이름으로 클러스터 내부에서 Pod IP로 트래픽을 전달

즉, 같은 네임스페이스(default)에 있는 Service라면 이름만(nginx)으로도 접근이 가능한 구조입니다.

참고: netshoot에 설정된 resolve의 nameserver IP는 CoreDNS의 Service IP입니다.
즉, Pod 내부에서의 모든 DNS 요청은 해당 ClusterIP로 전달되고, 이 IP는 실제로 CoreDNS가 백엔드단에서 처리합니다.

만약, DNS가 아닌 IP 접근이라면?

위와 같이 nginx에 대한 접근이 DNS가 아니라, IP:Port를 통한 접근이라면 CoreDNS는 필요하지 않습니다.
DNS의 핵심은 "Name Resolve"입니다.
CoreDNS는 오직 nginx라는 Service name을 ClusterIP로 변환하는 역할을 합니다.

이미 ClusterIP를 알거나, Node의 IP:Nodeport 혹은 LB IP로 직접 요청하면 DNS 해석이 필요하지 않는 것입니다.

내용 정리

  1. netshoot > coredns로 도메인을 IP로 해석하기 위해 DNS 쿼리 요청
  2. CoreDNS Pod가 도메인을 해석하여 IP로 변경
  3. 해당 내용을 netshoot pod로 전달
  4. ClusterIP를 아는 netshoot는 nginx Service의 ClusterIP로 요청을 보냄

요청을 받은 nginx pod는 curl에 대해 응답

외부 DNS 통신

CoreDNS는 외부 DNS 통신 시에도 활용된다고 언급했었습니다.
default 값으로 Pod는 CoreDNS를 바라보며, 모든 DNS 쿼리 요청은 CoreDNS로 전달됩니다.

  1. netshoot > CoreDNS 요청
  1. CoreDNS Service > CoreDNS Pod
  1. CoreDNS > 외부 DNS서버로 포워딩
  1. 외부 DNS > CoreDNS 응답
  1. CoreDNS > netshoot 응답
  1. netshoot > 실제 google 서버와 통신

별도 설정없이 ping 가능

위 구조가 가능한 이유?
CoreDNS는 내부 DNS 요청만 처리하는 것이 아닌, 외부 DNS 요청도 forward 플러그인을 통해 처리할 수 있도록 설정되어 있음

CoreDNS 설정 파일

kubectl -n kube-system describe configmap coredns

Share This Post

Check out these related posts

개발팀의 애자일 도입 이야기2

개발팀의 애자일 도입 이야기 1

Lambda@Edge 고급 로깅 제어 기능