「vCluster」で仮想Kubernetesクラスターを構築する

2025年4月24日(木)
Takeaki Kato
第14回の今回は、Kubernetes上で仮想的なクラスターを構築する「vCluster」を利用して、短時間で軽量な仮想クラスターを構築する方法を解説します。

はじめに

3-shakeのSreake事業部に所属する加藤です。第14回目の今回は、Kubernetesクラスター内に仮想Kubernetesクラスターを構築できる「vCluster」について紹介します。

皆さんは、自分だけのKubernetesクラスターを自由に作成したり、破棄したりできる環境がほしいと考えていたりしませんか。

vClusterの概要

vClusterとは

vClusterはKubernetes上で仮想的なクラスターを構築するプロジェクトです。2021年4月にLoft Lab社がOSSとしてリリースを開始し、現在ではOSS版のほか、Enterprise PlanやvCluster Cloudという有償プランも利用可能です。

有償プランの詳細を見ると、企業での運用に必要な認証、他社ツールやクラウドプロバイダーとの統合や、大規模クラスター運用で必要な機能が多くサポートされています。

【出典】vCluster Pricing

vCluster Cloudは2024年11月に発表された、マネージドクラスターの中で仮想クラスターを管理するサービスで、クラウドとオンプレ環境のどちらでも利用できる形で提供されています。

vCluster Cloudも有償プランでは企業での運用に必要な認証、他社ツールやクラウドプロバイダーとの統合や、大規模クラスター運用で必要な機能が多くサポートされています。各料金プランで利用可能な機能一覧はPricingページ下部の「vCluster Cloud」の章を参照してください。

Architecture

vClusterの仮想クラスターはホストクラスターで指定したnamespaceに立ち上がるPodとして構築されます。DeploymentやCRDといったハイレベルなリソースは仮想クラスター内に作成・保存され、PodやServiceといったローレベルなリソースが仮想クラスターで作成されると、syncerというコンポーネントを介してホストクラスターのリソースとして同期されます。

ネットワーク管理のため仮想クラスター内にcorednsのPodが立ち上がりますが、デフォルトの状態ではホストクラスターのスケジューラーが共有されます(Virtual Schedulerを有効化することも可能)。

ホストクラスターと仮想クラスター間のリソース同期

ここでsyncerがホストクラスターと仮想クラスター間で同期する項目について、いくつか見ていこうと思います。

ノード
vClusterはホストクラスターのノードをpsuedoノードとして仮想クラスターを作成します。vcluster.yamlファイルを作成してpsuedoノードを作成せず、実際のホストクラスターのノードをマップさせたり、NodeSelectorでホストクラスターの複数のノードを1つのpsedoノードにマップさせたりすることも可能です(詳細はNodesページを参照)。

試しに、3ノード構成のホストクラスターを作成してみました。

$ kubectl get nodes -o wide
NAME          STATUS   ROLES           AGE   VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION     CONTAINER-RUNTIME
vc-test       Ready    control-plane   21m   v1.32.0   192.168.49.2   <none>        Ubuntu 22.04.5 LTS   6.10.14-linuxkit   docker://27.4.1
vc-test-m02   Ready    <none>          21m   v1.32.0   192.168.49.3   <none>        Ubuntu 22.04.5 LTS   6.10.14-linuxkit   docker://27.4.1
vc-test-m03   Ready    <none>          20m   v1.32.0   192.168.49.4   <none>        Ubuntu 22.04.5 LTS   6.10.14-linuxkit   docker://27.4.1

作成した仮想クラスターのノードを見てみると、作成されたpsuedoノードがホスト側のvc-test-m02ノードにマップしていることが分かります。

$ vcluster create test-cluster1 -n tc1
15:18:02 info Creating namespace tc1
15:18:02 info Create vcluster test-cluster1...
15:18:02 info execute command: helm upgrade test-cluster1 /var/folders/zm/g7vnp6sx79z7fmzxpb1kvgbw0000gn/T/vcluster-0.24.1.tgz-4191263510 --create-namespace --kubeconfig /var/folders/zm/g7vnp6sx79z7fmzxpb1kvgbw0000gn/T/2851582382 --namespace tc1 --install --repository-config='' --values /var/folders/zm/g7vnp6sx79z7fmzxpb1kvgbw0000gn/T/3586232792
15:18:03 done Successfully created virtual cluster test-cluster1 in namespace tc1
15:18:05 info Waiting for vcluster to come up...
15:18:19 info vcluster is waiting, because vcluster pod test-cluster1-0 has status: Init:1/3
15:18:42 done vCluster is up and running
15:18:42 info Starting background proxy container...
15:18:44 done Switched active kube context to vcluster_test-cluster1_tc1_vc-test
- Use `vcluster disconnect` to return to your previous kube context
- Use `kubectl get namespaces` to access the vcluster
$ kubectl get nodes -o wide
NAME          STATUS   ROLES    AGE   VERSION   INTERNAL-IP     EXTERNAL-IP   OS-IMAGE                KERNEL-VERSION      CONTAINER-RUNTIME
vc-test-m02   Ready    <none>   17s   v1.32.0   10.111.103.63   <none>        Fake Kubernetes Image   4.19.76-fakelinux   docker://19.3.12

サービス
OSS版の場合、デフォルトの状態ではサービスが同期されないため、自分で同期したいサービスを設定する必要があります。仮想クラスター内のサービスをホストクラスターや別の仮想クラスターで利用したいとき、またその逆の場合には、vcluster.yamlに定義して仮想クラスター作成時または更新時に適用します。

・ホストクラスターのサービスを仮想クラスターに同期
networking:
  replicateServices:
    fromHost:
    - from: my-host-namespace/my-host-service
      to: my-virtual-namespace/my-virtual-service
・仮想クラスターのサービスをホストクラスターに同期
networking:
  replicateServices:
    toHost:
    - from: my-virtual-namespace/my-virtual-service
      to: my-host-service

詳細は、Replicate networking servicesを参照してください。

その他同期項目
その他、デフォルトの状態で同期されるものや、デフォルトの状態では同期されないが有効化すれば同期可能なものについては、以下の公式ページを参照してください。

Platform configuration

仮想クラスターの構成をデフォルト設定から変更したい場合には、Platform configurationの変更が必要になります。Platform configurationは大きくInstall settings、Operational settings、Agent settingsの3つに分かれており、Operational settings以外は仮想クラスター作成時またはアップグレード時のみ適用可能な設定です。

クラスター作成時の設定を変更するには、自分でvClusterが使用しているhelmチャートのvalues.yamlファイルを修正し、helmコマンドを実行する知識が必要になります。values.yamlのデフォルト値はplatform Helm chart (loft-sh/loft)で確認できます。

values.yamlのconfigセクション(Operational settingsに該当)はクラスターが作成された後の設定を行う部分で、vcluster.yamlに定義してオーバーライドすることが可能です。configセクションで設定可能なものはloft-sh/loft/chart/values.yamlで確認できます。

詳細はPlatform configurationページを参照してください。

vClusterの基本的な使い方

インストール

筆者の環境はMacなので、Homebrewを使用してvcluster CLIをインストールしました。その他の環境へのインストール方法についてはDeploy vClusterを参照してください。

brew install loft-sh/tap/vcluster-experimental
$ vcluster --version
vcluster version 0.24.0

仮想クラスター作成

必要に応じてvcluster.yamlファイルを作成します。以下の例では、仮想クラスターとホストクラスター間でIngressリソースの同期を有効化します(詳細はvcluster.yaml configuration referenceを参照)。

---
sync:
  fromHost:
    ingressClasses:
      enabled: true
  toHost:
    ingresses:
      enabled: true

「myvc1」という仮想クラスターを「vc1」というnamespaceに作成します。

$ vcluster create myvc1 -n vc1 -f vcluster.yaml
16:20:10 info Create vcluster myvc1...
16:20:10 info execute command: helm upgrade myvc1 /var/folders/zm/g7vnp6sx79z7fmzxpb1kvgbw0000gn/T/vcluster-0.24.0.tgz-371407530 --create-namespace --kubeconfig /var/folders/zm/g7vnp6sx79z7fmzxpb1kvgbw0000gn/T/15222157 --namespace vc1 --install --repository-config='' --values /var/folders/zm/g7vnp6sx79z7fmzxpb1kvgbw0000gn/T/3466153873 --values vcluster.yaml
16:20:11 done Successfully created virtual cluster myvc1 in namespace vc1
16:20:13 info Waiting for vcluster to come up...
16:20:27 info vcluster is waiting, because vcluster pod myvc1-0 has status: Init:1/3
16:20:50 done vCluster is up and running
16:20:50 info Starting background proxy container...
16:20:50 done Switched active kube context to vcluster_myvc1_vc1_vc-test
- Use `vcluster disconnect` to return to your previous kube context
- Use `kubectl get namespaces` to access the vcluste

構築された仮想クラスターを確認すると、クラスター内にcorednsのPodが作成されています。

$ kubectl get pods -A -o wide
NAMESPACE     NAME                     READY   STATUS    RESTARTS   AGE   IP           NODE          NOMINATED NODE   READINESS GATES
kube-system   coredns-94f599b5-vpq4w   1/1     Running   0          91s   10.244.1.2   vc-test       <none>           <none>
$ kubectl get namespace 
NAME              STATUS   AGE
default           Active   1d07h
kube-node-lease   Active   1d07h
kube-public       Active   1d07h
kube-system       Active   1d07h

ホストクラスターを確認すると、仮想クラスターで使用されているcorednsと仮想クラスターのPodが指定したvc1というnamespaceに作成されており、syncerによりホストクラスターでは「coredns-94f599b5-vpq4w-x-kube-system-x-myvc1」というPodが、仮想クラスター内では「coredns-94f599b5-vpq4w」として扱われていることが分かります。

$ vcluster disconnect 
15:10:31 info Successfully disconnected and switched back to the original context: vc-test
$ kubectl get pods -n vc1 -o wide
NAME                                           READY   STATUS    RESTARTS      AGE     IP            NODE      NOMINATED NODE   READINESS GATES
coredns-94f599b5-vpq4w-x-kube-system-x-myvc1   1/1     Running   0             59m     10.244.1.2    vc-test   <none>           <none>
myvc1-0                                        1/1     Running   0             59m     10.244.2.2    vc-test   <none>           <none>
$ kubectl get namespace
NAME              STATUS   AGE
default           Active   1d07h
ingress-nginx     Active   1d07h
kube-node-lease   Active   1d07h
kube-public       Active   1d07h
kube-system       Active   1d07h
vc1               Active   59m

vClusterの基本コマンド

# 仮想クラスタの作成(--connect=falseを追加するとクラスタ作成後にkube contextを変更しない)
vcluster create {{ クラスター名 }} --namespace {{ namespace }} [--connect=false]

# 既存仮想クラスターの設定更新
vcluster create --upgrade {{ クラスター名 }} -n {{ namespace }} -f vcluster.yaml

# デフォルトはk3sですが、別なdistroを指定することも可能
vcluster create --upgrade {{ クラスター名 }} -n {{ namespace }} --distro k0s

# 接続中の仮想クラスターへの接続を切断してホストクラスターに戻る
vcluster disconnect

# 仮想クラスター一覧
vcluster list

# 仮想クラスターへ接続
vcluster connect {{ クラスター名 }} --namespace {{ namespace }}

# 仮想クラスター削除
vcluster delete {{ クラスター名 }} --namespace {{ namespace }}

アプリケーションのデプロイ

作成した仮想クラスターに、以下の設定でdeployment.yamlを作成しました。

・vc1-nginx.yaml
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-vc1
  namespace: vc1
spec:
  selector:
    app: nginx-vc1
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: 80
  type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-vc1
  namespace: vc1
spec:
  selector:
    matchLabels:
      app: nginx-vc1
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx-vc1
    spec:
      containers:
      - name: nginx-container
        image: nginx:latest
        ports:
          - name: http
            containerPort: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-vc1-ingress
  namespace: vc1
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
  - http:
      paths:
      - path: /vc1
        pathType: Prefix
        backend:
          service:
            name: nginx-vc1
            port:
              number: 80

上記yamlをデプロイしました。

$ vcluster connect myvc1 -n vc1
17:30:40 done vCluster is up and running
17:30:40 info Starting background proxy container...
17:30:40 done Switched active kube context to vcluster_myvc1_vc1_vc-test
- Use `vcluster disconnect` to return to your previous kube context
- Use `kubectl get namespaces` to access the vcluster
$ kubectl create namespace vc1
namespace/vc1 created
$ kubectl apply -f vc1-nginx.yaml
service/nginx-vc1 created
deployment.apps/nginx-vc1 created
ingress.networking.k8s.io/nginx-vc1-ingress created

別ターミナルからデプロイしたアプリケーションを確認すると、無事に接続できました。

$ curl http://127.0.0.1/vc1 -I
HTTP/1.1 200 OK
Date: Fri, 04 Apr 2025 08:36:35 GMT
Content-Type: text/html
Content-Length: 120
Connection: keep-alive
Last-Modified: Fri, 04 Apr 2025 07:32:04 GMT
ETag: "67ef8af4-78"
Accept-Ranges: bytes

仮想クラスターの削除

クラスターの削除も短時間で行うことができます。

$ vcluster delete myvc1 -n vc1
17:57:55 info Stopping background proxy...
17:57:55 info Delete vcluster myvc1...
17:57:57 done Successfully deleted virtual cluster myvc1 in namespace vc1
17:57:57 done Successfully deleted virtual cluster namespace vc1
17:57:57 info Waiting for virtual cluster to be deleted...
17:58:08 done Virtual Cluster is deleted

ユースケース

vClusterを使えば、ホストクラスターに複数の仮想クラスターを簡単に構築できることをお分かりいただけたでしょうか。

マルチテナントの実現という観点からも、vClusterはソフトマルチテナントでテナントの分離に必要な複雑なポリシーやアクセスコントロールの設定を1つのNamespaceに集約でき、ハードマルチテナントで必要なテナント毎に必要なリソースを確保したり、共通のリソースを作成したりせずにホストクラスターのリソースを共有できます。

【出典】vCluster Comparison

一部のローレベルなリソース(コンテナランタイムやCNIプラグイン等)はホスト環境に依存するため、特定の仮想クラスターで異なるものは利用できないという制限はありますが、チーム内でセルフサービスとして簡単にクラスターを作成・削除できる環境を提供して、アプリケーションのテストやツールの検証、オペレーターのテスト、異なるバージョンでの動作検証の並列化などの目的で使ったり、CI/CDパイプラインに実行環境として組み込むといった用途にはとても適しているように見えます。

PoC的な環境として、短時間でDevlopment/Staging/Production環境を構築するようなことにも向いていそうです。

おわりに

今回は、vClusterを利用して、短時間で軽量な仮想クラスターを構築する方法について解説しました。vClusterで複数クラスターの運用にかかっているリソースや管理の効率化を検討されてみてはいかがでしょうか。

【参考】
vCluster公式ドキュメントページ
LoftLabs社
Kubernetes Namespaces vs. Virtual Clusters
Kubernetes Multi-Tenancy: Why Virtual Clusters Are The Best Solution

株式会社スリーシェイク Sreake事業部
2025年に3-shakeのSreake事業部にJoin。オンプレ、Kubernetesやクラウドネイティブ技術支援、SREとして活動中。
---
スリーシェイクは、ITインフラ領域の技術力に強みをもつテクノロジーカンパニーです。SREコンサルティング事業「Sreake」では、AWS/Google Cloud/Kubernetesに精通したプロフェッショナルが技術戦略から設計・開発・運用を一貫してサポートしています。また、ノーコード型ETLツール「Reckoner」、フリーランスエンジニア特化型人材紹介サービス「Relance」、セキュリティサービス「Securify」を提供しています。
会社HP: https://3-shake.com/

連載バックナンバー

仮想化/コンテナ技術解説
第14回

「vCluster」で仮想Kubernetesクラスターを構築する

2025/4/24
第14回の今回は、Kubernetes上で仮想的なクラスターを構築する「vCluster」を利用して、短時間で軽量な仮想クラスターを構築する方法を解説します。
仮想化/コンテナ技術解説
第13回

「kubeshark」でKubernetesのトラフィックをリアルタイムに可視化する

2025/3/7
第13回の今回は、KubernetesのAPIトラフィックアナライザである「kubeshark」によるリアルタイムのトラフィック可視化について解説します。
仮想化/コンテナ技術解説
第12回

「OpenClarity」によるk8sワークロードの脆弱性スキャン

2025/2/21
第12回の今回は、セキュリティリスクを検出するOSSツール「OpenClarity」におけるKubernetesワークロードの脆弱性スキャンを解説します。

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています