Recommanded Free YOUTUBE Lecture: Dockerizing with Spring Boot Hello World

이 문서는 Minikuber와 함께하는 Kubernetes Study 의 일부분이다. 아직 Minikuber와 함께하는 Kubernetes Study를 읽기 않았다면, 먼저 읽도록 하자.

NameSpace

Kubernetes는 여러 서비스를 실행하는 컨테이너 기반의 애플리케이션 실행 플랫폼이다. 여기에는 서로 다른 여러 애플리케이션들이 실행될 수 있기 때문에 이들을 격리할 수 있어야 한다.

Kubernetes는 네임스페이스(NameSpace) 를 이용해서 하나의 물리적 클러스터위에 여러 개의 가상의 클러스터를 구성할 수 있다. 네임스페이스를 사용하면 동일한 클러스터라고 하더라도 별도의 논리적 파티션을 생성할 수 있기 때문에 즉, 격리(isolation)할 수 있기 때문에 애플리케이션들을 서로 간섭없이 실행할 수 있다.

이 문서에서는 Kubernetes 네임스페이스가 무엇인지 언제, 어떻게 사용해야 하는지 살펴보려 한다.

NameSpace 기본

먼저 네임스페이스의 주요 기능과 이를 사용함으로써 얻을 수 있는 이점을 살펴보자.

기능 이점
네임스페이스별 Role-based access control(RBAC) 보안 강화
리소스 격리, API가 대규모 클러스터가 아닌 좀 더 작은 네임스페이스에서 실행 성능 향상
네임스페이스별 리소스 쿼터(Quota) 더 나은 용량관리
네임스페이스 별 관리 범위 설정 효율적인 조직 구성

네임스페이스가 제공하는 이런 중요한 기능과 이점은 네임스페이스가 일종의 "가상 클러스터" 혹은 "하위 클러스터"를 만들기 때문에 누릴 수 있다. 네임스페이스로 격리되기 때문에 각 리소스 이름은 네임스페이스 안에서만 유일하면 되며 다른 네임스페이스간에는 중복되도 된다.

Kubernetes NameSpace

대부분의 Kubernetes 리소스(pods, services, replication controllers, ...)들은 네임스페이스에 있다. 하지만 nodes나 psersistentVolumes와 같은 몇몇 저수준 리소스들은 특정 네임스페이스에 위치하지 않는다. 아래와 같이 kubectl로 네임스페이스 정보를 확인할 수 있다.

# 네임스페이스에서 작동하는 리소스
kubectl api-resources --namespaced=true

# 네임스페이스 바깥에서 작동하는 리소스
kubectl api-resources --namespaced=false

Kubernetes 네임스페이스를 사용해야 하는 경우

  • 대규모 팀으로 이루어진 조직의 경우 네임스페이스를 사용해서 마이크로서비스를 격리할 수 있다. 팀은 서로 다른 작업 공간에서 충돌없이 리소스를 재사용할 수 있다. 또한 특정 작업공간에서 한 작업이 다른 작업공간에 영향을 미치지 않는다.

  • 개발, 테스트, 프로덕션을 단일 클러스터를 통해서 개발 및 배포하는 경우 네임스페이스를 사용해서 환경을 격리할 수 있다. 이렇게 하면 개발 환경의 작업결과가 프로덕션에 영향을 미치지 않도록 할 수 있다.

  • 네임스페이스를 사용하면 RBAC를 사용할 수 있으므로 역할기반으로 권한을 정의할 수 있다. RBAC를 이용해서 인증된 사용자만 지정된 네임스페이스의 리소스에 접근하도록 보장할 수 있다.

  • 관리자는 리소스 할당량을 설정해서 네임스페이스에서 사용할 수 있는 리소스 제한을 설정할 수 있다. 이렇게 해서 특정 네임스페이스가 모든 리소스를 독차지하는 일을 막을 수 있다.

  • 네임스페이스를 사용하면, 검색 범위가 줄어들기 때문에 더 빠르게 API 작업을 수행할 수 있다.

기본 네임스페이스

쿠버네티스 클러스터가 만들어지면 4개의 초기 네임스페이스를 가진다.

default
기본적으로 만들어지는 네임스페이스이기 때문에, 새로운 네임스페이스를 만들지 않고도 애플리케이션을 배포할 수 있다. 학습 혹은 테스트 목적으로 사용된다.

kuber-node-lease
분산 시스템의 경우 공유 리소스를 잠그고 노드간의 활동을 조절하는 매커니즘인 "리스(lease)"가 필요하다. Kubernetes에서 lease는 노드의 heartbeat와 리더 선출과 같은 시스템 핵심 기능에서 사용된다.

kube-public
공개적으로 접근할 수 있는 데이터가 포함된 네임스페이스다. 이 네임스페이스에는 ConfigMap 객체인 cluster-info가 포함된다. ConfigMap은 Key-Value 형태의 공개 데이터를 저장한다.

kube-system
Kubernetes 시스템에서 생성한 오브젝트(시스템 프로세스)를 위한 네임스페이스다.

네임스페이스 기본 사용하기

네임스페이스 목록 확인

kubectl 명령을 사용해서 Kubernetes의 네임스페이스를 확인 할 수 있다.

$ kubectl get namespace                   
NAME                   STATUS   AGE
default                Active   161d
istio-system           Active   104d
kube-node-lease        Active   161d
kube-public            Active   161d
kube-system            Active   161d
kubernetes-dashboard   Active   161d

네임스페이스 생성과 삭제

"joinc-test"라는 이름의 네임스페이스를 만들어보자.

kubectl create namespace joinc-test

네임스페이스가 만들어졌는지 확인해보자.

$ kubectl get ns                     
NAME                   STATUS   AGE
default                Active   161d
istio-system           Active   104d
joinc-test             Active   20s
kube-node-lease        Active   161d
kube-public            Active   161d
kube-system            Active   161d
kubernetes-dashboard   Active   161d

이제 네임스페이스를 삭제해보자.

$ kubectl delete ns joinc-test           
namespace "joinc-test" deleted

작업에 특정 네임스페이스를 설정하기

--namespce 플래그를 이용해서 현재 요청을 실행할 네임스페이스를 설정할 수 있다.

kubectl run nginx --image=nginx --namespace=<insert-namespace-name-here>
kubectl get pods --namespace=<insert-namespace-name-here>

그럼 joinc-test 네임스페이스를 만들고 여기에 nginx 컨테이너를 실행해보자.

$ kubectl create namespace joinc-test
namespace/joinc-test created

$ kubectl run nginx --image=nginx --namespace=joinc-test
pod/nginx created

이제 pods를 확인해보자.

$ kubectl get pods --namespace=joinc-test
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          32s

--namespace를 설정하지 않을 경우 "default"가 기본 설정된다.

선호하는 네임스페이스 설정하기

매번 명령을 내릴 때마다 --namespace 옵션을 설정하는 것이 귀찮다면, kubectl 명령에서 사용하는 네임스페이스를 컨텍스트에 영구적으로 저장할 수 있다.

kubectl config set-context --current --namespace=<insert-namespace-name-here>
# 확인하기
kubectl config view --minify | grep namespace:

joinc-test를 컨텍스트에 설정하고 테스트해보자.

$ kubectl config set-context --current --namespace=joinc-test
Context "minikube" modified.

$ kubectl config view --minify | grep namespace              
    namespace: joinc-test

 # default 네임스페이스가 아닌 joinc-test 네임스페이스에서 명령이 실행된다.
$ kubectl get pods                             
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          17m

NameSpace에서 Service 만들기

kubernetes에서 제공하는 이미지를 이용해서 service를 만들어보자. 먼저 현재 네임스페이스가 joinc-test 인지 확인한다.

$ kubectl config view --minify -o jsonpath='{..namespace}'   
joinc-test

Deployment를 생성한다.

$ kubectl create deployment hello-node --image=registry.k8s.io/e2e-test-images/agnhost:2.39 -- /agnhost netexec --http-port=8080

hello-node deployment가 joinc-test 네임스페이스에서 만들어졌는지 확인해보자.

$ kubectl describe deployments hello-node                          
Name:                   hello-node
Namespace:              joinc-test
CreationTimestamp:      Sat, 22 Jul 2023 11:35:20 +0900
Labels:                 app=hello-node
Annotations:            deployment.kubernetes.io/revision: 1

kubectl expose 명령어로 파드를 노출해보자.

$ kubectl expose deployment hello-node --type=LoadBalancer --port=8080     
service/hello-node exposed

minikube tunnel로 터널을 만들고 curl로 테스트를 진행해보자.

$ minikube tunnel
[sudo] yundream 암호:    
Status:  
       machine: minikube  
       pid: 1046753  
       route: 10.96.0.0/12 -> 192.168.49.2  
       minikube: Running  
       services: [istio-ingressgateway, hello-node]  
   errors:    
               minikube: no errors  
               router: no errors  
               loadbalancer emulator: no errors

$ kubectl get services 
NAME         TYPE           CLUSTER-IP       EXTERNAL-IP      PORT(S)          AGE
hello-node   LoadBalancer   10.107.151.162   10.107.151.162   8080:31188/TCP   5m9s

$ curl 10.107.151.162:8080
NOW: 2023-07-22 03:11:22.570469401 +0000 UTC m=+2152.017558423

$ curl 10.107.151.162:8080
NOW: 2023-07-22 03:11:25.930869962 +0000 UTC m=+2155.377958974

이제 yundream-test 네임스페이스를 만들고 동일한 애플리케이션을 배포해보자.

$ kubectl create namespace yundream-test                                                                                        
namespace/yundream-test created

네임스페이스 context를 yundream-test로 전환한다.

$ kubectl config set-context --current --namespace=yundream-test
Context "minikube" modified.

hello-node를 실행한다.

$ kubectl create deployment hello-node --image=registry.k8s.io/e2e-test-images/agnhost:2.39 -- /agnhost netexec --http-port=8080
deployment.apps/hello-node created

같은 노드였다면 error: failed to create deployment: deployments.apps "hello-node" already exists 에러가 떴겠지만, 네임스페이스가 다르기 때문에 성공했다. deployments 정보를 확인해보자.

$ kubectl get deployments --all-namespaces | grep hello-node
joinc-test             hello-node                  1/1     1            1           40m
yundream-test          hello-node                  1/1     1            1           25s

두 개의 네임스페이스에 hello-node가 실행된 걸 확인 할 수 있다. pod를 expose 시켜보자.

$ kubectl expose deployment hello-node --type=LoadBalancer --port=8080
service/hello-node exposed

$ kubectl get services --all-namespaces | grep hello-node
joinc-test             hello-node                  LoadBalancer   10.107.151.162   10.107.151.162   8080:31188/TCP  20m
yundream-test          hello-node                  LoadBalancer   10.104.38.46     10.104.38.46     8080:31403/TCP  103s

두 개의 hello-node 가 실행된 걸 확인할 수 있다. curl로 두 개 서비스를 모두 테스트해보자.

$ curl 10.107.151.162:8080
NOW: 2023-07-22 03:24:36.237923291 +0000 UTC m=+2945.685012303

$ curl 10.104.38.46:8080  
NOW: 2023-07-22 03:24:45.062096052 +0000 UTC m=+584.241377926

참고