도커나 도커 스웜 모드에는 컨테이너를 논리적으로 나눠 관리하는 개념이 없다. docker ps를 실행하면 호스트에 떠 있는 모든 컨테이너가 한 목록에 뒤섞여 나온다. 컨테이너 수가 늘어날수록 어떤 것이 어떤 애플리케이션에 속하는지 구분하기가 어려워진다.
쿠버네티스는 이 문제를 네임스페이스(Namespace)라는 오브젝트로 해결한다. 네임스페이스는 파드, 레플리카셋, 디플로이먼트, 서비스 같은 리소스들이 묶여 있는 하나의 가상 공간이다.
리소스를 용도별로 묶어 두면, 서로 다른 목적의 리소스가 한 클러스터 안에서 뒤섞이지 않고 논리적으로 분리된 채 운영된다.
네임스페이스는 namespace 또는 축약형 ns로 다룬다. 현재 클러스터의 네임스페이스 목록은 다음 명령어로 확인한다.
kubectl get namespaces
kubectl get ns
별도로 만들지 않아도 클러스터에는 기본 네임스페이스 몇 개가 이미 존재한다. 그 중 가장 자주 쓰는 것이 default이다. 쿠버네티스 설치 시 자동으로 설정되며, kubectl 명령에 네임스페이스를 지정하지 않으면 이 default가 대상이 된다.
kubectl get pods --namespace default특정 네임스페이스를 지정할 때는 --namespace 대신 축약형 -n을 쓸 수 있다. 다음은 kube-system 네임스페이스의 파드를 조회하는 명령이다.
kubectl get pods -n kube-systemkubectl이 기본으로 사용하는 네임스페이스는 default이지만, 이 값은 고정된 것이 아니다. kubeconfig 파일의 컨텍스트 설정을 수정하면 기본 네임스페이스를 원하는 것으로 바꿀 수 있다.
특정 네임스페이스에서 주로 작업한다면 기본값을 바꿔 두어 매번 -n 옵션을 붙이는 번거로움을 줄일 수 있다.
이처럼 네임스페이스는 리소스를 논리적으로 묶어 하나의 가상 클러스터처럼 다룰 수 있게 해준다. 하나의 클러스터를 여러 명이 함께 사용한다면 사용자마다 네임스페이스를 따로 두어 서로의 리소스가 섞이지 않게 할 수 있다.
용도에 따라 네임스페이스를 나누는 방식도 흔하다. 특정 목적의 디플로이먼트와 서비스가 지정한 네임스페이스에서만 존재하도록 두는 것으로, 보통 모니터링, 로드 밸런싱, 인그레스처럼 성격이 뚜렷한 컴포넌트를 묶는 데 사용한다.
다만 네임스페이스는 어디까지나 논리적 구분일 뿐, 물리적으로 격리된 공간은 아니다. 서로 다른 네임스페이스에서 생성된 파드가 같은 노드 위에 함께 떠 있을 수 있다. 네임스페이스가 나누는 것은 리소스를 바라보고 관리하는 단위이지, 파드가 실제로 배치되는 물리적 위치가 아니가.
*리눅스 네임스페이스
이름은 같지만 별개의 개념이다. 리눅스 네임스페이스는 컨테이너에 격리된 공간을 만들기 위해 리눅스 커널이 제공하는 자체 기능으로, 네트워크 / 마운트 / 프로세스 네임스페이스 등을 가리킨다. 쿠버네티스의 네임스페이스는 클러스터 리소스를 묶는 논리적 단위라는 점에서 층위가 다르다.
리소스를 묶는다는 점에서 네임스페이스는 라벨(Label)과 비슷해 보인다. 라벨도 다음처럼 특정 조건의 파드만 골라낼 수 있기 때문이다.
kubectl get pods -l app=webserver그러나 네임스페이스는 라벨보다 넓은 용도로 쓰인다. 라벨이 리소스를 선택하고 묶는 수준에 그친다면, 네임스페이스는 그 경계를 기준으로 정책을 적용하는 단위가 된다.
예를 들어 ResourceQuota 오브젝트로 특정 네임스페이스에서 생성되는 파드의 자원 사용량을 제한하거나, 애드미션 컨트롤러(Admission Controller)를 이용해 특정 네임스페이스의 파드에는 항상 사이드카 컨테이너가 붙도록 강제할 수 있다.
무엇보다 네임스페이스는 사용 목적에 따라 파드, 서비스 같은 리소스를 경계 단위로 격리해, 관리 대상을 편리하게 구분하게 해 준다.
네임스페이스는 명령 한 줄로도, YAML 매니페스트로도 만들 수 있다.
kubectl create namespace <name>
kubectl apply -f namespace.yml
생성 여부는 목록에서 이름으로 걸러 확인한다.
kubectl get ns | grep <name>특정 네임스페이스에 리소스를 만드는 방법은 간단하다. 리소스 YAML의 metadata.namespace 항목에 네임스페이스 이름을 적으면 된다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
namespace: my-namespace
spec:
# ...
하나의 YAML 파일 안에 ---를 구분자로 넣으면 여러 리소스를 한 번에 정의할 수도 있다. 네임스페이스와 그 안에 들어갈 디플로이먼트, 서비스를 한 파일에 담아 함께 적용하는 식이다.
kubectl apply -f deploy-svc-ns.yaml특정 네임스페이스의 리소스를 조회할 때는 -n으로 지정하고, 네임스페이스에 상관없이 전체를 보려면 --all-namespaces를 쓴다.
kubectl get pods,services -n <name>
kubectl get pods --all-namespaces
쿠버네티스 클러스터 안에서는 서비스 이름만으로 그 서비스에 접근할 수 있고, 서비스가 트래픽을 뒤에 묶인 파드로 라우팅한다. 다만 이는 정확히는 같은 네임스페이스 안에서만 성립한다. 다른 네임스페이스에 있는 서비스는 이름만으로는 접근할 수 없다.
다른 네임스페이스의 서비스에 접근하려면 서비스 이름 뒤에 네임스페이스 이름을 붙인다.
<서비스 이름>.<네임스페이스 이름>파드 안의 DNS 설정(resolv.conf)에 svc.cluster.local 같은 검색 도메인이 등록돼 있어, 위처럼 서비스 이름과 네임스페이스만 적어도 나머지 경로가 자동으로 채워져 접근된다.
이를 끝까지 펼친 서비스의 완전한 도메인 이름(FQDN, Fully Qualified Domain Name)은 일반적으로 다음 형식으로 구성된다.
<서비스 이름>.<네임스페이스 이름>.svc.cluster.local같은 네임스페이스 안에서는 앞부분만으로 접근이 가능하기 때문에 서비스 이름만 써도 되는 것이고, 네임스페이스를 넘어설 때는 뒤쪽 경로를 함께 명시해야 하는 것이다.
네임스페이스는 매니페스트 파일이나 이름으로 삭제한다.
kubectl delete -f <YAML>
kubectl delete namespace <name>
단, 네임스페이스를 삭제하면 그 안에 존재하던 모든 리소스가 함께 삭제된다. 파드, 서비스, 디플로이먼트 등이 한꺼번에 사라지므로, 삭제 전에 대상 네임스페이스에 어떤 리소스가 들어 있는지 반드시 확인해야 한다.
모든 리소스가 네임스페이스로 구분되는 것은 아니다. A라는 네임스페이스에서 파드를 만들면 그 파드는 A에서만 보인다. 이렇게 특정 네임스페이스에 소속되는 경우를 두고 '오브젝트가 네임스페이스에 속한다(namespaced)'고 표현한다.
네임스페이스에 속하는 오브젝트의 종류는 다음 명령으로 확인한다.
kubectl api-resources --namespaced=true반대로 네임스페이스에 속하지 않는 오브젝트도 있다. 대표적인 예가 노드(Node)다. 노드는 쿠버네티스 클러스터가 사용하는 저수준 오브젝트로, 네임스페이스로 구분되지 않는다. 따라서 노드를 조회할 때 --namespace 옵션을 붙여도 의미가 없다.
네임스페이스에 속하지 않는 오브젝트의 종류는 다음 명령으로 확인할 수 있다.
kubectl api-resources --namespaced=false