동일한 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에서 리소스가 생성된다.
apiVersion: v1
kind: Namespace
metadata:
name: aaa
위 yaml 을 통해 생성할 수 있다.
$ kubectl create namespace bbb
또한, 명령어를 통해 생성할 수도 있다.
기본적으로 Namespace는 논리적으로 분리된 환경을 뜻하나, 접근을 못하는것은 아니다.
A Namespace에서 B Namespace로 접근하는 방법은 1. FQDN과 2.Domain Search 방법이 있다.
Full Qualified Domain Name. 즉 전체 도메인 이름을 직접 기재하여 접근하는 방식을 뜻한다.
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 레코드를 생성한다. 사용자는 IP 주소 대신에 일관된 DNS 네임을 통해서 서비스에 접속할 수 있다.
쿠버네티스는 DNS를 설정 하기 위해 사용되는 파드와 서비스에 대한 정보를 발행한다. Kubelet은 실행 중인 컨테이너가 IP가 아닌 이름으로 서비스를 검색할 수 있도록 파드의 DNS를 설정한다.
클러스터 내의 서비스에는 DNS 네임이 할당된다. 기본적으로 클라이언트 파드의 DNS 검색 리스트는 파드 자체의 네임스페이스와 클러스터의 기본 도메인을 포함한다.
쿠버네티스 클러스터 내 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
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를 통해 수행한다. 그렇기에 쿠버네티스 클러스터 환경 안에서 자체적인 도메인 네임 시스템을 가질 수 있다.
# 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를 추가하여 호출 시 정상적으로 나오는 것으로 확인이 된다.