一、 GitLab CI/CD 核心概念

首先,理解几个关键名词:

  1. **CI - 持续集成**

    * **核心**:开发者频繁地将代码集成到主干分支。

    * **实践**:每次集成都通过自动化的构建和测试来验证,从而尽快发现错误。

    * **好处**:减少集成问题,让团队更快地开发软件。

  2. **CD - 持续交付/持续部署**

    * **持续交付**:是 CI 的下一步。代码通过 CI 流程后,可以**一键手动**部署到生产环境。

    * **持续部署**:是更自动化的持续交付。代码通过 CI 流程后,**自动**部署到生产环境。

    * **区别**:部署到生产环境这一步是手动的还是自动的。

  3. **GitLab Runner**

    * **是什么**:一个用来执行 CI/CD **任务** 的轻量级、高可扩展的应用程序。

    * **它在哪运行**:它可以运行在任何机器上——你的本地电脑、云服务器、Kubernetes 集群等。

    * **作用**:它“监听” GitLab 实例,当有新的 CI/CD 任务(如代码推送)时,GitLab 会将任务分派给 Runner,Runner 则按照指令执行。

  4. **Pipeline - 流水线**

    * **是什么**:一次 CI/CD 执行的顶层结构。它定义了从构建、测试到部署的完整流程。

    * **触发**:通常由代码推送(git push)或合并请求(Merge Request)触发。

  5. **Stage - 阶段**

    * **是什么**:Pipeline 中的一个逻辑分组,例如 build(构建)test(测试)deploy(部署)阶段。

    * **特点**:

    \*   一个 Pipeline 可以包含多个 Stage。
    
    \*   \*\*Stage 是按顺序执行的\*\*,下一个 Stage 必须等上一个 Stage 的所有 Job 都成功后才能开始。
    
    ​*​   同一个 Stage 中的多个 Job 会*​\*并行执行\*\*。
    
  6. **Job - 任务**

    * **是什么**:Stage 里的一个具体执行任务。它是 CI/CD 的最小执行单元。

    * **例子**:在 test 阶段,你可能会有 unit-test(单元测试)integration-test(集成测试)等多个 Job。

    Job 里包含了真正要运行的*脚本**(script)。

  7. **.gitlab-ci.yml 文件**

    * **是什么**:GitLab CI/CD 的**配置文件**,位于项目的根目录。

    * **作用**:它定义了 Pipeline 的结构和行为,包括有哪些 Stage,每个 Job 做什么。

    * **没有这个文件,CI/CD 就不会工作**。

**关系总结**:

一个 **Pipeline** 由多个 **Stage** 组成,每个 **Stage** 包含多个 **Job**,而 **Job** 则由 **GitLab Runner** 来执行。所有这些都定义在 **.gitlab-ci.yml** 文件中。


二、 快速开始:一个完整的实战示例

假设我们有一个 Node.js 项目,我们来为它配置一个简单的 CI/CD 流程。

第一步:准备项目

在项目根目录创建一个 .gitlab-ci.yml 文件。

第二步:编写 .gitlab-ci.yml 配置文件

```yaml

1. 定义 Pipeline 有哪些阶段,按顺序执行

stages:

  • install_deps
  • test
  • build
  • deploy

2. 定义全局变量,可以被所有 Job 继承

variables:

NODE_VERSION: "18"

3. 缓存 node_modules,加速后续 Job 的执行

cache:

key: ${CI_COMMIT_REF_SLUG} # 使用分支名作为缓存 key

paths:

- node\_modules/

--- 第一个阶段:安装依赖 ---

install_dependencies:

stage: install_deps

image: node:$NODE_VERSION # 指定执行环境为 Node.js 官方镜像

script:

- npm install

artifacts: # 将 node_modules 传递给后续阶段

paths:

  - node\_modules/

only: # 只有 master 分支和合并请求时触发此 Job

- master

- merge\_requests

--- 第二个阶段:运行测试 ---

run_unit_tests:

stage: test

image: node:$NODE_VERSION

script:

- npm run test

dependencies: # 显式声明依赖 install_dependencies Job 的 artifacts

- install\_dependencies

only:

- master

- merge\_requests

--- 第三个阶段:构建项目 ---

build_project:

stage: build

image: node:$NODE_VERSION

script:

- npm run build

artifacts: # 将构建产物(dist/)传递给后续阶段或提供下载

paths:

  - dist/

dependencies:

- install\_dependencies

only:

- master

--- 第四个阶段:部署(示例:部署到服务器) ---

deploy_to_server:

stage: deploy

image: alpine:latest # 使用一个轻量级 Linux 镜像

before_script:

# 安装 SSH 密钥和 rsync(这里是最简示例,实际需配置 CI/CD Variables)

- apk add --no-cache openssh-client rsync

- eval \$(ssh-agent -s)

- echo "\$SSH\_PRIVATE\_KEY" | tr -d '\\r' | ssh-add -

- mkdir -p \~/.ssh

- chmod 700 \~/.ssh

script:

# 使用 rsync 同步文件到服务器

- rsync -avz --delete -e "ssh -o StrictHostKeyChecking=no" ./dist/ user@your-server.com:/path/to/www/

environment: # 定义部署环境

name: production

url: https://your-website.com

dependencies:

- build\_project

only:

- master # 只有推送到 master 分支才执行部署

```

第三步:配置 GitLab Runner

  1. **获取注册令牌**:

    * 进入你的 GitLab 项目页面。

    * 进入 设置 -> CI/CD -> Runner 展开。

    * 在 “设置特定于项目的Runner” 部分,找到 “注册令牌”,复制它。

  2. **安装并注册 Runner**(以在一台 CentOS/Ubuntu 服务器上为例):

    ```bash

    下载 GitLab Runner 二进制文件 (Linux x64)

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

    赋予执行权限

    sudo chmod +x /usr/local/bin/gitlab-runner

    创建一个 GitLab Runner 用户

    sudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash

    安装并作为服务运行

    sudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner

    sudo gitlab-runner start

    开始注册流程

    sudo gitlab-runner register

    ```

    * 根据提示输入:

    \*   \*\*GitLab 实例 URL\*\*: `https://gitlab.com`(如果是私有化部署,则换成你的地址)
    
    \*   \*\*注册令牌\*\*:刚才复制的令牌。
    
    \*   \*\*描述\*\*:给你的 Runner 起个名字,如 `my-project-runner`。
    
    \*   \*\*标签\*\*:可以给 Runner 打上标签,如 `node, linux`。在 `.gitlab-ci.yml` 中可以通过 `tags` 来指定由哪个 Runner 执行。
    
    \*   \*\*执行器\*\*:推荐使用 `docker`,因为它最干净。这里我们示例中使用 `shell`(更简单,但环境需自己准备)。
    
  3. **配置 SSH 密钥(用于部署)**:

    * 在运行 Runner 的机器上生成 SSH 密钥对 ssh-keygen -t rsa -b 4096 -C "gitlab-runner@server"

    * 将公钥 id_rsa.pub)添加到目标部署服务器的 ~/.ssh/authorized_keys 文件中。

    * 在 GitLab 项目设置中,进入 设置 -> CI/CD -> Variables 展开。

    * 点击 “添加变量”

    \*   \*\*Key\*\*: `SSH_PRIVATE_KEY`
    
    \*   \*\*Value\*\*: 复制刚才生成的\*\*私钥\*\*`id_rsa`)的\*\*全部内容\*\*。
    
    \*   \*\*勾选\*\* `“Mask variable”` 和 `“Protect variable”`(增强安全性)。
    

第四步:触发 Pipeline

完成以上步骤后,当你向 master 分支推送代码或者创建一个合并请求时,GitLab 会自动检测到 .gitlab-ci.yml 文件,并开始运行 Pipeline。

你可以在项目的 CI/CD -> Pipelines 页面查看运行状态和日志。


三、 .gitlab-ci.yml 常用关键字详解

* stages:定义 Pipeline 的阶段顺序。

* variables:定义环境变量。

* cache:缓存文件或目录,加速后续 Job。

* image:指定 Docker 镜像作为 Job 的运行环境。

**script*必须**,由 Runner 执行的 Shell 脚本。

* before_script:在 script 之前执行,用于设置环境。

* after_script:在 script 之后执行,无论 Job 成功与否。

* artifacts:指定在 Job 成功时打包的文件/目录,传递给后续 Stage 或提供下载。

* dependencies:指定当前 Job 依赖哪个上游 Job 的 artifacts

* only / except:控制 Job 在什么情况下运行(如特定分支、标签)。

**rules*更强大和推荐**的替代 only/except 的规则系统,支持 ifchanges 等条件判断。

* tags:指定由哪个标签的 Runner 来执行此 Job。

* environment:定义部署目标环境。

* when:控制 Job 的运行时机,如 on_success(默认)on_failure, manual(手动触发)。

四、 最佳实践

  1. **保持 Pipeline 快速**:快速反馈是关键。优化测试和构建时间,使用缓存。
  2. **使用 rules 代替 only/except**rules 更灵活,功能更强大。
  3. **利用缓存和 Artifacts**:避免重复工作,显著提升速度。
  4. **编写有意义的 Job 名称**:让日志更易读。
  5. **处理敏感信息**:**永远不要**将密码、密钥等写在 .gitlab-ci.yml 文件里。始终使用 GitLab 的 **CI/CD Variables**。
  6. **从失败中学习**:仔细阅读 Job 日志,它是调试的最好朋友。
  7. **使用 Docker 镜像**:保证环境的一致性,避免“在我机器上是好的”问题。

通过这个教程,你应该已经对 GitLab CI/CD 的核心概念、配置方法和实战流程有了清晰的认识。现在就去你的项目中创建一个 .gitlab-ci.yml 文件开始实践吧!