Kubernetes 이야기

Kubernetes에서 NodeLocal DNSCache 사용 본문

Kubernetes/일반

Kubernetes에서 NodeLocal DNSCache 사용

kmaster 2022. 9. 6. 09:16
반응형

기본적으로 Pod는 kube-dns 서비스에 쿼리를 보냅니다 . Pod의 /etc/resolv.conf 에 nameserver가 자동으로 세팅된다.

# cat /etc/resolv.conf
search test.svc.cluster.local svc.cluster.local cluster.local
nameserver 10.96.0.10
options ndots:5

 

Kubernetes 클러스터에서 DNS를 구현하는 가장 일반적인 방법은 서비스 추상화를 사용하는 것이다. 기본적으로 서비스 추상화는 DNAT를 사용하여 Service ClusterIP로 들어오는 요청을 DNS Pod로 균형을 맞추는 iptables 규칙 집합이다. 이 메커니즘은 conntrack 모듈을 사용하여 커널에서 처리된다.

 

Linux 커널 conntrack 모듈은 동일한 소켓을 통해 동시에 다른 스레드에서 전송된 UDP 패킷은 영향을 받는다.  경쟁이 발생하면 UDP 패킷이 삭제되고 결과적으로 호스트 이름이 전혀 확인되지 않는다.

 

이러한 이유로 Kubernetes의 DNS 확인이 안정적으로 작동하지 않는 경우가 있다. 때때로 5초 후에 시간이 초과되는 경우이다. DNS 쿼리에 문제가 발생하면 올바른 애플리케이션 실행 시 시간 초과로 종료될 수 있다.

 

이러한 문제를 완화하려면 여러 가지 해결 방법이 존재하지만 이러한 문제와 기타 문제의 장기적인 완화로 Kubernetes DNS 아키텍처가 재설계되었으며 결과는 Nodelocal DNS 캐시 프로젝트 가 되었습니다.

 

NodeLocal DNSCache는 클러스터 노드에서 DaemonSet으로 DNS 캐싱 에이전트를 실행하여 클러스터 DNS 성능을 향상시킨다. 

 

'ClusterFirst' DNS 모드의 Pod는 DNS 쿼리를 위해 kube-dns에 도달한다.  이것은 kube-proxy에 의해 추가된 iptables 규칙을 통해 kube-dns/CoreDNS 끝점으로 변환된다. DNSCache에서의 Pod는 동일한 노드에서 실행되는 DNS 캐싱 에이전트에 도달하므로 iptables DNAT 규칙 및 연결 추적을 피할 수 있다. 

 

아키텍처

NodeLocal DNSCache가 활성화된 후 DNS 쿼리가 따라오는 경로는 다음과 같다.

https://kubernetes.io/docs/tasks/administer-cluster/nodelocaldns/

이 기능은 다음 단계를 사용하여 활성화할 수 있습니다.

 

# wget https://github.com/kubernetes/kubernetes/raw/master/cluster/addons/dns/nodelocaldns/nodelocaldns.yaml

이 manifest 파일에는 여러 변수가 포함되어 있다.

  • __PILLAR__LOCAL__DNS__ : NodeLocal DNSCache에 대해 선택된 로컬 수신 IP 주소
  • __PILLAR__DNS__DOMAIN__ : 클러스터 도메인을 나타내며 기본값은 cluster.local
  • __PILLAR__DNS__SERVER__ : kubectl get svc -n kube-system | grep kube-dns | awk '{ print $3 }'

다음과 같이 설정 한다.

# kubedns=`kubectl get svc kube-dns -n kube-system -o jsonpath={.spec.clusterIP}`
# domain=cluster.local
# localdns=169.254.20.10

IPTABELS 모드인 경우에는

# sed -i "s/__PILLAR__LOCAL__DNS__/$localdns/g; s/__PILLAR__DNS__DOMAIN__/$domain/g; s/__PILLAR__DNS__SERVER__/$kubedns/g" nodelocaldns.yaml

IPVS 모드인 경우에는

# sed -i "s/__PILLAR__LOCAL__DNS__/$localdns/g; s/__PILLAR__DNS__DOMAIN__/$domain/g; s/,__PILLAR__DNS__SERVER__//g; s/__PILLAR__CLUSTER__DNS__/$kubedns/g" nodelocaldns.yaml
IPVS 모드에서 kube-proxy를 사용하는 경우 NodeLocal DNSCache가 수신 대기 중인 <node-local-address>를 사용하도록 kubelet에 대한 --cluster-dns 플래그를 수정해야 한다. 그렇지 않으면 NodeLocal DNSCache가 kube-dns 서비스 IP와 <node-local-address>를 모두 수신하므로 --cluster-dns 플래그 값을 수정할 필요가 없다.

 

nodelocaldns.yaml 을 이제 클러스터에 배포하자.

# kubectl create -f nodelocaldns.yaml

 

설치가 완료되면 다음과 같은 pod가 생성된다.

# k get pods -n kube-system | grep node-local
node-local-dns-2fncz                       1/1     Running   0          98s
node-local-dns-cb422                       1/1     Running   0          98s
node-local-dns-f22bq                       1/1     Running   0          98s

 

테스트

테스트 전에 local-dns 로그를 확인 전 log 를 남기도록 수정해보자. ( log 행을 추가한다. )

# kubectl -n kube-system edit configmap node-local-dns
...
apiVersion: v1
data:
Corefile: |
cluster.local:53 {
  log
  errors
  cache {
    success 9984 30
    denial 9984 5
  }
...

수정 후 daemonset을 다시 rollout한다.

# kubectl rollout restart daemonset -n kube-system node-local-dns

 

이제 다음의 Pod를 실행한다.

# kubectl apply -f https://k8s.io/examples/admin/dns/dnsutils.yaml
# kubectl get pods dnsutils
NAME       READY   STATUS    RESTARTS   AGE
dnsutils   1/1     Running   0          60s

Pod에 접속하여 쿼리를 실행하자.

# k exec -it dnsutils -- /bin/sh

# dig +short @169.254.20.10 www.com
96.126.123.244
45.33.18.44
45.56.79.23
72.14.178.174
198.58.118.167
45.33.23.183
45.33.30.197
45.33.20.235
72.14.185.43
45.33.2.79
173.255.194.134
45.79.19.196
# dig +short @10.96.0.10 example.com
93.184.216.34

# nslookup kubernetes.default
Server:         10.96.0.10
Address:        10.96.0.10#53

Name:   kubernetes.default.svc.cluster.local
Address: 10.96.0.1

 

로그확인

# kubectl logs --namespace=kube-system -l k8s-app=node-local-dns -f
[INFO] 192.168.104.18:51908 - 32462 "A IN kubernetes.default.default.svc.cluster.local. udp 62 false 512" NXDOMAIN qr,aa,rd 155 0.001029601s
[INFO] 192.168.104.18:59100 - 39531 "A IN kubernetes.default.svc.cluster.local. udp 54 false 512" NOERROR qr,aa,rd 106 0.000509834s

 

LocalDNS 삭제

# kubectl delete -f nodelocaldns.yaml

 

참고

https://kubernetes.io/docs/tasks/administer-cluster/nodelocaldns/

https://www.sobyte.net/post/2021-11/use-nodelocal-dns-cache/

 

반응형

'Kubernetes > 일반' 카테고리의 다른 글

kubectl 활용 팁  (0) 2022.09.11
Kubernetes EndpointSlices  (0) 2022.09.06
Finalizers, ownerReferences  (0) 2022.08.30
Pod에서 tcpdump 패킷 캡처  (0) 2022.08.28
Pod 생성 시 FailedMount : no space left on device 오류  (0) 2022.08.23
Comments