唠唠闲话

推荐阅读
B站阿婆主 拿我格子衫来 的视频和博客
GitLab 官方文档

最近换了服务器,配置比之前搭博客的要好些,配置服务器的同时,正好一边记录。本篇介绍 GitLab 开发环境从零到一的搭建方法以及 GitLab 的协作流程。

GitLab 协作流程

GitLab workflow

个人开发用 GitHub 较多,以下是从 GitHub 向 GitLab 迁移时,对 GitLab 的理解。
20221203010938

流程说明:

  1. 主分支为项目稳定开发的分支,开发者在主分支的基础上创建子分支,并在独立分支下进行开发(push code changes)
  2. 完成阶段性工作后,向主分支发起合并请求(Pull Request/PR)
  3. 提交 PR 将触发单元测试和部署测试(unit test/deploy test),如果测试报错或 Reviewer 给了修改意见,根据意见修改代码后继续提交测试。整个过程称为持续集成(Continuous Integration/CI)
  4. Reviewer 审核通过后,将分支并入主分支,再一次触发测试和部署,并自动推送网站文件和部署网页。
  5. 项目后期,功能雏形基本出来后,开始用 tag 打包发行版本。从 v0.1.0 开始递增,各阶段代码环境以 tag 的方式标记。

补充说明:

  • 为确保主分支的可靠性,稳定性和安全性,通常设置主分支保护。即:不允许任何成员向主分支直接 push commit,而必须采用 Request 的方式提交合并请求,在代码审查和测试通过后,再并入主分支。
  • 为减少冲突和调试难度,Pull Request 应在阶段工作后开启,不应积累太多代码。当然也不要写一点就提交,但可以通过 Draft 标签表示功能还在完善中,Reviewer 可以不用看,也可以给些建议。

管理员端

初始设置

  1. 创建组
    右上角点击 +,选择 New group,创建组。
    20221130090759
    填写组名,选择可见性,点击 Create group
    20221130090839

  2. 成员管理
    进入组后,点击左侧 Settings -> Members,管理成员,根据用户名或账号名搜索,添加成员。
    20221130091529
    成员分四种权限,开发者设置为 Developer,代码 Reviewer 以及仓库更高权限设置为 Maintainer,权限细节参考表格(内网)

  3. 创建项目
    点击 New project,填写项目名,选择可见性,点击 Create project
    20221130091019
    这里也可以选择 Import project,从其他 Git 仓库导入项目。

  4. 主分支保护
    20221130221659
    注:为确保主分支开发可靠性和稳定性,应避免任何用户对主分支的直接更改

  5. 镜像更新
    镜像更新可以用于代码备份,这里则是为了将主仓库主分支自动同步到所有 fork 仓库的主分支。在 GitHub 协作中,这一步通常是由用户主动更新(sync fork),但 GitLab 似乎只能用镜像更新的方式。

    • 进入成员仓库,关闭成员仓库主分支的写入保护
    • 点击左侧 Settings -> Repository,点击 Mirror a repository,填写目标仓库地址,输入用户密码,选择只复制主分支,点击 Mirror repository。提交成功后,下方出现相应的镜像记录。
      20221130122445
      注:管理员需对目标仓库用户拥有权限

代码审查

  1. 点击左侧 Merge Requests,可以看到合并请求,点击相应请求
    20221130100951
    如果设置了 CI/CD 流程,也可以看到 CI/CD 流程的状态

  2. 查看更改
    在界面底部查看代码内容,可以选中代码行进行评论,或者直接对文件进行修改
    20221130101323

  3. 内容无误,CI/CD 流程通过后,且不产生冲突,点击 Merge,合并代码。

开发端

创建分支

  1. 注册账号
    访问内网服务器的 GitLab 地址,点击 Register,填写用户名、邮箱、密码,点击 Register,其中 Full name 为昵称,username 为标识账号的用户名
    ![深度截图_选择区域_20221130092530](https://qiniu.wzhecnu.cn/PicBed3/picgo/深度截图_选择区域

注册后将用户名(username)告诉组织管理员,待邀请进组后,可以在 Groups -> Your groups 中看到该组。
深度截图_选择区域_20221130092911

  1. 创建 dev 分支

    • 进入成员组,可以看到该组下的所有项目,点击进入项目
      深度截图_选择区域_20221130093117
    • 点击 + 号,选择 New branch,创建分支
      20221130094156
    • 分支命名为 dev 或根据开发功能命名
      深度截图_选择区域_20221130093753
    • 为避免工作区冲突,开发工作均在自己创建的分支上推进。
  2. 克隆仓库(可选)
    当开发人员较多,分支较多时,通常用克隆仓库的方式来独立各个开发者的工作区(特别对于开源项目)。该功能可选,如果希望独立工作区可以按这节方法设置,如果觉得麻烦按上一步工作就行了。

    • 进入项目,选择 fork 将仓库克隆到个人账号
      20221130093235
    • 操作后,自动跳转到 fork 的仓库
      20221130093413
    • 为方便协作,点击仓库左侧设置,将组织管理员添加为仓库管理者,
      深度截图_选择区域_20221130111912
    • 赋予权限后,组织管理员能直接对该仓库进行设置。

    后续开发方式同上一小节,创建 dev 分支,在分支中进行开发。

本地连接仓库

  1. 在仓库页面点击 clone 按钮,复制 http 链接
    20221203012056

  2. 在复制的链接中加入用户名和密码,比如

    1
    2
    3
    4
    # 复制链接
    http://172.23.148.38:9190/Rex/demoproject.git
    # 加入用户名和密码后
    http://myuser:mycode@172.23.148.38:9190/Rex/demoproject.git

    注意将 myusermycode 替换为自己的用户名和密码。特别留意,这里填的是账号的 username 而不是 fullname
    20221203012210

  3. 本地使用 git clone 命令,将仓库克隆到本地

    1
    git clone http://myuser:mycode@172.23.148.38:9190/Rex/demoproject.git

代码交流方式

  1. 代码开发(push changes)
    为演示方便,下例在云端直接对代码操作。
  • 以添加 .gitignore 文件为例:选择 dev 分支,点击 + 号,选择 New file,创建文件
    深度截图_选择区域_20221130094256
  • 填写文件名和内容,点击下方 commit changes 提交更改
    20221130094623
  1. 合并请求(PR)

    • 提交更改后,点击右上角 create merge request 提交合并请求
      深度截图_选择区域_20221130094813
    • 进入预提交界面,如下图
      20221130095111
    • 信息显示内容
      • PR 指向了主账号仓库的 master 分支
      • Title 和 Description 可选,填写此次更改的摘要
      • 对于一次性开发的分支,可以选择提交后删除
    • 页面最下方可以看到当前合并给主仓库带来的更改,确认内容无误(自己先简单 review 一遍)后,点击 Submit merge request
      20221130095606
  2. 测试与交流

    • 如果仓库设置过 CI(自动测试)和 CD(自动部署),提交 PR 后会触发这些任务。下图为 GitHub 的 CI/CD 界面
      20221130100444
    • 代码报错,修改意见等均在这个界面下进行
      20221130101904
    • 如果采用 fork 的方式协作,当代码合并到主仓库后,主仓库会自动向 fork 仓库的主分支提交更新(如果设置正确),因此 fork 仓库的开发也不要在主分支上进行,避免被覆盖。

GItLab 配置

GitLab 安装配置

服务器系统:Ubuntu 20.04,参考官方文档以及 CSDN

  1. 执行以下命令安装 GitLab

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # 更新源
    sudo apt-get update
    # 安装依赖
    sudo apt-get update
    sudo apt-get install -y curl openssh-server ca-certificates tzdata perl
    # 添加 GitLab 官方仓库
    curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.deb.sh | sudo bash
    # 安装 GitLab -- 需要较长时间
    sudo apt-get install gitlab-ee

    成功安装的界面
    20221129182632

  2. 安装完成后,修改脚本

    1
    2
    # 修改配置文件
    sudo vi /etc/gitlab/gitlab.rb

    添加以下内容,根据自己的需求修改

    1
    2
    3
    4
    # 设置域名和端口
    external_url 'http://gitlab.wzhecnu.cn:1415'
    # 相应设置 nginx
    nginx['listen_port'] = 1234

    这里端口 1234 根据自己需求设置,此外可以考虑添加 ssl 证书

    1
    2
    3
    4
    5
    6
    # 设置 ssl 协议,注意要更改上一步链接为 https
    letsencrypt['enable'] = false
    nginx['redirect_http_to_https'] = true
    nginx['redirect_http_to_https_port'] = 1234
    nginx['ssl_certificate'] = "/etc/gitlab/ssl/8925639_gitlab.wzhecnu.cn.pem"
    nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/8925639_gitlab.wzhecnu.cn.key"

    此外,设置 ssl 协议后 external_url 的端口可能需要修改。个人只在使用 80 端口时成功过,其他端口设置似乎会比较麻烦,有空继续研究。文档对应链接-ssl配置

  3. 重启 GitLab

    1
    2
    3
    4
    5
    6
    # 更新配置 -- 首次运行需等待较长时间
    gitlab-ctl reconfigure
    # 启动 GitLab
    gitlab-ctl start
    # 查看 GitLab 状态
    gitlab-ctl status
  4. 访问前边设置的域名,顺利的话会看到如下页面
    深度截图_选择区域_20221203000027

    登录 root 账号,密码可以在 /etc/gitlab/initial_root_password 中查看。

  5. 工作区备份

    1
    2
    3
    4
    # GitLab 环境备份 -- 默认保存在 /var/opt/gitlab/backups
    sudo e
    # 通过修改参数,可以指定备份路径,比如
    gitlab_rails['backup_path'] = '/mnt/backups'

踩坑点:首次打开时,可能还是会出现连接超时之类的错误,多刷几次。如果多刷几次还是不行,请注意服务器上的防火墙是否已经关闭。执行 systemctl stop firewalld 后,如果还是不行,则可能是云服务器的安全组没有配置好,需要在云服务器安全组的入方向中添加端口。

邮件设置等,后续补充。

Gitlab 安装配置 – Docker 版

由于实验室服务器的 Gitlab 使用 Docker 安装,但在配置过程中遇到了一些问题,所以在自己服务器上用 Docker 安装了一遍,方便排查问题以及避免误操作。

参考链接:简书-使用 Docker 部署 GitLab

  1. 创建文件夹

    1
    mkdir -p /data/gitlab/config /data/gitlab/logs /data/gitlab/data
  2. 创建容器,使用脚本或直接粘贴以下内容

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #!/bin/sh
    GITLAB_HOME=/data/gitlab/
    sudo docker run --detach \
    --hostname gitlab.wzhecnu.cn \
    --publish 2233:443 --publish 9190:80 --publish 10080:22 \
    --name gitlab \
    --restart always \
    --volume $GITLAB_HOME/config:/etc/gitlab \
    --volume $GITLAB_HOME/logs:/var/log/gitlab \
    --volume $GITLAB_HOME/data:/var/opt/gitlab \
    --volume $GITLAB_HOME/gitlab_backup:/storage/gitlab_backup\
    gitlab/gitlab-ee:latest

    参数说明:

    • --hostname:设置域名或 IP
    • --publish:设置端口映射,避免端口占用,格式为 宿主机端口:容器端口
    • https 协议端口:宿主机端口 2233 映射为容器端口 443
    • http 协议端口:宿主机端口 9190 映射为容器端口 80
    • ssh 协议端口:宿主机端口 10080 映射为容器端口 22
  3. 修改配置文件

    1
    vi /usr/local/gitlab/config/gitlab.rb

    在最前边添加内容:

    1
    2
    3
    4
    5
    6
    # 端口映射修改 - 避免与宿主机端口冲突
    gitlab_rails['gitlab_shell_ssh_port'] = 10080 # 映射为 22
    gitlab_rails['forti_authenticator_port'] = 2233 # 映射为 443
    # 修改访问链接
    external_url 'http://gitlab.wzhecnu.cn:9190'
    nginx['listen_port'] = 80
  4. 进入容器,并重启配置

    1
    2
    3
    4
    5
    6
    7
    8
    # 进入gitlab bash
    docker exec -it gitlab bash
    # 重新应用gitlab的配置
    gitlab-ctl reconfigure
    # 重启gitlab服务
    gitlab-ctl restart
    # 查看gitlab运行状态
    gitlab-ctl status

    和前边类似,这里也需要修改服务器的安全组,在入方向添加相应端口。

后续登录等操作与前边一致。

配置 GitLab Runner

使用 Docker(推荐)

  1. 下载 GitLab-Runner 镜像

    1
    docker pull gitlab/gitlab-runner:latest
  2. 创建容器

    1
    2
    3
    4
    sudo docker run -d --name gitlab-runner --restart always \
    -v /srv/gitlab-runner/config:/etc/gitlab-runner \
    -v /var/run/docker.sock:/var/run/docker.sock \
    gitlab/gitlab-runner:latest
  3. 使用 Docker 注册 Runner,参考官网教程-Docker

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    docker run --rm -v /srv/gitlab-runner/config:/etc/gitlab-runner gitlab/gitlab-runner register \
    --non-interactive \
    --executor "docker" \
    --docker-image alpine:latest \
    --url "http://gitlab.wzhecnu.cn:1234/" \
    --registration-token "TOKEN" \
    --description "mysecond-docker-runner" \
    --tag-list "mytest2" \
    --run-untagged="true" \
    --locked="false" \
    --access-level="not_protected"

    其中 urlregistration-token 在 GitLab 页面获取
    20221203003957
    若干注记:

    • 其他两种类型 Runner 的设置类似,只是获取链接和 Token 的位置不同,有效范围也不同。
    • tag-list 设置 Runner 的标签,自动任务通过标签来指定运行容器。
    • docker run--rm 参数指:退出容器以后,这个容器就被删除了,方便在临时测试使用。不加 --rm 退出容器后,容器只是停止运行,数据仍然被保留。不过容器内数据卷的内容不会被删除。
  4. 执行脚本后, /etc/gitlab-runner/ 目录下生成了配置文件 config.toml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    concurrent = 1
    check_interval = 0
    shutdown_timeout = 0
    [[runners]]
    name = "myfirst-docker-runner"
    url = "http://gitlab.wzhecnu.cn:1234/"
    id = 1
    token = "<对应token>"
    volumes = ["/cache"]
    shm_size = 0
    • concurrent 设置并发任务数,为减少性能占用,默认为串行,此处应根据任务需求调高,以减少测试的运行时间
    • session_timeout 设置任务时间上限,超过时间将被终止
    • volumes 设置容器内的数据卷,用于缓存等,根据任务情况,有时要求改成
      1
      volumes = ["/cache", "/var/run/docker.sock:/var/run/docker.sock", "usr/bin/docker:/usr/bin/docker"]

直接安装

一开始尝试了用 Docker 安装 Runner,但一直连不上 GitLab,报错如下
深度截图_选择区域_20221203000601
一通捣鼓才发现是网络问题,所以也尝试了二进制编译安装的方式,这里顺便记录一下,参考官网教程-二进制安装

  1. 下载二进制文件

    1
    sudo curl -L --output /usr/local/bin/gitlab-runner "https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64"

    如果在服务器下载可能较慢,可以本地下载后再上传,并重命名到相应位置。

  2. 赋予执行权限

    1
    sudo chmod +x /usr/local/bin/gitlab-runner
  3. 创建 GitLab-Runner 用户

    1
    sudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash
  4. 安装并运行服务

    1
    2
    sudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner
    sudo gitlab-runner start
  5. 注册 Runner,与 Docker 的方法一致

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    gitlab-runner register \
    --non-interactive \
    --executor "docker" \
    --docker-image alpine:latest \
    --url "http://gitlab.wzhecnu.cn:1234/" \
    --registration-token "TOKEN" \
    --description "myfirst-docker-runner" \
    --tag-list "mytest" \
    --run-untagged="true" \
    --locked="false" \
    --access-level="not_protected"

注册成功后,可以在 GitLab 页面看到 Runner。
深度截图_选择区域_20221203004718

故障排除

在注册 GitLab Runner 时,个人服务器上测试顺利,但实验室服务器一直报错,信息如下

1
2
3
RROR: Registering runner... failed
runner=4KzFfK5b status=POST http://172.23.148.38:9190/api/v4/runners: 500 Internal Server Error
PANIC: Failed to register the runner.

20221205184929

这个问题捣鼓了很久,在自己服务器上做了许多尝试也没能复现这个错误,也排除了网络问题:

  • 服务器联网正常,Docker 联网正常
  • 内网能 ping 通服务器
  • 不是 Token 或链接的问题,因为更改 Token 后得到的报错信息不同,说明 Token 是能验证的,但注册不了

在外网翻了许多帖子没找到方案,没想到最后在 CSDN 到了一个有效的解决方案。这可能是服务器以前做过备份或迁移引起的?

官网链接:Reset runner registration tokens

1
2
3
4
5
6
7
8
9
10
11
12
## Clear project tokens
UPDATE projects SET runners_token = null, runners_token_encrypted = null;
## Clear group tokens
UPDATE namespaces SET runners_token = null, runners_token_encrypted = null;
## Clear instance tokens
UPDATE application_settings SET runners_registration_token_encrypted = null;
## Clear key used for JWT authentication
## This may break the $CI_JWT_TOKEN job variable:
## https://gitlab.com/gitlab-org/gitlab/-/issues/325965
UPDATE application_settings SET encrypted_ci_jwt_signing_key = null;
## Clear runner tokens
UPDATE ci_runners SET token = null, token_encrypted = null;

root@txGitlabServer108:/var/log/gitlab/gitlab-rails# gitlab-rails dbconsole
psql (12.7)
Type “help” for help.

gitlabhq_production=> UPDATE projects SET runners_token = null, runners_token_encrypted = null;
UPDATE 247
gitlabhq_production=> UPDATE namespaces SET runners_token = null, runners_token_encrypted = null;
UPDATE 91
gitlabhq_production=>
gitlabhq_production=>
gitlabhq_production=> UPDATE application_settings SET runners_registration_token_encrypted = null;
UPDATE 1
gitlabhq_production=> UPDATE application_settings SET encrypted_ci_jwt_signing_key = null;
UPDATE 1
gitlabhq_production=>
gitlabhq_production=> UPDATE ci_runners SET token = null, token_encrypted = null;
UPDATE 0
gitlabhq_production=>

使用外部 nginx

https://stackoverflow.com/questions/29403212/forwarding-to-gitlab-subdomain-with-existing-nginx-installation

CI/CD

GitLab 的 Pipeline 指一个完整的 CI/CD 流程,包括了编译、测试、部署等环节。
Pipeline 包括:

  • Jobs,定义了具体的任务,例如编译、测试等
  • Stages,定义了任务的执行顺序,例如先编译再测试

一般规则:

  • Jobs 由 Runner 执行,如果有足够的 Runner,同一 Stage 中的 Jobs 会并行执行
  • 如果同一 Stage 中的所有 Jobs 都成功,Pipeline 会继续执行下一个 Stage
  • 如果同一 Stage 中的任意一个 Job 失败,Pipeline 会停止执行,不会执行下一个 Stage
  • 一般情况下,Pipeline 会自动执行,不需要人工干预,但也有例外,例如手动触发 Pipeline
  • 一个典型的 Pipeline 可能包括四个 Stage,执行顺序如下:
    • Build Stage,包含一个 Job,叫 compile
    • Test Stage,包含两个 Job,叫 test1test2
    • Staging Stage,包含一个 Job,叫 deploy-to-stage
    • Production Stage,包含一个 Job,叫 deploy-to-prod

配置 GitLab Runner

这一步前边已经完成了。

Yaml 文件

触发规则

You can trigger a pipeline for a branch or tag by generating a trigger token and using it to authenticate an API call. The token impersonates a user’s project access and permissions.

Prerequisite:

You must have at least the Maintainer role for the project.
To create a trigger token:

On the top bar, select Main menu > Projects and find your project.
On the left sidebar, select Settings > CI/CD.
Expand Pipeline triggers.
Enter a description and select Add trigger.
You can view and copy the full token for all triggers you have created.
You can only see the first 4 characters for tokens created by other project members.

可以通过生成一个触发 Token 并使用它来对分支或标签触发 Pipeline,该 Token 模拟用户的项目访问和权限。

前提条件:

  • 至少具有 Maintainer 权限

创建触发 Token:

  • 在项目的 CI/CD 设置页面展开 Pipeline triggers
    20221203110358
  • 输入描述并选择 Add trigger

https://docs.gitlab.com/ee/ci/triggers/

1
2
3
4
5
6
7
trigger_pipeline:
stage: deploy
script:
- 'curl --fail --request POST --form token=$MY_TRIGGER_TOKEN --form ref=main "https://gitlab.example.com/api/v4/projects/123456/trigger/pipeline"'
rules:
- if: $CI_COMMIT_TAG
environment: production

版本相关

通过tag 标签进行发行

版本号采用 Semantic Versioning

格式 中文说明 英文说明
x.y.z 大版本.修订版.补丁 MAJOR.MINOR.PATCH

20221203012909

简单来说:

  1. 进行不兼容的 API 更改时,增加主版本 Major
  2. 以向后兼容的方式添加功能时,增加次要版本 Minor
  3. 进行向后兼容的错误修复时,增加补丁版本 Patch


用户权限管理

  1. 创建用户

    1
    2
    3
    4
    sudo su # 切换到root用户
    adduser rex
    passwd rex # 设置密码
    vi /etc/sudoers # 添加用户权限

    修改内容如下,其中 NOPASSWD: 表示不需要密码

    1
    2
    root ALL=(ALL:ALL) ALL
    rex ALL=(ALL:ALL) NOPASSWD:ALL
  2. 联网工具

    1
    2
    3
    apt install net-tools # ifconfig
    apt-get install network-manager
    apt install bridge-utils # brctl
  3. 安装 Docker

    1
    curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
  4. 给 Docker 配置网络,参考 stack

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # 关闭 Docker
    pkill docker
    # 刷新 IP
    iptables -t nat -F
    ifconfig docker0 down
    brctl delbr docker0
    docker -d
    # 重启 Docker
    service docker restart