기존에 운영하던 애플리케이션은 개발환경 dev, staging, production 마다 별도의 GCP(Google Cloud Platform) 프로젝트로 분리되어 있었으며, 각 환경마다 별도의 GKE 클러스터를 쓰고 있었다. 환경 별로 프로젝트를 분리하면 어떤 자원을 쓰고 있는지 명확히 볼 수 있고 요금 관리를 할 수 있는 장점은 있다.
만약 GCP에서 애플리케이션 배포에 App Engine을 활용한다면, 눈물을 머금고 환경마다 프로젝트를 분리해야 하지만...쿠버네티스 클러스터를 애플리케이션 인프라로 사용할 때는 좋은 방법은 아니다.
왜냐하면 GKE(Google Kubernetes Engine)는 한 결제 계정 당 하나의 클러스터 마스터 노드 까지는 무료로 제공하나, 그 이후 추가되는 클러스터의 마스터 노드에는 한달에 약 7만원에서 10만원 정도 비용을 청구한다.
쿠버네티스는 단일 클러스터 내에서 여러 환경 및 애플리케이션을 논리적으로 분리하고, 리소스를 제한할 수 있는 namespace라는 메커니즘을 제공한다. 오늘은 namespace에 대해 설명하고 도입한 과정을 소개하고자 한다.
쿠버네티스에서는 namespace를 통해서 단일 클러스터 내에 리소스들을 그룹화하여 격리할 수 있다. 리소스의 이름은 namespace 안에서 유일해야하며, 클러스터 전체에서 유일할 필요는 없다.
Deployment, service같은 오브젝트는 namespace로 분리할 수 있지만, storage class나 persistent volume과 같은 클러스터 전역적인 오브젝트는 namespace로 분리할 수 없다.
Namespace는 클러스터를 논리적으로 분리하는 것이지 물리적으로 분리하는 것은 아니다. 예컨데 클러스터에 전체에 장애가 나면 네임스페이스와 관계 없이 문제가 생긴다. 또 클러스터 내 특정 노드에 문제가 생기면, 네임스페이스와 관련 없이 노드에서 실행되고 있는 모든 pod들에 문제가 생기므로 namespace가 클러스터를 물리적으로 분리하는 것은 절대 아니다.
Namespace를 사용하기 위해서 아래와 같이 yaml을 작성하여 배포하면 된다.
apiVersion: v1
kind: Namespace
metadata:
name: production
spec:
limits:
- default:
cpu: 1
type: Container
metadata의 name이 namespace의 identifier가 된다. spec:을 통해 namespace 내 리소스 할당량도 지정할 수 있다. 이를 통해 팀 및 환경 별 클러스터 사용량을 정할 수 있어 클러스터 관리에 용이하다.
특정 deployment 에 namespace를 지정하려면 아래와 같이 설정하면 된다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
labels:
app: backend
namespace: production
생성된 네임스페이스를 보고싶다면, 다음 명령어를 통해 조회할 수 있다.
kubectl get namespaces
만든 namespace를 삭제하는 것도 가능하다.
kubectl delete namespace
위 명령어를 실행하면 namespace가 삭제되며 이 때 namespace 안에 있는 모든 오브젝트들이 한번에 삭제된다.
기존 애플리케이션의 관리 방식과 다르게 이번 개발 프로젝트에서는 하나의 GCP 프로젝트를 만들고, 단일 GKE 클러스터 내에서 namespace를 활용하여 dev, staging, production 각각의 개발환경을 구축하고 분리시켰다.
Celery worker를 실행하는데 사용하는 메시지 브로커인 RabbitMQ는 RabbitMQ 자체적으로 Vhost를 통해 Multi tenant 기능을 제공하기 때문에 Rabbitmq와 관련된 오브젝트들은 rabbitmq namespace로 분리하였다.
GCP 프로젝트 통합과 namespace별 환경 분리를 통해서, 클라우드 인프라 비용을 더 효율적으로 사용할 수 있게 되었으며, 클러스터 관리도 좀 더 수월해졌다. 다만 예전에는 프로젝트 별 IAM을 통해 클러스터 접근 권한을 제어할 수 있어서 편했는데, 이제는 RBAC와 같은 k8s 내부의 접근 권한 제어를 사용해야해서 조금 번거로워졌다. 이 부분은 개발 팀이 더 커지고 피쳐 이슈가 줄어들면 고려해보기로...(지금은 POC 하느라 정신이..)