본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.
본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.
이미지 로딩 중...
AI Generated
2025. 11. 29. · 17 Views
Namespace로 쿠버네티스 클러스터 분리하기
쿠버네티스 클러스터에서 Namespace를 활용하여 리소스를 논리적으로 분리하고 멀티테넌시 환경을 구축하는 방법을 알아봅니다. 초급 개발자도 쉽게 이해할 수 있도록 실무 예제와 함께 설명합니다.
목차
1. Namespace 개념과 용도
어느 날 김개발 씨가 쿠버네티스 클러스터에 새로운 서비스를 배포하려고 했습니다. 그런데 이미 같은 이름의 서비스가 존재한다는 오류가 발생했습니다.
"분명히 저는 처음 배포하는 건데요?" 옆에 있던 박시니어 씨가 웃으며 말했습니다. "Namespace를 사용해야 할 때가 온 것 같네요."
Namespace는 하나의 쿠버네티스 클러스터를 여러 개의 가상 클러스터로 나누는 방법입니다. 마치 하나의 대형 사무실을 파티션으로 나누어 여러 팀이 독립적으로 사용하는 것과 같습니다.
이를 통해 리소스 이름 충돌을 방지하고, 팀별로 리소스를 격리하며, 접근 권한을 세밀하게 관리할 수 있습니다.
다음 코드를 살펴봅시다.
# 현재 클러스터의 모든 Namespace 조회
kubectl get namespaces
# 특정 Namespace의 리소스만 조회
kubectl get pods -n development
# Namespace를 지정하여 리소스 생성
kubectl create deployment nginx --image=nginx -n development
# 기본 Namespace 변경하기
kubectl config set-context --current --namespace=development
# Namespace 상세 정보 확인
kubectl describe namespace development
김개발 씨는 입사한 지 6개월 된 주니어 데브옵스 엔지니어입니다. 회사에서 운영하는 쿠버네티스 클러스터에 테스트용 nginx 서버를 배포하려고 했는데, 이미 존재한다는 오류 메시지를 마주했습니다.
분명히 본인은 처음 배포하는 건데 왜 이런 일이 생긴 걸까요? 선배 개발자 박시니어 씨가 다가와 상황을 살펴봅니다.
"아, 다른 팀에서 이미 같은 이름으로 배포해 놓은 게 있네요. 이럴 때 Namespace를 사용하면 문제가 해결됩니다." 그렇다면 Namespace란 정확히 무엇일까요?
쉽게 비유하자면, Namespace는 마치 대형 공유 오피스의 개별 사무실과 같습니다. 건물 전체는 하나의 쿠버네티스 클러스터이고, 각 사무실은 개별 Namespace입니다.
A 회사 사무실에 있는 프린터와 B 회사 사무실에 있는 프린터는 같은 모델이어도 서로 다른 것으로 취급됩니다. 마찬가지로 development Namespace의 nginx와 production Namespace의 nginx는 완전히 별개의 리소스입니다.
Namespace가 없던 시절에는 어땠을까요? 모든 리소스가 하나의 공간에 뒤섞여 있었습니다.
개발팀의 테스트 서버와 운영팀의 프로덕션 서버가 같은 곳에 있으니, 이름 충돌은 물론이고 실수로 잘못된 리소스를 삭제하는 사고도 종종 발생했습니다. 더 큰 문제는 누가 어떤 리소스를 사용하는지 파악하기 어려웠다는 것입니다.
바로 이런 문제를 해결하기 위해 Namespace가 등장했습니다. Namespace를 사용하면 같은 이름의 리소스를 여러 개 만들 수 있습니다.
또한 팀별로 독립적인 작업 공간을 제공할 수 있습니다. 무엇보다 접근 권한을 Namespace 단위로 설정할 수 있어서 보안 관리가 훨씬 수월해집니다.
위의 코드를 하나씩 살펴보겠습니다. 먼저 kubectl get namespaces 명령어는 클러스터에 존재하는 모든 Namespace를 조회합니다.
기본적으로 default, kube-system, kube-public 등이 보일 것입니다. 다음으로 -n 옵션을 사용하면 특정 Namespace의 리소스만 조회할 수 있습니다.
실제 현업에서는 어떻게 활용할까요? 예를 들어 개발, 스테이징, 프로덕션 환경을 하나의 클러스터에서 운영한다고 가정해봅시다.
각 환경을 development, staging, production이라는 Namespace로 분리하면, 개발자가 실수로 프로덕션 서버를 건드리는 사고를 방지할 수 있습니다. 하지만 주의할 점도 있습니다.
초보 개발자들이 흔히 하는 실수 중 하나는 Namespace를 지정하지 않고 리소스를 생성하는 것입니다. 이렇게 하면 default Namespace에 리소스가 생성되어 나중에 찾기 어려워집니다.
따라서 항상 -n 옵션으로 Namespace를 명시하는 습관을 들이는 것이 좋습니다. 다시 김개발 씨의 이야기로 돌아가 봅시다.
박시니어 씨의 조언대로 development Namespace를 만들어 그곳에 nginx를 배포하니 문제가 깔끔하게 해결되었습니다. "이제 이름 충돌 걱정 없이 마음껏 테스트할 수 있겠네요!"
실전 팁
💡 - 항상 -n 옵션으로 Namespace를 명시하는 습관을 들이세요
- kubectl config set-context로 기본 Namespace를 설정해두면 매번 입력할 필요가 없습니다
2. 기본 Namespace 이해
김개발 씨가 kubectl get namespaces 명령어를 실행하자 처음 보는 Namespace들이 나타났습니다. default, kube-system, kube-public, kube-node-lease.
"이건 제가 만든 게 아닌데 어디서 온 거죠?" 박시니어 씨가 설명을 시작했습니다. "쿠버네티스가 기본으로 제공하는 Namespace들이에요.
각각 중요한 역할을 하고 있죠."
쿠버네티스 클러스터를 생성하면 네 가지 기본 Namespace가 자동으로 만들어집니다. default는 사용자가 Namespace를 지정하지 않았을 때 사용되고, kube-system은 쿠버네티스 시스템 컴포넌트가 위치합니다.
kube-public은 모든 사용자가 읽을 수 있는 공개 리소스용이며, kube-node-lease는 노드의 상태를 추적합니다.
다음 코드를 살펴봅시다.
# 기본 Namespace들 확인
kubectl get namespaces
# NAME STATUS AGE
# default Active 10d
# kube-node-lease Active 10d
# kube-public Active 10d
# kube-system Active 10d
# kube-system의 중요 컴포넌트 확인
kubectl get pods -n kube-system
# 특정 Namespace의 상세 정보
kubectl describe namespace kube-system
# default Namespace에서 리소스 조회 (Namespace 생략 시 기본값)
kubectl get pods
김개발 씨는 호기심이 생겼습니다. 자신이 만들지도 않은 Namespace들이 이미 클러스터에 존재하고 있었기 때문입니다.
이 Namespace들은 도대체 무엇이고, 왜 존재하는 걸까요? 박시니어 씨가 차근차근 설명을 시작했습니다.
먼저 default Namespace는 이름 그대로 기본값입니다. 마치 컴퓨터의 다운로드 폴더처럼, 별도로 위치를 지정하지 않으면 모든 것이 이곳에 저장됩니다.
처음 쿠버네티스를 배우는 사람들은 대부분 이 Namespace에서 작업하게 됩니다. 다음으로 kube-system은 매우 중요한 Namespace입니다.
이곳에는 쿠버네티스의 핵심 컴포넌트들이 실행되고 있습니다. CoreDNS, kube-proxy, etcd 같은 시스템 Pod들이 여기에 위치합니다.
마치 컴퓨터의 운영체제 폴더와 같다고 생각하면 됩니다. 잘못 건드리면 클러스터 전체가 망가질 수 있으니 조심해야 합니다.
kube-public은 조금 특별한 Namespace입니다. 이곳의 리소스는 인증 없이도 모든 사용자가 읽을 수 있습니다.
주로 클러스터 정보나 공개 설정을 저장하는 데 사용됩니다. 실무에서는 잘 사용하지 않지만, 클러스터 부트스트래핑 과정에서 중요한 역할을 합니다.
마지막으로 kube-node-lease가 있습니다. 이 Namespace는 쿠버네티스 1.14 버전부터 도입되었습니다.
각 노드의 하트비트 정보를 저장하여 노드가 살아있는지 효율적으로 추적합니다. 노드 상태 확인을 위한 성능 최적화 용도라고 이해하면 됩니다.
위의 코드에서 kubectl get pods -n kube-system 명령어를 실행하면 클러스터의 핵심 컴포넌트들을 볼 수 있습니다. coredns, kube-apiserver, kube-scheduler 등의 Pod들이 나열됩니다.
이들은 클러스터의 두뇌와 같은 역할을 합니다. 실제 현업에서 이 기본 Namespace들은 어떻게 관리할까요?
대부분의 회사에서는 kube-system을 절대 건드리지 않는다는 규칙을 세웁니다. 시스템 컴포넌트가 있는 곳이니까요.
반면 default Namespace는 되도록 비워두고, 항상 용도에 맞는 별도의 Namespace를 만들어 사용합니다. 주의할 점이 있습니다.
초보자들이 자주 하는 실수는 kube-system에 자신의 애플리케이션을 배포하는 것입니다. "시스템용이니까 안전하겠지"라고 생각할 수 있지만, 오히려 시스템 리소스와 섞여서 관리가 복잡해집니다.
사용자 애플리케이션은 반드시 별도의 Namespace에 배포해야 합니다. 김개발 씨가 고개를 끄덕였습니다.
"아, 그래서 회사에서 default 대신 꼭 Namespace를 만들어 쓰라고 했던 거군요!"
실전 팁
💡 - kube-system Namespace의 리소스는 함부로 삭제하거나 수정하지 마세요
- default Namespace는 비워두고, 용도별로 별도의 Namespace를 생성하여 사용하세요
3. Namespace 생성 및 관리
박시니어 씨의 설명을 들은 김개발 씨가 물었습니다. "그러면 저희 팀만의 Namespace는 어떻게 만들 수 있나요?" 박시니어 씨가 미소를 지으며 답했습니다.
"두 가지 방법이 있어요. 명령어로 바로 만들거나, YAML 파일로 선언적으로 만들거나."
Namespace 생성은 크게 두 가지 방법으로 할 수 있습니다. kubectl create namespace 명령어를 사용하는 명령형 방식과, YAML 매니페스트 파일을 사용하는 선언형 방식입니다.
선언형 방식은 버전 관리가 가능하고 재사용성이 높아 실무에서 더 권장됩니다. 생성된 Namespace는 삭제, 라벨 추가 등 다양한 방식으로 관리할 수 있습니다.
다음 코드를 살펴봅시다.
# 방법 1: 명령형으로 Namespace 생성
kubectl create namespace development
# 방법 2: YAML 파일로 Namespace 생성
# namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
environment: production
team: backend
# YAML 파일 적용
kubectl apply -f namespace.yaml
# Namespace에 라벨 추가
kubectl label namespace development team=frontend
# Namespace 삭제 (주의: 내부 모든 리소스도 함께 삭제됨)
kubectl delete namespace development
김개발 씨는 드디어 자신만의 Namespace를 만들 시간이 되었습니다. 팀에서 사용할 개발 환경용 Namespace가 필요했거든요.
어떻게 만들어야 할까요? 박시니어 씨가 두 가지 방법을 알려주었습니다.
첫 번째는 명령형 방식입니다. kubectl create namespace development라고 입력하면 끝입니다.
마치 폴더를 만들 때 mkdir 명령어를 사용하는 것처럼 간단합니다. 빠르게 테스트할 때 유용한 방법이죠.
두 번째는 선언형 방식입니다. YAML 파일에 Namespace의 설정을 작성하고, kubectl apply 명령어로 적용합니다.
이 방법은 조금 더 손이 가지만 큰 장점이 있습니다. 파일을 Git에 저장하면 변경 이력을 추적할 수 있고, 다른 환경에서도 동일한 설정을 재사용할 수 있습니다.
왜 선언형 방식이 실무에서 더 선호될까요? 인프라를 코드로 관리하는 Infrastructure as Code 원칙 때문입니다.
YAML 파일로 Namespace를 정의해두면, 새로운 클러스터를 구축할 때도 동일한 파일을 적용하기만 하면 됩니다. 명령어로 일일이 입력하는 것보다 훨씬 실수가 적고 일관성 있게 관리할 수 있습니다.
위의 코드에서 labels 부분을 주목해보세요. 라벨은 Namespace를 분류하고 검색하는 데 유용합니다.
environment: production이라는 라벨을 붙여두면 나중에 모든 프로덕션 환경의 Namespace만 조회할 수 있습니다. team: backend 라벨로는 백엔드 팀이 관리하는 Namespace를 쉽게 파악할 수 있죠.
Namespace 삭제 시에는 매우 주의해야 합니다. kubectl delete namespace development 명령어를 실행하면 해당 Namespace 안의 모든 리소스가 함께 삭제됩니다.
Pod, Service, ConfigMap 등 모든 것이 사라집니다. 마치 폴더를 삭제하면 안에 있는 파일이 모두 삭제되는 것과 같습니다.
실수로 프로덕션 Namespace를 삭제하면 대참사가 벌어질 수 있으니 항상 신중하게 확인해야 합니다. 실무에서는 Namespace 삭제 권한을 엄격히 제한합니다.
대부분의 회사에서는 일반 개발자에게 Namespace 삭제 권한을 주지 않습니다. RBAC를 설정하여 관리자만 삭제할 수 있도록 제한하죠.
이 부분은 나중에 권한 관리를 배울 때 더 자세히 다루게 됩니다. 김개발 씨가 팀용 Namespace를 성공적으로 만들었습니다.
"이제 우리 팀만의 작업 공간이 생겼네요!"
실전 팁
💡 - 실무에서는 YAML 파일로 Namespace를 정의하고 Git으로 관리하세요
- Namespace 삭제 전에는 반드시 내부 리소스를 확인하세요. 모든 것이 함께 삭제됩니다
4. 리소스 쿼터 설정
얼마 후 김개발 씨가 황급히 박시니어 씨를 찾아왔습니다. "선배님, 클러스터가 너무 느려졌어요!" 확인해보니 테스트 팀에서 부하 테스트를 하면서 클러스터의 모든 리소스를 사용해버린 상황이었습니다.
"이런 일을 방지하려면 ResourceQuota를 설정해야 해요."
ResourceQuota는 Namespace별로 사용할 수 있는 리소스의 최대량을 제한하는 기능입니다. 마치 휴대폰 요금제처럼 CPU, 메모리, Pod 개수 등에 상한선을 설정할 수 있습니다.
이를 통해 하나의 팀이 클러스터 전체 리소스를 독점하는 것을 방지하고, 공정하게 리소스를 분배할 수 있습니다.
다음 코드를 살펴봅시다.
# resource-quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: development-quota
namespace: development
spec:
hard:
requests.cpu: "4" # CPU 요청 총합 최대 4코어
requests.memory: 8Gi # 메모리 요청 총합 최대 8GB
limits.cpu: "8" # CPU 상한 총합 최대 8코어
limits.memory: 16Gi # 메모리 상한 총합 최대 16GB
pods: "20" # 최대 Pod 개수
services: "10" # 최대 Service 개수
persistentvolumeclaims: "5" # 최대 PVC 개수
# ResourceQuota 적용
kubectl apply -f resource-quota.yaml
# 현재 사용량 확인
kubectl describe resourcequota development-quota -n development
김개발 씨는 당황스러웠습니다. 분명 자신은 조용히 개발만 하고 있었는데, 갑자기 클러스터 전체가 느려져서 작업을 할 수 없게 되었거든요.
원인을 찾아보니 옆 팀에서 부하 테스트를 진행하면서 CPU와 메모리를 모두 사용해버린 것이었습니다. 박시니어 씨가 해결책을 제시했습니다.
"이런 일을 방지하려면 ResourceQuota를 설정해야 해요." ResourceQuota는 무엇일까요? 쉽게 비유하자면, 마치 월세 아파트의 관리비와 같습니다.
각 세대는 정해진 양의 전기와 수도를 사용할 수 있고, 그 이상 사용하면 제한됩니다. 한 세대가 전력을 독점해서 다른 세대가 피해를 보는 일이 없도록 말이죠.
ResourceQuota도 마찬가지로 각 Namespace가 사용할 수 있는 리소스의 최대량을 정해둡니다. 위의 YAML 파일을 자세히 살펴보겠습니다.
requests와 limits라는 두 가지 개념이 있습니다. requests는 "최소한 이만큼은 필요해요"라는 의미이고, limits는 "이 이상은 사용할 수 없어요"라는 의미입니다.
예를 들어 requests.cpu: "4"는 해당 Namespace 전체에서 CPU 요청의 총합이 4코어를 넘을 수 없다는 뜻입니다. pods: "20"은 어떤 의미일까요?
해당 Namespace에서 최대 20개의 Pod만 실행될 수 있다는 뜻입니다. 21번째 Pod를 생성하려고 하면 쿼터 초과 오류가 발생합니다.
이렇게 하면 테스트 팀이 아무리 많은 Pod를 만들어도 20개까지만 생성되니, 다른 팀에 영향을 주지 않습니다. ResourceQuota를 설정하면 어떤 일이 벌어질까요?
새로운 Pod를 생성할 때 쿠버네티스가 자동으로 쿼터를 확인합니다. 쿼터를 초과하는 요청은 거부됩니다.
"리소스 쿼터를 초과했습니다"라는 오류 메시지와 함께요. 개발자는 자신이 속한 Namespace의 리소스 사용량을 확인하고, 필요하다면 기존 리소스를 정리해야 합니다.
실무에서는 팀별로 다른 쿼터를 설정합니다. 예를 들어 프로덕션 Namespace에는 넉넉한 리소스를 할당하고, 개발 Namespace에는 상대적으로 적은 리소스를 할당합니다.
이렇게 하면 개발 환경에서 아무리 실수를 해도 프로덕션 서비스에 영향을 주지 않습니다. 주의할 점도 있습니다.
ResourceQuota를 설정하면 Pod 생성 시 반드시 resources 필드를 명시해야 합니다. requests와 limits를 지정하지 않은 Pod는 생성이 거부됩니다.
이 부분에서 처음 접하는 개발자들이 많이 헤매는데, LimitRange라는 기능으로 기본값을 설정해두면 편합니다. 김개발 씨가 ResourceQuota의 중요성을 깨달았습니다.
"앞으로는 테스트할 때도 우리 팀 Namespace 안에서만 영향이 있겠네요!"
실전 팁
💡 - ResourceQuota를 설정하면 Pod에 반드시 resources 필드를 명시해야 합니다
- LimitRange를 함께 사용하면 기본 리소스 값을 자동으로 적용할 수 있습니다
5. Namespace 간 통신
김개발 씨의 팀이 개발한 프론트엔드 서비스는 frontend Namespace에, 다른 팀이 개발한 백엔드 API는 backend Namespace에 배포되어 있었습니다. "그런데 프론트엔드에서 백엔드 API를 어떻게 호출하죠?
Namespace가 다르잖아요." 박시니어 씨가 DNS에 대해 설명하기 시작했습니다.
Namespace가 다르더라도 서비스 간 통신은 가능합니다. 쿠버네티스의 DNS 시스템을 통해 다른 Namespace의 서비스를 호출할 수 있습니다.
서비스 이름 뒤에 Namespace를 붙여 <서비스명>.<네임스페이스>.svc.cluster.local 형식으로 접근합니다. 필요하다면 NetworkPolicy로 통신을 제한할 수도 있습니다.
다음 코드를 살펴봅시다.
# 같은 Namespace 내에서 서비스 호출 (Namespace 생략 가능)
curl http://api-service
# 다른 Namespace의 서비스 호출 (전체 DNS 이름 사용)
curl http://api-service.backend.svc.cluster.local
# 축약형으로도 호출 가능
curl http://api-service.backend
# NetworkPolicy로 특정 Namespace에서만 접근 허용
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-only
namespace: backend
spec:
podSelector: {}
ingress:
- from:
- namespaceSelector:
matchLabels:
name: frontend
김개발 씨는 새로운 고민에 빠졌습니다. 프론트엔드 애플리케이션을 개발했는데, 백엔드 API가 다른 Namespace에 있었거든요.
"Namespace로 분리해서 좋긴 한데, 이러면 통신은 어떻게 하죠?" 박시니어 씨가 웃으며 답했습니다. "걱정 마세요.
쿠버네티스에는 훌륭한 DNS 시스템이 있어요." 쿠버네티스 내부에는 CoreDNS라는 DNS 서버가 있습니다. 마치 전화번호부처럼, 서비스 이름을 IP 주소로 변환해줍니다.
같은 Namespace 안에서는 서비스 이름만으로 통신이 가능합니다. api-service라고만 입력해도 자동으로 같은 Namespace의 api-service를 찾아줍니다.
하지만 다른 Namespace의 서비스는 어떨까요? 이때는 전체 DNS 이름을 사용해야 합니다.
형식은 <서비스명>.<네임스페이스>.svc.cluster.local입니다. 예를 들어 backend Namespace에 있는 api-service에 접근하려면 api-service.backend.svc.cluster.local이라고 입력합니다.
다행히 축약형도 사용 가능합니다. api-service.backend만 입력해도 됩니다.
svc.cluster.local 부분은 생략해도 쿠버네티스가 알아서 찾아줍니다. 하지만 명확성을 위해 전체 이름을 사용하는 것도 좋은 습관입니다.
그런데 모든 Namespace가 서로 통신할 수 있다면 보안상 문제가 되지 않을까요? 바로 이럴 때 NetworkPolicy가 필요합니다.
NetworkPolicy는 네트워크 수준에서 트래픽을 제어하는 방화벽과 같은 역할을 합니다. 위의 예제에서는 backend Namespace의 서비스가 frontend Namespace에서 오는 요청만 허용하도록 설정했습니다.
위의 NetworkPolicy YAML을 자세히 살펴보겠습니다. namespaceSelector를 사용하여 frontend라는 라벨이 붙은 Namespace에서 오는 트래픽만 허용합니다.
다른 Namespace에서 접근하려고 하면 연결이 차단됩니다. 이렇게 하면 개발 환경에서 실수로 프로덕션 데이터베이스에 접근하는 사고를 방지할 수 있습니다.
실무에서는 기본적으로 모든 통신을 차단하고, 필요한 것만 허용하는 방식을 사용합니다. 이를 화이트리스트 방식이라고 합니다.
처음에는 번거롭지만, 보안 사고를 예방하는 데 매우 효과적입니다. 특히 민감한 데이터를 다루는 Namespace는 NetworkPolicy 설정이 필수입니다.
김개발 씨가 환하게 웃었습니다. "Namespace로 분리하면서도 필요한 통신은 할 수 있고, 불필요한 통신은 막을 수 있군요!"
실전 팁
💡 - 다른 Namespace의 서비스 호출 시 <서비스명>.<네임스페이스> 형식을 사용하세요
- 보안이 중요한 환경에서는 NetworkPolicy로 Namespace 간 통신을 제한하세요
6. 멀티테넌시 구현
김개발 씨의 회사가 성장하면서 여러 고객사에게 같은 서비스를 제공하게 되었습니다. "각 고객사마다 별도의 클러스터를 만들어야 하나요?
비용이 너무 많이 들 것 같은데요." 박시니어 씨가 말했습니다. "Namespace를 활용한 멀티테넌시로 해결할 수 있어요."
멀티테넌시란 하나의 시스템을 여러 사용자 또는 조직이 독립적으로 사용하는 아키텍처입니다. 쿠버네티스에서는 Namespace를 활용하여 각 테넌트(고객사)에게 독립된 환경을 제공할 수 있습니다.
ResourceQuota, NetworkPolicy, RBAC를 함께 사용하면 리소스 격리, 네트워크 격리, 접근 권한 격리를 모두 구현할 수 있습니다.
다음 코드를 살펴봅시다.
# 테넌트별 Namespace 생성
kubectl create namespace tenant-companya
kubectl create namespace tenant-companyb
# 테넌트별 ResourceQuota 적용
apiVersion: v1
kind: ResourceQuota
metadata:
name: tenant-quota
namespace: tenant-companya
spec:
hard:
requests.cpu: "2"
requests.memory: 4Gi
pods: "10"
# 테넌트별 RBAC 설정
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: tenant-admin
namespace: tenant-companya
subjects:
- kind: User
name: companya-admin
roleRef:
kind: ClusterRole
name: admin
apiGroup: rbac.authorization.k8s.io
김개발 씨의 회사가 빠르게 성장했습니다. 이제 여러 고객사에게 SaaS 서비스를 제공하게 되었는데, 각 고객사마다 독립된 환경이 필요했습니다.
고객사 A의 데이터가 고객사 B에게 보여서는 안 되니까요. 처음에는 고객사마다 별도의 클러스터를 만들까 고민했습니다.
하지만 비용이 문제였습니다. 쿠버네티스 클러스터 하나를 운영하는 데도 상당한 비용이 드는데, 고객사가 100개라면 100개의 클러스터를 운영해야 할까요?
박시니어 씨가 더 좋은 방법을 제안했습니다. "멀티테넌시를 구현하면 됩니다." 멀티테넌시란 무엇일까요?
마치 대형 쇼핑몰과 같습니다. 하나의 건물 안에 여러 상점이 입주해 있지만, 각 상점은 독립적으로 운영됩니다.
한 상점의 고객이 다른 상점의 재고를 볼 수 없고, 각 상점은 자신만의 공간을 가집니다. 쿠버네티스에서도 하나의 클러스터 안에 여러 테넌트(고객사)가 독립적으로 존재할 수 있습니다.
이를 구현하려면 세 가지 격리가 필요합니다. 첫째, 리소스 격리입니다.
앞서 배운 ResourceQuota로 각 테넌트가 사용할 수 있는 CPU, 메모리, Pod 개수를 제한합니다. 한 고객사가 모든 리소스를 독점하면 다른 고객사가 피해를 보니까요.
둘째, 네트워크 격리입니다. NetworkPolicy로 테넌트 간 네트워크 통신을 차단합니다.
고객사 A의 Pod가 고객사 B의 데이터베이스에 접근하면 안 되니까요. 셋째, 접근 권한 격리입니다.
RBAC(Role-Based Access Control)을 설정하여 각 테넌트의 관리자가 자신의 Namespace만 관리할 수 있도록 합니다. 고객사 A의 관리자가 고객사 B의 리소스를 삭제하면 안 되니까요.
위의 RoleBinding 예제를 살펴보겠습니다. companya-admin이라는 사용자에게 tenant-companya Namespace에 대한 admin 권한을 부여합니다.
이 사용자는 자신의 Namespace에서는 무엇이든 할 수 있지만, 다른 Namespace에는 접근조차 할 수 없습니다. 완벽한 격리가 이루어진 것이죠.
실무에서 멀티테넌시를 구현할 때 고려할 점이 있습니다. Namespace 이름에 테넌트 식별자를 포함하는 것이 좋습니다.
tenant-companya처럼요. 그리고 모든 설정을 자동화하는 것이 중요합니다.
새로운 고객사가 추가될 때마다 Namespace, ResourceQuota, NetworkPolicy, RBAC를 수동으로 설정하면 실수가 발생하기 쉽습니다. Helm 차트나 Operator 패턴을 활용하여 자동화하는 것을 권장합니다.
주의할 점도 있습니다. Namespace 기반 멀티테넌시는 소프트 멀티테넌시라고 부릅니다.
커널이나 네트워크 레벨의 완벽한 격리가 아니기 때문입니다. 극도로 민감한 데이터를 다루는 경우에는 별도의 클러스터를 사용하는 것이 안전합니다.
하지만 대부분의 상황에서는 Namespace 기반 격리로 충분합니다. 김개발 씨가 감탄했습니다.
"하나의 클러스터로 여러 고객사를 관리할 수 있다니, 비용도 절약되고 관리도 편해지겠네요!"
실전 팁
💡 - 멀티테넌시 구현 시 ResourceQuota, NetworkPolicy, RBAC를 반드시 함께 설정하세요
- 새로운 테넌트 추가 과정을 자동화하여 일관성을 유지하고 실수를 방지하세요
이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!
댓글 (0)
함께 보면 좋은 카드 뉴스
Istio 보안 완벽 가이드
마이크로서비스 환경에서 필수적인 Istio 보안 기능을 실무 중심으로 설명합니다. mTLS부터 인증, 인가까지 단계별로 학습하여 안전한 서비스 메시를 구축할 수 있습니다.
Istio 트래픽 관리 완벽 가이드
Istio의 트래픽 관리 기능을 마스터하는 완벽 가이드입니다. VirtualService와 DestinationRule을 활용한 라우팅부터 트래픽 분할, 헤더 기반 라우팅까지 실무에 필요한 모든 내용을 다룹니다.
Istio 설치와 구성 완벽 가이드
Kubernetes 환경에서 Istio 서비스 메시를 설치하고 구성하는 방법을 초급 개발자도 쉽게 이해할 수 있도록 실무 스토리와 비유로 풀어낸 가이드입니다. istioctl 설치부터 사이드카 주입까지 단계별로 학습합니다.
서비스 메시 완벽 가이드
마이크로서비스 간 통신을 안전하고 효율적으로 관리하는 서비스 메시의 핵심 개념부터 실전 도입까지, 초급 개발자를 위한 완벽한 입문서입니다. Istio와 Linkerd 비교, 사이드카 패턴, 실무 적용 노하우를 담았습니다.
Helm 마이크로서비스 패키징 완벽 가이드
Kubernetes 환경에서 마이크로서비스를 효율적으로 패키징하고 배포하는 Helm의 핵심 기능을 실무 중심으로 학습합니다. Chart 생성부터 릴리스 관리까지 체계적으로 다룹니다.