我们如何将持续更新交付到客户平台

在True Engineering,我们已经设置了将更新持续交付给客户服务器的过程,并希望分享这种经验。

首先,我们为客户开发了一个在线系统,并将其部署在我们自己的Kubernetes集群中。 现在,我们的高负载解决方案已移至客户的平台,为此我们建立了全自动的持续部署流程。 因此,我们加快了产品上市时间-将变更交付到产品环境中。

在本文中,我们将讨论持续部署(CD)流程中的所有步骤或向客户平台提供更新:

  1. 这个过程如何开始
  2. 与客户的Git存储库同步,
  3. 后端和前端组装
  4. 在测试环境中自动部署应用程序,
  5. 在Prod上自动部署。

在此过程中,我们将共享设置的详细信息。



1.启动CD


持续部署始于开发人员将所做更改发布到我们的Git存储库的release分支。

我们的应用程序基于微服务架构工作,其所有组件都存储在一个存储库中。 因此,所有微服务都已组装并安装,即使其中一项已更改也是如此。

出于以下几个原因,我们通过一个存储库组织了工作:

  • 易于开发-应用程序正在积极开发中,因此您可以立即使用所有代码。
  • 单个CI / CD管道可确保应用程序作为单个系统通过所有测试,并交付给客户的产品环境。
  • 我们排除了版本之间的混淆-我们不必存储微服务版本的映射,也不必在Helm脚本中描述每个微服务的配置。

2.与客户源代码的Git存储库同步


所做的更改会自动与客户的Git存储库同步。 在那里,配置了应用程序的程序集,该程序集在更新分支和部署到生产后开始。 这两个过程都在其环境中从Git存储库发生。

我们无法直接与客户的存储库合作,因为我们需要自己的开发和测试环境。 我们将Git存储库用于这些目的-它与他们的Git存储库同步。 开发人员将更改发布到我们存储库的相应分支后,GitLab会立即将这些更改发送给客户。



之后,您需要进行装配。 它包括几个阶段:组装后端和前端,测试并交付给产品。

3.构建后端和前端


后端和前端程序集是在GitLab Runner系统中执行的两个并行任务。 她对原始程序集的配置位于同一存储库中。

用于编写要在GitLab中构建的YAML脚本的教程

GitLab Runner从所需的存储库中获取代码,收集Java应用程序构建命令,并将其发送到Docker注册表。 在这里,我们收集后端和前端,获取Docker映像,并将其放入客户端的存储库中。 要管理Doker图像,请使用Gradle插件

我们将映像的版本与发布版本同步,该版本将发布在Docker中。 为了顺利运行,我们进行了以下设置:

1.在测试环境和杂货容器之间不进行重新组装。 我们进行了参数化,以便同一容器可以工作,而无需在测试环境和产品中使用所有设置,环境变量和服务进行重建。

2.要通过Helm更新应用程序,必须指定其版本。 我们有后端程序集,前端和应用程序更新-这是三个不同的任务,因此在各处使用相同版本的应用程序很重要。 对于此任务,我们使用Git历史记录中的数据,因为我们拥有K8S集群配置,并且应用程序位于同一Git存储库中。

我们从命令结果中获取应用程序版本
git describe --tags --abbrev=7

4.自动部署测试环境(UAT)中的所有更改


此构建脚本的下一步是自动更新K8S集群。 只要组装了整个应用程序并将所有工件发布到Docker Registry,就会发生这种情况。 之后,将开始测试环境的更新。

使用Helm Update启动群集更新。 如果结果出了问题,Helm将自动并独立地回滚所有更改。 他的工作不需要控制。

与装配一起,我们提供了K8S集群的配置。 因此,下一步是对其进行更新:configMaps,部署,服务,机密以及我们更改的任何其他K8S配置。

之后,Helm在测试环境中启动RollOut更新应用程序本身。 在将应用程序部署到产品之前。 这样做是为了让用户手动检查我们在测试环境中发布的业务功能。

5.自动将所有更改部署到产品


要将更新部署到产品环境,只需在GitLab中单击一个按钮-即可将容器立即交付到产品环境。

一个应用程序可以在不重建测试和生产环境的情况下正常工作。 我们使用相同的工件而不更改应用程序中的任何内容,并且从外部设置参数。

应用程序设置的灵活参数化取决于将运行此应用程序的环境。 我们删除了所有环境设置:通过K8S配置和Helm参数对所有参数进行了参数化。 当Helm将程序集部署到测试环境中时,将对其应用测试参数,而将产品参数应用于产品环境。

最困难的事情是参数化所使用的所有服务和变量,这些服务和变量取决于环境,并将它们转换为环境变量以及Helm的环境参数的描述-配置。

应用程序参数使用环境变量。 它们的值使用K8S配置图在容器中设置,该配置图使用Go模板进行模板化。 例如,可以通过以下方式将环境变量设置为域名:

 APP_EXTERNAL_DOMAIN: {{ (pluck .Values.global.env .Values.app.properties.app_external_domain | first) }} 

.Values.global.env-环境名称(产品,阶段,UAT)存储在此变量中。
.Values.app.properties.app_external_domain-在此变量中,我们在.Values.yaml文件中设置所需的域

在更新应用程序时,Helm根据模板创建configmap.yaml文件,并根据应用程序更新开始的环境,用所需的值填充APP_EXTERNAL_DOMAIN值。 此变量已在容器中设置。 分别从应用程序访问它,在应用程序的每个环境中,此变量的值将不同。

相对较新,Spring Cloud引入了对K8S的支持,包括与configMaps一起使用: Spring Cloud Kubernetes 。 尽管该项目正在积极开发和变更中,但我们不能在生产中使用它。 但是我们会主动监控其状况并将其用于DEV配置中。 一旦稳定下来,我们就会从使用环境变量切换到它。

合计


因此,连续部署已启动并正在运行。 所有更新均在单击按钮时发生。 将变更交付到食品环境是自动的。 而且,重要的是,更新不会停止系统。



未来计划:自动基础迁移


我们考虑过升级数据库以及回滚这些更改的能力。 毕竟,该应用程序的两个不同版本可以同时工作:旧版本可以工作,而新版本可以使用。 而且只有当我们确信新版本正在运行时,我们才会关闭旧版本。 数据库迁移应允许同时使用该应用程序的两个版本。

因此,我们不能只更改列名或其他数据。 但是我们可以创建一个新列,将数据从旧列复制到其中,并编写触发器,当数据更新时,触发器将同时在另一个列中复制和更新它们。 在成功部署了新版本的应用程序之后,经过一段时间的启动后支持,我们可以删除旧列和不再需要的触发器。

如果新版本的应用程序无法正常运行,我们可以回滚到先前的版本,包括数据库的先前版本。 简而言之,我们所做的更改将允许同时使用该应用程序的多个版本。

我们计划通过将K8S作业嵌入CD进程中来自动进行数据库迁移。 我们一定会在Habré上分享这一经验。

Source: https://habr.com/ru/post/zh-CN447812/


All Articles