kubernetes上使用vcluster虚拟集群
官方主页:https://www.vcluster.com
开源地址:https://github.com/loft-sh/vcluster
简述虚拟集群
虚拟集群是完整的Kubernetes集群,运行在其他Kubernetes集群之上。与完全独立的“真实”集群相比,虚拟集群没有自己的节点池。但是它们可以在底层集群内调度工作负载,同时具有自己单独的控制平面。
虚拟集群本身仅由核心Kubernetes组件组成:API服务器、控制器管理器和存储后端(如 etcd、sqlite、mysql等)。
虚拟集群支持多种Kubernetes发行版,如k0s、k3s和k8s。除了控制平面之外,还有一个 Kubernetes虚拟机监控程序,它取代了Kubernetes调度程序,并模拟了虚拟集群中完整的Kubernetes设置。此组件在虚拟集群和主机集群之间同步对集群功能至关重要的核心资源:
- Pod:在虚拟集群中启动的所有容器都将被重写,然后在主机集群中虚拟集群的命名空间中启动。ServiceAccount、ENV、DNS和其他配置将交换为指向虚拟集群而不是主机集群。在容器中,容器似乎是在虚拟集群中启动的,而不是在主机集群中启动的。
- Service:所有servcie和endpoint都在主机集群的虚拟集群的命名空间中重写和创建。虚拟集群和主机集群共享相同的服务集群IP。这也意味着可以从虚拟集群内访问主机集群中的服务,而不会降低任何性能。
- PVC:如果在虚拟集群中创建了PVC,则它们将同步在主机集群的虚拟集群所在的命名空间中创建。如果它们绑定了主机集群中的PV,则相应的PV信息将同步回虚拟集群。
- ConfigMap和Secret:虚拟集群中挂载到Pod的ConfigMap或Secret将同步到主机集群,所有其他ConfigMap或Secret将保留在虚拟集群中。
- 其他资源:Deployment、Statefulset、CRD、ServiceAccount等不会同步到主机集群,而是纯粹存在于虚拟集群中。
除了同步虚拟和主机集群资源之外,虚拟机监控程序还将某些Kubernetes API请求代理到主机集群,例如pod端口转发或容器命令执行。它实质上充当虚拟集群的反向代理。
虚拟集群的优势
虚拟集群解决了命名空间存在的许多问题,例如:
- 集群范围的资源:某些资源全局存在于集群中,无法使用命名空间隔离它们。例如,无法在单个集群中以不同的版本安装istio或任何其他组件。虚拟集群具备独立的资源管理并且被隔离在独立的命名空间中。
- 共享Kubernetes控制平面:API服务器、etcd、调度程序和控制器管理器在单个 Kubernetes集群中共享。基于命名空间的请求或存储速率限制非常困难,错误的配置可能会使整个集群瘫痪。虚拟集群提供了完整的控制平面。
启用虚拟集群
# 下载vcluster工具
[root@vm ~]# curl -s -L "https://github.com/loft-sh/vcluster/releases/latest" | sed -nE 's!.*"([^"]*vcluster-linux-amd64)".*!https://github.com\1!p' | xargs -n 1 curl -L -o vcluster && chmod +x vcluster;
[root@vm ~]# sudo mv vcluster /usr/local/bin;
[root@vm ~]# vcluster -v
vcluster version 0.7.1
# 为了能通过主机集群的NodePort独立访问虚拟集群API,先创建NodePort服务
[root@vm ~]# cat vcluster-nodeport.yaml
apiVersion: v1
kind: Service
metadata:
name: vcluster-nodeport
spec:
selector:
app: vcluster
ports:
- name: https
port: 443
targetPort: 8443
protocol: TCP
type: NodePort
# 主机集群上创建部署虚拟集群的命名空间和NodePort服务
[root@vm ~]# kubectl create ns vcluster-1
namespace/vcluster-1 created
[root@vm ~]# kubectl apply -f vcluster-nodeport.yaml -n vcluster-1
service/vcluster-nodeport created
[root@vm ~]# kubectl get svc vcluster-nodeport -n vcluster-1
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
vcluster-nodeport NodePort 10.43.112.147 <none> 443:32121/TCP 47s
# 创建vcluster配置文件,添加虚拟集群访问ip,即主机集群节点地址
[root@vm ~]# cat value.yaml
syncer:
extraArgs:
- --tls-san=192.168.x.11,192.168.x.12,192.168.x.13
# 创建虚拟集群,使用k0s发行版
[root@vm ~]# vcluster create vcluster-1 -n vcluster-1 --distro k0s -f value.yaml
[info] officially unsupported host server version 1.20, will fallback to virtual cluster version v1.22
[info] execute command: helm upgrade vcluster-1 vcluster-k0s --repo https://charts.loft.sh --version 0.7.1 --kubeconfig C:\Users\wangw\DOCUME~1\MOBAXT~1\slash\tmp\1920354934 --namespace vcluster-1 --install --repository-config='' --values C:\Users\wangw\DOCUME~1\MOBAXT~1\slash\tmp\2268190059 --values value.yaml
[done] √ Successfully created virtual cluster vcluster-1 in namespace vcluster-1.
- Use 'vcluster connect vcluster-1 --namespace vcluster-1' to access the virtual cluster
- Use `vcluster connect vcluster-1 --namespace vcluster-1 -- kubectl get ns` to run a command directly within the vcluster
# 从主机集群中查看vcluster-1命名空间资源
[root@vm ~]# kubectl get all -n vcluster-1
NAME READY STATUS RESTARTS AGE
pod/coredns-86d5cb86f5-k9t4c-x-kube-system-x-vcluster-1 1/1 Running 0 32s
pod/vcluster-1-0 2/2 Running 0 95s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
AGE
service/kube-dns-x-kube-system-x-vcluster-1 ClusterIP 10.43.94.24 <none> 53/UDP,53/TCP,9153/TCP
33s
service/vcluster-1 ClusterIP 10.43.227.133 <none> 443/TCP
97s
service/vcluster-1-headless ClusterIP None <none> 443/TCP
97s
service/vcluster-1-node-vm190118 ClusterIP 10.43.94.216 <none> 10250/TCP
33s
service/vcluster-nodeport NodePort 10.43.112.147 <none> 443:32121/TCP
8m37s # 虚拟集群API对外访问端口32121
NAME READY AGE
statefulset.apps/vcluster-1 1/1 97s # 虚拟集群控制平面
使用虚拟集群
# 获取虚拟集群kubeconfig
[root@vm ~]# vcluster connect vcluster-1 -n vcluster-1 --server=https://192.168.x.11:32121
[info] Use `vcluster connect vcluster-1 -n vcluster-1 -- kubectl get ns` to execute a command directly within this terminal
[done] √ Virtual cluster kube config written to: ./kubeconfig.yaml. You can access the cluster via `kubectl --kubeconfig ./kubeconfig.yaml get namespaces`
[root@vm ~]# ls
vcluster-nodeport.yaml kubeconfig.yaml value.yaml
# 配置当前kubectl会话使用虚拟集群的kubeconfig
[root@vm ~]# export KUBECONFIG=./kubeconfig.yaml
[root@vm ~]# kubectl get ns
NAME STATUS AGE
default Active 7m36s
kube-node-lease Active 7m50s
kube-public Active 7m50s
kube-system Active 7m51s
# 虚拟集群下只有coredns组件
[root@vm ~]# kubectl get po -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-86d5cb86f5-k9t4c 1/1 Running 0 9m2s
# 在虚拟集群下创建应用
[root@vm ~]# kubectl run nginx --image=nginx:stable --port=80
pod/nginx created
[root@vm ~]# kubectl get po
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 36s
# 此时在主机集群下查看pod,会发现虚拟集群下创建的pod直接同步到了其主机集群命名空间下,并且pod名称附带了pod在虚拟集群下的命名空间和虚拟集群名称
[root@vm ~]# kubectl get po -n vcluster-1
NAME READY STATUS RESTARTS AGE
coredns-86d5cb86f5-k9t4c-x-kube-system-x-vcluster-1 1/1 Running 0 13m
nginx-x-default-x-vcluster-1 1/1 Running 0 58s
vcluster-1-0 2/2 Running 0 15m
# 为虚拟集群的应用创建servcie
[root@vm ~]# kubectl expose pod nginx --port=80
service/nginx exposed
[root@vm ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.43.227.133 <none> 443/TCP 20m
nginx ClusterIP 10.43.146.179 <none> 80/TCP 6s
# 再查看主机集群下的虚拟集群所在命名空间的服务,虚拟集群中的应用服务也被同步了出来
[root@vm ~]# kubectl get svc -n vcluster-1
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns-x-kube-system-x-vcluster-1 ClusterIP 10.43.94.24 <none> 53/UDP,53/TCP,9153/TCP 22m
nginx-x-default-x-vcluster-1 ClusterIP 10.43.146.179 <none> 80/TCP 101s
vcluster-1 ClusterIP 10.43.227.133 <none> 443/TCP 23m
vcluster-1-headless ClusterIP None <none> 443/TCP 23m
vcluster-1-node-vm190118 ClusterIP 10.43.94.216 <none> 10250/TCP 22m
vcluster-nodeport NodePort 10.43.112.147 <none> 443:32121/TCP 30m
清理虚拟集群
[root@vm ~]# vcluster delete vcluster-1 -n vcluster-1
[info] Delete helm chart with helm delete vcluster-1 --namespace vcluster-1 --kubeconfig C:\Users\wangw\DOCUME~1\MOBAXT~1\slash\tmp\89266231 --repository-config=''
[done] √ Successfully deleted virtual cluster vcluster-1 in namespace vcluster-1
[done] √ Successfully deleted virtual cluster pvc data-vcluster-1-0 in namespace vcluster-1