我们在客户平台上实施持续部署

我们 True Engineering 已经建立了一个向客户服务器持续交付更新的流程,并希望分享这一经验。

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

在本文中,我们将讨论持续部署 (CD) 流程或向客户平台交付更新的所有阶段:

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

我们将一路分享设置细节。

我们在客户平台上实施持续部署

1. 启动光盘

持续部署从开发人员将更改推送到 Git 存储库的发布分支开始。

我们的应用程序在微服务架构上运行,其所有组件都存储在一个存储库中。 因此,即使其中一个微服务发生了更改,所有微服务都会被收集和安装。

我们通过一个存储库组织工作有以下几个原因:

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

2、与客户源代码的Git仓库同步

所做的更改会自动与客户的 Git 存储库同步。 在那里配置应用程序程序集,该程序集在更新分支后启动,并部署到延续。 这两个进程都源自其环境中的 Git 存储库。

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

我们在客户平台上实施持续部署

之后您需要进行组装。 它由几个阶段组成:后端和前端组装、测试和交付生产。

3. 组装后端和前端

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

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

GitLab Runner 从所需的存储库中获取代码,使用 Java 应用程序构建命令对其进行组装,并将其发送到 Docker 注册表。 在这里,我们组装后端和前端,获取 Docker 镜像,并将其放入客户侧的存储库中。 为了管理我们使用的 Docker 镜像 Gradle插件.

我们将镜像的版本与将在 Docker 中发布的发布版本进行同步。 为了顺利运行,我们做了一些调整:

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

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

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

4.自动部署所有变更到测试环境(UAT)

此构建脚本的下一步是自动更新 K8S 集群。 如果整个应用程序已构建并且所有工件已发布到 Docker 注册表,则会发生这种情况。 之后,测试环境更新开始。

集群更新开始使用 头盔更新。 如果结果没有按计划进行,Helm 将自动且独立地回滚所有更改。 他的工作不需要受到控制。

我们提供 K8S 集群配置以及组件。 因此,下一步是更新它:configMaps、部署、服务、密钥以及我们更改的任何其他 K8S 配置。

然后,Helm 在测试环境中运行应用程序本身的 RollOut 更新。 在将应用程序部署到生产环境之前。 这样做是为了让用户可以手动测试我们放入测试环境的业务功能。

5.自动部署所有变更到Prod

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

相同的应用程序可以在不同的环境(测试和生产)中运行,而无需重建。 我们使用相同的工件,而不更改应用程序中的任何内容,并在外部设置参数。

应用程序设置的灵活参数化取决于应用程序的执行环境。 我们已将所有环境设置移至外部:所有内容均通过 K8S 配置和 Helm 参数进行参数化。 当 Helm 将程序集部署到测试环境时,测试设置将应用于该程序集,而产品设置将应用于生产环境。

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

应用程序设置使用环境变量。 它们的值是使用 K8S configmap 在容器中设置的,该配置映射使用 Go 模板进行模板化。 例如,可以将环境变量设置为域名,如下所示:

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

.Values.global.env – 该变量存储环境的名称(prod、stage、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.com

添加评论