Profile picture

[k8s] Deep Dive - Cluster DNS

JaehyoJJAng2023년 04월 04일

Pod 특성 복습

  • Pod는 고유한 IP주소가 존재하며 일시적인 특성을 지니고 있고 불안정한 리소스이다.
  • 클라이언트 관점에서 서비스를 지원하는 Pod의 수와 IP에 상관하지 않아야 하며 모든 Pod는 단일 IP주소로 Access할 수 있어야 함.
  • 쿠버네티스는 이러한 문제점을 해결하기 위해 "Service" 라는 리소스 유형을 제공하고 있음.
  • Service는 어떤 파드가 어디에 존재하는지(또는 어떤 IP를 가지는지)에 관계 없이 Pod 앞단에서 여러 Pod 중 하나로 연결하여 요청을 처리하도록 함.
  • 서비스를 지원하는 Pod는 여러개일 수 있고, Label Selector를 통해 서비스와 연결된 Pod를 정의할 수 있음.

image


DNS를 통한 서비스 검색

Service 이름을 도메인 주소로도 사용이 가능하다. 이는 쿠버네티스에서 제공하는 DNS 서버가 있기 때문에 가능하다.

  • kube-system 네임스페이스 내부에 kube-dns 라는 파드가 존재함
  • kube-dns 파드는 DNS 서버를 실행하며, 클러스터에서 실행 중인 다른 모든 파드는 자동으로 이를 사용하도록 구성함.
    • 쿠버네티스는 각 컨테이너의 /etc/resolv.conf 파일을 수정하여 이를 수행함.
  • 파드에서 실행 중인 프로세스에서 수행된 모든 DNS 쿼리는 시스템에서 실행 중인 모든 서비스를 알고 있는 쿠버네티스의 자체 DNS 서버로 처리된다.

리눅스 시스템에서 DNS 서버 설정을 담당하는 /etc/resolv.conf 파일을 확인해보자.

# 파드 컨테이너 접속
$ kubectl exec -n default -it pod/was-fastapi-77bd9975cf-cjd9l -- /bin/bash
root@was-fastapi-77bd9975cf-cjd9l:/usr/src/app# cat /etc/resolv.conf
search default.svc.cluster.local svc.cluster.local cluster.local
nameserver 10.96.0.10
options ndots:5

네임서버에 10.96.0.10 이라는 IP를 확인할 수 있는데, 쿠버네티스의 모든 Pod들은 해당 IP로 DNS를 조회한다.
그리고 이 IP(10.96.0.10)의 주인은 바로 kube-dns 서비스의 IP 주소이다.

$ kubectl get svc kube-dns -n kube-system --show-labels
NAME       TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE   LABELS
kube-dns   ClusterIP   10.96.0.10   <none>        53/UDP,53/TCP,9153/TCP   6d    k8s-app=kube-dns,kubernetes.io/cluster-service=true,kubernetes.io/name=CoreDNS

이제, kube-app=kube-dns 라벨 정보를 이용하여 어떤 Pod들이 매핑되는지 확인해보면 CoreDNS가 매핑 되어있는 것을 확인할 수 있을 것이다.

$ kubectl -n kube-system get pods -l k8s-app=kube-dns
NAME                      READY   STATUS    RESTARTS       AGE
coredns-9d5499d77-6tg4x   1/1     Running   0              5d5h
coredns-9d5499d77-w8zj4   1/1     Running   1 (5d6h ago)   5d5h

모든 Pod들은 클러스터의 내·외부 질의를 CoreDNS를 통해 수행한다. 그렇기에 쿠버네티스 클러스터 환경 안에서 자체적인 도메인 네임 시스템을 가질 수 있는 것이다.
image


URL을 통한 서비스 접근

요청(curl) URL에서 호스트 이름으로 서비스 이름을 사용하여 서비스에 접근할 수도 있다.
Case1. 서비스가 DNS 조사하는 Pod와 같은 네임스페이스에 속한 경우

# test Service가 test 파드에 연결된 경우
$ curl http://test

# test Service가 exam 파드에 연결된 경우
$ curl http://test.exam

Case2. 서비스가 서로 다른 네임스페이스에 있는 경우

  • .
  • ..svc
  • ..svc.cluster.local
# default 네임스페이스에 속한 my-service
$ curl http://my-service.default

# 아래 명령어도 같은 출력을 나타낸다.
$ curl http://my-service.default.svc
$ curl http://my-service.default.svc.cluster.local

서비스 IP에 핑이 안되는 경우

앞에서 서비스가 어떻게 파드로 포워딩 되는지 확인할 수 있었다. 그러나 만약 서비스가 파드에 정상적으로 포워딩 되지 않는다면 어떻게 될까? 아마 일반적으로 서비스 IP로 ping을 시도하여 서비스 작동 여부를 확인해볼 것이다.

$ kubectl exec -it pod/pod-1 -c nginx -- ping pod-svc
PING pod-svc (10.109.89.148): 56 data bytes
^C
--- quiz ping statistics ---
7 packets transmitted, 0 packets received, 100% packet loss
command terminated with exit code 1

결과를 보면 알 수 있듯이 서비스로 curl은 동작하지만 응답은 받을 수 없었다. 이는 서비스의 ClusterIP가 가상 IP이기에 서비스 포트와 결합된 경우에만 의미가 있기 때문이다. 지금으로서는 서비스 IP에 ping이 불가능하다는 것만 참고하고 넘어가도록 하자.


Loading script...