NodeLocalDNS
NodeLocalDNS란?
NodeLocal DNSCache는 Kubernetes 클러스터의 각 Node에서 DNS 캐싱 기능을 수행하는 Agent를 DaemonSet으로 실행하여 DNS 성능과 안정성을 개선하는 기능입니다. 기존 아키텍처에서는 모든 DNS 쿼리가 kube-dns/CoreDNS의 Service IP를 통해 전달되는데, 이는 kube-proxy에 의해 추가된 iptables DNAT 규칙을 거쳐 최종적으로 kube-dns/CoreDNS 엔드포인트로 변환되었습니다. 하지만 이러한 방식은 경로가 복잡하고 트래픽에 대해 추적을 할 때나 디버깅할 때 매우 복잡하고 네트워크 복잡도가 높아 성능상 비효율적입니다.
NodeLocal DNSCache는 각 Node에 위치한 로컬 DNS 캐시 Agent가 DNS 요청을 직접 수신함으로써 이러한 경로를 우회하게 합니다. 이를 통해 iptables을 생략하고, 네트워크 지연을 줄이며, DNS 트래픽의 추적 및 분석을 단순화할 수 있어 전체 DNS 성능을 향상시킵니다.
실습
실습 환경 구성
실습 환경 소개
vagrant를 통해 k8s-ctr, k8s-w1, router로 총 3개의 실습 환경을 구성합니다.
이때, router는 loop1/loop2 dump 인터페이스 배치되고, 사내망 10.10.0.0/16대역과 통신하며, kubernetes cluster에 join 되지 않은 서버입니다. 추가로 cilium이 배포되어있는 환경입니다.
NodeLocalDNS 설치
iptables 확인
iptables-save | tee before.txt
현재 iptables를 확인해보겠습니다.
상당히 복잡한 것을 알 수 있습니다.
nodelocaldns.yaml 다운로드
wget https://github.com/kubernetes/kubernetes/raw/master/cluster/addons/dns/nodelocaldns/nodelocaldns.yaml
NodeLocal DNSCache의 DaemonSet 구성 파일을 다운로드합니다.
환경 변수 지정 및 확인
kubedns=`kubectl get svc kube-dns -n kube-system -o jsonpath={.spec.clusterIP}`
domain='cluster.local' ## default 값
localdns='169.254.20.10' ## default 값
NodeLocal DNSCache는 DNS 쿼리 캐시 실패시에 kube-dns/CoreDNS 서비스의 IP로 쿼리를 포워딩하기 때문에 해당 값을 변수로 지정하고, Cluster의 기본 DNS 도메인(cluster.local)과 로컬 DNS 캐시가 사용할 IP(169.254.20.10)를 환경 변수로 지정합니다.
echo $kubedns $domain $localdns
지정된 환경 변수를 확인해보겠습니다.
nodelocaldns.yaml 수정
sed -i "s/__PILLAR__LOCAL__DNS__/$localdns/g; s/__PILLAR__DNS__DOMAIN__/$domain/g; s/__PILLAR__DNS__SERVER__/$kubedns/g" nodelocaldns.yaml
iptables 모드 사용 중으로 위 명령어를 통해 nodelocaldns.yaml 파일 내의 플레이스홀더(placeholder)를 수정합니다.
__PILLAR__LOCAL__DNS__ 은 로컬 DNS 캐시 에이전트가 수신할 IP 주소로 환경 변수로 지정한 $localdns로 변경하고, __PILLAR__DNS__DOMAIN__은 클러스터 DNS 도메인으로 환경 변수로 지정한 $domain으로 변경합니다.
마지막으로 __PILLAR__DNS__SERVER__ 은 실제 kube-dns/CoreDNS 서비스의 ClusterIP인 $kubedns으로 변경합니다.
nodelocaldns 설치 및 확인
kubectl apply -f nodelocaldns.yaml
그렇게 수정한 nodelocaldns.yaml을 배포합니다.
kubectl get pod -n kube-system -l k8s-app=node-local-dns -owide
배포된 nodelocaldns 관련 pod들을 확인해보겠습니다.
2개의 node에 배포되어 있는 것을 확인하실 수 있습니다.
log 설정
kubectl edit cm -n kube-system node-local-dns
실제로 coreDNS의 활동을 확인해보기 위해 CoreDNS 설정에 로그를 추가합니다.
'cluster.local' 과 '.:53' 에 log 추가를 추가합니다.
이때, nodelocaldns pod는 2분마다 configmap을 갱신하기 때문에 재시작할 필요는 없습니다.
NodeLocalDNS 활동 확인
샘플 애플리케이션 배포
샘플 애플리케이션 배포
cat << EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: webpod
spec:
replicas: 2
selector:
matchLabels:
app: webpod
template:
metadata:
labels:
app: webpod
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- sample-app
topologyKey: "kubernetes.io/hostname"
containers:
- name: webpod
image: traefik/whoami
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: webpod
labels:
app: webpod
spec:
selector:
app: webpod
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
EOF
curl-pod 파드
cat << EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: curl-pod
labels:
app: curl
spec:
containers:
- name: curl
image: nicolaka/netshoot
command: ["tail"]
args: ["-f", "/dev/null"]
terminationGracePeriodSeconds: 0
EOF
로그 실시간 확인
kubectl -n kube-system logs -l k8s-app=kube-dns -f
kubectl -n kube-system logs -l k8s-app=node-local-dns -f
실제로 dns 질의 시 어떻게 동작하는지 확인해보기 위해 kube-dns와 node-local-dns pod에 로그를 실시간으로 확인해보겠습니다.