跳转到内容

GitLab 二次开发

GitLab 是常见的开源研发平台,很多企业有进行二次开发的需求,这里从开发、部署、维护三个阶段总结了一些实际经验,希望对你有帮助。

开发阶段

官方流程

要二次开发,首先需要一个源码修改的开发流程,要保证后续能轻松与上游同步,这个流程最好是跟上游一致。首先我们来看一下 GitLab 官方的开发迭代流程:

  1. 开发任务日常都在默认分支 master 下
  2. 当达到版本条件(比如 GitLab 每月版本)时,切出版本分支(命名 xxx-stable-ee)供发版使用,每个次要版本一个分支
  3. 版本分支中会处理一些版本特有的任务,比如修改版本号和部署配置
  4. 所有提交默认分支仍然是 master,有需要则会同步到已有的版本分支中,这里可能会有冲突需要处理

二开流程

综上,我们想做二次开发并保持上游同步,我们需要这么做:

  1. 先定义两个上游一样的分支:主分支(master-my),版本分支(17-10-stable-my)
  2. 企业二次开发直接在主分支上进行(master-my),例如图里的三个功能提交 my feature x,主分支需要每个版本开始前同步上游:
    • 同步上游主分支: 这里需要找到上游版本分支切出来的那个 commit,就是图里的 17-10-base,可以通过以下 git 命令找到:git merge-base --all master 17-10-stable-ee
  3. 当需要发布我们版本时,切出版本分支(17-10-stable-my),然后同步上游对应版本代码:
    • 同步上游版本分支:比如你要二次开发的版本为 17.10.0,那就直接合并上游的 v17.10.0-ee
  4. 在我们版本分支上继续处理类似上游的发布任务,验证全部完成后打上我们的版本标签 v17.10.0-my 进行发布
  5. 上述的 my feature 3 可以并行在我们主分支上进行,由于这次发布是在之前切出来的,因此不包含这个功能

上述流程第一次见会觉得有点复杂?但实际上这已经是最精简的了,我们可能见过很多团队将各种不同源的分支进行相互合并,最终导致出现非预期的冲突甚至丢失代码的问题。仔细观察你会发现我们二开流程中的合并都是同源的,未来出现冲突也是很清晰容易解决的。

如果你做到上述流程,恭喜你实现了与 GitLab 官方中国版一致、稳定可靠的开发流程,他们的主分支和版本分支分别叫 main-jh, 17-10-stable-jh

开发环境

确定好了开发流程,现在还需要搭建好一个开发环境。GitLab 组件较多,因此开发环境也比较复杂,官方单独为开发环境创建了两个项目:

  1. GDK: 原生开发环境
  2. GCK: 基于容器的开发环境,环境更简单纯净,但是仍有一些功能支持不完善

官方推荐的仍然是 GDK 环境,对容器比较熟有能力自己处理一些问题的人也可以尝试用 GCK,我的体验是基本也是可以完成开发工作的。

对于 GDK 环境,建议直接从官方提供的虚拟机项目开始,不需要从零开始搭建,也不用担心弄坏你的主机环境。

部署阶段

对于二开这种需要长期修改源码的构建部署方案有 Omnibus 和云原生两种,以下是总结的一些对比:

Omnibus 方案

Omnibus 方案就是构建 Linux 安装包的方式,要从源码开始构建我们自己的包,可以参考官方文档 Building your own package。构建安装包完成后如果你使用容器部署,可以再使用官方 Dockerfile 构建镜像:omnibus-gitlab/docker

这个方案的优点有:

  1. 生成单一安装包,部署简单
  2. 支持功能最全,所有组件都可以通过这种方式进行配置

云原生方案

云原生方案就是 Kubernates 各组件分开定义维护的方式。要构建我们自己定制源码的包,可以参考官方文档:Building Images

这个方案的优点有:

  1. 精细化定制,构建发版时长大大缩短,比如二次开发只修改了 rails 组件,那么只重新构建 rails CNG 镜像即可发布
  2. 云原生支持最好,如果你是 K8s 部署环境,使用这个方案可以直接复用官方的部署配置,后续维护升级更可靠

维护阶段

开发和部署都解决了之后,剩下是考虑如何让系统更稳定可靠。在维护阶段,主要从热修复、自动化测试、容灾备份三个方面讲解。

热修复

首先 GitLab 是基础的研发平台,在工作时间对系统可靠性要求是很高的。如果出现一些紧急问题,完全走一遍上述的构建部署流程来修复,时间上可能不能接受。这里我们可以利用二次开发的好处,直接引入一个热修复功能。可以这样做:

  1. 修改 GitLab 源码,在布局页面中引入外部 JS 文件:
    haml
    %script{src: "https://oss-server/index.js", defer: true}
  2. 上述的 oss-server 是一个公开的对象存储服务,用来存储实际热修复代码
  3. GitLab 安全策略有可能会禁止加载外部脚本,如果遇到控制台报错,可以对 GitLab 进行相关配置解决

自动化测试

GitLab 功能复杂,每次发版需要确保功能运行正常,实际上 GitLab 官方有完善的 QA 自动化测试,具体见项目 GitLab QA

我们在二次开发之后,一个是希望修改的功能有效,还一个是要保证不能影响现有的功能。这个可以通过预发布环境加自动化测试来解决:

  1. 增加一个预发布环境,做为正式环境前的验证和跑自动化测试
  2. 根据官方指引,搭建 GitLab QA 项目,对预发布环境每日定时运行自动化测试,遇到错误及时通知到系统管理员
  3. GitLab QA 项目本身有完善的测试用例,对于我们修改了的功能,需要同步修改这些测试用例

容灾备份

根据对系统的要求和实际情况,可以逐步引入以下机制,增强系统的可靠性:

  1. 添加全量备份能力:
    • 备份和恢复都需要做到自动化完成,减少人为操作造成的问题
    • 恢复的自动化可以结合部署,添加一个容灾环境,实现最新备份的自动化还原。线上数据丢失或者遇到不可恢复问题,可以快速切换到该环境。
  2. 搭建 GEO 架构:
    • 添加一个新的地理城市,全新搭建一个同样的 GitLab 系统,参考官方文档配置两个系统之间的 GEO 架构
    • 如果你 GitLab 使用了外部数据库增强数据安全,则需要配合云厂商的数据库容灾使用,例如阿里云 PG 异地容灾
    • 搭建了 GEO 架构后,升级版本时需要多注意 GEO 相关影响,比起单站点架构升级流程会复杂一些,请参考文档:Upgrading the Geo sites

一般的系统要求建议完成全量备份即可,继续进一步搭建 GEO 架构,会增加需要维护成本。不过如果以下功能的确很吸引你或者你的团队,就可以尝试了:

  1. 线上需要做到无延时故障恢复(这是 GEO 多站点最大的优势,多一套环境)
  2. 我的 GitLab 系统并发很高,需要区分主备流量,保证核心服务的稳定(可以将非核心的流量导向 GEO 备站点)
  3. 重大升级故障支持快速回滚(这个可以在重大升级前,暂停 GEO 备站点的同步来实现)

总结

以上就是 GitLab 二次开发的所有内容,我们先来回顾一下: GitLab 二次开发

总结起来,就是对 GitLab 做二次开发,需要有一套健壮的开发流程,一个方便快捷的部署方案以及有一些可靠稳健的维护手段。