基于Kubernetes的拉取請求測試:使用vCluster實現環境隔離和成本控制
亮点
本周的文章是关于每个拉取请求的Kubernetes测试系列的第三篇也是最后一篇文章。在第一篇文章中,我介绍了应用程序以及如何在本地使用Testcontainers和GitHub工作流进行测试。在第二篇文章中,重点介绍了设置目标环境并运行Kubernetes上的端到端测试。
我通过提到一个重要的挑战来总结了这一结论。为每个工作流创建专用集群显著增加了运行时间。在GKE上,启动一个新的集群大约需要5到7分钟。如果你在上游创建一个GKE实例,则会遇到两个问题:
- 由于实例一直运行,这会增加成本。虽然这些成本是合理的,但如果你已经在为成本问题挣扎,它们可能会成为一个决策因素。无论如何,我们可以利用内置的云自动扩展工具。另外请注意,成本主要来自于工作负载,控制平面的成本几乎可以忽略。
- 另外,某些更改会影响到整个集群,例如 CRD 版本的变更。CRD 是集群范围内的资源。在这种情况下,我们需要一个专用集群以避免不兼容的更改。从工程角度来看,需要判断哪些 PR 可以共享集群,哪些需要专用集群。这种复杂性会减慢交付速度。
在这篇文章中,我将展示如何利用vCluster的优势:在一个单一集群中,实现每个PR测试的完全隔离,从而充分利用两种方法的好处。
完全功能的Kubernetes集群嵌套在物理主机集群内部,提供更好的隔离性和灵活性,以更好地支持多租户环境。多个团队可以在同一物理基础设施中独立运作,同时减少冲突,增加自主性并降低成本。
— 什么是虚拟集群?
有了虚拟集群,我们就可以既享受一个成本低廉的物理集群,又能拥有完全独立隔离的虚拟集群。
如何将vCluster整合到GitHub流程中
将 vCluster 整合到 GitHub 工作流中只需要三个步骤。
- 安装 vCluster
- 创建虚拟集群
- 连接到虚拟集群
- name: 安装 vCluster 插件
uses: loft-sh/setup-vcluster@main #1
with:
kubectl-install: false
- name: 创建 vCluster
id: vcluster #2
run: 运行时间 vcluster create vcluster-pipeline-${{github.run_id}} #3
- name: 连接 vCluster
run: vcluster connect vcluster-pipeline-${{github.run_id}} #4
- 安装 vCluster。默认情况下,此操作会安装最新可用版本。您可以选择覆盖它。
- 步骤 ID 只在后续步骤中引用时才需要。我们将需要这些步骤 ID。
- 创建虚拟集群。为了避免命名冲突,我们将其命名为工作流名称加上 GitHub 运行 ID 的后缀。
- 着手连接到虚拟集群
输出大致如下:
> 运行时间:vcluster create vcluster-pipeline-12632713145
12:44:13 信息 正在创建命名空间
12:44:13 信息 正在创建虚拟集群 vcluster-pipeline-12632713145...
12:44:13 信息 执行命令:helm upgrade vcluster-pipeline-12632713145 /tmp/vcluster-0.22.0.tgz-2721862840 --create-namespace --kubeconfig /tmp/3273578530 --namespace vcluster-vcluster-pipeline-12632713145 --install --repository-config='' --values /tmp/3458157332
12:44:19 完成 成功在命名空间 vcluster-vcluster-pipeline-12632713145 中创建虚拟集群 vcluster-pipeline-12632713145
12:44:23 信息 等待虚拟集群启动...
12:44:35 信息 虚拟集群正在等待,因为 pod vcluster-pipeline-12632713145-0 的状态为:Init:1/3
12:45:03 完成 虚拟集群已经启动并运行
12:45:04 信息 正在启动后台代理容器...
12:45:11 完成 切换到活动的上下文为 vcluster_vcluster-pipeline-12632713145_vcluster-vcluster-pipeline-12632713145_gke_vcluster-pipeline_europe-west9_minimal-cluster
- 使用 `vcluster disconnect` 返回到之前的 kube 上下文
- 使用 `kubectl get namespaces` 查看虚拟集群中的命名空间
real 1m2.947s
user 0m0.828s
sys 0m0.187s
> 运行 vcluster connect vcluster-pipeline-12632713145
12:45:13 完成 虚拟集群已经启动并运行
12:45:13 信息 正在启动后台代理容器...
12:45:16 完成 切换到活动的上下文为 vcluster_vcluster-pipeline-12632713145_vcluster-vcluster-pipeline-12632713145_gke_vcluster-pipeline_europe-west9_minimal-cluster
- 使用 `vcluster disconnect` 返回到之前的 kube 上下文
- 使用 `kubectl get namespaces` 查看虚拟集群中的命名空间
为了公平起见,我使用了time命令来精确测量虚拟集群的创建耗时。并通过查看GitHub的工作流日志来测量其他步骤。
安装 vCluster(虚拟集群)并连接到虚拟集群只需要大约一秒钟。创建一个虚拟集群大约要一分钟;而创建一个完整的 GKE 实例则至少需要五分钟。
工作流的变更这里有个大好消息:工作流的所有步骤都不需要做任何改变。我们可以继续用同样的步骤,因为虚拟集群与普通的Kubernetes集群使用相同的界面。
这其中包括:
- 安装 PostgreSQL Helm 图
- 创建 PostgreSQL 连接参数
ConfigMap
(配置映射) - 创建 GitHub 注册表
Secret
(密钥) - 应用 Kustomized 表单
- 并获取
LoadBalancer
的外部 IP!
如果你可能已经在使用 Kubernetes 了,因为你在读这篇帖子,那么在日常工作中的话,引入 vCluster 不需要任何破坏性的改动。
搞干净到目前为止,我们还没有清理任何创建的对象。这意味着我们的应用和 PostgreSQL 的 Pod 一直在集群中堆积,更不用说 Service
对象了,这使得可用端口变得紧张。这并非疏忽:原因是单独删除每个对象会带来很大的负担。我本可以将运行中的工作流的所有对象部署在一个专用的命名空间中,然后删除该命名空间。不幸的是,我之前曾因 命名空间卡在[终止状态](https://www.baeldung.com/ops/delete-namespace-terminating-state)
而遭受过困扰。
相反地,删除一个虚拟群集是简单的。我们再给工作流流程加上最后一步。
- 名称:
删除 vCluster
执行: vcluster delete vcluster-pipeline-${github.run_id}
还有个问题:如果 GitHub 工作流中的一个步骤失败了,也就是返回了一个非零的退出码,那么任务会立刻失败,GitHub 会直接跳过执行后续步骤。因此,如果端到端测试失败,上述清理就不会执行了。例如,如果出了问题,你可能有意保留集群的状态。在这种情况下,你应该依赖监控来实现这个目的,就像平时在生产环境里那样。我建议你无论何种情况都删除你的环境。
GitHub 提供了一个 如果
属性,可以根据条件来运行一个步骤。例如,它提供了 if: always()
,这意味着不论之前的步骤是否成功,GitHub 都会执行该步骤。这样在没有先创建虚拟集群时删除它是多余的。我们只应在创建成功的情况下才删除它:
- 名称: 删除 vCluster
条件: ${{ !cancelled() && steps.vcluster.conclusion == 'success' }} #1
执行: vcluster delete vcluster-pipeline-${{github.run_id}}
- 如果作业没有被取消 且
vcluster
步骤(如上定义)成功,则执行。作业取消的保护措施并非必要,但可以让集群一直运行。
通过这种设置,每个拉取请求(pull request)都能在独立的沙盒中运行,避免冲突并节省成本。这样你可以简化你的工作流程,降低风险,专注于交付功能而不必担心破坏共享环境。
结束本文结束了我们在Kubernetes上测试Pull Requests的系列文章。在第一篇文章中,我们本地运行了Testcontainers的单元测试,并建立了GitHub工作流的基础。我们还利用了GitHub服务容器来完善我们的流水线。在第二篇文章中,我们创建了GKE实例,部署了我们的应用程序及其PostgreSQL数据库,获取了Service
URL,并运行了端到端测试。本文中,我们使用了vCluster来隔离每个PR并控制成本。
虽然我不能涵盖每一个可能的选项,但该系列为你在 Kubernetes 集群上开始端到端测试 PR 的旅程提供了一个坚实的基础。
本文的完整源代码可以在GitHub上找到,具体网址如下:
GitHub - ajavageek/vcluster-pipeline 在 GitHub 上通过创建一个帐户来为 ajavageek/vcluster-pipeline 项目贡献代码。更进一步,
共同學習,寫下你的評論
評論加載中...
作者其他優質文章