Kubernetes Namespace & DNS

신동수·2024년 5월 8일
0

K8S

목록 보기
10/14

Namespace


동일한 Cluster에서 논리적으로 가상 Cluster의 개념으로 분리하기위한 리소스이다. 즉, A Namesapce와 B Namespace는 모두 동일한 물리 Cluster에 존재하나, 서로 논리적으로 분리되어 있다.
일반적으로 다른 Namespace에 존재하는 리소스에 영향을 주지 않기 위해 Namespace를 쓰는 경우가 많다.

Kubernets에서 kube-system, kube-public, default 와 같이 3개의 Namespace가 기본적으로 생성되면 context를 변경하지 않으면 default Namespace에서 모든 작업이 이뤄진다.
- kube-system : k8s 시스템에서 생성한 오브젝트를 관리하기 위한 Namespace
- kube-public : 모든 사용자가 읽기 권한으로 접근할 수 있으며, 주로 공개적으로 확인되어 읽을 수 있는 리소스를 할당
- default : 다른 Namespace가 없는 오브젝트를 위한 기본 Namespace

Namespace로 논리적으로 분리함으로써 얻을 수 있는 장점은 아래와 같다.
1. 사용자별로 Namespace 접근 권한을 다르게 설정할 수 있다.
2. Namespace별로 리소스 할당량을 지정할 수 있다.(ResourceQuota 사용)
3. Namepsace 별로 리소스(pod, Service...)를 나눠서 관리할 수 있다.

다만, 반대로 아래의 단점이 있다.
1. 물리적인 Cluster 분리가 아니므로 Cluster에 장애가 발생하면 모든 Namespace가 타격을 받는다.
2. 리소스를 생성할 때 반드시 Namespace 지정이 필요하다.
- 반드시는 아니지만, 지정하지 않으면 default Namespace에서 리소스가 생성된다.

Namespace 생성방법

yaml 방식

apiVersion: v1
kind: Namespace
metadata: 
 name: aaa

위 yaml 을 통해 생성할 수 있다.

kubectl 명령어 방식

$ kubectl create namespace bbb

또한, 명령어를 통해 생성할 수도 있다.

다른 Namespace 접근 방법

기본적으로 Namespace는 논리적으로 분리된 환경을 뜻하나, 접근을 못하는것은 아니다.
A Namespace에서 B Namespace로 접근하는 방법은 1. FQDN과 2.Domain Search 방법이 있다.

FQDN 방법의 접근

Full Qualified Domain Name. 즉 전체 도메인 이름을 직접 기재하여 접근하는 방식을 뜻한다.

Domain Search 방법의 접근

FQDN과 다르게 절대 경로를 전부 적지 않고, 부분적으로 기재하는 방식이며 나머지 부분은 Search 기능을 통해 자동으로 입력해준다. 흡사 크롬의 자동 완성 기능과 비슷하다고 볼 수 있다.

아래는 FQDN, Domain Search 방법의 접근 예시이다.

1. curl {서비스명}.{Namespace명}.svc.cluster.local:{Port}
2. curl {서비스명}.{Namespace명}.svc:{Port}
3. curl {서비스명}.{Namespace명}:{Port}
4. curl {서비스명}:{Port}

서비스 및 파드용 DNS

파드와 서비스를 위한 DNS 레코드를 생성한다. 사용자는 IP 주소 대신에 일관된 DNS 네임을 통해서 서비스에 접속할 수 있다.
쿠버네티스는 DNS를 설정 하기 위해 사용되는 파드와 서비스에 대한 정보를 발행한다. Kubelet은 실행 중인 컨테이너가 IP가 아닌 이름으로 서비스를 검색할 수 있도록 파드의 DNS를 설정한다.
클러스터 내의 서비스에는 DNS 네임이 할당된다. 기본적으로 클라이언트 파드의 DNS 검색 리스트는 파드 자체의 네임스페이스와 클러스터의 기본 도메인을 포함한다.

CoreDNS

쿠버네티스 클러스터 내 POD에서 어떤 도메인을 찾고자 할 때 kube-system 네임스페이스에 실행되고 있는 CoreDNS가 네임서버로 사용된다. 기존에 Kube-DNS가 이 역할을 했는데 1.12버전부터 CoreDNS가 표준으로 채택되었다. 그래서 kubeadm으로 설치하는 경우 CoreDNS가 설치된다.
CoreDNS도 POD로 실행되기 때문에 외부 요청을 받기 위해 Service 오브젝트가 존재한다.

$ kubectl get svc kube-dns -n kube-system --show-labels
NAME       TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE   LABELS
kube-dns   ClusterIP   10.96.0.10   <none>        53/UDP,53/TCP,9153/TCP   14h   k8s-app=kube-dns,kubernetes.io/cluster-service=true,kubernetes.io/name=CoreDNS

$ kubectl get po -n kube-system -l k8s-app=kube-dns
NAME                       READY   STATUS    RESTARTS     AGE
coredns-565d847f94-vxnwv   1/1     Running   1 (3h ago)   14h
coredns-565d847f94-xwfn6   1/1     Running   1 (3h ago)   14h

Cluster 내부에서 Pod가 DNS 질의를 할때 동작


1. 파드에서 DNS Query를 수행하면 먼저 파드 내부에 Local DNS Resolver로 전달한다. 여기서 resolv.conf에 구성된 파일을 확인하고 DNS 조회를 수행한다.
2. NodeLocalDNS는 DNS 요청 결과를 기록해 두는 캐시 역할을 수행하며 빠르게 DNS Query를 처리하도록 돕습니다.
3. 만약 캐싱된 정보에 대상이 없을 경우 CoreDNS로 전달한다.
4. CoreDNS는 Kubernetes 클러스터 내부의 서비스와 리소스에 대한 DNS 조회를 처리한다. (서비스 조회, 외부 DNS 조회, 캐싱)
5. CoreDNS 구성은 corefile에 의해 관리되며 필요에 따라 커스터마이징할 수 있다. (kubectl describe cm -n kube-system coredns 명령어를 통해 확인할 수 있다.)

참고

# kubectl describe cm -n kube-system **coredns
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 {
       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>

CoreDNS의 여러가지 기능은 Corefile설정 파일에 원하는 것들만 플러그인처럼 추가할 수 있다. 이 Corefile 파일은 ConfigMap 오브젝트에 저장되어 있다.

다른 서비스 접근 실습

# reqpod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: request-pod
  namespace: aaa
spec:
  containers:
  - name: container
    image: kubetm/init

---
# pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod
  namespace: aaa
  labels:
    app: service-test
spec:
  containers:
  - name: container
    image: kubetm/app

---
# svc.yaml 
apiVersion: v1
kind: Service
metadata:
  name: svc
  namespace: aaa
spec:
  selector:
    app: service-test
  ports:
  - port: 80
    targetPort: 8080
# pod, svc 생성
$ kubectl create -f reqpod.yaml
pod/request-pod created
$ kubectl create -f pod.yaml
pod/pod created
$ kubectl create -f svc.yaml
service/svc created

# pod, svc 확인
$ kubectl get all -n aaa
NAME              READY   STATUS    RESTARTS   AGE
pod/pod           1/1     Running   0          68s
pod/request-pod   1/1     Running   0          71s

NAME          TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
service/svc   ClusterIP   10.99.89.249   <none>        80/TCP    65s

# exec 를 통한 aaa 네임스페이스에 있는 request-pod 접속
$ kubectl exec request-pod -n aaa -it /bin/bash

# hostname 확인
$ hostname
request-pod

# DNS 서버 설정을 담당하는 /etc/resolv.conf 파일을 확인
$ cat /etc/resolv.conf
search aaa.svc.cluster.local svc.cluster.local cluster.local
nameserver 10.96.0.10
options ndots:5

# Domain 접속 확인
$ curl svc/hostname
Hostname : pod
$ curl svc.aaa/hostname
Hostname : pod
$ curl svc.aaa.svc/hostname
Hostname : pod
# FQDN 접속 확인
$ curl svc.aaa.svc.cluster.local/hostname
Hostname : pod
# ClusterIP 접속 확인
$ curl 10.99.89.249/hostname
Hostname : pod

결과

파드에서 확인된 Nameserver 가 Kubernetes에서 10.96.0.10 이라는 IP를 확인할 수 있다. Kubernetes의 모든 Pod들은 바로 이 IP로 DNS를 조회한다. 
그리고 이 IP의 주인은 바로 kube-dns IP 주소이다.


모든 Pod들은 클러스터의 내·외부 질의를 CoreDNS를 통해 수행한다. 그렇기에 쿠버네티스 클러스터 환경 안에서 자체적인 도메인 네임 시스템을 가질 수 있다.

다른 Namespace 의 서비스 접근 실습

# reqpod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: request-pod
  namespace: bbb
spec:
  containers:
  - name: container
    image: kubetm/init
# pod, svc 생성
$ kubectl create -f reqpod2.yaml
pod/request-pod created
# pod, svc 확인

# exec 를 통한 bbb 네임스페이스에 있는 request-pod 접속
$ kubectl exec request-pod -n bbb -it /bin/bash

# hostname 확인
$ hostname
request-pod

# DNS 서버 설정을 담당하는 /etc/resolv.conf 파일을 확인
$ cat /etc/resolv.conf
search bbb.svc.cluster.local svc.cluster.local cluster.local
nameserver 10.96.0.10
options ndots:5

# Domain 접속 확인
$ curl svc/hostname
curl: (6) Could not resolve host: svc; Unknown error
$ curl svc.aaa/hostname
Hostname : pod
$ curl svc.aaa.svc/hostname
Hostname : pod
# FQDN 접속 확인
$ curl svc.aaa.svc.cluster.local/hostname
Hostname : pod
# ClusterIP 접속 확인
$ curl 10.99.89.249/hostname
Hostname : pod

결과

위 결과에서 svc/hostname 으로 호출 시 실패하는 이유는 해당 서비스가 동일한 Namespace 에 존재하지 않아 도메인을 찾을 수 없기 때문에 호출하지 못하였다. 하지만 뒤에 Namespace를 추가하여 호출 시 정상적으로 나오는 것으로 확인이 된다.

profile
조금씩 성장하는 DevOps 엔지니어가 되겠습니다. 😄

0개의 댓글

관련 채용 정보