我们 True Engineering 已经建立了一个向客户服务器持续交付更新的流程,并希望分享这一经验。
首先,我们为客户开发了一个在线系统,并将其部署在我们自己的 Kubernetes 集群中。 现在我们的高负载解决方案已经转移到客户的平台上,我们为此建立了全自动的持续部署流程。 因此,我们加快了上市时间——交付产品环境的变化。
在本文中,我们将讨论持续部署 (CD) 流程或向客户平台交付更新的所有阶段:
- 这个过程是如何开始的?
- 与客户的 Git 存储库同步,
- 后端和前端的组装,
- 在测试环境中自动部署应用程序,
- 自动部署到产品。
我们将一路分享设置细节。
1. 启动光盘
持续部署从开发人员将更改推送到 Git 存储库的发布分支开始。
我们的应用程序在微服务架构上运行,其所有组件都存储在一个存储库中。 因此,即使其中一个微服务发生了更改,所有微服务都会被收集和安装。
我们通过一个存储库组织工作有以下几个原因:
- 易于开发 - 应用程序正在积极开发,因此您可以立即使用所有代码。
- 单个 CI/CD 管道,保证应用程序作为单个系统通过所有测试并交付到客户的生产环境。
- 我们消除了版本混乱 - 我们不必存储微服务版本映射并在 Helm 脚本中描述每个微服务的配置。
2、与客户源代码的Git仓库同步
所做的更改会自动与客户的 Git 存储库同步。 在那里配置应用程序程序集,该程序集在更新分支后启动,并部署到延续。 这两个进程都源自其环境中的 Git 存储库。
我们无法直接使用客户的存储库,因为我们需要自己的开发和测试环境。 我们将 Git 存储库用于这些目的 - 它与他们的 Git 存储库同步。 一旦开发人员将更改发布到我们存储库的相应分支,GitLab 就会立即将这些更改推送给客户。
之后您需要进行组装。 它由几个阶段组成:后端和前端组装、测试和交付生产。
3. 组装后端和前端
构建后端和前端是在 GitLab Runner 系统中执行的两个并行任务。 其原始程序集配置位于同一存储库中。
GitLab Runner 从所需的存储库中获取代码,使用 Java 应用程序构建命令对其进行组装,并将其发送到 Docker 注册表。 在这里,我们组装后端和前端,获取 Docker 镜像,并将其放入客户侧的存储库中。 为了管理我们使用的 Docker 镜像
我们将镜像的版本与将在 Docker 中发布的发布版本进行同步。 为了顺利运行,我们做了一些调整:
1.测试环境和生产环境之间不重建容器。 我们进行了参数化,以便同一个容器可以在测试环境和生产环境中使用所有设置、环境变量和服务,而无需重建。
2. 要通过 Helm 更新应用程序,您必须指定其版本。 我们构建后端、前端并更新应用程序 - 这是三个不同的任务,因此在任何地方使用相同版本的应用程序非常重要。 对于此任务,我们使用 Git 历史记录中的数据,因为我们的 K8S 集群配置和应用程序位于同一个 Git 存储库中。
我们从命令执行结果中获取应用程序版本
git describe --tags --abbrev=7
.
4.自动部署所有变更到测试环境(UAT)
此构建脚本的下一步是自动更新 K8S 集群。 如果整个应用程序已构建并且所有工件已发布到 Docker 注册表,则会发生这种情况。 之后,测试环境更新开始。
集群更新开始使用
我们提供 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:
在总
因此,持续部署已配置并正在运行。 所有更新均通过一次按键完成。 对产品环境的更改的交付是自动的。 而且,重要的是,更新不会停止系统。
未来计划:自动数据库迁移
我们考虑了升级数据库以及回滚这些更改的可能性。 毕竟,应用程序的两个不同版本同时运行:旧版本正在运行,新版本正在运行。 只有当我们确定新版本可以工作时,我们才会关闭旧版本。 数据库迁移应该允许您使用应用程序的两个版本。
因此,我们不能简单地更改列名或其他数据。 但是我们可以创建一个新列,将旧列中的数据复制到其中,并编写触发器,在更新数据时,将同时在另一列中复制和更新数据。 成功部署新版本的应用程序后,在启动后支持期结束后,我们将能够删除旧列和不再需要的触发器。
如果新版本的应用程序不能正常工作,我们可以回滚到以前的版本,包括以前版本的数据库。 简而言之,我们的更改将允许您同时使用该应用程序的多个版本。
我们计划通过 K8S 作业自动化数据库迁移,并将其集成到 CD 流程中。 我们一定会在哈布雷身上分享这段经历。
来源: habr.com