쿠버네티스에서 멀티테넌시를 설계하다 보면 네임스페이스 기반 논리 격리(soft isolation)와 클러스터 분리(physical isolation) 사이에서 늘 고민하게 됩니다. 이 글에서는 주요 클라우드/보안 벤더의 가이드와 제 경험적 관점을 엮어, 어디까지를 같은 클러스터에서 공유하고 어디부터 분리할지를 판단하는 프레임을 정리해보겠습니다.
멀티테넌시 격리, “경계”부터 다시 잡기
멀티테넌시 격리를 이야기할 때 핵심은 “무엇을 서로 못 보게/못 만지게 할 것인가”입니다. Sysdig는 격리 경계를 크게 3개로 나눕니다.
- 컨트롤플레인/API 경계: Namespace, RBAC 등으로 “리소스 접근”을 분리합니다.
- 호스트/런타임 경계: 컨테이너는 결국 리눅스 커널을 공유하므로, 노드 침해/커널 취약점/권한상승 같은 리스크가 남습니다.
- 네트워크 경계: NetworkPolicy 등으로 동서 트래픽을 제어합니다.
많은 팀이 첫 번째(네임스페이스+RBAC)에서 시작하지만, 실제로 문제가 되는 지점은 두 번째(노드/커널 경계)거나, 운영적으로는 “리소스 보장” 같은 가용성 이슈인 경우가 많습니다.
“Namespace + RBAC + Quota + NetworkPolicy”는 왜 soft isolation인가
AWS EKS와 Azure AKS 가이드에서 공통적으로 강조하는 메시지는 명확합니다.
- Namespace, RBAC, ResourceQuota, NetworkPolicy는 논리적(soft) 격리입니다.
- 더 강한 보안 경계는 결국 클러스터/노드(호스트) 수준에 가깝습니다.
- 호스트가 침해되면(또는 권한상승이 발생하면) 같은 노드/클러스터 내 다른 테넌트의 Secret, 네트워크, 메타데이터로 피해가 번질 수 있습니다.
EKS 문서에서는 예시로 기본 설정에서 발생 가능한 DNS(CoreDNS) 기반 정보 노출 같은 리스크도 언급하며, “기본값을 믿지 말고” 플러그인/정책으로 보완하거나 필요 시 샌드박싱(Fargate 등) 까지 고려하라고 권합니다. AKS 역시 “비신뢰(적대적) 테넌트”의 경우에는 논리 격리만으로는 부족하며, 하이퍼바이저 수준 신뢰가 필요할 수 있어 물리적으로 분리된 클러스터가 더 적절하다고 봅니다.
정리하면, 네임스페이스 중심 설계는 “좋은 기본”이지만, 위협 모델이 바뀌는 순간 한계가 분명합니다.
운영 관점의 현실: 제가 자주 부딪힌 건 “보안”보다 “최소 보장 리소스”였습니다
대화에서 저는 “클러스터 분리의 명확한 기준”을 고민하다가, 결국 워크로드 성격별 리소스 단위로 보고 싶다는 이야기가 나왔습니다. 특히 공감했던 포인트는 이거였습니다.
- Namespace + ResourceQuota는 최대치(폭주) 제한엔 유리하지만,
- 현장에서 더 어려운 건 최소치(보장) 입니다.
- 보장 실패는 최종적으로 P95 응답지연 악화나 OOM 같은 형태로 드러납니다.
여기서 중요한 인사이트가 하나 있습니다.
- Quota만으로는 “최소 보장”이 만들어지지 않습니다.
- 최소 보장은 결국 스케줄러가 이해하는 단위인 requests(예약), 그리고 경쟁 상황에서 누구를 살릴지 결정하는 PriorityClass/Preemption 쪽으로 내려가야 합니다.
- “설계자 관점에서 마음 편한 방식”으로 자주 선택되는 것이 전용 노드풀(dedicated node pool) 입니다. (클러스터를 쪼개는 것보다는 운영 복잡도가 낮아지는 경우가 많습니다)
스윗 스팟: “클러스터는 공유하되, 워크로드 클래스별로 격리 레벨을 다르게”
모든 워크로드를 클러스터로 분리하면 보안/격리는 강해지지만 비용과 운영 복잡도가 급격히 올라갑니다. 반대로 모두를 한 클러스터에 담고 네임스페이스만 나누면, 설계는 단순해도 보안팀/감사/장애 전파 측면에서 곧 벽을 만납니다.
제가 현실적인 중간 지점(sweet spot)으로 보는 접근은 다음과 같습니다.
1) 테넌트를 “팀”이 아니라 “워크로드 클래스”로 정의하기
예를 들어 이런 식입니다.
- Public-facing (인터넷 노출)
- PII/규제 데이터 처리
- Batch/ETL
- Internal tools
- 실험/개발 환경
이렇게 나누면 “누가 소유하냐”보다 “어떤 위험/요구사항을 갖느냐”로 격리 강도를 결정할 수 있습니다.
2) 기본은 네임스페이스 기반 + 하드닝 번들로 시작하기
AKS가 제시하는 축(인증/인가, 네트워크, 정책, 런타임 하드닝)은 정석입니다.
- RBAC 최소권한
- NetworkPolicy default-deny(필요한 통신만 허용)
- ResourceQuota/LimitRange로 폭주 제한
- Pod Security Admission(PSA) 등으로 특권 실행을 구조적으로 막기
- 가능하면 seccomp / AppArmor 같은 런타임 하드닝도 함께
이 조합은 “같은 클러스터에서 최대한 안전하게 공유”하기 위한 기본 체력에 가깝습니다.
3) “최소 보장 리소스”가 핵심이면 스케줄링 계층을 설계에 포함하기
최소 보장을 실질적으로 다루려면 아래가 같이 움직여야 합니다.
resources.requests를 제대로 잡아 노드에서 예약되게 만들기- 중요 워크로드는
PriorityClass로 우선순위를 부여하고, 필요하면 preemption을 허용하기 - (상황에 따라) HPA/VPA로 수요 변화에 대응하기
간단한 예시는 아래처럼 시작할 수 있습니다.
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: tier-critical
value: 100000
preemptionPolicy: PreemptLowerPriority
globalDefault: false
description: "Latency SLO가 엄격한 크리티컬 서비스용 우선순위"
apiVersion: v1
kind: Pod
metadata:
name: api
spec:
priorityClassName: tier-critical
containers:
- name: api
image: my-api:1.0
resources:
requests:
cpu: "500m"
memory: "1Gi"
limits:
cpu: "1"
memory: "1Gi"
requests는 “최소 보장에 가까운 예약”을 만드는 출발점입니다.limits를 어떻게 잡느냐는 서비스 성격에 따라 다르지만, 메모리는 특히 OOM과 직결되므로 운영 정책이 필요합니다.
4) 그래도 마음이 불편한 구간은 “전용 노드풀”로 한 단계 올리기
제가 동의했던 포인트는, 전용 노드풀은 설계자가 보기엔 경계가 명확해진다는 점입니다. 구현은 보통 이런 형태로 갑니다.
- 특정 워크로드 클래스 전용 노드풀에
taint를 주고 - 해당 워크로드만
toleration을 가져가도록 강제합니다. - 필요하면
nodeAffinity까지 더해 “이 클래스는 여기로만 간다”를 고정합니다.
이 방식은 “클러스터 분리”보다 한 단계 약하지만, 최소 보장 리소스나 고장 전파 최소화(blast radius) 측면에서 체감 효과가 큽니다. 대신 bin-packing이 깨지고 유휴 비용이 생길 수 있으니, 클래스 수를 과도하게 늘리면 스윗 스팟을 넘기기 쉽습니다.
결국 클러스터 분리는 언제? “비신뢰 테넌트”와 “경계 증명”이 필요할 때입니다
Azure 문서의 표현처럼, 테넌트가 “적대적”일 수 있다면(서로 신뢰하지 않는 고객, 외부 조직, 강한 규제) 논리 격리는 원천적으로 불리해집니다. 같은 커널/호스트를 공유하는 순간, 아무리 RBAC를 잘해도 호스트 침해 시나리오를 완전히 지우기 어렵기 때문입니다.
따라서 제가 권하는 판단 기준은 이렇게 정리됩니다.
- 목표가 비용/운영 효율이고, 테넌트가 조직 내부이며 위협 모델이 제한적이라면
→ 네임스페이스 기반 + 하드닝 + (필요 시) 전용 노드풀 - 목표가 강한 보안 경계의 “증명”(감사/규제/외부 고객 계약)이고, 테넌트가 비신뢰라면
→ 클러스터 분리(또는 샌드박스/하이퍼바이저 경계) 쪽으로 기우는 게 합리적
GKE 문서가 “운영 관점의 준비”와 멀티클러스터/Fleet 같은 관리 모델을 강조하는 것도 같은 맥락입니다. 분리는 보안을 올리지만 운영을 어렵게 만들기 때문에, 결국 멀티클러스터를 관리하는 체계가 같이 필요해집니다.
멀티테넌시 모델 선택지: 클러스터를 몇 개로 쪼갤 것인가, 컨트롤플레인을 쪼갤 것인가
CECG 글은 멀티테넌시 모델을 비교합니다.
- 멀티클러스터: 격리 강하지만 비용/운영 부담 증가
- 다중 컨트롤플레인(vcluster, Kamaji 등): 격리/커스터마이징 균형점이 될 수 있음
- 공유 컨트롤플레인: 운영 효율은 좋지만 격리 한계가 큼
여기서 얻을 수 있는 인사이트는, “클러스터 분리”만이 답이 아니라 컨트롤플레인 분리라는 중간 선택지도 있다는 점입니다. 다만 도입하면 플랫폼 팀의 역량(업그레이드, 애드온, 장애 대응)이 필수로 따라옵니다.
마무리: 격리는 보안만의 문제가 아니라, ‘보장’과 ‘경계’를 어디에 둘지의 문제입니다
네임스페이스 기반 격리는 기본이지만, 그것만으로는 충분하지 않은 순간이 분명히 옵니다. 제가 생각하는 현실적인 접근은 워크로드를 클래스화하고, 기본 하드닝을 깔되, “최소 보장 리소스”나 강한 경계가 필요한 클래스만 전용 노드풀(혹은 샌드박스/클러스터 분리) 로 단계적으로 올리는 것입니다. 결국 중요한 건, 우리 조직의 SLO(예: P95 latency 절대 기준)와 실패 신호(예: OOM은 크리티컬)를 합의해두고, 그에 맞는 격리 레벨을 설계하는 일입니다.