https://youtu.be/cBUgtfXl_U8?si=dRckphcTIOBhsLJk&t=336
1. 들어가며
pod가 DNS요청을 할 때, 클라이언트가 의도하지 않는 DNS 요청을 할 때가 있습니다.
예를 들어 google.com만 DNS 요청을 했지만, 의도하지 않은 DNS요청이 여러 번 수행되었습니다.
coredns pod에서도 당연히 의도하지 않는 DNS요청을 받고 DNS응답을 줬습니다.
왜 의도하지 않는 DNS요청이 생성될까요?
2. 리눅스 리졸버의 ndots와 search
의도하지 않은 DNS요청이 생긴 이유는 dots와 search설정 때문입니다. ndots와 search설정은 pod안에서 /etc/resolv.conf파일에서 확인할 수 있습니다.
cat /etc/resolv.conf
ndots설정을 이해하려면 절대(absoulte) 도메인을 알아야합니다. 절대 도메인은 FQDN(Fully Qualified Domain Name)이라고도 불립니다. 절대 도메인은 끝에 점이 있는 도메인을 말합니다.
저희가 일상에서 도메인을 사용할 때, 도메인 끝에 점을 붙이지 않습니다. 끝에 점이 없는 도메인을 상대(relative) 도메인 또는 로컬 도메인이라고 부릅니다.
RFC문서에 써있는 것처럼 사용자가 상대 도메인을 사용하면 nslookup, curl, 웹브라우저 같은 소프트웨어가 상대 도메인을 절대 도메인 또는 FQDN으로 변경해야 합니다.
여담이지만 HTTP프로토콜이 등장하고 웹브라우저가 사용되면서 RFC표준이 어긋나기 시작했습니다. 많은 도메인이 점을 포함하지 않기 시작했습니다. 또한 localhost사용량이 많아지면서 더이상 도메인 끝에 점을 붙여야 하는 표준을 안쓰기 시작했습니다. 이러한 변화 때문에 RFC 2396에서 도메인 표준을 변경합니다. 도메인 끝에 점을 안붙여도 된다고 말이죠.
DNS서버를 자체 구축한 최신회사는 점이 없는 도메인을 인식하지 못합니다. 대표적인 예가 트위터(현재 서비스 이름: X)입니다.
다시 pod로 돌와와서 ndots설정을 살펴보겠습니다. google.com은 끝에 점이 없으므로 상대 도메인입니다. 그래서 nslookup이 상대 도메인을 절대 도메인으로 변경합니다. nslookup은 시스템 리졸버에 의존하여 상대 도메인을 절대 도메인으로 변경합니다. pod에서는 리눅스 운영체제를 많이 사용합니다. 따라서 pod는 리눅스 커널의 리졸버 설정을 따릅니다.
리눅스 리졸버는 상대 도메인 끝에 점을 붙여 절대 도메인으로 변경합니다. 예를 들어 점이 없는 google.com을 요청하면 자동으로 점이 붙습니다.
그런데 리눅스 리졸버에 만약 ndots라는 옵션이 설정되어 있으면 의도하지 않는 DNS요청을 실행합니다. ndots는 도메인에 점의 개수를 세서 ndots설정 미만이면 search도메인을 생성해서 DNS요청을 합니다.
search도메인은 /etc/resolv.conf에서 설정합니다. google.com은 점의 개수가 1개이므로 ndots설정인 5보다 작습니다. 따라서 리눅스 리졸버는 search도메인을 만들어 DNS요청을 합니다.
3. 모든 search도메인을 생성할까?
리눅스 리졸버는 모든 search도메인을 요청하지 않습니다. DNS응답결과가 있을 때까지 즉, NOERROR응답을 받을 때까지 search도메인 DNS요청을 합니다. NXDOAMIN은 DNS응답이 없다는 뜻입니다.
또는 클라이언트가 내가 요청한 도메인은 절대 도메인이라고 명시하면 됩니다. 명시하는 방법은 도메인 끝에 점을 추가하면 됩니다.
nslookup google.com.
4. 쿠버네티스 ndots 기본 설정
쿠버네티스는 ndots를 5로 기본으로 설정하고 쿠버네티스 서비스 도메인 규칙을 search도메인 후보로 사용합니다.
5. 불필요한 search도메인 DNS요청을 안하려면?
불필요한 DNS요청이 많아지면 coredns pod에 부하가 발생합니다. 그러므로 되도록이면 불필요한 DNS요청은 안해야 됩니다. ndots를 2을 하는 것이 보통인데 nginx.default와 같이 사용하는 사례를 호환하기 위해 ndots를 2로 설정합니다. EKS best practice에서도 ndots를 2로 설정합니다.
- EKS best practice 문서: https://aws.github.io/aws-eks-best-practices/scalability/docs/cluster-services/#scale-coredns
쿠버네티스에서는 dnsConfig설정으로 ndots를 변경할 수 있습니다.
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
dnsConfig:
options:
- name: ndots
value: "2"
Pod개수가 많아지면 일일이 설정하기 어려우니 Admission controller의 mutation기능을 활용하는 방법도 있습니다.
참고자료
- kubedns 명세: https://github.com/kubernetes/dns/blob/master/docs/specification.md
- kubernetes dns 호출방법: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/
- kubernetes에서 추천하는 kubedns pod: https://kubernetes.io/docs/tasks/access-application-cluster/configure-dns-cluster/
- kubeadm에서 coredns를 어떻게 설치할까?: https://coredns.io/plugins/kubernetes/
- coredns kubernetes syntax: https://coredns.io/plugins/kubernetes/
- dns 서비스 사용자 정의하기: https://kubernetes.io/ko/docs/tasks/administer-cluster/dns-custom-nameservers/
- RFC문서: https://www.ietf.org/rfc/rfc1034.txt
- trailing dot 인증서 문제: https://superuser.com/questions/1467958/why-does-putting-a-dot-after-the-url-remove-login-information
- medium: https://medium.com/yavar/understanding-absolute-and-relative-domain-names-in-dns-ff431f662c76
- RFC문서에서 trailling dot 기준을 변경된 이유: https://webmasters.stackexchange.com/questions/73989/how-should-websites-handle-hostname-with-trailing-dot
- strace curl: https://serverfault.com/questions/335359/how-is-it-possible-that-i-can-do-a-host-lookup-but-not-a-curl
- man resolv.conf: https://man7.org/linux/man-pages/man5/resolv.conf.5.html
- EKS best practice: https://aws.github.io/aws-eks-best-practices/scalability/docs/cluster-services/#scale-coredns
이하여백
'전공영역 공부 기록' 카테고리의 다른 글
ssh키쌍으로 데이터 암호화, 복호화 (2) | 2024.07.28 |
---|---|
Ansible mysql 플러그인을 잘못 사용해서 발생한 오류 (0) | 2024.07.26 |
쿠버네티스에서 DNS주소 끝에 cluster.local이 붙는 이유 (0) | 2024.07.20 |
ansible playbook에서 AWS Secret 값을 가져오는 방법 (0) | 2024.07.16 |
harbor저장소에 docker login할 때 발생하는 오류 (0) | 2024.07.16 |