안녕하세요. 인포그랩 DevOps 엔지니어 Chris입니다. Kubernetes는 현대 클라우드 네이티브 애플리케이션의 확장성과 복원력을 지원하는 핵심 기술입니다. 그러나 Kubernetes 환경이 성장함에 따라 여러 클러스터를 관리하는 과정에서 예상치 못한 운영 부담과 비용 증가 문제가 발생합니다.
예를 들어, 물리적 Kubernetes 클러스터를 여러 개 운영하면 컴퓨팅 노드, 스토리지, 네트워킹 리소스 비용이 많이 듭니다. 클러스터 관리와 운영에도 상당한 시간과 노력이 필요하죠. 이에 클러스터 간 일관성을 유지하고, 보안 정책을 동일하게 적용하는 과정에서 엔지니어의 피로도는 많이 증가합니다.
특히 DevOps 팀은 개발자에게 격리된 샌드박스 환경을 제공해야 할 때가 많은데요. 아울러 개발 환경과 테스트 환경, 운영 환경을 분리해 독립적인 환경을 마련해야 할 때도 많습니다. 이를 위해 초기에는 네임스페이스(Namespace) 기반 분리를 시도하는데요. 그러나 이 방법만으로는 CRD(Custom Resource Definition) 충돌 방지나 세분화된 클러스터 롤(Cluster Role) 분리가 어렵습니다. 결국 팀별·환경별로 물리적 Kubernetes 클러스터를 생성해 ‘운영 부담과 비용 증가’라는 악순환을 반복하죠.
그러나 vCluster(virtual Cluster)를 사용하면 이 문제를 원활히 해결할 수 있습니다. vCluster는 기존에 구성된 Kubernetes 클러스터 안에 가상화된 경량 Kubernetes 클러스터를 생성하는 기술인데요. 이는 물리적 클러스터와 비슷한 수준의 격리 효과를 제공하고, 전체 관리 부담과 운영 비용도 크게 절감합니다.
이 글에서는 vCluster 설치부터 애플리케이션 배포, 리소스 연결과 격리, 네트워크 구조에 이르기까지 vCluster 환경을 실질적으로 운용하는 데 필요한 핵심 과정을 실습 예제와 함께 자세히 살펴보겠습니다.
vCluster 개념과 구성
vCluster(virtual Cluster)는 Kubernetes 클러스터의 네임스페이스 내부에서 작동하는 경량 가상 클러스터 생성 기술입니다. 이는 일반적인 가상 머신(VM)처럼 가상화돼 있지 않고, Kubernetes Control Plane 자체를 가상화한 점이 특징이죠. vCluster는 CNCF(Cloud Native Computing Foundation) 샌드박스 단계에 있는 프로젝트로, 큰 잠재력과 혁신성을 인정받고 있습니다.
vCluster 아키텍처

vCluster는 기본적으로 StatefulSet으로 관리되는 단일 Pod로 배포됩니다. 주요 구성 요소는 다음과 같습니다.
Virtual Control Plane
- API 서버: 가상 클러스터 내의 모든 API 요청을 관리하는 인터페이스입니다. 기본값은 Vanilla Kubernetes이며, 경량 Kubernetes(k3s)나 제로 Kubernetes(k0s) 등 다양한 Kubernetes 배포판을 지원합니다.
- Controller Manager: Pod를 비롯한 Kubernetes 리소스의 상태를 관리하는 제어 컴포넌트입니다. 사용자가 원하는 상태와 실제 상태를 일치시키기 위해 지속적으로 리소스를 조정합니다.
- Data Store: 가상 클러스터의 상태 정보를 저장하는 데이터베이스 시스템입니다. 기본적으로 SQLite를 사용하며, 클러스터의 설정과 리소스 상태를 안전하게 관리합니다.
- Syncer: 가상 클러스터 리소스를 호스트 클러스터에 동기화하는 메커니즘입니다. 가상 클러스터에는 실제 워커노드나 네트워크가 없습니다. 대신 Syncer를 활용해 가상 클러스터에 위치한 Pod를 호스트 클러스터에 동기화할 수 있습니다. Syncer에는 기본적으로 활성화되는 동기화 목록과 비활성화되는 동기화 목록이 있습니다.
참고로, 호스트 클러스터는 물리적 리소스를 제공하는 클러스터입니다. 가상 클러스터는 호스트 클러스터의 특정 네임스페이스에 생성됩니다. 이는 호스트 네임스페이스에서 StatefulSet으로 관리되는 싱글 Pod로 동작합니다. 이로써 호스트 클러스터의 리소스를 활용해 논리적 분리와 관리를 보장합니다.
실습 환경 구성
지금부터 vCluster를 활용한 Kubernetes 리소스 격리와 클러스터 가상 격리 기술에 기반한 클러스터 생성, 관리를 각각 실습하겠습니다. 먼저 실습 환경을 구성하기 위해 minikube를 설치하고, Kubernetes를 실행하겠습니다.
minikube 설치
"minikube start" 문서를 참고해 운영 체제에 맞게 minikube를 설치합니다. 아래 명령어를 실행하세요.
- macOS 환경
brew install minikube
- Linux(x86-64/amd64) 환경
curl -LO https://github.com/kubernetes/minikube/releases/latest/download/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube && rm minikube-linux-amd64
- Windows 환경: 재부팅이 필요할 수 있습니다.
New-Item -Path 'c:\' -Name 'minikube' -ItemType Directory -Force
Invoke-WebRequest -OutFile 'c:\minikube\minikube.exe' -Uri 'https://github.com/kubernetes/minikube/releases/latest/download/minikube-windows-amd64.exe' -UseBasicParsing
$oldPath = [Environment]::GetEnvironmentVariable('Path', [EnvironmentVariableTarget]::Machine)
if ($oldPath.Split(';') -inotcontains 'C:\minikube'){
[Environment]::SetEnvironmentVariable('Path', $('{0};C:\minikube' -f $oldPath), [EnvironmentVariableTarget]::Machine)
}
Kubernetes 실행
1.minikube를 설치한 뒤, 아래 명령어로 Kubernetes를 실행합니다.
minikube start --kubernetes-version=v1.32.0
2.Kubernetes의 “도구 설치” 문서를 참고해 kubectl을 설치합니다.
3.kubectl을 설치한 뒤, 아래 명령어로 Kubernetes 리소스 상태를 확인합니다.
$ kubectl get all -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system pod/coredns-668d6bf9bc-kx98p 1/1 Running 0 2m2s
kube-system pod/etcd-minikube 1/1 Running 0 2m7s
kube-system pod/kube-apiserver-minikube 1/1 Running 0 2m7s
kube-system pod/kube-controller-manager-minikube 1/1 Running 0 2m7s
kube-system pod/kube-proxy-sjxt4 1/1 Running 0 2m2s
kube-system pod/kube-scheduler-minikube 1/1 Running 0 2m7s
kube-system pod/storage-provisioner 1/1 Running 0 2m6s
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 2m8s
kube-system service/kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 2m7s
NAMESPACE NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
kube-system daemonset.apps/kube-proxy 1 1 1 1 1 kubernetes.io/os=linux 2m7s
NAMESPACE NAME READY UP-TO-DATE AVAILABLE AGE
kube-system deployment.apps/coredns 1/1 1 1 2m7s
NAMESPACE NAME DESIRED CURRENT READY AGE
kube-system replicaset.apps/coredns-668d6bf9bc 1 1 1 2m2s
실습 환경 구성을 모두 마쳤습니다. 이제 로컬 환경에서 Kubernetes 클러스터를 자유롭게 생성하고 관리할 수 있습니다. 다음 단계에서는 vCluster를 설치하고, 가상 클러스터를 생성하는 실습을 진행하겠습니다.
vCluster 설치 ~ 클러스터 연결 실습
이어서 vCluster를 설치하고 가상 클러스터를 생성, 연결하겠습니다. 또 vCluster를 연결하고 해제할 때, Kubernetes 리소스 상태가 어떻게 달라지는지도 함께 비교하겠습니다.
vCluster 설치
운영 체제에 맞게 vCluster를 설치합니다. 아래 명령어를 실행하세요.
- macOS 환경
brew install loft-sh/tap/vcluster
- Linux(x86-64/amd64) 환경
curl -L -o vcluster "https://github.com/loft-sh/vcluster/releases/latest/download/vcluster-linux-amd64" && sudo install -c -m 0755 vcluster /usr/local/bin && rm -f vcluster
- Windows 환경: 재부팅이 필요할 수 있습니다.
md -Force "$Env:APPDATA\vcluster"; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]'Tls,Tls11,Tls12';
Invoke-WebRequest -URI "https://github.com/loft-sh/vcluster/releases/latest/download/vcluster-windows-amd64.exe" -o $Env:APPDATA\vcluster\vcluster.exe;
$env:Path += ";" + $Env:APPDATA + "\vcluster";
[Environment]::SetEnvironmentVariable("Path", $env:Path, [System.EnvironmentVariableTarget]::User);
가상 클러스터 생성, 연결
1.vCluster를 설치한 뒤, 격리시킬 네임스페이스를 지정하고 가상 클러스터를 생성, 연결합니다. 아래 명령어를 실행하세요.
vcluster create poc-vcluster --namespace vcluster-poc
2.가상 클러스터가 생성되면, 자동으로 vCluster에 연결됩니다. 연결된 상태에서 아래 명령어로 Kubernetes 리소스 상태를 확인합니다. 이 실습에서는 리소스가 간소화된 걸로 나타났습니다.
$ kubectl get all -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system pod/coredns-94f599b5-zvqf4 1/1 Running 0 7h7m
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default service/kubernetes ClusterIP 10.110.213.16 <none> 443/TCP 7h7m
kube-system service/kube-dns ClusterIP 10.110.38.252 <none> 53/UDP,53/TCP,9153/TCP 7h7m
NAMESPACE NAME READY UP-TO-DATE AVAILABLE AGE
kube-system deployment.apps/coredns 1/1 1 1 7h7m
NAMESPACE NAME DESIRED CURRENT READY AGE
kube-system replicaset.apps/coredns-94f599b5 1 1 1 7h7m
3.아래 명령어로 연결을 해제합니다. 해제 후 다시 Kubernetes 리소스 상태를 조회하면, 원래 클러스터의 리소스를 확인할 수 있습니다.
# vCluster 연결 해제
$ vcluster disconnect
12:58:17 info Successfully disconnected and switched back to the original context: minikube
$ kubectl get all -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system pod/coredns-668d6bf9bc-kx98p 1/1 Running 2 (7h15m ago) 2d
kube-system pod/etcd-minikube 1/1 Running 2 (7h15m ago) 2d
kube-system pod/kube-apiserver-minikube 1/1 Running 2 (7h15m ago) 2d
kube-system pod/kube-controller-manager-minikube 1/1 Running 3 (7h15m ago) 2d
kube-system pod/kube-proxy-sjxt4 1/1 Running 2 (7h15m ago) 2d
kube-system pod/kube-scheduler-minikube 1/1 Running 2 (7h15m ago) 2d
kube-system pod/storage-provisioner 1/1 Running 4 (7h15m ago) 2d
vcluster-poc pod/coredns-94f599b5-zvqf4-x-kube-system-x-poc-vcluster 1/1 Running 0 7h13m
vcluster-poc pod/poc-vcluster-0 1/1 Running 0 7h13m
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 2d
kube-system service/kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 2d
vcluster-poc service/kube-dns-x-kube-system-x-poc-vcluster ClusterIP 10.110.38.252 <none> 53/UDP,53/TCP,9153/TCP 7h13m
vcluster-poc service/poc-vcluster ClusterIP 10.110.213.16 <none> 443/TCP,10250/TCP 7h13m
vcluster-poc service/poc-vcluster-headless ClusterIP None <none> 443/TCP 7h13m
vcluster-poc service/poc-vcluster-node-minikube ClusterIP 10.98.177.159 <none> 10250/TCP 7h13m
NAMESPACE NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
kube-system daemonset.apps/kube-proxy 1 1 1 1 1 kubernetes.io/os=linux 2d
NAMESPACE NAME READY UP-TO-DATE AVAILABLE AGE
kube-system deployment.apps/coredns 1/1 1 1 2d
NAMESPACE NAME DESIRED CURRENT READY AGE
kube-system replicaset.apps/coredns-668d6bf9bc 1 1 1 2d
NAMESPACE NAME READY AGE
vcluster-poc statefulset.apps/poc-vcluster 1/1 7h13m
vCluster 리소스 확인, 재연결
1.vCluster를 생성한 네임스페이스인 ‘vcluster-poc’에 vCluster 관련 리소스가 있는 걸 확인합니다. 아래 명령어를 실행하세요.
$ kubectl get all -n vcluster-poc
NAME READY STATUS RESTARTS AGE
pod/coredns-94f599b5-zvqf4-x-kube-system-x-poc-vcluster 1/1 Running 0 7h14m
pod/poc-vcluster-0 1/1 Running 0 7h14m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kube-dns-x-kube-system-x-poc-vcluster ClusterIP 10.110.38.252 <none> 53/UDP,53/TCP,9153/TCP 7h14m
service/poc-vcluster ClusterIP 10.110.213.16 <none> 443/TCP,10250/TCP 7h14m
service/poc-vcluster-headless ClusterIP None <none> 443/TCP 7h14m
service/poc-vcluster-node-minikube ClusterIP 10.98.177.159 <none> 10250/TCP 7h14m
NAME READY AGE
statefulset.apps/poc-vcluster 1/1 7h14m
2.생성한 vCluster 목록을 아래 명령어로 확인하고, 기존 vCluster에 다시 연결합니다.
$ vcluster list
NAME | NAMESPACE | STATUS | VERSION | CONNECTED | AGE
---------------+--------------+---------+---------+-----------+-----------
poc-vcluster | vcluster-poc | Running | 0.24.1 | True | 7h16m24s
18:15:56 info Run `vcluster disconnect` to switch back to the parent context
$ vcluster connect poc-vcluster
18:16:31 done vCluster is up and running
18:16:31 info Stopping background proxy...
18:16:32 info Starting background proxy container...
18:16:33 done Switched active kube context to vcluster_poc-vcluster_vcluster-poc_minikube
- Use `vcluster disconnect` to return to your previous kube context
- Use `kubectl get namespaces` to access the vcluster
지금까지 vCluster 설치와 연결, 해제 과정을 실습하며 Kubernetes 리소스 상태 변화를 확인했습니다. 이 환경에 기반해 팀별로 격리된 개발 환경을 구축하거나, 멀티 테넌시 구조를 테스트하고, 운영 효율성을 높이는 다양한 실험을 수행할 수 있습니다. 다음 단계에서는 이러한 vCluster 환경에 실제 애플리케이션을 배포하며, 구체적인 실무 시나리오의 적용 방법을 실습하겠습니다.