虚拟集群是一种在现有 Kubernetes 集群(Host 集群)之上创建的轻量级 Kubernetes 集群。它提供了一个独立的 Kubernetes 环境,但实际上是通过共享 Host 集群的资源来实现的。这种方式允许多个虚拟集群运行在同一个物理集群中,为不同的团队或项目提供隔离的开发、测试和生产环境,而不需要为每个环境创建单独的物理集群。
vCluster[1] 是一种轻量级的虚拟集群解决方案,允许你在 Kubernetes 集群中创建和管理虚拟的 Kubernetes 集群。它是由 Loft Labs 开发的,用于多租户环境、开发测试环境以及简化复杂的 Kubernetes 集群管理。
关于 vCluster 的更多信息,后面我会再写一篇深入介绍下。
Cilium[2] 是一个基于 eBPF[3](extended Berkeley Packet Filter)技术的容器网络接口(CNI)插件,旨在为 Kubernetes 和其他容器平台提供高效、安全的网络和负载均衡功能。Cilium 的核心目标是通过使用 eBPF 实现更高性能、更灵活的网络数据处理,并简化网络安全策略的管理。在之前的文章 Kubernetes 网络学习之 Cilium 与 eBPF 和 深入探索 Cilium 的工作机制 中曾介绍过
接下来我们看下如何在 Cilium CNI 集群上运行 vCluster 虚拟集群。
准备 Kubernetes 集群,使用 v1.28.13+k3s1
版本的 K3s 作为 Host 集群,禁用 flannel。
export INSTALL_K3S_VERSION=v1.28.13+k3s1
curl -sfL https://get.k3s.io | sh -s - --disable traefik --disable metrics-server --flannel-backend=none --cluster-cidr=10.42.0.0/16 --disable-network-policy --write-kubeconfig-mode 644 --write-kubeconfig ~/.kube/config
集群安装后,查看 Pod 状态。Pending
状态是因为没有 CNI 插件。
kubectl get po -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-6799fbcd5-h8cfh 0/1 Pending 0 41s
kube-system local-path-provisioner-5ccc7458d5-scfq4 0/1 Pending 0 41s
安装 Cilium。
curl -L --remote-name-all https://github.com/cilium/cilium-cli/releases/latest/download/cilium-linux-amd64.tar.gz{,.sha256sum}
sha256sum --check cilium-linux-amd64.tar.gz.sha256sum
sudo tar xzvfC cilium-linux-amd64.tar.gz /usr/local/bin
rm cilium-linux-amd64.tar.gz{,.sha256sum}
目前最新的 stable 版本未 v1.16.1
cilium version
cilium-cli: compiled with go1.23.0 on linux/amd64
cilium image (default): v1.16.0
cilium image (stable): v1.16.1
cilium image (running): unknown. Unable to obtain cilium version. Reason: release: not found
安装 Cilium 到集群:
cilium install
等待 Cilium 安装完成。
cilium status --wait
/¯¯\
/¯¯\__/¯¯\ Cilium: 2 warnings
/¯¯\
/¯¯\__/¯¯\ Cilium: OK
\__/¯¯\__/ Operator: OK
/¯¯\__/¯¯\ Envoy DaemonSet: OK
\__/¯¯\__/ Hubble Relay: disabled
\__/ ClusterMesh: disabled
DaemonSet cilium Desired: 1, Ready: 1/1, Available: 1/1
Deployment cilium-operator Desired: 1, Ready: 1/1, Available: 1/1
DaemonSet cilium-envoy Desired: 1, Ready: 1/1, Available: 1/1
Containers: cilium Running: 1
cilium-envoy Running: 1
cilium-operator Running: 1
Cluster Pods: 2/2 managed by Cilium
Helm chart version:
Image versions cilium-operator quay.io/cilium/operator-generic:v1.16.0@sha256:d6621c11c4e4943bf2998af7febe05be5ed6fdcf812b27ad4388f47022190316: 1
cilium quay.io/cilium/cilium:v1.16.0@sha256:46ffa4ef3cf6d8885dcc4af5963b0683f7d59daa90d49ed9fb68d3b1627fe058: 1
cilium-envoy quay.io/cilium/cilium-envoy:v1.29.7-39a2a56bbd5b3a591f69dbca51d3e30ef97e0e51@sha256:bd5ff8c66716080028f414ec1cb4f7dc66f40d2fb5a009fff187f4a9b90b566b: 1
待 Cilium 安装完成后,所有的 Pod 都正常运行。
kubectl get po -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system cilium-envoy-t2vbd 1/1 Running 0 75s
kube-system cilium-gfk5r 1/1 Running 0 75s
kube-system cilium-operator-885db8fcf-kp2dr 1/1 Running 0 75s
kube-system coredns-6799fbcd5-4xmcd 1/1 Running 0 94s
kube-system local-path-provisioner-5ccc7458d5-scfq4 1/1 Running 0 94s
这里使用 vCluster CLI 来管理虚拟集群,首先安装 vCluster CLI。
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
最新的版本为 vCluster
vCluster version
vCluster version 0.20.0
查看 Host 集群的命名空间。
kubectl get ns
NAME STATUS AGE
default Active 2m8s
kube-node-lease Active 2m8s
kube-public Active 2m8s
kube-system Active 2m8s
使用 vCluster create NAME
创建名为 vc-a
的虚拟集群。
vCluster create vc-a
07:02:38 info Creating namespace vCluster-vc-a
07:02:38 info Create vCluster vc-a...
07:02:38 info execute command: helm upgrade vc-a /tmp/vCluster-0.20.0.tgz-759956343 --create-namespace --kubeconfig /tmp/1343191442 --namespace vCluster-vc-a --install --repository-config='' --values /tmp/3416084562
07:02:39 done Successfully created virtual cluster vc-a in namespace vCluster-vc-a
07:02:44 info Waiting for vCluster to come up...
07:02:55 warn vCluster is waiting, because vCluster pod vc-a-0 has status: Init:2/3
07:03:15 done vCluster is up and running
07:03:15 done Switched active kube context to vCluster_vc-a_vCluster-vc-a_default
- Use `vCluster disconnect` to return to your previous kube context
- Use `kubectl get namespaces` to access the vCluster
vCluster 会在 Host 集群上为虚拟集群创建一个独立的命名空间,比如这里的 vCluster-vc-a
就是虚拟集群 vc-a
在 Host 集群上的命名空间。
kubectl get ns
NAME STATUS AGE
default Active 7m51s
kube-node-lease Active 7m51s
kube-public Active 7m51s
kube-system Active 7m51s
vCluster-vc-a Active 2m8s
在该命名空间下,有 vCluster 的控制面和 coredns。默认情况下,vCluster 的组件都是 StatefulSet 单实例运行。这种单实例架构适合开发环境或者 CI/CD 环境,但生产环境建议使用 高可用方案[4] 部署。
kubectl get po -n vCluster-vc-a
NAME READY STATUS RESTARTS AGE
coredns-5c7466bb88-zgqqk-x-kube-system-x-vc-a 1/1 Running 0 2m19s
vc-a-0 1/1 Running 0 2m49s
这里 vc-a-0
就是虚拟集群 vc-a
的控制面实例,在这个实例中包含了:
使用同样的方式,我们再创建一个虚拟集群 vc-b
:
vCluster create vc-b
查看已有的虚拟集群。
vCluster list
NAME | NAMESPACE | STATUS | VERSION | CONNECTED | AGE
-------+---------------+---------+---------+-----------+---------
vc-a | vCluster-vc-a | Running | 0.20.0 | | 41m34s
vc-b | vCluster-vc-b | Running | 0.20.0 | | 16m36s
虚拟集群的 KubeConfig 保存在对应的 Host 集群的命名空间中,比如虚拟集群 vc-a
的 kubeconfig 保存在 Host 集群的命名空间 vCluster-vc-a
下的 Secret vc-vc-a
中。
kubectl get secret -n vCluster-vc-a
NAME TYPE DATA AGE
sh.helm.release.v1.vc-a.v1 helm.sh/release.v1 1 46m
vc-a-certs Opaque 25 46m
vc-config-vc-a Opaque 1 46m
vc-vc-a Opaque 4 45m
通过下面的命令可以查看 kubeconfig 的内容。
kubectl get secret -n vCluster-vc-a vc-vc-a -o jsonpath='{.data.config}' | base64 -d
要连接到虚拟集群不需要直接使用 kubeconfig,vCluster CLI 提供了命令可以快捷地连接到虚拟集群。
07:51:42 done vCluster is up and running
07:51:42 done Switched active kube context to vCluster_vc-a_vCluster-vc-a_default
- Use `vCluster disconnect` to return to your previous kube context
- Use `kubectl get namespaces` to access the vCluster
连接成功后,就可以操作虚拟集群了。
kubectl get po -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-5c7466bb88-zgqqk 1/1 Running 0 48m
通过命令 vCluster disconnect
可以断开连接,切换到 Host 集群。
在虚拟集群 vc-a
上部署应用 deathstar
、tiefighter
和 xwing
。
cat < ---
apiVersion: v1
kind: Service
metadata:
name: deathstar
labels:
app.kubernetes.io/name: deathstar
spec:
type: ClusterIP
ports:
- port: 80
selector:
org: empire
class: deathstar
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: deathstar
labels:
app.kubernetes.io/name: deathstar
spec:
replicas: 2
selector:
matchLabels:
org: empire
class: deathstar
template:
metadata:
labels:
org: empire
class: deathstar
app.kubernetes.io/name: deathstar
spec:
containers:
- name: deathstar
image: docker.io/cilium/starwars
---
apiVersion: v1
kind: Pod
metadata:
name: tiefighter
labels:
org: empire
class: tiefighter
app.kubernetes.io/name: tiefighter
spec:
containers:
- name: spaceship
image: docker.io/tgraf/netperf
---
apiVersion: v1
kind: Pod
metadata:
name: xwing
labels:
app.kubernetes.io/name: xwing
org: alliance
class: xwing
spec:
containers:
- name: spaceship
image: docker.io/tgraf/netperf
EOF
待应用启动后测试服务调用。
kubectl exec tiefighter -- curl -s -XPOST deathstar.default.svc.cluster.local/v1/request-landing
kubectl exec xwing -- curl -s -XPOST deathstar.default.svc.cluster.local/v1/request-landing
如果显示下面的结果,访问正常,说明容器网络没有问题。
Ship landed
Ship landed
vCluster 在使用 Cilium CNI 的 Host 集群上容器网络是没有问题的,可以说 vCluster 使用的还是 Host 集群的容器网络,不受 CNI 实现的影响。
但如果要在虚拟集群上使用 Cilium 的网络策略,则会受到限制。
这是因为 Syncer 是 vCluster 架构中的一个关键组件,负责在虚拟集群和 Host 集群之间同步 Kubernetes 资源。它使得 vCluster 能够在宿主集群上运行,同时保持与虚拟集群的 Kubernetes API Server 一致。
简单说 Syncer 在 Host 集群和虚拟集群间完成资源的“转译”,实现资源的同步,但仅限于 Kubernetes 的原生资源(如 Pods、Services、ConfigMaps 等)。
在 vCluster v0.14 - 0.19 中,可以通过扩展 vcluster-generic-crd-sync-plugin[5] 完成特定 CRD 的同步,但这个仓库已经一年多未更新。