从零开始的 Web 开发:CI/CD 基础设施和开发流程搜索信息、问题的相关性典型的开发流程基础设施材料

2025-05-27

从零开始的 Web 开发:CI/CD 基础设施和开发流程

搜索信息、问题的相关性

典型开发流程

基础设施

材料

新组建团队构建 CI/CD 基础设施和开发流程的指南

这是本文的英文版。感谢Akkarine

一年多前,我亲眼目睹了我管理的整个Web开发部门是如何从一个与IT无关的公司内部项目发展而来的。工作流程似乎已经稳定下来,每个人都很满意,但仍然存在一些问题:

  • 每个分支都在本地进行检查。我们必须回滚数据库中上次检查的更改,构建前端。当几位开发人员即将完成需要检查细节的工作时,情况却变成了人间地狱;
  • 生产和开发环境不同,导致了这种错误:“它在我的计算机上运行”。

我内心的完美主义者渴望把一切都安排得井井有条。在这里,我分享了自己寻找“什么才是真正的正确方法”这个问题的答案的成果。

我们的成就:

  • 在生产中轻松快速地部署(为了实验,我们连续两周每天都进行部署);
  • 保证防止因应用环境差异而导致的错误;
  • 有可能与客户进行有效互动:
    • 演示每个功能分支;
    • 提供访客访问权限以创建任务并监控工作进度。

如果您符合以下情况,本文将很有用:

  • 您是一家年轻的IT公司,或者这是您第一次在一个大型项目上进行团队合作;
  • 您希望更新旧的开发工作流程;
  • 您正在寻找最佳实践并想看看其他人是如何做的;
  • 您经常会遇到有关 DevOps、CI/CD、云的文章;想要一键创建测试环境,并确保每次生产更新都不是俄罗斯轮盘赌。

你会发现:

  • 从任务到发布的典型工作流程;
  • 使用最少的工具构建任何现代开发流程的基础设施解决方案;
  • 一个常见案例的例子:Web 应用程序开发。

替代文本

本文由三部分组成:

  • 我对典型开发过程的看法;
  • 实施任何现代工作流程的基础设施;
  • 一个网络开发的案例。

搜索信息、问题的相关性

在寻找最佳实践的过程中,我接触到了很多关于方法论和各种工具的理论,但信息却很零散。没有任何文章能够从经理、开发人员和系统管理员(例如 DevOps)的角度展示一个统一的流程。例如,这些关于开发流程的抽象 讨论文章并没有解答这些问题:“好吧,我应该使用什么工具来做这件事?”

需要一个“基本”流程实现的真实实例,以便您可以用它来构建自己的流程。文章作者似乎认为这不言而喻。一个显而易见的选择是借鉴大公司的经验或聘请具有此类经验的人员,但这种方法可能无效。因为大公司的基础设施很可能是为比您当前需求复杂得多的任务量身定制的,并且需要大量的资源和知识来实施。

最终,我查阅了大量相关资料,熟悉了各种基础设施工具,并与自身经验进行了比较。在实施过程中,我遇到了各种官方文档中几乎没有涉及的陷阱,但为了“最佳实践”,我必须克服它们。调整部门以适应新的工作方式也需要时间。

尽管我一年前就已经有过这样的经历,但谷歌显示我曾经寻找的指南还没有出现。

那么,让我们开始吧。

您将需要:

  • 一些可供您使用的计算能力。可能是您自己的服务器或云基础设施;
  • 了解您的应用程序:它如何工作,如何部署;
  • 网络、git、Linux、Docker、GitLab、Traefik 的基本知识。

典型开发流程

必需组件

1. 使用 git 中的经典模型

替代文本

Vincent Driessen 提出的成功的 Git 分支模型

最低要求是具有以下分支:master、devfeature

功能:
每个功能分支都是为单个功能/错误修复而创建的,它们从dev分支分支出来。在更改合并到dev分支后,它们将被删除。

Dev
dev中,所有新更改都会进行最终的共同调试和测试,之后将发布部署到master

Master
版本发布到生产服务器时,会从此分支进行部署。此外,如果需要应用紧急修复,可以从 master 分支创建hotfix分支,然后合并回 master 分支并删除。Master和dev分支是固定分支,不会直接推送。

2. 任务追踪器中的协作。记录所有已做出的决策

替代文本

这非常重要。在多个功能分支之间切换时,程序员第二天就会完全忘记背景信息。创建像“检查 xxx 出了什么问题”这样的低优先级任务不足以记住这是怎么回事。所有评论都必须记录在线程的合并请求讨论中。维护项目 Wiki 非常有必要,这样可以加快新团队成员的适应速度并批准已做出的决策。

你应该永远记住,如果某件事没有被写下来,它就不存在。

GitLab 的经历就是一种极端的记录保存方式,在疫情爆发之前,这家公司就没有办公室了。

3. 测试和发布的基础设施自动化

很简单——解决方案投入生产的速度越快,可靠性就越高,竞争优势也就越大。我们经常会看到一些文章,统计每月/每周/每天的发布数量。

我相信这塑造了 DevOps,并成为所有现代 IT 巨头发展的催化剂。首先,他们实现了单体应用测试和部署的自动化。但随之而来的是等待时间过长以及无法在本地部署开发环境的问题。解决方案是引入微服务架构,但这也带来了新的挑战。就在这时,容器化(LXC)出现了,然后是 Docker 和编排器,一切由此螺旋式发展……

职能角色

在团队合作中,你需要了解谁负责什么。请注意,这些是职能角色,而不是职位。这意味着一个人可能身兼数职。我相信在每个项目中,这些职能都会得到一定程度的履行,即使团队没有意识到这一点。我分享我的观点,是因为很多文章都写得好像每个人天生就了解谁是谁。

专案经理

该团队成员负责与关键客户代表和高级管理层沟通,确定关键指标,维护文档流,解决所有财务和人力资源问题,并推广产品——无论是独立完成还是通过与公司其他部门的互动。该成员对业务结果负责,并向产品负责人施加压力。

产品负责人

担任此职位的人对产品有总体规划,知道产品应该是什么样子,以及它能给客户带来什么。他是产品待办事项列表(任务列表)的维护者,负责确定任务的优先级,熟悉所有产品功能,并在一定程度上了解技术方面。他必须具备开发经验。他应该能说出“团队需要更多人手”,并保护团队免受管理压力。

分析师/技术作家

该团队成员始终贴近产品的最终用户,研究客户的业务流程,并在每个功能实施后收集反馈。分析师/技术文档撰写人可以被称为“产品负责人的信息提供者”,他们帮助制定技术需求。他们还必须了解所有产品功能。该人员参与客户培训并为客户撰写文档。

设计师UI / UX

设计师负责让产品易于使用。这是成功的关键因素(当然,除非你是微软)。

建筑师

这位团队成员可能参与了多个项目。架构师是公司里最有经验的开发人员。架构师可以咨询团队负责人。

团队负责人

经验丰富的开发人员,负责咨询产品负责人,评估任务的复杂性,在开发人员之间分配任务,并负责进一步分解和技术完善。负责最终验收。

开发人员

此人编写并记录代码;执行同事的代码审查。

根据项目的不同,开发人员专注于各自的领域:后端、前端、移动开发等。

测试员(QA/QC)

质量控制 (QC) 负责测试产品,包括手动测试和编码测试。质量保证 (QA) 测试人员也参与项目架构和基础架构的开发,以确保将对高质量结果的关注贯穿到生产流程中(丰田模式——质量嵌入原则)。例如,对即将上线生产的 Docker 镜像进行精确测试,而不是在测试结束后重新构建。

系统管理员(DevOps)

就像建筑师一样,团队成员可能同时参与多个项目。他们在项目开始时创建基础设施,并随着项目的发展进行修改。

信息安全

软件开发的不同阶段需要不同类型的信息系统专家。但他们都必须确保应用程序管理的数据是保密的、完整的且可用的。

开发过程

替代文本

工作流阶段

  1. 任何任务都始于对某种改进(功能)的需求或发送给产品负责人的错误报告。这些信息会被记录在跟踪器中。
  2. 产品负责人自行或在分析师的帮助下了解所有细节。所有内容都已写入任务中。对工作时间进行初步估算。设定优先级,并可能将任务添加到项目管理计划中。
  3. 到了实施阶段,我们会与团队负责人一起分解任务(将其划分为子任务),确定执行者,并共同完成整个任务,并记录对执行者来说足够详细的实施说明。如果您需要进一步了解任务细节,请咨询产品负责人。
  4. 从开发阶段创建一个功能分支,并编写代码。如果任务规模较大且包含多个子任务,则选择主功能分支,并将子任务分支合并到主功能分支中。如果已为此任务做出此类决定,则需要编写测试。

    注意:为了最大限度地减少合并分支时的冲突,您的应用程序架构必须保持最小的模块耦合。此外,如果某个任务的实现与另一个任务中已更改的代码片段相同,但该任务的合并请求尚未被接受,则您不应开始执行该任务。

  5. 创建对 dev-branch 的合并请求,构建、测试和部署功能分支。

  6. 其他开发人员审查代码,并进行手动测试。如果发现任何缺陷,则再次运行自动测试,部署分支并重新检查。

  7. 团队负责人进行最后的检查并将完成的功能分支带到开发中。

  8. 当下一次发布时,将从 dev-branch 创建一个合并请求,将所有最新更改合并到 master,并执行与第 5、6 点相同的操作。

  9. 正如第 7 点一样,产品所有者可能会参与其中。

  10. 让用户了解已引入的变更(创建变更日志)以及更新产品帮助非常有用。更新文档并将变更接受到主版本。

  11. 这些更改将自动或手动部署到生产中。

  12. 应用程序受到监控。本文不涉及此内容。

基础设施

选择工具时,使用以下标准:

  • 生产就绪,
  • 大型社区,
  • 学习其他工具的难度不太高,
  • 尽可能少的(每个都有大量的功能集)。

最终选择了以下技术:TraefikGitLabDocker

替代文本

  • 使用了三台服务器:[Production][Staging][Services]。它们可以是物理机或虚拟机,数量可以更多或更少,或者所有内容都可以存储在云端。这里给出了可靠性/价格比方面最有效的配置。最重要的是[Production]应该是独立的并且是最可靠的。GitLab以及一些次要服务(监控、docker registry:Portainer、ELK、Harbor等)(我们将其称为 Services)安装在[Services]服务器上。本示例不介绍它们的配置。所有应用程序都在 Docker 容器中运行。最好单独安装GitLab,但这取决于可用容量。

  • Traefik通过 TCP 连接到[Staging]docker 并提供访问权限,收集 .dev.company.ru 运行环境的动态 DNS 信息。它还会自动为[Production]上的应用程序获取 SSL 证书。如果Traefik不支持您的 DNS 提供商,则使用单独的容器 *letsencrypt-dns 获取通配符 (WC) 证书.dev.company.ru。Traefik会使用此证书或自行获取的证书,截断来自客户端的 SSL 连接,并通过域名将 http 请求重定向到相应的服务。它与主应用程序App一起在[Production]上运行

  • GitLab使用安装在其他虚拟机上的GitLab-runners在[Services]上运行命令。通过向devmaster分支发送合并请求 (MR),GitLab根据项目的.gitlab-ci.yml文件,管理[Staging][Production]上运行的 docker 镜像。

  • 构建、测试和准备工作均在[Staging]上进行

  • 在这个解决方案中,GitLab还充当Docker Registry 的角色,用于存储构建的应用程序镜像。

  • GitLabTraefikGitlab-runners也在 docker 容器中运行,这使得更新和迁移基础设施变得容易。

这里有一个 Github 仓库的链接,里面逐步描述了创建这个基础设施的过程。为了避免这篇长文显得冗长,请大家直接去那里阅读:

https://github.com/Akkarine/demo_cicd

警告

  • 此基础架构解决方案更像是一个入门平台,用于理解基本原理;尚未进行负载测试。很大程度上取决于硬件和应用程序架构。对于高负载、高可靠性以及云端工作,建议考虑使用 Traefik 和 GitLab 的企业版,并寻求专家的建议。
  • 存储库包含您显然需要自定义的部分配置。例如,时区、邮政地址、域名等。
  • 自一年前开展这项工作以来,Traefik 和 GitLab 随着时间的推移取得了显著的发展,许多方面已经可以优化。例如,Traefik 现在支持 Yandex DNS(这其中也少不了我的一点贡献),并且不再需要中间服务。而且 GitLab 拥有更灵活的配置选项,例如规则
  • 还要注意“可以立即改进什么”部分。

Web 开发案例:

https://github.com/Akkarine/demo_cicd_project

该示例针对一个小型 Web 应用程序提供,以便帮助理解基本原理,因为它假设:

  • 更新期间应用程序不可用。为了在不停机的情况下组织部署,您需要应用程序代码的支持(后端 API 版本控制、分阶段数据库迁移)、更复杂的负载均衡器设置和部署算法,理想情况下还需要另一层基础设施——Kubernetes。因此,这远非“入门级”。
  • 在docker中运行数据库(影响性能)
  • 复制生产数据库以进行暂存(数据保密性,大型数据库存在问题)
  • 在容器中以 root 身份运行命令(根本不是最佳实践)

仓库中最重要的是.gitlab-ci.yml文件。让我们根据工作流程中的步骤来考虑管道阶段及其中的任务:

  • 基础图像重建

    • rebuild-base-backend:构建过程分为两个阶段,以加快速度。目前,第一个阶段会构建一个基础镜像,该镜像仅在依赖项描述文件发生更改时才会启动。第二个阶段(构建阶段)会构建应用程序。
  • 重建开发数据库

    • rebuild-dev-db:在此任务中,为测试分支准备一个通用数据库映像,并在映像内直接部署数据库的备份。
  • 建造

    • rebuild-proxy-img:由于 nginx 代理服务器的镜像很少更新,因此可以立即使用“最新”标签创建该镜像
    • build-backend:该应用程序使用当前更改构建,目前已标记问题编号(整个 GitLab 独有)
  • 测试

    • 测试:运行自动化测试
  • 部署-审查

    • deploy_review:部署测试服务器,它几乎与生产服务器相同,只是服务器配置对资源的侵蚀较小。
  • skip_review:如果在开发的这个阶段不需要,则用于跳过测试服务器的创建。

  • 审查

    • approve-dev:手动激活。当合并请求到达 dev 分支(即当前分支为 feature 分支)时,无需推送。此任务仅用于在流水线上打上绿色勾号。
    • approve-staging:手动激活。当合并请求提交到 master 分支(即当前分支为 hotfix 或 dev 分支,且发布正在进行中)时,在构建阶段测试过的镜像将被标记为“latest”,并替换仓库中的旧版本。为了确保它不会被下一个最新版本覆盖,上传时也会带有“任务编号”标签。
    • 拒绝:手动激活。它只会在管道上显示红色。这样,从合并请求列表中就能清楚地看出该分支存在问题。
    • stop_review:可以自动或手动激活。停止已提升的测试服务器
  • 重建已批准的数据库图像

    • rebuild-approved-db-img:如果审核成功,并且在创建数据库映像的上下文中更新了文件,则会创建一个带有“最新”标签的新映像并将其上传到存储库。
  • 部署产品

    • deploy-production:在生产环境中,数据库会备份,容器也会更新到最新版本。如果备份失败,则不会进行部署。
    • deploy-production-wo-containers:如果数据库未部署备份,则跳过此操作。
  • 清除:临时服务器和生产服务器中的垃圾已清除

    • 清洁暂存
    • 清洁产品
  • 恢复数据库

    • restore-db:对于第一次部署或极其不成功的更新,它从备份中恢复数据库。

材料

Traefik

Nginx 上的替代反向代理 + SSL

GitLab

GitLab SSL 配置

GitLab 注册表

Gitlab 运行器

Docker

其他有用链接

分析docker镜像的命令(该实用程序在docker中运行)
sudo docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock wagoodman/dive:latest gitlab/gitlab-runner:latest

文章来源:https://dev.to/hostman_com/web-development-from-scratch-ci-cd-infrastruct-development-process-3hpl
PREV
JavaScript 函数概述
NEXT
GitHub Foundations 认证现在免费!💲 🇧🇷