在企业级 DevOps 实践中,流水线配置的重复编写是一个长期存在的效率瓶颈。不同项目之间相似的构建、测试、安全扫描步骤,往往通过「复制粘贴 + 局部修改」的方式传递,导致版本碎片化、维护成本居高不下。极狐GitLab 从 16.0 开始引入的 CI/CD 组件(Components) 与 组件目录(Catalog),正是为了解决这一问题:把流水线中的通用能力封装为可版本化、可参数化的复用单元,让团队从「复制粘贴」走向「引用组件」。
本文基于极狐GitLab 官方文档,系统梳理 CI/CD 组件的核心概念、目录化发布流程与落地实践,并给出可直接使用的 .gitlab-ci.yml 示例。
一、为什么需要 CI/CD 组件
在引入组件之前,极狐GitLab 已经支持 include:template、include:project 和 include:remote 等方式复用流水线配置。但这些方式各有局限:
include:template只能引用极狐GitLab 内置模板,无法承载团队自定义逻辑;include:project可以引用其他项目的文件,但缺乏版本语义,引用分支意味着随时可能引入破坏性变更;include:remote依赖外部 URL,版本控制与审计追踪都不理想。
CI/CD 组件在以上基础上做了三个关键增强:
- 目录化 :组件可以发布到 CI/CD 组件目录,团队内可搜索、可发现;
- 版本化 :组件支持语义版本(Semantic Versioning),调用方可以精确锁定到
1.0.0,也可以使用1或~latest自动获取兼容的最新版本; - 参数化 :通过
spec:inputs定义输入参数,调用方通过inputs传参,避免硬编码带来的耦合。
版本要求:CI/CD 组件在极狐GitLab 17.0 成为 GA(正式发布),组件目录在 16.7 进入 Beta、17.0 GA。当前每个项目最多支持 100 个组件(18.5 起)。
二、组件的核心语法:include:component
引用一个组件的标准格式如下:
yaml
include:
- component: $CI_SERVER_FQDN/my-group/my-project/secret-detection@1.0.0
inputs:
stage: test
各段含义:
$CI_SERVER_FQDN:极狐GitLab 实例的预定义变量,避免硬编码域名;my-group/my-project:组件所在项目的完整路径;secret-detection:组件名称,对应templates/secret-detection.yml或templates/secret-detection/template.yml;1.0.0:组件版本,可以是标签、提交 SHA、分支名,或~latest。
版本解析优先级
组件版本按以下优先级解析(从高到低):
| 优先级 | 类型 | 示例 |
|---|---|---|
| 1 | 提交 SHA | e3262fdd0914fa823210cdb79a8c421e2cef79d8 |
| 2 | 标签 | 1.0.0(推荐) |
| 3 | 分支名 | main |
| 4 | 部分语义版本 / ~latest |
1、1.2、~latest |
使用部分版本时,系统会自动选择匹配范围内的最新稳定版本,不会选中预发布版本 (如 1.0.1-rc)。
三、如何创建一个组件
一个合格的组件项目需要满足以下目录结构:
├── templates/
│ └── secret-detection.yml # 单文件组件
│ └── build-image/
│ ├── template.yml # 多文件组件(仅 template.yml 对外暴露)
│ ├── Dockerfile
│ └── test.sh
├── README.md # 必须:记录所有组件的说明
├── LICENSE.md
└── .gitlab-ci.yml
单文件组件示例
以下是一个用于密钥检测的组件定义:
yaml
# templates/secret-detection.yml
spec:
inputs:
stage:
default: test
description: "密钥检测作业所在的阶段"
---
gitleaks-scan:
stage: $[[ inputs.stage ]]
image:
name: zricethezav/gitleaks:latest
entrypoint: [""]
script:
- gitleaks detect --source . --verbose --redact
artifacts:
reports:
secret_detection: gl-secret-detection-report.json
when: always
关键说明:
spec:inputs定义了调用方可传入的参数,未传则使用default默认值;$[[ inputs.stage ]]是 CI/CD 表达式语法,用于在组件内部引用输入值;---分隔符将spec头部与实际的作业定义分开。
多文件组件示例
当组件需要附带辅助文件(如脚本、配置模板)时,使用目录形式:
yaml
# templates/build-image/template.yml
spec:
inputs:
image_name:
description: "输出的镜像名称"
image_tag:
default: latest
dockerfile:
default: Dockerfile
---
build-container:
stage: build
image: gcr.io/kaniko-project/executor:debug
script:
- /kaniko/executor
--context "$CI_PROJECT_DIR"
--dockerfile "$CI_PROJECT_DIR/$[[ inputs.dockerfile ]]"
--destination "$CI_REGISTRY_IMAGE/$[[ inputs.image_name ]]:$[[ inputs.image_tag ]]"
目录中的 Dockerfile、test.sh 等文件仅用于组件自身的构建或测试,不会被调用方直接引用。
四、组件上下文:让组件知道自己是谁
从极狐GitLab 18.6(Beta)/ 18.7(GA)起,组件可以通过 组件上下文 访问自身的元数据:
yaml
spec:
component: [name, version, reference]
inputs:
stage:
default: build
---
build-image:
stage: $[[ inputs.stage ]]
image: registry.example.com/$[[ component.name ]]:$[[ component.version ]]
script:
- echo "Building with component $[[ component.name ]]@$[[ component.version ]]"
- echo "Reference: $[[ component.reference ]]"
支持的上下文字段:
name:组件名称;version:被解析后的实际版本;reference:调用方原始引用的版本字符串;sha:组件的提交 SHA。
这在需要把组件版本信息注入产物元数据或日志追踪时非常有用。
五、发布到 CI/CD 组件目录
组件目录是极狐GitLab 实例内的「组件市场」。发布流程如下:
- 确保项目结构合规 :包含
README.md和templates/目录; - 创建语义版本标签 :如
git tag -a v1.0.0 -m "Initial release" && git push origin v1.0.0; - 发布到目录 :在项目的 设置 > CI/CD > 组件目录 中,选择要发布的组件并确认;
- 验证发布 :在实例的 探索 > CI/CD 组件目录 中搜索组件名称,确认可见。
注意:发布到目录的组件必须使用语义版本标签 (如
1.0.0、1.1.0),v1.0.0前缀的 Git 标签也会被正确解析。
六、在项目中引用组件:完整示例
假设团队已经发布了以下组件:
my-group/ci-components/secret-detection@1.0.0my-group/ci-components/build-image@2.1.0
项目中的 .gitlab-ci.yml 可以这样组合使用:
yaml
stages:
- build
- test
- deploy
include:
- component: $CI_SERVER_FQDN/my-group/ci-components/build-image@2.1
inputs:
image_name: my-app
image_tag: $CI_COMMIT_SHORT_SHA
dockerfile: Dockerfile.prod
- component: $CI_SERVER_FQDN/my-group/ci-components/secret-detection@1.0.0
inputs:
stage: test
- component: $CI_SERVER_FQDN/my-group/ci-components/unit-test@~latest
inputs:
stage: test
coverage_threshold: 80
deploy-staging:
stage: deploy
image: bitnami/kubectl:latest
script:
- kubectl set image deployment/my-app
my-app=$CI_REGISTRY_IMAGE/my-app:$CI_COMMIT_SHORT_SHA
--namespace=staging
environment:
name: staging
url: https://staging.example.com
only:
- main
这个示例展示了三个关键实践:
- 精确版本锁定 :
secret-detection@1.0.0确保安全扫描行为稳定不变; - 部分版本自动升级 :
build-image@2.1自动获取2.1.x的最新补丁版本,兼顾稳定性与缺陷修复; ~latest快速迭代 :unit-test@~latest适合仍在快速演进的内部工具,但需谨慎用于生产关键路径。
七、组件与 include 其他方式的对比
| 特性 | include:component |
include:template |
include:project |
|---|---|---|---|
| 版本控制 | 语义版本 / SHA / 分支 | 无(跟随实例版本) | 分支 / 标签(非语义化) |
| 参数化 | 支持 spec:inputs |
不支持 | 不支持 |
| 目录化发现 | 支持(CI/CD Catalog) | 不支持 | 不支持 |
| 适用场景 | 团队自定义复用组件 | 极狐GitLab 官方模板 | 跨项目文件引用 |
八、安全与维护建议
对于组件使用者
- 审计组件源码 :在引入第三方组件前,审查其
templates/下的实际逻辑; - 固定版本 :优先使用提交 SHA 或精确标签,避免
~latest引入意外变更; - 最小权限:为组件项目配置范围最小的访问令牌,避免过度授权。
对于组件维护者
- 启用分支保护:要求所有变更通过合并请求进入默认分支;
- 签署提交:确保组件仓库的提交可追溯、可验证;
- 使用受保护标签:为发布标签配置保护规则,防止误删或篡改。
九、总结
CI/CD 组件与组件目录的引入,让极狐GitLab 的流水线配置从「文件级复用」跃迁到「组件级复用」。通过语义版本、参数化输入和目录化发现,团队可以把最佳实践固化为可共享、可演进的流水线资产,显著降低多项目维护成本。
对于已经运行在极狐GitLab 17.0+ 的团队,建议从以下路径开始落地:
- 识别团队内重复率最高的流水线片段(如镜像构建、安全扫描、单元测试);
- 将其提取为组件项目,定义清晰的
spec:inputs; - 发布到 CI/CD 组件目录,并在 2-3 个试点项目中引用验证;
- 逐步推广至全团队,建立组件的维护与版本治理规范。
参考来源