✔️ Challenge
default NS에 myweb-svc 서비스를 만드시오
dev 라는 NS를 만들어서 nettool 파드를 띄우시오
그렇다면 nettool Pod(dev NS) ↔ myweb-svc SVC(default NS) 어떻게 통신할 것인가 ?
vagrant@k8s-node1 kubectl create ns dev
namespace/dev created
vagrant@k8s-node1 ~/kubespray/inventory/mycluster/group_vars/k8s_cluster ➦ e7508d7d kubectl get ns
NAME STATUS AGE
default Active 4d6h
dev Active 3d4h
kube-node-lease Active 4d6h
kube-public Active 4d6h
kube-system Active 4d6h
우선 dev NS를 생성한다.
vagrant@k8s-node1 ~/kubespray/inventory/mycluster/group_vars/k8s_cluster ➦ e7508d7d kubectl run nettool -it --image ghcr.io/c1t1d0s7/network-multitool -n dev --rm
dev NS에 nettool 파드를 띄운다.
vagrant@k8s-node1 ~ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.233.0.1 <none> 443/TCP 70m
myweb-svc ClusterIP 10.233.13.143 <none> 80/TCP 69m
myweb-svc-named ClusterIP 10.233.21.79 <none> 80/TCP 61m
vagrant@k8s-node1 ~ kubectl get po -n dev
NAME READY STATUS RESTARTS AGE
nettool 1/1 Running 0 43s
default NS에 myweb-svc
가 존재하며 dev NS에 nettool
파드가 존재하는 것을 확인할 수 있다.
/ # cat /etc/resolv.conf
search dev.svc.cluster.local svc.cluster.local cluster.local default.svc.cluster.local kornet
nameserver 169.254.25.10
options ndots:5
dev NS에 존재하는 nettool
에서 /etc/resolv.conf
파일을 확인하면 아까와 달리 dev
가 붙어있는 것을 확인할 수 있다.
이를 가지고 DNS에 질의하면 NXDOMAIN
응답을 받게될 것이다.
/ # host myweb-svc.dev.svc.cluster.local
Host myweb-svc.dev.svc.cluster.local not found: 3(NXDOMAIN)
실제로 NXDOMAIN
를 응답한다.
/ # host myweb-svc.svc.cluster.local
Host myweb-svc.svc.cluster.local not found: 3(NXDOMAIN)
/ # host myweb-svc.cluster.local
Host myweb-svc.cluster.local not found: 3(NXDOMAIN)
2번째 3번째 도메인 역시 존재하지 않는다.
/ # host myweb-svc.default.svc.cluster.local
myweb-svc.default.svc.cluster.local has address 10.233.13.143
마지막 도메인만이 ip를 응답한다.
이는 k8s의 개선된 사항으로 1.20 버전까지는 nettool
이라는 파드를 dev NS에 만들면 /etc/resolv.conf
파일에 마지막 default.svc.cluster.local
도메인은 등록이 안돼있었다.
따라서 이름만 가지고 검색하는 것이 불가능했다.
버전에 따라 다르므로 권장하는 바는 최소한 NS를 붙이는 것이다.
/ # host myweb-svc.default
myweb-svc.default.svc.cluster.local has address 10.233.13.143
서비스가 실제로 어떤 NS에 있는지 따라서 이름과 NS를 꼭 지정해줘야 한다.
이것을 안붙이면 잘못된 결과를 낳을 수 있기 때문이다.
리소스의 이름은 NS에서만 유일하면 되기 때문에 default NS에도 myweb-svc
가 있고 dev NS에도 myweb-svc
가 있는 것은 가능하다.
/ # host myweb-svc
myweb-svc.default.svc.cluster.local has address 10.233.13.143
다음과 같이 질의했을 때
/ # cat /etc/resolv.conf
search dev.svc.cluster.local svc.cluster.local cluster.local default.svc.cluster.local kornet
nameserver 169.254.25.10
options ndots:5
/etc/resolv.conf
의 내용대로 첫번째 질의는 첫번째 도메인인 dev.svc.cluster.local
을 붙여 질의할 것이다.
내가 접속하기를 원했던 ip는 myweb-svc.default.svc.cluster.local
이지만 실제로 myweb-svc.dev.svc.cluster.local
가 존재한다면 이 ip로 접속하게 된다.
이름이 같아서 생기는 문제가 발생한다. 같은 NS에서 먼저 찾기 때문이다.
따라서 가장 추천하는 것은 풀네임을 다 쓰는 것이며 최소한 NS를 붙여 질의하는 하는 것이 문제 발생 확률을 줄인다.
📌 ndots:5
- 우리가 질의할 FQDN
에 .
이 5개 있어야 한다는 의미이다.myweb-svc.default.svc.cluster.local.
마지막은 원래 .
이 존재한다.
그래서 실제 DNS 서버에 셋팅할 때는 항상 .
을 붙여줘야 한다.
마지막의 이 .
은 Root Hint 라고 한다.
도메인은 Hierarchical Domain을 가진다. 최상단에 .
이 있으며 이를 Root Hint라고 한다.
그 하위로 com
, net
, org
등이 있으며 그 하위에 naver.com
, daum.net
이런 것들이 존재한다.
그리고 가장 하위에 도메인인 www
가 존재한다.
✔️ nodelocal DNS
모든 파드는 DNS 서버로 169.254.25.10
을 바라본다.
vagrant@k8s-node1 ~/kubespray/inventory/mycluster/group_vars/k8s_cluster ➦ e7508d7d ip a s
4: nodelocaldns: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default
link/ether fa:9b:ee:b9:01:9f brd ff:ff:ff:ff:ff:ff
inet 169.254.25.10/32 scope global nodelocaldns
valid_lft forever preferred_lft forever
nodelocaldns
의 ip가 nodelocaldns
이다.
node가 3대가 있고 각 노드마다 가상의 nodelocaldns
인터페이스가 있다.
파드가 어떤 노드에 뜨는지 상관없이 기본적으로 169.254.25.10
여기에 질의한다.
중요한 것은 이 인터페이스에 실제 DNS 서버가 있는 것이 아니다.
vagrant@k8s-node1 ~/kubespray/inventory/mycluster/group_vars/k8s_cluster ➦ e7508d7d sudo ss -tnlp
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 4096 127.0.0.1:41471 0.0.0.0:* users:(("containerd",pid=645,fd=15))
LISTEN 0 4096 169.254.25.10:9254 0.0.0.0:* users:(("node-cache",pid=2269,fd=7))
169.254.25.10:9254
node-cache
라고 된 것이 있다.node-cache
는 프로세스이다. 169.254.25.10:9254
로 질의하면 node-cache
라는 프로세스가 받는다.
이것을 DNS Cache Server라고 한다.
파드가169.254.25.10
(DNS Cache Server)으로 질의를 한다.
이 DNS Cache Server는 실제 해당되는 레코드를 가지지 않는다.
DNS Forwarder 라고 해서 자체적으로 알고 있는 정보는 없으나 질의를 받아서 실제 coredns 서버에게 재질의를 한다.
그러면 coredns 서버는 요청에 대한 응답을 해주고 이 응답을 DNS Cache Server의 로컬에 기록한다. 그리고 파드로 응답을 돌려준다.
DNS Cache Server는 coredns의 응답을 임시로 저장하고 있기 때문에 다른 파드가 똑같은 정보를 요청하면 딜레이없이 바로 응답한다.
물론 DNS Cache Server가 모르는 것은 coredns에게 질의하고 알고 있는 정보는 바로 응답해주게 된다.
https://kubernetes.io/docs/tasks/administer-cluster/nodelocaldns/
client 파드는 Local DNS Cache에 요청을 한다. 알고 있는 내용이면(Cache Hit) 응답을 바로 해주면 되고 모르는 내용이면 (Cache Miss) 실제 kubeDNS 서버에게 물어본다. 그리고 캐시에 저장한다.
영구적인 저장은 아니며 TTL 만큼의 시간만 저장할 수 있다.
Cache DNS Server가 모르는 정보를 물어보는 대상은 coredns이다.
vagrant@k8s-node1 ~ kubectl get po -A -o wide
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kube-system nodelocaldns-hbm44 1/1 Running 3 (178m ago) 34h 192.168.100.102 node3 <none> <none>
kube-system nodelocaldns-mq9nm 1/1 Running 150 (178m ago) 4d7h 192.168.100.101 node2 <none> <none>
kube-system nodelocaldns-qc6vf 1/1 Running 153 (179m ago) 4d7h 192.168.100.100 node1 <none> <none>
nodelocaldns
파드가 있고 파드의 ip 정보는 다음과 같다.
각 호스트에 nodelocaldns
가 떠있는 것이다.
vagrant@k8s-node1 ~ kubectl get po -A
kube-system coredns-8474476ff8-4bmms 1/1 Running 8 (3h1m ago) 4d7h
kube-system coredns-8474476ff8-q7svm 1/1 Running 9 (3h1m ago) 4d7h
vagrant@k8s-node1 ~ kubectl get ep -n kube-system
NAME ENDPOINTS AGE
coredns 10.233.90.36:53,10.233.96.56:53,10.233.90.36:53 + 3 more... 4d7h
kube-system NS에 있는 coredns
서비스로 접근하면 실제 coredns
서버 파드로 접근한다.
nodelocal DNS 캐시 사용할 때
Pod --dns → 169.254.25.10(node-cache): DNS Cache Server → coredns SVC(kube-system NS) → coredns POD
AWS EKS에서는 nodelocalDNS는 add-on이다. 기본 구성이 아니다.nodelocalDNS
add-on이 설치되지 않은 시스템은 파드들이 있으면 파드들의 /etc/resolv.conf
파일을 보면 DNS 서버의 주소가 coredns
의 ip가 부여되어있다. coredns
로 바로 질의하는 것이다.
nodelocalDNS
가 있다는 것은 각 노드마다 캐시 서버가 있다는 뜻이고nodelocalDNS
를 설치하지 않으면 바로 coredns(DNS server)로 질의하는 것이다.
⭐️ 무슨 차이일까 ? ⭐️
노드와 파드가 굉장히 많은 상태라고 가정해보자coredns
라는 파드가 컨트롤 플레인에만 있고 몇개 없는 상태이다.
그럼 무수히 많은 파드의 요청을 컨트롤 플레인이 Direct로 받게 된다. 컨트롤 플레인에 엄청난 부하가 생긴다.
그래서 DNS Server에 Direct로 질의하지 말고 로컬에 Cache Server를 두자고 하는 것이다.
모르는 정보에 대해서는 어쩔 수 없이 DNS Server로 질의해야 하겠지만 최소한 파드가 로컬의 Cache Server에서 1차로 답을 얻을 수 있다.
nodelocal DNS 캐시 사용을 하지 않을 때
파드 → dns → coredns SVC(kube-system NS) → coredns 파드
모든 파드는 바로 coredns SVC에 요청하고 그 뒤에 바로 파드가 있다. 너무 많아지면 부하가 너무 많이 걸린다.
DNS 이용한 Service Discovery는 나중에 서비스가 들어오더라도 그 서비스는 coredns Server한테 자동으로 생성되기 때문에 나중에 들어온 서비스도 얼마든지 질의할 수 있다.
'DevOps > Kubernetes' 카테고리의 다른 글
[Kubernetes] Service - LoadBalancer ( + METALLB : on-prem 환경의 LB) (0) | 2022.05.23 |
---|---|
[Kubernetes] Service - NodePort (1) | 2022.05.23 |
[Kubernetes] Service - Service Discovery (1) (0) | 2022.05.21 |
[Kubernetes] Service - ClusterIP (0) | 2022.05.20 |
[Kubernetes] Service & DNS (서비스와 DNS) (0) | 2022.05.20 |
영차영차 성장 블로그
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!