从 Jenkins 迁移
- Tier: Free, Premium, Ultimate
- Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
如果您正在从 Jenkins 迁移到 GitLab CI/CD,您可以创建能够复制并增强 Jenkins 工作流的 CI/CD 管道。
主要相似点和差异点
GitLab CI/CD 和 Jenkins 是一些功能相似的 CI/CD 工具。GitLab 和 Jenkins 都:
- 使用阶段(stages)来组织作业(jobs)的集合。
- 支持基于容器的构建。
此外,两者之间还有一些重要差异:
- GitLab CI/CD 管道全部在 YAML 格式的配置文件中进行配置。Jenkins 使用 Groovy 格式的配置文件(声明式管道)或 Jenkins DSL(脚本式管道)。
- GitLab 提供 GitLab.com,这是一个多租户 SaaS 服务,以及 GitLab Dedicated,这是一个完全隔离的单租户 SaaS 服务。您也可以运行自己的 GitLab Self-Managed 实例。Jenkins 部署必须自托管。
- GitLab 提供开箱即用的源代码管理(SCM)。Jenkins 需要单独的 SCM 解决方案来存储代码。
- GitLab 提供内置的容器镜像仓库。Jenkins 需要单独的解决方案来存储容器镜像。
- GitLab 提供内置的代码扫描模板。Jenkins 需要第三方插件来进行代码扫描。
功能和概念对比
许多 Jenkins 功能和概念在 GitLab 中都有对应的功能,提供相同的功能。
配置文件
Jenkins 可以使用 Groovy 格式的 Jenkinsfile 进行配置。GitLab CI/CD 默认使用 .gitlab-ci.yml 文件。
Jenkinsfile 示例:
pipeline {
agent any
stages {
stage('hello') {
steps {
echo "Hello World"
}
}
}
}等效的 GitLab CI/CD .gitlab-ci.yml 文件:
stages:
- hello
hello-job:
stage: hello
script:
- echo "Hello World"Jenkins 管道语法
Jenkins 配置由包含节(sections)和指令(directives)的 pipeline 块组成。GitLab CI/CD 具有类似的功能,使用 YAML 关键字进行配置。
节(Sections)
| Jenkins | GitLab | 说明 |
|---|---|---|
agent |
image |
Jenkins 管道在代理(agents)上执行,agent 节定义管道如何执行以及要使用的 Docker 容器。GitLab 作业在运行器(runners)上执行,image 关键字定义要使用的容器。您可以在 Kubernetes 或任何主机上配置自己的运行器。 |
post |
after_script 或 stage |
Jenkins post 节定义在阶段或管道结束时应该执行的操作。在 GitLab 中,使用 after_script 在作业结束时运行命令,使用 before_script 在作业中的其他命令之前运行操作。使用 stage 来选择作业应该运行的确切阶段。GitLab 支持 .pre 和 .post 阶段,这些阶段总是在所有其他定义的阶段之前或之后运行。 |
stages |
stages |
Jenkins 阶段是作业的组。GitLab CI/CD 也使用阶段,但更加灵活。您可以有多个阶段,每个阶段包含多个独立的作业。在顶层使用 stages 来定义阶段及其执行顺序,在作业级别使用 stage 来定义该作业的阶段。 |
steps |
script |
Jenkins steps 定义要执行的内容。GitLab CI/CD 使用类似的 script 节。script 节是一个 YAML 数组,每个命令按顺序作为单独的条目。 |
指令(Directives)
| Jenkins | GitLab | 说明 |
|---|---|---|
environment |
variables |
Jenkins 使用 environment 来设置环境变量。GitLab CI/CD 使用 variables 关键字来定义可在作业执行期间使用的 CI/CD 变量,也可用于更动态的管道配置。这些变量也可以在 GitLab UI 的 CI/CD 设置中设置。 |
options |
不适用 | Jenkins 使用 options 进行额外配置,包括超时和重试值。GitLab 不需要单独的选项节,所有配置都作为 CI/CD 关键字添加到作业或管道级别,例如 timeout 或 retry。 |
parameters |
不适用 | 在 Jenkins 中,触发管道时可能需要参数。在 GitLab 中,参数通过 CI/CD 变量处理,这些变量可以在许多地方定义,包括管道配置、项目设置、通过 UI 或 API 在运行时手动设置。 |
triggers |
rules |
在 Jenkins 中,triggers 定义管道何时再次运行,例如通过 cron 表达式。GitLab CI/CD 可以因多种原因自动运行管道,包括 Git 更新和合并请求更新。使用 rules 关键字来控制为哪些事件运行作业。计划管道在项目设置中定义。 |
tools |
不适用 | 在 Jenkins 中,tools 定义要在环境中安装的额外工具。GitLab 没有类似的关键字,因为推荐使用预先构建了作业所需确切工具的容器镜像。这些镜像可以被缓存,并且可以构建为已经包含您需要的工具。如果作业需要额外的工具,它们可以作为 before_script 节的一部分安装。 |
input |
不适用 | 在 Jenkins 中,input 添加用户输入提示。与 parameters 类似,输入在 GitLab 中通过 CI/CD 变量处理。 |
when |
rules |
在 Jenkins 中,when 定义何时应该执行阶段。GitLab 也有一个 when 关键字,它定义作业是否应该根据先前作业的状态开始运行,例如作业是否通过或失败。要控制何时将作业添加到特定管道,请使用 rules。 |
常用配置
本节介绍常用的 CI/CD 配置,展示如何从 Jenkins 转换为 GitLab CI/CD。
Jenkins 管道生成自动化的 CI/CD 作业,在发生某些事件时触发,例如推送新提交。Jenkins 管道在 Jenkinsfile 中定义。GitLab 的等效文件是 .gitlab-ci.yml 配置文件。
Jenkins 不提供存储源代码的地方,因此 Jenkinsfile 必须存储在单独的源代码控制仓库中。
作业
作业是一组按特定顺序运行的命令,以实现特定结果。
例如,构建一个容器然后部署到生产环境,在 Jenkinsfile 中:
pipeline {
agent any
stages {
stage('build') {
agent { docker 'golang:alpine' }
steps {
apk update
go build -o bin/hello
}
post {
always {
archiveArtifacts artifacts: 'bin/hello'
onlyIfSuccessful: true
}
}
}
stage('deploy') {
agent { docker 'golang:alpine' }
when {
branch 'staging'
}
steps {
echo "Deploying to staging"
scp bin/hello remoteuser@remotehost:/remote/directory
}
}
}
}此示例:
- 使用
golang:alpine容器镜像。 - 运行一个构建代码的作业。
- 将构建的可执行文件存档为产物。
- 添加第二个作业部署到
staging,该作业:- 仅当提交目标是
staging分支时存在。 - 在构建阶段成功后启动。
- 使用来自先前作业的构建可执行文件产物。
- 仅当提交目标是
等效的 GitLab CI/CD .gitlab-ci.yml 文件:
default:
image: golang:alpine
stages:
- build
- deploy
build-job:
stage: build
script:
- apk update
- go build -o bin/hello
artifacts:
paths:
- bin/hello
expire_in: 1 week
deploy-job:
stage: deploy
script:
- echo "Deploying to Staging"
- scp bin/hello remoteuser@remotehost:/remote/directory
rules:
- if: $CI_COMMIT_BRANCH == 'staging'
artifacts:
paths:
- bin/hello并行执行
在 Jenkins 中,不依赖于先前作业的作业可以在添加到 parallel 节时并行运行。
例如,在 Jenkinsfile 中:
pipeline {
agent any
stages {
stage('Parallel') {
parallel {
stage('Python') {
agent { docker 'python:latest' }
steps {
sh "python --version"
}
}
stage('Java') {
agent { docker 'openjdk:latest' }
when {
branch 'staging'
}
steps {
sh "java -version"
}
}
}
}
}
}此示例并行运行 Python 和 Java 作业,使用不同的容器镜像。Java 作业仅在 staging 分支更改时运行。
等效的 GitLab CI/CD .gitlab-ci.yml 文件:
python-version:
image: python:latest
script:
- python --version
java-version:
image: openjdk:latest
rules:
- if: $CI_COMMIT_BRANCH == 'staging'
script:
- java -version在这种情况下,不需要额外配置即可使作业并行运行。作业默认并行运行,每个作业在不同的运行器上运行(假设有足够的运行器运行所有作业)。Java 作业设置为仅在 staging 分支更改时运行。
矩阵
在 GitLab 中,您可以使用矩阵在单个管道中多次并行运行作业,但每个作业实例使用不同的变量值。Jenkins 顺序运行矩阵。
例如,在 Jenkinsfile 中:
matrix {
axes {
axis {
name 'PLATFORM'
values 'linux', 'mac', 'windows'
}
axis {
name 'ARCH'
values 'x64', 'x86'
}
}
stages {
stage('build') {
echo "Building $PLATFORM for $ARCH"
}
stage('test') {
echo "Building $PLATFORM for $ARCH"
}
stage('deploy') {
echo "Building $PLATFORM for $ARCH"
}
}
}等效的 GitLab CI/CD .gitlab-ci.yml 文件:
stages:
- build
- test
- deploy
.parallel-hidden-job:
parallel:
matrix:
- PLATFORM: [linux, mac, windows]
ARCH: [x64, x86]
build-job:
extends: .parallel-hidden-job
stage: build
script:
- echo "Building $PLATFORM for $ARCH"
test-job:
extends: .parallel-hidden-job
stage: test
script:
- echo "Testing $PLATFORM for $ARCH"
deploy-job:
extends: .parallel-hidden-job
stage: deploy
script:
- echo "Testing $PLATFORM for $ARCH"容器镜像
在 GitLab 中,您可以使用 image 关键字 在独立的 Docker 容器中运行 CI/CD 作业。
例如,在 Jenkinsfile 中:
stage('Version') {
agent { docker 'python:latest' }
steps {
echo 'Hello Python'
sh 'python --version'
}
}此示例显示在 python:latest 容器中运行的命令。
等效的 GitLab CI/CD .gitlab-ci.yml 文件:
version-job:
image: python:latest
script:
- echo "Hello Python"
- python --version变量
在 GitLab 中,使用 variables 关键字定义 CI/CD 变量。使用变量来重用配置数据、实现更动态的配置或存储重要值。变量可以全局定义或按作业定义。
例如,在 Jenkinsfile 中:
pipeline {
agent any
environment {
NAME = 'Fern'
}
stages {
stage('English') {
environment {
GREETING = 'Hello'
}
steps {
sh 'echo "$GREETING $NAME"'
}
}
stage('Spanish') {
environment {
GREETING = 'Hola'
}
steps {
sh 'echo "$GREETING $NAME"'
}
}
}
}此示例展示如何使用变量将值传递给作业中的命令。
等效的 GitLab CI/CD .gitlab-ci.yml 文件:
default:
image: alpine:latest
stages:
- greet
variables:
NAME: "Fern"
english:
stage: greet
variables:
GREETING: "Hello"
script:
- echo "$GREETING $NAME"
spanish:
stage: greet
variables:
GREETING: "Hola"
script:
- echo "$GREETING $NAME"变量也可以 在 GitLab UI 的 CI/CD 设置中定义。在某些情况下,您可以使用 受保护的 和 屏蔽的 变量来存储机密值。这些变量可以在管道作业中像在配置文件中定义的变量一样访问。
例如,在 Jenkinsfile 中:
pipeline {
agent any
stages {
stage('Example Username/Password') {
environment {
AWS_ACCESS_KEY = credentials('aws-access-key')
}
steps {
sh 'my-login-script.sh $AWS_ACCESS_KEY'
}
}
}
}等效的 GitLab CI/CD .gitlab-ci.yml 文件:
login-job:
script:
- my-login-script.sh $AWS_ACCESS_KEY此外,GitLab CI/CD 为每个管道和作业提供 预定义变量,其中包含与管道和仓库相关的值。
表达式和条件
当新管道启动时,GitLab 检查哪些作业应该在该管道中运行。您可以配置作业根据变量状态或管道类型等因素运行。
例如,在 Jenkinsfile 中:
stage('deploy_staging') {
agent { docker 'alpine:latest' }
when {
branch 'staging'
}
steps {
echo "Deploying to staging"
}
}在此示例中,作业仅在我们提交到的分支名为 staging 时运行。
等效的 GitLab CI/CD .gitlab-ci.yml 文件:
deploy_staging:
stage: deploy
script:
- echo "Deploy to staging server"
rules:
- if: '$CI_COMMIT_BRANCH == staging'运行器
与 Jenkins 代理类似,GitLab 运行器是运行作业的主机。如果您使用 GitLab.com,可以使用 实例运行器集群 来运行作业,而无需配置自己的运行器。
要将 Jenkins 代理转换为用于 GitLab CI/CD,请卸载代理,然后安装并注册运行器。运行器不需要太多开销,因此您可能能够使用与之前使用的 Jenkins 代理类似的配置方式。
关于运行器的一些关键细节:
- 运行器可以配置为在实例间共享、在组间共享,或专用于单个项目。
- 您可以使用
tags关键字进行更精细的控制,并将运行器与特定作业关联。例如,您可以为需要专用、更强大或特定硬件的作业使用标签。 - GitLab 支持运行器自动扩展。使用自动扩展仅在需要时配置运行器,在不需要时缩减规模。
例如,在 Jenkinsfile 中:
pipeline {
agent none
stages {
stage('Linux') {
agent {
label 'linux'
}
steps {
echo "Hello, $USER"
}
}
stage('Windows') {
agent {
label 'windows'
}
steps {
echo "Hello, %USERNAME%"
}
}
}
}等效的 GitLab CI/CD .gitlab-ci.yml 文件:
linux_job:
stage: build
tags:
- linux
script:
- echo "Hello, $USER"
windows_job:
stage: build
tags:
- windows
script:
- echo "Hello, %USERNAME%"产物
在 GitLab 中,任何作业都可以使用 artifacts 关键字定义作业完成时要存储的一组产物。产物是可以在后续作业中使用的文件,例如用于测试或部署。
例如,在 Jenkinsfile 中:
stages {
stage('Generate Cat') {
steps {
sh 'touch cat.txt'
sh 'echo "meow" > cat.txt'
}
post {
always {
archiveArtifacts artifacts: 'cat.txt'
onlyIfSuccessful: true
}
}
}
stage('Use Cat') {
steps {
sh 'cat cat.txt'
}
}
}等效的 GitLab CI/CD .gitlab-ci.yml 文件:
stages:
- generate
- use
generate_cat:
stage: generate
script:
- touch cat.txt
- echo "meow" > cat.txt
artifacts:
paths:
- cat.txt
expire_in: 1 week
use_cat:
stage: use
script:
- cat cat.txt
artifacts:
paths:
- cat.txt缓存
当作业下载一个或多个文件并保存以便将来更快访问时,会创建缓存。使用相同缓存的后续作业不需要再次下载文件,因此执行速度更快。缓存在运行器上存储,如果启用了分布式缓存,会上传到 S3。Jenkins 核心不提供缓存功能。
例如,在 .gitlab-ci.yml 文件中:
cache-job:
script:
- echo "This job uses a cache."
cache:
key: binaries-cache-$CI_COMMIT_REF_SLUG
paths:
- binaries/Jenkins 插件
Jenkins 中通过插件启用的某些功能在 GitLab 中通过提供类似功能的关键字和特性得到原生支持。例如:
| Jenkins 插件 | GitLab 功能 |
|---|---|
| Build Timeout | timeout 关键字 |
| Cobertura | 覆盖率报告产物 和 代码覆盖率 |
| Code coverage API | 代码覆盖率 和 覆盖率可视化 |
| Embeddable Build Status | 管道状态徽章 |
| JUnit | JUnit 测试报告产物 和 单元测试报告 |
| Mailer | 通知邮件 |
| Parameterized Trigger Plugin | trigger 关键字 和 下游管道 |
| Role-based Authorization Strategy | GitLab 权限和角色 |
| Timestamper | 作业 日志默认带有时间戳 |
安全扫描功能
您可能使用过插件来处理 Jenkins 中的代码质量、安全或静态应用程序扫描。GitLab 提供开箱即用的安全扫描器来检测 SDLC 所有部分的漏洞。您可以使用模板在 GitLab 中添加这些插件,例如要在管道中添加 SAST 扫描,将以下内容添加到您的 .gitlab-ci.yml:
include:
- template: Jobs/SAST.gitlab-ci.yml您可以通过使用 CI/CD 变量来自定义安全扫描器的行为,例如使用 SAST 扫描器。
机密信息管理
特权信息,通常称为"机密信息",是您在 CI/CD 工作流中需要的敏感信息或凭据。您可能使用机密信息来解锁受保护资源或工具、应用程序、容器和云原生环境中的敏感信息。
Jenkins 中的机密信息管理通常使用 Secret 类型字段或凭据插件处理。存储在 Jenkins 设置中的凭据可以通过凭据绑定插件作为环境变量暴露给作业。
对于 GitLab 中的机密信息管理,您可以使用外部服务的支持的集成之一。这些服务在您的 GitLab 项目之外安全存储机密信息,但您必须订阅该服务:
GitLab 还支持对支持 OIDC 的其他第三方服务使用 OIDC 身份验证。
此外,您可以通过将凭据存储在 CI/CD 变量中来使其对作业可用,但以明文存储的机密信息容易意外暴露,与 Jenkins 中相同。您应该始终将敏感信息存储在屏蔽的和受保护的变量中,这样可以降低一些风险。
另外,切勿将机密信息作为变量存储在您的 .gitlab-ci.yml 文件中,该文件对所有有权访问项目的用户都是公开的。将敏感信息存储在变量中应仅在项目、组或实例设置中进行。
查看安全指南以提高 CI/CD 变量的安全性。
迁移规划和执行
以下推荐步骤列表是在观察能够快速完成此迁移的组织后创建的。
创建迁移计划
在开始迁移之前,您应该创建一个迁移计划来为迁移做准备。对于从 Jenkins 的迁移,请准备时问自己以下问题:
- Jenkins 中的作业使用了哪些插件?
- 您确切知道这些插件的作用吗?
- 是否有插件包装了常见的构建工具?例如 Maven、Gradle 或 NPM?
- Jenkins 代理上安装了什么?
- 是否使用了共享库?
- 您如何从 Jenkins 进行身份验证?是否使用 SSH 密钥、API 令牌或其他机密信息?
- 是否有其他项目需要从您的管道中访问?
- Jenkins 中是否有访问外部服务的凭据?例如 Ansible Tower、Artifactory 或其他云服务提供商或部署目标?
先决条件
在进行任何迁移工作之前,您应该首先:
- 熟悉 GitLab。
- 阅读关键的 GitLab CI/CD 功能。
- 按照教程创建您的第一个 GitLab 管道和更复杂的管道,构建、测试和部署静态网站。
- 查看CI/CD YAML 语法参考。
- 设置和配置 GitLab。
- 测试您的 GitLab 实例。
- 确保运行器可用,要么使用共享的 GitLab.com 运行器,要么安装新的运行器。
迁移步骤
- 将项目从您的 SCM 解决方案迁移到 GitLab。
- (推荐)您可以使用可用的导入器来自动从外部 SCM 提供商批量导入。
- 您可以通过 URL 导入仓库。
- 在每个项目中创建一个
.gitlab-ci.yml文件。 - 将 Jenkins 配置迁移到 GitLab CI/CD 作业,并配置它们直接在合并请求中显示结果。
- 通过使用云部署模板、环境和GitLab Kubernetes 代理来迁移部署作业。
- 检查是否有任何 CI/CD 配置可以跨不同项目重用,然后创建并共享 CI/CD 模板。
- 查看管道效率文档,了解如何使您的 GitLab CI/CD 管道更快、更高效。
其他资源
-
您可以使用 JenkinsFile Wrapper 在 GitLab CI/CD 作业中运行完整的 Jenkins 实例,包括插件。使用此工具帮助过渡到 GitLab CI/CD,通过延迟迁移不太紧急的管道。
JenkinsFile Wrapper 未与 GitLab 一起打包,不在支持范围内。有关更多信息,请参阅支持声明。
如果您有此处未回答的问题,GitLab 社区论坛可能是一个很好的资源。