Kubernetes에서 ndots와 search 설정은 DNS 동작 방식을 결정짓는 중요한 요소입니다. 적절한 ndots 값을 설정하지 않으면 불필요한 DNS 요청이 증가하거나, 외부 도메인 접근에 문제가 발생할 수 있습니다.
FQDN
FQDN이란?
FQDN은 Fully Qualified Domain Name의 약자로, 특정 호스트를 인터넷이나 네트워크에서 고유하게 식별할 수 있는 전체적인 도메인 이름을 의미합니다. 특히, 호스트 이름과 도메인 이름이 결합된 형태로 네트워크 내에서 충돌 없이 특정 호스트를 고유하게 식별 가능한 절대 경로를 나타내는데, 주로 DNS 시스템에서 이름을 IP 주소로 변환할 때 사용됩니다.
Kubernetes에서 FQDN
<리소스 이름>.<네임스페이스 이름>.<리소스 유형 도메인>.cluster.local
Kubernetes에서 FQDN은 클러스터 내부에서 Service나 Pod와 같은 리소스를 고유하게 식별하기 위해 사용되는 전체적인 도메인 이름입니다. Kubernetes의 DNS 시스템인 CoreDNS에 의해 FQDN을 IP 주소로 변환하여 Pod, 서비스, 또는 외부 네트워크와의 통신이 가능합니다.
Service의 FQDN
my-service.default.svc.cluster.local.
- my-service: 서비스 이름
- default: 네임스페이스 이름
- svc.cluster.local: 클러스터의 기본 도메인 (이때 마지막 local뒤에 붙이는 . 은 생략이 가능합니다.)
Pod의 FQDN
my-pod.default.pod.cluster.local.
- my-pod: Pod 이름
- default: 네임스페이스 이름
- pod.cluster.local: 클러스터의 기본 도메인(이때 마지막 local뒤에 붙이는 . 은 생략이 가능합니다.)
예시
보통 Pod의 /etc/resolv.conf 에 아래와 같은 설정이 있습니다.
nameserver 10.96.0.10
search ingress-controller.svc.cluster.local svc.cluster.local cluster.local ap-northeast-2.compute.internal
options ndots:5
myservice를 조회한다고 한다면, 질의한 내용의 ndots의 갯수를 먼저 파악하여 설정되어있는 ndots의 갯수보다 작을 경우 Kubernetes에서는 search 도메인을 붙여 순차적으로 확인합니다.
1. my-service.ingress-controller.svc.cluster.local -> 질의 실패
2. my-service.svc.cluster.local cluster.local -> 질의 실패
3. my-service.cluster.local -> 질의 실패
4. my-service.ap-northeast-2.compute.internal -> 질의 실패
5. my-service -> 질의 성공
위의 순서로 dns resolve가 성공할때까지 dns 질의를 진행합니다. 하지만 질의하는 도메인에 . 이 설정되어있는 ndots의 갯수보다 많을 경우 FQDN으로 간주하고 그대로 DNS 질의를 합니다.
또 다른 예시로 DNS 설정은 위와 같고, default namespace에 떠있는 test-svc에 접근하려고 한다면 어떻게 될까요?
test-svc.default.svc.cluster.local.
이 경우 질의하는 도메인의 . 의 개수가 5개이므로 설정되어있는 ndots의 갯수와 같기 때문에 보다 FQDN으로 간주되어 search 검색을 하지 않고 바로 질의하게 됩니다.
1. test-svc.default.svc.cluster.local. -> 한번에 질의 성공
Search
Search란?
search는 Short Name으로 간주된 DNS 이름 뒤에 자동으로 추가되는 도메인으로 /etc/resolv.conf의 search 항목에 정의된 도메인 리스트를 순차적으로 확인하며 DNS 질의를 수행합니다.
동작 방식
1. 사용자가 Short Name으로 DNS 질의를 시도합니다.
2. DNS 해석 과정(ndots 추론등)에서 /etc/resolv.conf의 search 도메인을 이름 뒤에 추가합니다.
3. 각 search 도메인을 추가한 이름으로 순차적으로 DNS 서버에 질의를 보냅니다.
4. DNS 질의가 성공하면 질의가 종료되며, 실패 시 다음 search 도메인을 사용하여 추가 질의를 합니다.
예시
nameserver 10.96.0.10
search ingress-controller.svc.cluster.local svc.cluster.local cluster.local
options ndots:5
my-service로 질의 시 ndots(5) 기준에서 Short Name으로 간주됩니다. 그렇기에 search 도메인을 아래와 같이 순차적으로 추가하며 DNS 질의를 합니다.
1. my-service.ingress-controller.svc.cluster.local → 실패 -> 다음 serach 도메인 추가하여 추가 질의
2. my-service.svc.cluster.local → 실패 -> 다음 serach 도메인 추가하여 추가 질의
3. my-service.cluster.local → 실패 -> 다음 serach 도메인 추가하여 추가 질의
4. my-service → 성공 -> 질의 종료
Ndots
위의 예시에서 살펴본 것 처럼 도메인 질의시에 . 의 갯수가 중요했는데요. . 은 무엇일까요?
Ndots이란?
ndots은 DNS 검색 동작과 관련된 설정으로, DNS 쿼리 이름을 FQDN으로 간주할지에 대한 판단하는 기준을 설정하는 옵션입니다. 이 설정은 Pod의 /etc/resolv.conf 파일의 options 항목에서 사용되며, 이름에 포함된 점(.)의 개수를 기준으로 DNS 쿼리 처리가 결정됩니다.
Kubernetes에서는 기본적으로 ndots 은5로 설정되며, DNS 이름에 점이 5개 이상 포함되어 있으면 FQDN으로 간주하고, 검색 도메인(search domain)을 붙이지 않습니다.
예시
nameserver 10.96.0.10
search ingress-controller.svc.cluster.local svc.cluster.local cluster.local ap-northeast-2.compute.internal
options ndots:5
ndots < 5
my-service을 질의한다고 하면 해당 도메인에 . 이 포함되지 않기에 ndots은 5보다 작기 때문에 위의 FQDN의 예시처럼 순차적으로 search 도메인을 붙여 확인합니다.
1. my-service.ingress-controller.svc.cluster.local -> 질의 실패
2. my-service.svc.cluster.local -> 질의 실패
3. my-service.cluster.local -> 질의 실패
4. my-service.ap-northeast-2.compute.internal -> 질의 실패
5. my-service. -> 질의 성공
ndots >=5
test-svc.test-ns.svc.cluster.local. 을 질의할 때에 . 의 개수가 이미 5개 이상이기에 kubernetes에서는 FQDN으로 간주되어 search 도메인을 추가하지 않고 바로 질의합니다.
ndots을 5 이하로 낮추었을 때의 동작
위에서 보신바와 같이 kubernetes에서는 ndots을 기본으로 5로 설정하고 있습니다. 이 경우 불필요한 DNS 요청이 증가하여 서비스에 영향일 미칠 수 있는데요. 만약, ndots을 조정한다면 어떻게 될까요?
ndots(0)
모든 도메인 요청을 Short Name으로 간주하며, 항상 search 도메인을 붙여가며 쿼리를 시도합니다.
-> 이때 동작에 문제가 발생합니다. FQDN으로 접근해야 할 경우에도 search 도메인이 붙기 때문에, 외부 DNS를 사용할 경우 오류가 발생하거나 성능이 저하됩니다.
예를 들어, my-service.example.com 을 조회하려고 하면 모든 경우에 search 도메인이 붙기 때문에 아래의 순서대로 쿼리를 시도합니다.
1. my-service.example.com.ingress-controller.svc.cluster.local. -> 실패
2. my-service.example.com.svc.cluster.local. -> 실패
3. my-service.example.com.cluster.local. -> 실패
4. my-service.example.com.ap-northeast-2.compute.internal. -> 질의실패
5. my-service.example.com. -> 질의 성공
이처럼 외부 DNS를 사용할 때 성능 저하가 발생할 수 있습니다.
ndots(1)
. 이 0개인 이름만 Short Name으로 간주하기에 . 이 하나라도 있으면 FQDN으로 처리합니다. 그렇기에 같은 네임스페이스의 서비스 접근할 때에는 정상적으로 동작하지만, 다른 네임스페이스 접근할 때에는 FQDN을 사용하지 않으면 동작하지 않습니다.
같은 네임스페이스에서 my-service 질의
my-service에는 . 이 없으므로 Short Name으로 간주되어, 아래처럼 search 도메인이 순차적으로 붙으며 DNS 질의를 시도합니다.
1. my-service.ingress-controller.svc.cluster.local -> 실패
2. my-service.svc.cluster.local -> 실패
3. my-service.cluster.local -> 실패
4. my-service.ap-northeast-2.compute.internal -> 실패
5. my-service -> 질의 성공
다른 네임스페이스에서 my-service.namespace.svc.cluster.local로 질의
my-service.namespace.svc.cluster.local에는 . 이 1개 이상 포함되어 있으므로 FQDN으로 간주되어 search 도메인이 추가되지 않고 바로 DNS 질의를 시도합니다.
1. my-service.namespace.svc.cluster.local -> 질의 성공
다른 네임스페이스에서 my-service.namespace 으로 질의
my-service.namespace.svc에는 . 이 2개 포함되어 있으므로 FQDN으로 간주되어 search 도메인을 추가하지 않고 바로 DNS 질의를 시도합니다. 하지만 my-service.namespace.svc은 완전한 FQDN이 아니기에 질의에 실패하게 됩니다.
1. my-service.namespace -> 질의 실패
ndots(2)
. 이 1개 이하인 이름만 Short Name으로 간주하고, 2개 이상일 경우 FQDN으로 간주되어 search 도메인을 추가하지 않고 질의합니다. 이때, 같은 네임스페이스의 경우에는 서비스 명만 사용해도 정상적으로 동작하고, 다른 네임스페이스인 경우에도 svc.namespace를 사용하기에 다른 네임스페이스 간 서비스 호출에 큰 문제가 없습니다.
같은 네임스페이스에서 my-service로 질의
my-service에는 . 이 없으므로 Short Name으로 간주되어 search 도메인이 순차적으로 붙으며 DNS 질의를 시도합니다.
1. my-service.ingress-controller.svc.cluster.local -> 실패
2. my-service.svc.cluster.local -> 실패
3. my-service.cluster.local -> 실패
4. my-service.ap-northeast-2.compute.internal -> 실패
5. my-service -> 질의 성공
다른 네임스페이스에서 my-service.namespace.svc.cluster.local로 질의
my-service.svc.cluster.local에는 . 이 2개 이상 포함되어 있으므로 FQDN으로 간주되어 search 도메인이 추가되지 않고 바로 DNS 질의를 시도합니다.
1. my-service.namespace.svc.cluster.local -> 질의 성공
다른 네임스페이스에서 my-service.namespace 으로 질의
my-service.namespace에는 . 이 1개 포함되어 있으므로 Short Name으로 간주되어 search 도메인이 순차적으로 붙으며 DNS 질의를 시도합니다.
1. my-service.namespace.ingress-controller.svc.cluster.local -> 실패
2. my-service.namespace.svc.cluster.local -> 질의 성공
ndots(3)~(5)
해당 설정은 별 차이 없습니다.
기본 ndots 실습
네트워크 테스트용 pod인 netshoot를 생성하여 dns 설정을 통해 기본 ndots에 관한 실습을 진행해보겠습니다.
실습 1 : search - myhome / ndots(0)
netshoot pod 생성
apiVersion: v1
kind: Pod
metadata:
name: netshoot
spec:
terminationGracePeriodSeconds: 0
containers:
- name: netshoot
image: nicolaka/netshoot
command:
- sleep
- "infinity"
dnsPolicy: "None"
dnsConfig:
nameservers:
- 1.1.1.1
searches:
- myhome
options:
- name: ndots
value: "0"
search로는 myhome, ndots은 0으로 설정하여 pod를 배포합니다.
DNS 설정 확인
kubectl exec -it netshoot -- cat /etc/resolv.conf
위의 명령어를 통해 netshoot pod에 접근하여 search와 ndots 설정을 확인해 보겠습니다.
위에서 설정한대로 search는 myhome으로, nameserver는 1.1.1.1, ndots는 0으로 설정되어 있습니다.
UDP Port 53 패킷 모니터링
kubectl exec -it netshoot -- tcpdump -nn udp port 53
새롭게 터미널을 열어서 위의 명령어를 통해 패킷 모니터링을 시작합니다.
nslookup을 활용한 DNS 쿼리 - google.com
kubectl exec -it netshoot -- nslookup google.com
google.com 도메인을 질의해 보겠습니다. 이때 ndots(0)으로 설정되어있어 바로 FQDN으로 질의를 하게 됩니다.
총 2번 응답받은 것을 확인할 수 있습니다.
패킷 모니터링에서 확인해 보면, A, AAAA 레코드 총 2번 질의한 것을 확인해 볼 수 있습니다.
nslookup을 활용한 DNS 쿼리 - google
kubectl exec -it netshoot -- nslookup -type=A google
위의 명령어로 google. 을 질의해 보겠습니다. (-type=A은 A 레코드만 질의하는 옵션입니다.)
google.으로 질의할 경우 ndots이 0으로 설정되어 있기에 그 자체로 FQDN으로 인식하여 질의가 실패하게 됩니다.
nslookup을 활용한 DNS 쿼리 - www.google.com
kubectl exec -it netshoot -- nslookup www.google.com
이번엔 www.google.com에 질의해보겠습니다.
마찬가지로 ndots(0)으로 설정되어있어 바로 FQDN으로 질의를 한 것을 확인하실 수 있습니다.
위에서 봤던 것처럼 패킷 모니터링에서 확인해 보면, A와 AAAA 레코드 총 2번 질의한 것을 확인해 볼 수 있습니다.
curl을 활용한 DNS 질의 - google
kubectl exec -it netshoot -- curl google
이번엔 nslookup이 아닌 curl로 응용 계층을 통해 google 도메인을 질의해보겠습니다.
nslookup으로 질의 했을 때와 마찬가지로 google이라는 질의를 했을 때 실패로 보입니다.
1. google.myhome -> 질의 실패
2. google -> 질의 실패
위의 순서로 질의한 것을 확인할 수 있습니다.
curl을 활용한 DNS 질의 - google.com
kubectl exec -it netshoot -- curl google.com
그렇다면 google.com이면 어떨까요?
google.com으로 정상적으로 질의했고, 응답까지 받은 것을 확인하실 수 있습니다.
dump도 살펴보면, ndots=0으로 설정되어 있기에 . 이 하나라도 포함된 이름은 FQDN으로 간주되기에 바로 google.com으로 질의한 내역들을 확인하실 수 있습니다.
실습 2 : search - come / ndots(0)
netshoot 파드 생성
apiVersion: v1
kind: Pod
metadata:
name: netshoot
spec:
terminationGracePeriodSeconds: 0
containers:
- name: netshoot
image: nicolaka/netshoot
command:
- sleep
- "infinity"
dnsPolicy: "None"
dnsConfig:
nameservers:
- 1.1.1.1
searches:
- com
options:
- name: ndots
value: "0"
DNS 설정 확인
kubectl exec -it netshoot -- cat /etc/resolv.conf
위의 명령어로 netshoot pod의 dns 설정을 확인해 보겠습니다.
이번엔 search는 com으로, nameserver는 1.1.1.1, ndots는 0으로 설정되어 있습니다.
UDP Port 53 패킷 모니터링
kubectl exec -it netshoot -- tcpdump -nn udp port 53
마찬가지로 새로운 터미널을 열어서 UDP Port 53 패킷 모니터링을 시작합니다.
nslookup을 활용한 DNS 쿼리 - google
kubectl exec -it netshoot -- nslookup google
위 명령어를 통해 netshoot pod에서 google에 대해 질의를 해보겠습니다.
질의에 실패한 것을 확인하실 수 있습니다.
dump에서도 마찬가지로 실패한 내용을 확인하실 수 있습니다.
nslookup을 활용한 DNS 쿼리 - google.com
kubectl exec -it netshoot -- nslookup google.com
이번엔 google.com으로 질의해 보겠습니다.
성공적으로 질의한 것을 확인할 수 있습니다.
dump에서도 마찬가지로 google.com으로 질의한 내용들을 확인할 수 있습니다.
curl을 활용한 DNS 질의 - google
kubectl exec -it netshoot -- curl google
search 옵션을 확인해 보기 위해 curl로 google에 질의해 보겠습니다.
오! 이번엔 응답이 정상적으로 온 것을 확인할 수 있습니다.
dump 내용을 확인해 보면 dns 설정에서 search가 com으로 설정되어 있기에 goole로 질의하면 goog.com. 가 먼저 조회되어 성공적으로 질의가 되었기에 google. 도메인 질의는 수행하지 않았습니다!
실습 3 : search - myhome+com / ndots(1)
pod 생성
apiVersion: v1
kind: Pod
metadata:
name: netshoot
spec:
terminationGracePeriodSeconds: 0
containers:
- name: netshoot
image: nicolaka/netshoot
command:
- sleep
- "infinity"
dnsPolicy: "None"
dnsConfig:
nameservers:
- 1.1.1.1
searches:
- myhome
- com
options:
- name: ndots
value: "1"
search로 myhome, com을 설정하고 ndots는 1로 설정한 pod를 배포합니다.
DNS 설정 확인
kubectl exec -it netshoot -- cat /etc/resolv.conf
netshoot pod로 접속하여 dns 설정을 확인합니다.
설정한 대로 search는 myhome과 com으로 설정되어 있고, ndots은 1로 설정된 것을 확인할 수 있습니다.
UDP Port 53 패킷 모니터링
kubectl exec -it netshoot -- tcpdump -nn udp port 53
마찬가지로 새로운 터미널을 열어서 UDP Port 53 패킷 모니터링을 시작합니다.
nslookup을 활용한 DNS 쿼리 - google
kubectl exec -it netshoot -- nslookup google
위의 명령어를 통해 google로 질의해 보겠습니다. 이전과 다른 점은 1로 설정되어 있는 ndots의 기준보다 작기에 search 옵션을 통해 질의하게 됩니다.
정상적으로 질의가 된 것을 확인할 수 있습니다.
dump를 확인해 보면 아래의 순서대로 질의한 것을 확인할 수 있습니다.
1. google.myhome. -> 질의 실패
2. google.com. -> 질의 성공
그렇기에 2번 만에 질의된 것을 확인할 수 있습니다.
curl을 활용한 DNS 질의 - google
kubectl exec -it netshoot -- curl www.google
ndots을 0으로 설정했을 때와는 다르게 1로 설정했을 경우 쿼리 도메인으로 먼저 질의 후 실패 시, search 도메인을 사용하게 됩니다.
질의는 성공한 것으로 확인됩니다. (중요한 건 dump!)
위에서 설명한 대로 ndots을 1로 설정하게 되면 질의한 쿼리부터 조회를 시작합니다.
1. www.google. -> 질의 실패
2. www.google.myhome. -> 질의 실패
3. www.google.com. -> 질의 성공
실습 4 : search-myhome + com/ ndots(2)
pod 생성
apiVersion: v1
kind: Pod
metadata:
name: netshoot
spec:
terminationGracePeriodSeconds: 0
containers:
- name: netshoot
image: nicolaka/netshoot
command:
- sleep
- "infinity"
dnsPolicy: "None"
dnsConfig:
nameservers:
- 1.1.1.1
searches:
- myhome
- co.kr
options:
- name: ndots
value: "2"
이번엔 search를 myhome, co.kr로 설정하고, ndots를 2로 설정한 netshoot pod를 배포해 보겠습니다.
DNS 설정 확인
kubectl exec -it netshoot -- cat /etc/resolv.conf
위의 명령어로 netshoot pod의 dns 설정을 확인해 보겠습니다.
이번엔 search는 myhome과 co.kr로 설정되었고, nameserver는 1.1.1.1, ndots는 2로 설정되어 있습니다.
UDP Port 53 패킷 모니터링
kubectl exec -it netshoot -- tcpdump -nn udp port 53
새로운 터미널을 열어서 UDP Port 53 패킷 모니터링을 시작합니다.
nslookup을 활용한 DNS 쿼리 - google
kubectl exec -it netshoot -- nslookup google
위의 명령어대로 google을 질의하게 되면 ndots(2) 만족하지 못하여 search 옵션을 통해 질의하게 됩니다.
질의는 성공한 것으로 보이는 데 왜 성공했는지 알기 위해 dump를 확인해 보겠습니다.
아래의 순서대로 질의한 것을 확인할 수 있습니다.
1. google.myhome. -> 질의 실패
2. google.co.kr. -> 질의 성공
nslookup을 활용한 DNS 쿼리 - google.co.kr
kubectl exec -it netshoot -- nslookup google.co.kr
google.co.kr로 질의하게 되면 어떻게 될까요?
google.co.kr로 질의하게 되면 ndots(2)를 만족하기에 질의한 google.co.kr로 질의하게 됩니다.
dump를 확인해 봐도 google.co.kr로 바로 질의한 것을 확인할 수 있습니다.
curl을 활용한 DNS 질의 - a.b.c
kubectl exec -it netshoot -- curl a.b.c
a.b.c를 curl로 질의해 보겠습니다.
정상적으로 질의가 이루어졌습니다.
1. a.b.c. -> 질의 실패
2. a.b.c.myhome. -> 질의 실패
3.a.b.c.co.kr -> 질의 성공
위 순서로 질의하여 a.b.c.co.kr로 질의가 성공한 것을 확인할 수 있습니다. (아래의 이미지가 호출된 사진입니다.)
Kubernetes search 기준 실습
해당 실습부터는 local에 kind를 통해 kubernetes cluster를 배포해서 진행해보겠습니다.
전체적인 실습 아키텍처는 위와 같습니다.
ndots값을 1와 2로 설정한 netshoot pod를 배포하여 같은 namespace내에 svc에 질의해보고, 다른 namespace의 svc에 질의해보고 마지막으로 외부 도메인에 질의해보는 실습을 진행해보겠습니다.
실습 환경 구성
[default 네임스페이스] deployment와 service 배포
apiVersion: apps/v1
kind: Deployment
metadata:
name: websrv
spec:
replicas: 2
selector:
matchLabels:
app: deploy-websrv
template:
metadata:
labels:
app: deploy-websrv
spec:
terminationGracePeriodSeconds: 0
containers:
- name: deploy-websrv
image: nginx:alpine
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: websrv
spec:
ports:
- name: svc-webport
port: 80
targetPort: 80
selector:
app: deploy-websrv
type: ClusterIP
위와 같이 default namespace에 deployment와 service를 배포합니다.
정상적으로 배포된 것을 확인합니다.
기본 DNS 정보 확인
kubectl exec -it deploy/websrv -- cat /etc/resolv.conf
위의 명령어를 통해 기본 DNS 정보를 확인해보겠습니다.
따로 설정해주지 않았기 때문에 kubernetes의 기본 DNS 설정인 search와 ndots(5)으로 구성되어 있는 것을 확인할 수 있습니다.
[mydev 네임스페이스] namespace와 deployment, service 배포
kubectl create ns mydev
먼저 mydev namespace를 생성해줍니다.
cat <<EOF | kubectl create -f - -n mydev
apiVersion: apps/v1
kind: Deployment
metadata:
name: websrv
spec:
replicas: 2
selector:
matchLabels:
app: deploy-websrv
template:
metadata:
labels:
app: deploy-websrv
spec:
terminationGracePeriodSeconds: 0
containers:
- name: deploy-websrv
image: nginx:alpine
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: websrv
spec:
ports:
- name: svc-webport
port: 80
targetPort: 80
selector:
app: deploy-websrv
type: ClusterIP
EOF
그 후 mydev namespace에 deployment와 service를 배포합니다.
위와 같이 정상적으로 배포된 것을 확인하실 수 있습니다.
coredns 수정
kubectl edit cm -n kube-system coredns
원활한 실습을 위해 로그 설정하고, AAAA(IPv6 도메인) 응답하지 않게 설정합니다.
kubectl scale deployment -n kube-system coredns --replicas 1
kubectl rollout restart deployment -n kube-system coredns
그 후 coredns replicas 1개로 축소하고 rollout restart 실행합니다.
위와 같이 정상적으로 reload된 로그를 확인하면 실습 준비 완료입니다!
실습 1 : search - k8s 기본 Search + AWS 기본 Search , ndots (1)
netshoot pod 생성
apiVersion: v1
kind: Pod
metadata:
name: netshoot
spec:
terminationGracePeriodSeconds: 0
containers:
- name: netshoot
image: nicolaka/netshoot
command:
- sleep
- "infinity"
dnsPolicy: "None"
dnsConfig:
nameservers:
- 10.96.0.10
searches:
- default.svc.cluster.local
- svc.cluster.local
- cluster.local
- ap-northeast-2.compute.internal
options:
- name: ndots
value: "1"
search 도메인에 k8s 기본 search 도메인과 aws 기본 search도메인이 설정되어있고, ndots(1)로 설정된 netshoot pod를 배포합니다.
DNS 설정 확인
kubectl exec -it netshoot -- cat /etc/resolv.conf
해당 netshoot pod의 dns 설정을 확인해보겠습니다.
설정한 대로 배포된 것을 확인하실 수 있습니다.
UDP Port 53 패킹 모니터링
kubectl exec -it netshoot -- tcpdump -nn udp port 53
새로운 터미널을 열어서 netshoot pod에 접속하여 tcpdump를 시작합니다.
동일 네임스페이스에 service 로 DNS 질의
kubectl exec -it netshoot -- nslookup websrv
service명으로만 dns 조회 해보겠습니다.
Name과 Address가 조회된것으로 보아 서버를 찾진 못했지만, 조회는 성공적으로 진행된것으로 확인됩니다.
dump의 내용을 살펴보면 질의 하는 domain에 . 이 없고, 설정된 ndots이 1이기에 FQDN으로 간주하지 않아서 search 도메인을 더하여 순차적으로 조회한 것을 확인하실 수 있습니다.
1. websrv.default.svc.cluster.local. -> 조회 성공(총 1번 질의)
동일 네임스페이스에 service.namespace로 DNS 질의
kubectl exec -it netshoot -- nslookup websrv.default
이번엔 service.namespace에 대해 dns 조회 해보겠습니다.
이번엔 조회가 실패한 것을 확인할 수 있습니다.
dump의 내용을 살펴보면 질의하는 domain에 . 이 1개 이기에 설정된 ndots에 따라 FQDN으로 간주하여 search 도메인을 더하여 조회하지 않고, 바로 조회합니다.
1. websrv.default. -> 조회 실패 (총 1번 질의)
동일 네임스페이스에 service.namespace.svc.cluster.local 로 DNS 질의
kubectl exec -it netshoot -- nslookup websrv.default.svc.cluster.local
이번엔 k8s에서 요구하는 FQDN의 조건대로 websrv.default.svc.cluster.local 로 질의해보겠습니다.
Name과 Address가 조회된것으로 보아 서버를 찾진 못했지만, 조회는 성공적으로 진행된것으로 확인됩니다.
dump의 내용을 살펴보면 질의하는 domain에 . 이 1개 이기에 설정된 ndots에 따라 FQDN으로 간주하여 search 도메인을 더하여 조회하지 않고, 바로 조회합니다.
1. websrv.default.svc.cluster.local. -> 질의 성공 (총 1번 질의)
다른 네임스페이스에 Service명으로 DNS 질의
kubectl exec -it netshoot -- nslookup websrv.mydev
이번엔 다른 네임스페이스에 배포되어있는 svc에 접근해보기 위해 websrv.mydev로 질의해보겠습니다.
조회가 실패한 것을 확인할 수 있습니다.
dump를 확인해보면 websrv.mydev는 . 이 1개 이기에 설정된 ndots(1)에 충족하여 FQDN으로 간주되어 바로 질의하게 되어 조회가 실패합니다.
1. websrv.mydec -> 질의 실패 (총 1번 질의)
다른 네임스페이스에 service.namespace.svc.cluster.local명으로 DNS 질의
kubectl exec -it netshoot -- nslookup websrv.mydev.svc.cluster.local
이번엔 FQDN의 형식으로 질의해보겠습니다.
Name과 Address가 조회된것으로 보아 서버를 찾진 못했지만, 조회는 성공적으로 진행된것으로 확인됩니다.
dump의 내용을 살펴보면 질의하는 domain에 . 이 1개 이기에 설정된 ndots에 따라 FQDN으로 간주하여 search 도메인을 더하여 조회하지 않고, 바로 조회합니다.
1. websrv.mydev.svc.cluster.local. -> 질의 성공 (총 1번 질의)
외부 DNS 쿼리
kubectl exec -it netshoot -- nslookup google.com
이번엔 외부 DNS인 google.com로 질의해보겠습니다.
Name과 Address가 조회된것으로 보아 성공적으로 진행된것으로 확인됩니다.
dump를 확인해보면 goole.com 에서 . 의 수가 ndots(1)과 같아 FQDN으로 간주하여 바로 질의하게 된 것을 확인하실 수 있습니다.
1. google.com -> 질의 성공
kubectl exec -it netshoot -- nslookup google
하지만 위와 같이 google 로 조회한다면 해당 질의에서 . 의 개수가 ndots(1)보다 작기 때문에 search 도메인을 순차적으로 더하여 질의합니다.
1. google.default.svc.cluster.local. -> 질의 실패
2. google.svc.cluster.local. -> 질의 실패
3. google.cluster.local. -> 질의 실패
4. google.ap-northeast-2.compute.internal. -> 질의 실패
5. google. -> 질의 실패 (총 5회 질의)
조회한 결과 요약 - ndots(1)
구분 | 질의 도메인 | 질의 수 | 여부 |
동일 네임스페이스 | websrv | 1 | 성공 |
동일 네임 스페이스 | websrv.default | 1 | 실패 |
동일 네임 스페이스 | websrv.default.svc.cluster.local. | 1 | 성공 |
다른 네임 스페이스 | websrv | 1 | 성공 |
다른 네임 스페이스 | websrv.mydev | 1 | 실패 |
다른 네임 스페이스 | websrv.mydev.svc.cluster.local. | 1 | 성공 |
외부 도메인 | 5 | 실패 | |
외부 도메인 | google.com | 1 | 성공 |
실습 2 : search - k8s 기본 Search + AWS 기본 Search , ndots (2)
netshoot pod 생성
apiVersion: v1
kind: Pod
metadata:
name: netshoot
spec:
terminationGracePeriodSeconds: 0
containers:
- name: netshoot
image: nicolaka/netshoot
command:
- sleep
- "infinity"
dnsConfig:
searches:
- default.svc.cluster.local
- svc.cluster.local
- cluster.local
- ap-northeast-2.compute.internal
options:
- name: ndots
value: "2"
이번 실습에서는 ndots을 2로 설정해서 배포해보겠습니다.
DNS 설정 확인
kubectl exec -it netshoot -- cat /etc/resolv.conf
netshoot pod의 DNS설정을 확인해보겠습니다.
위에서 설정한 대로 ndots이 2로 설정된것을 확인하실 수 있습니다.
UDP Port 53 패킹 모니터링
kubectl exec -it netshoot -- tcpdump -nn udp port 53
새로운 터미널을 열어서 netshoot pod에 접속하여 tcpdump를 시작합니다.
동일 네임스페이스에 service 로 DNS 질의
kubectl exec -it netshoot -- nslookup websrv
동일한 네임스페이스에 배포되어있는 srv에 접근하기 위해 service 이름만으로 질의를 해보겠습니다.
질의가 성공한 것을 확인할 수 있습니다.
해당 질의에서 . 의 개수가 0이라서 설정되어있는 ndots(2)보다 작기 때문에 search 도메인을 순차적으로 더하여 질의합니다.
1. websrv.default.svc.cluster.local. -> 질의 성공 (총 1회 질의)
동일 네임스페이스에 service.namespace 로 DNS 질의
kubectl exec -it netshoot -- nslookup websrv.default
이번엔 service.namespace로 질의를 해보겠습니다.
질의가 성공한 것을 확인할 수 있습니다.
dump를 확인해보면 해당 질의에서 . 의 개수가 1이라서 설정되어있는 ndots(2)보다 작기 때문에 search 도메인을 순차적으로 더하여 질의합니다.
1. websrv.default.default.svc.cluster.local. -> 질의 실패
2. websrv.default.svc.cluster.local. -> 질의 성공 (총 2회 질의)
동일 네임스페이스에 service.namespace.svc.cluster.local 로 DNS 질의
kubectl exec -it netshoot -- nslookup websrv.default.svc.cluster.local
이번엔 FQDN의 형식을 갖춘 도메인으로 질의를 해보겠습니다.
Name과 Address가 조회된것으로 보아 성공적으로 진행된것으로 확인됩니다.
dump를 확인해보면, 해당 질의에서 도메인의 . 개수가 설정되어있는 ndots(2)보다 크기 때문에 FQDN으로 간주하여 바로 질의합니다.
1. websrv.default.svc.cluster.local. -> 질의 성공( 총 1회 질의)
다른 네임스페이스에 service.namespace로 DNS 쿼리
kubectl exec -it netshoot -- nslookup websrv.mydev
위와 같이 websrv.mydev로 질의를 해보겠습니다.
Name과 Address가 조회된것으로 보아 성공적으로 진행된것으로 확인됩니다.
dump를 확인해보면, 해당 질의에서 . 개수가 1개 이므로 설정되어있는 ndots(2)보다 작기 때문에 search 도메인을 추가하여 순차적으로 질의합니다.
1. websrv.mydev.default.svc.cluster.local. -> 질의 실패
2. websrv.mydev.svc.cluster.local. -> 질의 성공 (총 2회 질의)
다른 네임스페이스에 service.namespace.svc.cluster.local 로 DNS 쿼리
kubectl exec -it netshoot -- nslookup websrv.mydev.svc.cluster.local
이번엔 FQDN의 형식을 갖춘 service.namespace.svc.cluster.local 로 질의해보겠습니다.
이번에도 질의는 성공했습니다.
dump를 확인해보면, 해당 질의에서 도메인의 . 개수가 설정되어있는 ndots(2)보다 크기 때문에 FQDN으로 간주하여 바로 질의합니다.
1. websrv.mydev.svc.cluster.local. -> 질의 성공 (총 1회 질의)
외부 DNS 쿼리
kubectl exec -it netshoot -- nslookup google.com
외부 도메인인 google.com 을 질의해보겠습니다.
질의는 성공적으로 진행된 것을 확인하실 수 있습니다.
dump를 확인해보면, 해당 질의에서 도메인의 . 개수가 설정되어있는 ndots(2)보다 작기 때문에 search 도메인을 추가하여 순차적으로 질의합니다.
1. google.com.default.svc.cluster.local. -> 질의 실패
2. google.com.svc.cluster.local. -> 질의 실패
3. google.com.local. -> 질의 실패
4. google.com.ap-northeast-2.compute.internal. -> 질의 실패
5. google.com -> 질의 성공 (총 5회 질의)
kubectl exec -it netshoot -- nslookup www.google.com
이번엔 www.google.com을 질의해보겠습니다.
조회가 정상적으로 진행된 것을 확인할 수 있습니다.
dump를 확인해보면, 해당 질의에서 도메인의 . 개수가 설정되어있는 ndots(2)보다 크거나 같기 때문에 FQDN으로 간주하여 바로 질의합니다.
1. www.google.com. -> 질의 성공 ( 총 1회 질의)
조회한 결과 요약 - ndots(2)
구분 | 질의 도메인 | 질의 수 | 여부 |
동일 네임스페이스 | websrv | 1 | 성공 |
동일 네임 스페이스 | websrv.default | 2 | 성공 |
동일 네임 스페이스 | websrv.default.svc.cluster.local. | 1 | 성공 |
다른 네임 스페이스 | websrv | 1 | 성공 |
다른 네임 스페이스 | websrv.mydev | 1 | 성공 |
다른 네임 스페이스 | websrv.mydev.svc.cluster.local. | 1 | 성공 |
외부 도메인 | 5 | 실패 | |
외부 도메인 | google.com | 1 | 성공 |
실습 3 : search - k8s 기본 Search + AWS 기본 Search , ndots (5)
ndots이 기본 설정과 같이 5라면 어떻게 될까요?
동일 네임스페이스에 service 로 DNS 질의
이때는 . 의 개수가 0이라서 설정되어있는 ndots(2)보다 작기 때문에 search 도메인을 순차적으로 더하여 질의합니다.
1. websrv.default.svc.cluster.local. -> 질의 성공 (총 1회 질의)
동일 네임스페이스에 service.default 로 DNS 질의
이때는 . 의 개수가 1이라서 설정되어있는 ndots(2)보다 작기 때문에 search 도메인을 순차적으로 더하여 질의합니다.
1. websrv.default.default.svc.cluster.local. -> 질의 실패
2. websrv.default.svc.cluster.local. -> 질의 성공 (총 2회 질의)
동일 네임스페이스에 service.default.svc.cluster.local 로 DNS 질의
이때는 . 의 개수가 4이라서 설정되어있는 ndots(5)보다 작기 때문에 search 도메인을 순차적으로 더하여 질의합니다.
1. websrv.default.svc.cluster.local.default.svc.cluster.local. -> 질의 실패
2. websrv.default.svc.cluster.local.svc.cluster.local. -> 질의 실패
3. websrv.default.svc.cluster.local.local. -> 질의 실패
4. websrv.default.svc.cluster.local.ap-northeast-2.compute.internal. -> 질의 실패
5. websrv.default.svc.cluster.local -> 질의 성공 (총 5회 질의)
다른 네임스페이스에 service.namespace로 DNS 쿼리
이때는 . 의 개수가 1이라서 설정되어있는 ndots(5)보다 작기 때문에 search 도메인을 순차적으로 더하여 질의합니다.
1. websrv.mydev.default.svc.cluster.local. -> 질의 실패
2. websrv.mydev.svc.cluster.local. -> 질의 성공 (총 2회 질의)
다른 네임스페이스에 service.namespace.svc.cluster.local 로 DNS 쿼리
이때도 . 의 개수가 4이라서 설정되어있는 ndots(5)보다 작기 때문에 search 도메인을 순차적으로 더하여 질의합니다.
1. websrv.mydev.svc.cluster.local.default.svc.cluster.local. -> 질의 실패
2. websrv.mydev.svc.cluster.local.svc.cluster.local. -> 질의 실패
3. websrv.mydev.svc.cluster.local.local. -> 질의 실패
4. websrv.mydev.svc.cluster.local.ap-northeast-2.compute.internal. -> 질의 실패
5. websrv.mydev.svc.cluster.local -> 질의 성공 (총 5회 질의)
조회한 결과 요약 - ndots(5)
구분 | 질의 도메인 | 질의 수 | 여부 |
동일 네임스페이스 | websrv | 1 | 성공 |
동일 네임 스페이스 | websrv.default | 2 | 성공 |
동일 네임 스페이스 | websrv.default.svc.cluster.local. | 5 | 성공 |
다른 네임 스페이스 | websrv | 1 | 성공 |
다른 네임 스페이스 | websrv.mydev | 2 | 성공 |
다른 네임 스페이스 | websrv.mydev.svc.cluster.local. | 5 | 성공 |
외부 도메인 | 5 | 성공 | |
외부 도메인 | google.com | 5 | 성공 |
정리
Kubernetes에서 FQDN은 리소스를 고유하게 식별하며, ndots 설정에 따라 DNS 이름이 FQDN인지 Short Name인지 판단하고 search 도메인을 추가해 질의 순서를 결정합니다. 이때, ndots 값이 낮으면 불필요한 DNS 요청이 증가해 성능 저하가 발생할 수 있다는 것을 실습을 통해 확인할 수 있었습니다. 워크로드가 DNS를 통해 외부 서비스에 연결하는 경우나 이미 FQDN으로 호출하고 있다면 워크로드가 불필요하게 클러스터 내에서 DNS 쿼리를 클러스터링하지 않도록 ndots를 1이나 2로 설정하는 것이 가장 좋아 보입니다.
참고
https://aws.github.io/aws-eks-best-practices/ko/scalability/docs/cluster-services/#ndot
클러스터 서비스 - EKS 모범 사례 가이드
클러스터 서비스 클러스터 서비스는 EKS 클러스터 내에서 실행되지만 사용자 워크로드는 아닙니다. 리눅스 서버를 사용하는 경우 워크로드를 지원하기 위해 NTP, syslog 및 컨테이너 런타임과 같은
aws.github.io
mac : k8s 실습 환경 구성 with kind | Notion
참고 링크
gasidaseo.notion.site
'스터디 이야기 > 25' AWS EKS' 카테고리의 다른 글
Kubestr를 활용한 Kubernetes Storage 성능 테스트 (0) | 2025.02.19 |
---|---|
AWS ECR과 EKS 연동을 통한 컨테이너 이미지 배포하기 (0) | 2025.02.09 |
AWS EKS Cluster Endpoint (Public, Private, Public+Private) (0) | 2025.02.04 |