一、背景
- 为什么一个已经在使用 Kubernetes 本身方面已经很挣扎的开发人员还要处理虚拟集群呢?答案可能会让您感到惊讶,但我相信虚拟集群实际上比单独的物理集群更容易处理,并且与本地 k3d、KinD 或 minikube 部署的集群相比具有相当多的优势。
- 如果经常使用 Kubernetes,您可能知道问题所在:想尝试一个新应用程序,切换到另一个项目来工作,或者您有一段时间没有使用本地 Kubernetes 集群并且忘记了其中部署了什么?
- 由于使用新的空集群比重用现有集群要容易得多,因此只需重置整个集群。对我来说,这种情况经常发生,我每天多次重置我的本地 docker-desktop 实例,有时想同时处理多个项目,这些项目可能由于它们的 CRD 和 Operator 依赖关系而发生冲突。
二、KinD、k3d 和 minikube 来救场?
- 您可能告诉我这样太 Low,应该为每个项目使用单独的 KinD、k3d 或 minikube 集群而不是一遍又一遍地重置 docker-desktop 实例。但你应该知道这种方法也有它的问题。如果您定期重置这些集群,甚至同时运行多个集群,将很难在本地 docker 安装中与磁盘空间和资源开销做权衡。
- 问题源于这些工具创建 Kubernetes 集群的方式,您可能已经注意到,在创建新的 KinD、k3d 或 minikube(docker 驱动程序)集群时,它们会创建一个运行整个 Kubernetes 集群的单节点容器。在 minikube 和 KinD 的情况下,这是一个包含 vanilla Kubernetes 二进制文件的容器,而在 k3d 的情况下,毫无疑问它是 k3s。节点本身包括小型 Kubernetes 设置所需的一切,包括单独的 systemd、containerd 以及通常的其他一些集群工具。虽然这很有效,但它也有几个缺点:需要重新拉取新集群中的所有容器镜像,跨本地集群的通信通常很困难,并且运行这些集群会产生大量开销。
三、虚拟集群是解决方案
- 虚拟 Kubernetes 集群可以在这里进行改进,来一起看下虚拟 Kubernetes 集群与 KinD、k3d 和 minikube 的不同之处,以了解为什么它可以成为很好的替代品。
- 主要区别在于虚拟集群只复制 Kubernetes 控制平面,而不是节点本身。没有托管集群就无法存在,因此虚拟集群永远不能完全替代 docker-desktop、KinD 或 k3d 等发行版。将虚拟集群想象成虚拟机,如果没有物理的支持,它也无法存在。因此,虚拟集群不是复制一个完整的 Kuberentes 节点及其所有进程和 CNI 或 CRI 等底层驱动程序,而是重用现有 Kubernetes 集群的节点,并且仅为每个虚拟集群创建一个微小的单独的控制平面。
- 这具有很大的优势,可以重用主机集群(安装了虚拟集群的集群)中的许多部分,例如节点、存储和网络。所以你可以去掉运行 Kubernetes 集群所需的大部分其他进程,例如 kubelet、kube-proxy、CNI 和 CRI 驱动程序、containerd、systemd 等。顺便说一句,这也意味着你可以重用所有已经拉取到主机集群的镜像。另一个好处是访问另一个虚拟集群的应用程序也非常容易,因为它们共享相同的底层网络。
- 为了实现这一点,虚拟集群发行版只是重用现有的发行版,如 k3s、 k0s 甚至常规的 kubernetes 二进制文件来部署控制平面。因此,如果您认为 k3s 很小,可以尝试使用 k3s 的虚拟集群,并禁用其中的 90% 。除了控制平面之外,还有一个名为 syncer 的小型管理程序用于将纯虚拟控制平面中创建的工作负载实际同步到主机集群,从而将虚拟集群转变为实际可用的集群。这听起来非常复杂,但实际上它非常简单并且工作得很好。
四、结果验证
- 您可能会想: 这听起来不错,但我不想要一个难以使用的解决方案,我只想运行一个简单的命令来创建和删除一个集群,就像 KinD 或 minikube 正在做的那样。好消息是,在最新版本的 vcluster(完全开源且最流行的虚拟集群实现)0.10.0 中,已经将虚拟集群的处理简化为超级简单的一行命令:
https://github.com/loft-sh/vcluster
- 首先从发布页面,下载 vcluster 二进制文件:
https://github.com/loft-sh/vcluster/releases
https://www.vcluster.com/docs/quickstart
- 确保您已经设置了本地 Kubernetes 发行版(例如 docker-desktop、rancher-desktop、KinD、minikube 或 k3d),然后运行以下命令在其中创建一个新的虚拟集群:
$ vcluster create my-vcluster
- 恭喜,就是这样,刚刚部署了第一个虚拟集群,几秒钟后,vcluster 应该可以使用:
kube-node-lease Active 40s
$ kubectl wait --for=condition=ready pod -l app=guestbook
$ kubectl port-forward service/frontend 9080:80
- 然后在浏览器中导航到页面 http://localhost:9080/ 以查看正在运行的留言簿应用程序,要跳回原始集群,请使用:
$ vcluster disconnect
- 有趣的是,vcluster 将在主机集群的单个命名空间内创建所有同步资源,只有少数核心资源实际同步到主机集群,而大多数其他资源纯粹保留在虚拟集群中。要查看 vcluster 的同步工作负载,请在主机集群中运行以下命令:
$ kubectl get pods -n vcluster-my-vcluster
NAME READY STATUS RESTARTS AGE
coredns-76dd5485df-75jgf-x-kube-system-x-my-vcluster 1/1 Running 0 7m25s
frontend-f7d9c57d4-8wp44-x-default-x-my-vcluster 1/1 Running 0 7m13s
frontend-f7d9c57d4-d2trf-x-default-x-my-vcluster 1/1 Running 0 7m13s
frontend-f7d9c57d4-k6sb6-x-default-x-my-vcluster 1/1 Running 0 7m13s
my-vcluster-0 2/2 Running 0 7m35s
redis-master-857d99cc8-tr949-x-default-x-my-vcluster 1/1 Running 0 7m13s
redis-replica-6fd587fb56-gjht5-x-default-x-my-vcluster 1/1 Running 0 7m13s
redis-replica-6fd587fb56-mksx4-x-default-x-my-vcluster 1/1 Running 0 7m13s
- 可以看到 vcluster 将重命名工作负载,以确保具有相同名称的多个 pod 在同一主机命名空间内不会发生冲突。要了解有关哪些资源实际同步到主机集群的更多信息,您可以查看文档:
https://www.vcluster.com/docs/architecture/synced-resources
vcluster delete my-vcluster
五、总结
- 一个新的 Kubernetes 集群总是比一个已经存在的集群更好用。现在,虚拟集群不仅可以在复杂的多租户环境中使用,而且可以在本地测试或开发集群中使用。
- 虚拟集群不能单独存在,没有主机集群。但它们可以成为并行运行多个 KinD、k3d 或 minikube 实例的好选择。它们比完整的独立 Kubernetes 集群更轻量、更易于访问且速度更快。因此,如果您对不断重置本地 Kubernetes 集群感到恼火,请尝试使用虚拟集群。