Help us learn about your current experience with the documentation. Take the survey.

从 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_scriptstage 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 关键字添加到作业或管道级别,例如 timeoutretry
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 或其他云服务提供商或部署目标?

先决条件

在进行任何迁移工作之前,您应该首先:

  1. 熟悉 GitLab。
  2. 设置和配置 GitLab。
  3. 测试您的 GitLab 实例。
    • 确保运行器可用,要么使用共享的 GitLab.com 运行器,要么安装新的运行器。

迁移步骤

  1. 将项目从您的 SCM 解决方案迁移到 GitLab。
  2. 在每个项目中创建一个 .gitlab-ci.yml 文件。
  3. 将 Jenkins 配置迁移到 GitLab CI/CD 作业,并配置它们直接在合并请求中显示结果。
  4. 通过使用云部署模板环境GitLab Kubernetes 代理来迁移部署作业。
  5. 检查是否有任何 CI/CD 配置可以跨不同项目重用,然后创建并共享 CI/CD 模板。
  6. 查看管道效率文档,了解如何使您的 GitLab CI/CD 管道更快、更高效。

其他资源

  • 您可以使用 JenkinsFile Wrapper 在 GitLab CI/CD 作业中运行完整的 Jenkins 实例,包括插件。使用此工具帮助过渡到 GitLab CI/CD,通过延迟迁移不太紧急的管道。

    JenkinsFile Wrapper 未与 GitLab 一起打包,不在支持范围内。有关更多信息,请参阅支持声明

如果您有此处未回答的问题,GitLab 社区论坛可能是一个很好的资源。