본문 바로가기

Container/Kubernetes

[K8S] Kubernetes DNS

coreDNS는 쿠버네티스에서 기본적으로 사용되는 DNS 서버로, 클러스터 내부의 서비스들이 서로 도메인 이름을 통해 통신할 수 있도록 지원하는 DNS Provider이다. 

Pod간에 통신할 때 naimg service를 이용해서 서비스 디커버리와 네트워크 라우팅을 담당한다.

  • coreDNS의 주요 역할
    • service 및 Pod용 DNS, 즉 내부 서비스 간 통신 제공
    • kubernetes 서비스 이름을 IP 주소로 변경
    • kubernetes DNS는 클러스터에서 실행하는 모든 Pod가 사용할 수 있도록 구성된다.
root@master:~/network# kubectl get svc -A
NAMESPACE     NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE
default       kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP                  35d
kube-system   kube-dns     ClusterIP   10.96.0.10   <none>        53/UDP,53/TCP,9153/TCP   35d
# 특별히 바꾸지 않으면 kube-dns는 10.96.0.10으로 고정되어 있음.

root@master:~/network# kubectl get pod -A | grep coredns
kube-system   coredns-76f75df574-lwh6f                     1/1     Running   6 (77m ago)    35d
kube-system   coredns-76f75df574-t88tx                     1/1     Running   6 (77m ago)    35d
# master/secondary master 두 개가 작동 중이다.
# 이 두개의 coredns에 대한 단일 진입점이 10.96.0.10

작동 방식

쿠버네티스에서는 각 파드가 kube-dns 또는 coredns 서비스의 IP를 DNS 서버로 사용한다.

  • Cofigure :  /etc/coredns/Corefile을 이용해서 configure한다.
$ kubectl describe pod coredns-77d6fd4654-dg2sc -n kube-system
Name:                 coredns-77d6fd4654-dg2sc
....
Containers:
  coredns:
    Container ID:  containerd://85e7b6910f75705a5824ede6df26af3b42697f4e1fb82ec1e717213b8f881375
    Image:         registry.k8s.io/coredns/coredns:v1.10.1
    Image ID:      registry.k8s.io/coredns/coredns@sha256:a0ead06651cf580044aeb0a0feba63591858fb2e43ade8c9dea45a6a89ae7e5e
    Ports:         53/UDP, 53/TCP, 9153/TCP
    Host Ports:    0/UDP, 0/TCP, 0/TCP
    Args:
      -conf
      /etc/coredns/Corefile   # 여기서 확인 가능하다.

# Plugin을 작성해서 health monitoring등 지표를 만든다.
$ cat /etc/coredns/Corefile
    .:53 {
        errors
        health
        ready
        kubernetes cluster.local in-addr.arpa ip6.arpa { # 모든 Recored되는 DNS서버는 cluster.local 도메인에 존재한다.
            pods insecure
            fallthrough in-addr.arpa ip6.arpa
        }
        forward . /etc/resolv.conf
        cache 30
        loop
        reload
        loadbalance
        
• errors → 오류 발생 시 로그 출력
• health → CoreDNS 상태 체크 활성화
• ready → CoreDNS 준비 상태 확인 가능
• kubernetes cluster.local → 클러스터 내부의 서비스 이름을 DNS로 변환
• forward . /etc/resolv.conf → 외부 도메인 요청을 /etc/resolv.conf에 지정된 DNS 서버로 전달
• cache 30 → DNS 응답을 30초 동안 캐싱

 

  • 이러한 Corefile은 configMap으로 전달된다.
$ kubectl get configmap -n kube-system
NAME                                                   DATA   AGE
coredns                                                1      9m15s
# configMap 수정을 통해 coreDNS 구성을 변경할 수 있다.


# coredns configmap 조회
controlplane ~ ➜  kubectl describe configmap coredns -n kube-system
Name:         coredns
Namespace:    kube-system
Labels:       <none>
Annotations:  <none>

Data
====
Corefile:
----
.:53 {
    errors
    health {
       lameduck 5s
    }
    ready
    kubernetes cluster.local in-addr.arpa ip6.arpa {  # cluster.local: root domain/zone
       pods insecure
       fallthrough in-addr.arpa ip6.arpa
       ttl 30
    }
    prometheus :9153
    forward . /etc/resolv.conf {
       max_concurrent 1000
    }
    cache 30
    loop
    reload
    loadbalance
}



BinaryData
====

Events:  <none>

 

⚒ 서비스 네임 해석

쿠버네티스의 모든 서비스는 svc.cluster.local 도메인을 가진다.

 

<서비스이름>.<namespace>.svc.cluster.local
<Pod-IP-Address>.<namespace>.pod.cluster.local

  • nginx 서비스가 default 네임스페이스에 있을 때
$ nslookup nginx.default.svc.cluster.local  # FQDN
10.96.0.1 # clusterIP 변환
  • 다른 네임스페이스의 mysql 서비스
$ nslookup mysql.database.svc.cluster.local

 

CoreDNS가 SVC와 연결되는 과정

  1. 서비스가 생성됨 : ClusterIP 할당받음
  2. CoreDNS가 이를 감지하여 DNS 레코드 생성 (backend.default.svc.cluster.local -> 10.96.0.20)
  3. Pod가 서비스 이름으로 요청 (nslookup backed.default......)
  4. Pod가 해당 IP로 요청을 보냄 → 서비스가 트래픽을 해당 Pod로 전달
root@master:~/core-dns# cat deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      name: nginx-pod
      labels:
        app: web
    spec:
      containers:
      - name: nginx-container
        image: nginx:1.14
root@master:~/core-dns# kubectl apply -f deployment.yaml
deployment.apps/web created
root@master:~/core-dns# cat svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: svc-web
spec:
  clusterIP: 10.96.100.100
  selector:
    app: web
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
root@master:~/core-dns# kubectl apply -f svc.yaml
service/svc-web created
root@master:~/core-dns# kubectl get all
NAME                       READY   STATUS    RESTARTS   AGE
pod/web-7b67fd8c4f-97448   1/1     Running   0          53s
pod/web-7b67fd8c4f-jsrxk   1/1     Running   0          53s
pod/web-7b67fd8c4f-mfw29   1/1     Running   0          53s

NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP   35d
service/svc-web      ClusterIP   10.96.100.100   <none>        80/TCP    6s

NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/web   3/3     3            3           53s

NAME                             DESIRED   CURRENT   READY   AGE
replicaset.apps/web-7b67fd8c4f   3         3         3       53s

 

# nginx와 연결될 front pod를 하나 생성한다.
root@master:~/core-dns# kubectl run client-pod --image=centos:7 -it -- /bin/bash
If you don't see a command prompt, try pressing enter.

[root@client-pod /]# cat /etc/resolv.conf
search default.svc.cluster.local svc.cluster.local cluster.local  # 해당 항목 찾아서 연결해준다.
nameserver 10.96.0.10       # kube-dns의 IP가 등록되어 있음.
options ndots:5


# svc-web으로 curl 날려서 통신 확인하기.
[root@client-pod /]# curl 10.96.100.100
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>



[root@client-pod /]# curl svc-web.default.svc.cluster.local
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

# 서비스 이름만 입력해도 된다.
[root@client-pod /]# curl svc-web
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

# 이런식으로 DNS 사용함.

 

 

예제]  Pod 내 DNS 설정 

 

DNS for Services and Pods

Your workload can discover Services within your cluster using DNS; this page explains how that works.

kubernetes.io

 

root@master:~/core-dns# cat custom-dns.yaml
apiVersion: v1
kind: Pod
metadata:
  namespace: default
  name: dns-example
spec:
  containers:
    - name: test
      image: nginx
  dnsPolicy: "None"
  dnsConfig:
    nameservers:
      - 1.2.3.4
    searches:
      - ns1.svc.cluster-domain.example
      - my.dns.search.suffix
    options:
      - name: ndots
        value: "2"
      - name: edns0
root@master:~/core-dns# kubectl apply -f custom-dns.yaml
pod/dns-example created

root@master:~/core-dns# kubectl get pods
NAME                   READY   STATUS    RESTARTS        AGE
client-pod             1/1     Running   1 (7m51s ago)   16m
dns-example            1/1     Running   0               17s
web-7b67fd8c4f-97448   1/1     Running   0               19m
web-7b67fd8c4f-jsrxk   1/1     Running   0               19m
web-7b67fd8c4f-mfw29   1/1     Running   0               19m

root@master:~/core-dns# kubectl exec dns-example -it -- /bin/bash
root@dns-example:/# cat /etc/resolv.conf
search ns1.svc.cluster-domain.example my.dns.search.suffix
nameserver 1.2.3.4
options ndots:2 edns0

 

✅ kubernetes.default.svc.cluster.local 해석이 안될 때:

$ kubectl exec -it <pod-name> -- nslookup kubernetes.default

# SERVFAIL, NXDOMAIN이 나오면 DNS 설정 확인:

$ cat /etc/resolv.conf


예제]

controlplane ~ ➜  kubectl get service -n kube-system
NAME       TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)                  AGE
kube-dns   ClusterIP   172.20.0.10   <none>        53/UDP,53/TCP,9153/TCP   11m
# CoreDNS에 접근하기위해 만들어진 서비스 : kube-dns

controlplane ~ ➜  cat /etc/resolv.conf 
search ulz5ho36tm7svg7c.svc.cluster.local svc.cluster.local cluster.local us-central1-a.c.kk-lab-prod.internal c.kk-lab-prod.internal google.internal
nameserver 10.96.0.10
options ndots:5
# 직접 설정할 것 없이 쿠버네티스의 DNS가 자동으로 만들어낸다.
# 하지만 search 항목이 없으면 CoreDNS가 올바르게 설정되지 않았을 가능성이 있다.
controlplane ~ ✖ kubectl get pods
NAME              READY   STATUS    RESTARTS   AGE
hr                1/1     Running   0          44m
simple-webapp-1   1/1     Running   0          44m
test              1/1     Running   0          44m

controlplane ~ ➜  kubectl get svc
NAME           TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes     ClusterIP   172.20.0.1       <none>        443/TCP        28m
test-service   NodePort    172.20.17.17     <none>        80:30080/TCP   26m
web-service    ClusterIP   172.20.161.196   <none>        80/TCP         26m

# test application에서 hr web server로 접속하기 위해 사용되는 이름 : web-service
controlplane ~ ➜  kubectl describe svc web-service 
Name:                     web-service
Namespace:                default
Labels:                   <none>
Annotations:              <none>
Selector:                 name=hr # 연결된 application (Pod) 확인 가능
Type:                     ClusterIP
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       172.20.161.196
IPs:                      172.20.161.196
Port:                     <unset>  80/TCP
TargetPort:               80/TCP
Endpoints:                172.17.0.5:80
Session Affinity:         None
Internal Traffic Policy:  Cluster
Events:                   <none>

 

반응형

'Container > Kubernetes' 카테고리의 다른 글

[K8S] kube-scheduler  (0) 2024.04.25
[K8S] ETCD Backup 및 Restore  (0) 2024.04.21
[K8S] PV & PVC  (0) 2024.04.20
CKA 시험준비  (0) 2024.04.16
[K8S] cordon & drain  (0) 2024.04.13