需要安装docker并启动
xxxxxxxxxxcat > /etc/yum.repos.d/gitlab-ce.repo <<EOF[gitlab-ce]name=Gitlab CE Repositorybaseurl=https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el\$releasever/gpgcheck=0enabled=1EOF#yum install -y gitlab-ceyum install -y gitlab-ce-13.6.1# 修改默认的配置文件#vim /etc/gitlab/gitlab.rbsed -i "s#^\(external_url \).*#\1'http://gitlab.gotodev.cn'#" /etc/gitlab/gitlab.rbsed -i "s/^# \(gitlab_rails\['initial_root_password'\] = \).*/\1\"Pa55w@rd\"/" /etc/gitlab/gitlab.rb# 验证配置文件gitlab-ctl show-config# 重新配置,确保服务器时间配置正确gitlab-ctl reconfigure
xxxxxxxxxxgitlab-ctl start # 启动所有 gitlab 组件gitlab-ctl stop # 停止所有 gitlab 组件gitlab-ctl restart # 重启所有 gitlab 组件gitlab-ctl status # 查看服务状态gitlab-ctl tail # 查看日志gitlab-rake gitlab:check SANITIZE=true --trace # 检查 GitLab 系统健康状态
浏览器输入 http://<节点 IP>/, 访问 Gitlab。用户名root,密码Pa55w@rd登录 Gitlab。
配置中文:右上角头像 -> settings -> preferences -> localization -> language -> 简体中文 -> Save Changes
创建 gitlab-runner-test 仓库,配置 ssh public key,推送本地仓库到gitlab
配置 ssh public key,用于推送仓库:右上角头像 -> 设置 -> SSH秘钥
配置 kubernetes kubeconfig,用于连接到kubernetes集群:请参考与Kubernetes集群交互
xxxxxxxxxxcat > /etc/yum.repos.d/gitlab-runner.repo <<EOF[gitlab-runner]name=gitlab-runnerbaseurl=https://mirrors.tuna.tsinghua.edu.cn/gitlab-runner/yum/el\$releasever-\$basearch/repo_gpgcheck=0gpgcheck=0enabled=1gpgkey=https://packages.gitlab.com/gpg.keyEOF#yum install -y gitlab-runneryum install -y gitlab-runner-13.6.0-1
在Gitlab的左上角 🔧 设置 - Runnners界面,可以获取 registration-token。
注册shell executor类型的 runner
xxxxxxxxxxREGISTRATION_TOKEN=""gitlab-runner register \--non-interactive \--url "http://127.0.0.1/" \--registration-token $REGISTRATION_TOKEN \--executor "shell" \--description "shell runner" \--tag-list "build,k8s,go,cicd" \--run-untagged="true" \--locked="false" \--access-level="not_protected"
注册禁用 TLS 的 docker executor 类型的 runner
xxxxxxxxxxREGISTRATION_TOKEN=""gitlab-runner register \--non-interactive \--url "http://127.0.0.1/" \--registration-token $REGISTRATION_TOKEN \--executor "docker" \--description "docker runner no privileged" \--docker-image docker:26.1.4-cli-alpine3.20\--tag-list "build,k8s,go,cicd" \--run-untagged="true" \--locked="false" \--access-level="not_protected" \--docker-pull-policy="if-not-present"
要在 CI/CD 作业中运行 Docker 命令,您必须配置 GitLab Runner 以支持 docker 命令。此方法需要 privileged 模式。参考官方文档
此任务启用--docker-privileged。当您这样做时,您实际上是在禁用容器的所有安全机制并将您的主机暴露给特权升级。这样做会导致 container breakout。有关更多信息,请参阅有关运行时权限和 Linux 功能 的官方 Docker 文档。
xxxxxxxxxxREGISTRATION_TOKEN="XCLKnzkyk4zTUkfQkekv"gitlab-runner register \--non-interactive \--url "http://127.0.0.1/" \--registration-token $REGISTRATION_TOKEN \--executor "docker" \--description "docker runner with privileged" \--docker-image docker:26.1.4-cli-alpine3.20\--docker-privileged \--tag-list "build,k8s,go,cicd" \--run-untagged="true" \--locked="false" \--access-level="not_protected" \--docker-pull-policy="if-not-present"
xxxxxxxxxxgitlab-runner -vgitlab-runner restart# 查看已注册的runner(s),在Gitlab的设置 - Runnners界面上也可以看到刚刚注册好的设备:gitlab-runner list# 修改默认的配置文件,需要重启gitlab-runnervi /etc/gitlab-runner/config.toml# 移除一个已注册的runnergitlab-runner unregister --url &URL --token $REGISTRATION_TOKEN
运行gitlab-ci任务报错
xxxxxxxxxxReinitialized existing Git repository in /home/gitlab-runner/builds/xxx...xxx/.git/fatal: git fetch-pack: expected shallow listfatal: The remote end hung up unexpectedlyERROR: Job failed: exit status 1
GitLab Runner 在默认情况下可能会进行浅克隆(git clone --depth=50),git版本太低会报错,yum阿里云源里面最新的版本是1.18.3,升级 Git 即可。
此图表已经在 Google Kubernetes Engine 和 Azure 容器服务上进行了测试。
将 GitLab Runner 实例部署到 Kubernetes 集群的官方方法是使用gitlab-runner Helm chart。
此chart将 GitLab Runner 配置为:
添加 GitLab Helm 存储库:
xxxxxxxxxxhelm repo add gitlab https://charts.gitlab.io
配置 values.yaml
在gitlab查看注册token:
xxxxxxxxxxgitlabUrl: https://gitlab.cd.xsio.cn/runnerRegistrationToken: "GR1348941sWasRx1u5nm6ZyCgEnzQ"rbac:create: truetags: "cicd" # 给此runner定义一个tag
修改 templates/configmap.yaml,在# Start the runner 之前加如下代码:
xxxxxxxxxxcat >>/home/gitlab-runner/.gitlab-runner/config.toml <<EOF[[runners.kubernetes.volumes.host_path]]name = "docker-sock"mount_path = "/var/run/docker.sock"read_only = truehost_path = "/var/run/docker.sock"EOF# Start the runner
部署k8s的时候有两个问题,其一是就是要配置k8s的config文件,以此来获得部署的权限。其二是k8s部署模板。 两个问题我用了一种解决方法,通过在k8s中创建configMap并挂载到runner执行器中的方式。
xxxxxxxxxx# kubectl create cm kubeconfig --from-file=.kube/config# 用来挂载k8s的配置文件[[runners.kubernetes.volumes.config_map]]name = "kubeconfig"mount_path = "/root/.kube/config"sub_path = "config"
安装
xxxxxxxxxxhelm install --namespace <NAMESPACE> gitlab-runner -f values.yaml gitlab/gitlab-runnerhelm install --namespace <NAMESPACE> gitlab-runner -f values.yaml gitlab/gitlab-runner --version <RUNNER_HELM_CHART_VERSION>helm upgrade --namespace <NAMESPACE> -f values.yaml gitlab-runner gitlab/gitlab-runnerhelm upgrade gitlab-runner-helloworld2 -f gitlab-runner-helloworld2/values.yaml gitlab-runner/helm upgrade gitlab-runner-subgroup -f gitlab-runner-subgroup/values.yaml gitlab-runner/
您可以使用配置模板文件 来配置运行器。您可以使用配置模板配置运行器上的任何字段,而无需让 Helm 图表了解特定的运行器配置选项。
这是在图表存储库的文件中找到values.yaml的默认设置的片段。重要的是要注意,对于该config:部分,格式应该是toml(<parameter> = <value>而不是<parameter>: <value>),因为我们要嵌入config.toml到values.yaml.
xxxxxxxxxxrunners:config: |[[runners]][runners.kubernetes]image = "ubuntu:16.04"
其余配置记录在values.yaml.
该文件接受的许多字段values.yaml将随着 Helm Chart 1.0 版的引入而被删除。我们建议尽快远离它们。这些字段上方标有DEPRECATED:注释。
Kubernetes 执行器支持的所有配置选项都列在Kubernetes 执行器文档中。对于许多字段,中的旧名称与关键字values.yaml相同。对于某些,您必须重命名它们。例如,如果您使用设置 CPU 限制: helpers
xxxxxxxxxxhelpers:cpuLimit: 200m
现在您可以将它们设置为helper_cpu_limit. 确保您在该部分中使用toml格式(=而不是:)config::
xxxxxxxxxxrunners:config: |[[runners]][runners.kubernetes]image = "ubuntu:16.04"helper_cpu_limit = "200m"## helpers:## cpuLimit: 200m
确保从values.yaml文件中注释或删除旧的配置值以避免冲突。
如果您的集群启用了 RBAC,您可以选择让图表创建自己的服务帐户或自己提供一个。
要让图表为您创建服务帐户,请设置rbac.create为 true:
xxxxxxxxxxrbac:create: true
要使用已经存在的服务帐户,请使用:
xxxxxxxxxxrbac:create: falseserviceAccountName: your-service-account
部署在 Kubernetes 上的单个 GitLab Runner 能够通过自动启动额外的 Runner pod 来并行执行多个作业。该 concurrent设置 控制一次允许的最大 pod 数量,默认为10:
xxxxxxxxxx## Configure the maximum number of concurrent jobs## ref: https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-global-section##concurrent: 10
请参阅为运行器运行特权容器以了解如何启用它,以及关于运行 dind 的GitLab 运行器文档。
您可以告诉 GitLab Runner 使用特权容器运行。如果您需要在 GitLab CI/CD 作业中使用 Docker 可执行文件,则可能需要启用此功能。
这会带来一些风险,您可以在GitLab CI/CD Runner 文档中了解到这些风险 。
如果您可以接受这些风险,并且您的 GitLab Runner 实例是针对 GitLab 中您信任其 CI 作业的特定项目注册的,则可以在以下位置启用特权模式values.yaml:
xxxxxxxxxxrunners:## Run all containers with the privileged flag enabled## This will allow the docker:stable-dind image to run if you need to run Docker## commands. Please read the docs before turning this on:## ref: https://docs.gitlab.com/runner/executors/kubernetes.html#using-docker-dind##privileged: true
使用 Docker-in-Docker 在容器内构建容器需要 Docker 特权模式。谷歌的Kaniko是一种无需特权模式即可工作的替代方案,它已经在 Kubernetes GitLab Runner 上进行了测试。
在GitLab 视频中使用 Kaniko 构建最小权限容器是Kaniko Docker 构建 工作示例项目的演练。它使用了 使用 Kaniko 和 GitLab CI/CD 构建图像的文档。
可以将工作示例项目复制到您自己的组或实例中进行测试。有关演示了哪些其他 GitLab CI 模式的更多详细信息,请访问项目页面Kaniko Docker Build。
使用来自私有 registry 的镜像需要配置 imagePullSecrets。有关如何创建 imagePullSecrets 的更多详细信息,请参阅文档。
xxxxxxxxxxrunners:## Specify one or more imagePullSecrets#### ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/##imagePullSecrets:- [your-image-pull-secret]
注意格式。该值没有像 Kubernetes 资源中的惯例那样以“名称”标签为前缀。
您可以向 GitLab Runner Helm Chart 提供Kubernetes Secret ,它将用于填充容器的 /home/gitlab-runner/.gitlab-runner/certs目录。
Secret 中的每个密钥名称将用作目录中的文件名,文件内容是与密钥关联的值:
<gitlab-hostname>.crt,例如 gitlab.your-domain.com.crt.GitLab Runner Helm Chart 不会为您创建秘密。为了创建秘密,您告诉 Kubernetes 将证书存储为秘密并将其作为文件提供给 GitLab Runner 容器。为此,请运行以下命令:
xxxxxxxxxxkubectl--namespace <NAMESPACE>create secret generic <SECRET_NAME>--from-file=<CERTIFICATE_FILENAME>
然后,您需要将密钥的名称提供给 GitLab Runner 图表。将以下内容添加到您的values.yaml:
xxxxxxxxxx## Set the certsSecretName in order to pass custom certificates for GitLab Runner to use## Provide resource name for a Kubernetes Secret Object in the same namespace,## this is used to populate the /home/gitlab-runner/.gitlab-runner/certs/ directory## ref: https://docs.gitlab.com/runner/configuration/tls-self-signed.html#supported-options-for-self-signed-certificates##certsSecretName: <SECRET NAME>
目前无法在values.yaml文件中使用环境变量作为 pod 标签。我们正在解决这个问题:Can't set environment variable key as pod label。使用问题中描述的解决方法作为临时解决方案。
要注册一个新的跑步者,您可以 runnerRegistrationToken在中指定values.yml。要注册现有的跑步者,您可以使用runnerToken. 将令牌存储在其中可能存在安全风险values.yml,尤其是当您将这些令牌提交给git.
相反,您可以将这些令牌的值存储在 Kubernetes secret中,然后使用 secret 的名称 更新其中的runners.secret值。values.yml
如果您有现有的注册跑步者并想使用它,请 runner-token使用用于识别该跑步者的令牌进行设置。如果你想注册一个新的跑步者,你可以设置你想要 runner-registration-token的注册令牌。
例如:
xxxxxxxxxxapiVersion: v1kind: Secretmetadata:name: gitlab-runner-secrettype: Opaquedata:runner-registration-token: "NlZrN1pzb3NxUXlmcmVBeFhUWnIK" #base64 encoded registration tokenrunner-token: ""runners:secret: gitlab-runner-secret
此示例使用 secretgitlab-runner-secret并采用 的值 runner-registration-token来注册新的跑步者。
gitlab-runnerDocker 镜像默认情况下,GitLab Runner Helm Chart 使用gitlab/gitlab-runner图像的 Alpine 版本,它使用musl libc. 在某些情况下,您可能希望切换到基于 Ubuntu 的映像,它使用glibc.
为此,请values.yaml使用以下值更新您的文件:
xxxxxxxxxx# Specify the Ubuntu image. Remember to set the version. You can also use the `ubuntu` or `latest` tags.image: gitlab/gitlab-runner:v13.0.0# Update the security context values to the user ID in the ubuntu imagesecurityContext:fsGroup: 999runAsUser: 999
从 GitLab 8.0 开始,GitLab CI 就已经集成在 GitLab 中,我们只要在项目中添加一个 .gitlab-ci.yml 文件,然后添加一个 Runner,即可进行持续集成。 而且随着 GitLab 的升级,GitLab CI 变得越来越强大,本文将介绍如何使用 GitLab CI 进行持续集成。
在介绍 GitLab CI 之前,我们先看看一些持续集成相关的概念。
一次 Pipeline 其实相当于一次构建任务,里面可以包含多个流程,如安装依赖、运行测试、编译、部署测试服务器、部署生产服务器等流程。 任何提交或者 Merge Request 的合并都可以触发 Pipeline,如下图所示:
xxxxxxxxxx+------------------+ +----------------+| | trigger | || Commit / MR +---------->+ Pipeline || | | |+------------------+ +----------------+
Stages 表示构建阶段,说白了就是上面提到的流程。 我们可以在一次 Pipeline 中定义多个 Stages,这些 Stages 会有以下特点:
因此,Stages 和 Pipeline 的关系就是:
xxxxxxxxxx+--------------------------------------------------------+| || Pipeline || || +-----------+ +------------+ +------------+ || | Stage 1 |---->| Stage 2 |----->| Stage 3 | || +-----------+ +------------+ +------------+ || |+--------------------------------------------------------+
Jobs 表示构建工作,表示某个 Stage 里面执行的工作。 我们可以在 Stages 里面定义多个 Jobs,这些 Jobs 会有以下特点:
所以,Jobs 和 Stage 的关系图就是:
xxxxxxxxxx+------------------------------------------+| || Stage 1 || || +---------+ +---------+ +---------+ || | Job 1 | | Job 2 | | Job 3 | || +---------+ +---------+ +---------+ || |+------------------------------------------+
理解了上面的基本概念之后,有没有觉得少了些什么东西 —— 由谁来执行这些构建任务呢? 答案就是 GitLab Runner 了!
想问为什么不是 GitLab CI 来运行那些构建任务? 一般来说,构建任务都会占用很多的系统资源 (譬如编译代码),而 GitLab CI 又是 GitLab 的一部分,如果由 GitLab CI 来运行构建任务的话,在执行构建任务的时候,GitLab 的性能会大幅下降。
GitLab CI 最大的作用是管理各个项目的构建状态,因此,运行构建任务这种浪费资源的事情就交给 GitLab Runner 来做拉! 因为 GitLab Runner 可以安装到不同的机器上,所以在构建任务运行期间并不会影响到 GitLab 的性能~
配置好 Runner 之后,我们要做的事情就是在项目根目录中添加 .gitlab-ci.yml 文件了。 当我们添加了 .gitlab-ci.yml 文件后,每次提交代码或者合并 MR 都会自动运行构建任务了。
还记得 Pipeline 是怎么触发的吗?Pipeline 也是通过提交代码或者合并 MR 来触发的! 那么 Pipeline 和 .gitlab-ci.yml 有什么关系呢? 其实 .gitlab-ci.yml 就是在定义 Pipeline 而已拉!
我们先来看看 .gitlab-ci.yml 是怎么写的:
xxxxxxxxxx# 定义 stagesstages:- build- test# 定义 jobjob1:stage: testscript:- echo "I am job1"- echo "I am in test stage"# 定义 jobjob2:stage: buildscript:- echo "I am job2"- echo "I am in build stage"
写起来很简单吧!用 stages 关键字来定义 Pipeline 中的各个构建阶段,然后用一些非关键字来定义 jobs。 每个 job 中可以可以再用 stage 关键字来指定该 job 对应哪个 stage。 job 里面的 script 关键字是最关键的地方了,也是每个 job 中必须要包含的,它表示每个 job 要执行的命令。
回想一下我们之前提到的 Stages 和 Jobs 的关系,然后猜猜上面例子的运行结果?
xxxxxxxxxxI am job2I am in build stageI am job1I am in test stage
根据我们在 stages 中的定义,build 阶段要在 test 阶段之前运行,所以 stage:build 的 jobs 会先运行,之后才会运行 stage:test 的 jobs。
下面介绍一些常用的关键字,想要更加详尽的内容请前往 官方文档
定义 Stages,默认有三个 Stages,分别是 build, test, deploy。
stages 的别名。
定义任何 Jobs 运行前都会执行的命令。
要求 GitLab 8.7+ 和 GitLab Runner 1.2+
定义任何 Jobs 运行完后都会执行的命令。
要求 GitLab Runner 0.5.0+
定义环境变量。 如果定义了 Job 级别的环境变量的话,该 Job 会优先使用 Job 级别的环境变量。
xxxxxxxxxxvariables:MY_GLOBAL_VAR: "This is a global variable"job_name:script:- echo "This job has a variable: $MY_JOB_VAR"variables:MY_JOB_VAR: "This is a job-specific variable"
要求 GitLab Runner 0.7.0+
定义需要缓存的文件。 每个 Job 开始的时候,Runner 都会删掉 .gitignore 里面的文件。 如果有些文件 (如 node_modules/) 需要多个 Jobs 共用的话,我们只能让每个 Job 都先执行一遍 npm install。 这样很不方便,因此我们需要对这些文件进行缓存。缓存了的文件除了可以跨 Jobs 使用外,还可以跨 Pipeline 使用。
具体用法请查看 官方文档。
定义 Job 要运行的命令,必填项。
定义 Job 的 stage,默认为 test。
定义 Job 中生成的附件。 当该 Job 运行成功后,生成的文件可以作为附件 (如生成的二进制文件) 保留下来,打包发送到 GitLab,之后我们可以在 GitLab 的项目页面下下载该附件。 注意,不要把 artifacts 和 cache 混淆了。
xxxxxxxxxxtest:artifacts: # 保存和共享构建结果paths:- ./new_file.txtexpire_in: 10 hour
下面给出一个我自己在用的例子:
xxxxxxxxxxstages:- install_deps- test- build- deploy_test- deploy_productioncache:key: ${CI_BUILD_REF_NAME}paths:- node_modules/- dist/# 安装依赖install_deps:stage: install_depsonly:- develop- masterscript:- npm install# 运行测试用例test:stage: testonly:- develop- masterscript:- npm run test# 编译build:stage: buildonly:- develop- masterscript:- npm run clean- npm run build:client- npm run build:server# 部署测试服务器deploy_test:stage: deploy_testonly:- developscript:- pm2 delete app || true- pm2 start app.js --name app# 部署生产服务器deploy_production:stage: deploy_productiononly:- masterscript:- bash scripts/deploy/deploy.sh
上面的配置把一次 Pipeline 分成五个阶段:
install_deps)test)build)deploy_test)deploy_production)设置 Job.only 后,只有当 develop 分支和 master 分支有提交的时候才会触发相关的 Jobs。 注意,我这里用 GitLab Runner 所在的服务器作为测试服务器。
参考资料
文章作者 scarletsky 上次更新 2019-04-30 (95a170d)
发布时间 2025-04-05 00:47:54
在GitLab CI中,Pipeline配置文件(.gitlab-ci.yml)是自动化构建与部署的核心。本文将深入讲解only、except、rules与workflow的语法与使用场景,帮助开发者掌握Pipeline的创建规则与动态配置方法。
only与exceptonly和except是GitLab CI中用于限制Pipeline作业运行的分支和标签的关键字。通过它们,可以精确控制Pipeline的触发条件。
1.1 only语法
only用于指定Pipeline作业仅在某些分支或标签上运行。例如:
xxxxxxxxxxjob onlymastertags上述配置表示该作业仅在master分支或任何标签上运行。
1.2 except语法
except用于排除某些分支或标签的运行。例如:
xxxxxxxxxxjob exceptdevelop上述配置表示该作业在所有分支上运行,但排除develop分支。
1.3 示例:结合only与except
以下示例展示了如何同时使用only和except:
xxxxxxxxxxjob only/^feature-.+$/ # 仅运行在以feature-开头的分支 except/^feature-ignore-.+$/ # 排除以feature-ignore-开头的分支rulesrules是GitLab CI中更灵活的规则配置方式,用于动态决定作业的运行条件。与only和except相比,rules更加强大,支持条件判断、文件变化监听和文件存在检查。
2.1 if条件判断
if用于根据变量或环境条件决定作业的运行。例如:
xxxxxxxxxxjob rulesif'$CI_COMMIT_BRANCH == "master"' whenmanualwhenalways上述配置表示,当提交分支为master时,作业为手动触发;否则,作业始终运行。
2.2 changes监听文件变化
changes用于监听特定文件或目录的变化。例如:
xxxxxxxxxxjob rulesif'$CI_COMMIT_BRANCH == "develop"' changesREADME.mdsrc/**/*.py上述配置表示,当develop分支上的README.md或src目录下的.py文件发生变化时,作业将运行。
2.3 exists检查文件存在
exists用于检查特定文件是否存在。例如:
xxxxxxxxxxjob rulesif'$CI_COMMIT_BRANCH == "main"' existspackage.json上述配置表示,当main分支上存在package.json文件时,作业将运行。
2.4 示例:综合使用rules
以下示例展示了如何综合使用if、changes和exists:
xxxxxxxxxxjob rulesif'$CI_COMMIT_BRANCH == "main"' existspackage.json whenmanualchangessrc/**/*.py whenalwayswhenneverworkflowworkflow用于控制Pipeline的创建条件。通过rules中的if和when,可以灵活决定Pipeline的触发行为。
3.1 workflow语法
以下是一个简单的workflow配置示例:
xxxxxxxxxxworkflow rulesif'$CI_COMMIT_BRANCH == "main"' whenalwayswhennever上述配置表示,当提交分支为main时,Pipeline始终创建;否则,Pipeline不创建。
3.2 示例:结合workflow与rules
以下示例展示了如何结合workflow与rules实现更复杂的Pipeline控制:
xxxxxxxxxxworkflow rulesif'$CI_COMMIT_BRANCH == "main"' whenalwaysif'$CI_COMMIT_BRANCH == "develop"' whenmanualwhennever
job rulesif'$CI_COMMIT_BRANCH == "main"' whenmanualwhenalways以下表格列出了关于only、except、rules与workflow的常见问题及其解答:
| 问题 | 答案 |
|---|---|
only和except的区别是什么? | only用于指定作业运行的分支或标签,except用于排除特定分支或标签的运行。 |
rules是否可以替代only和except? | 是的,rules功能更强大,可以完全替代only和except。 |
changes和exists的区别是什么? | changes用于监听文件变化,exists用于检查文件是否存在。 |
workflow的when有哪些值? | when支持always和never两个值,分别表示始终创建和从不创建Pipeline。 |
| 如何实现手动触发的Pipeline? | 在rules中设置when: manual即可实现手动触发。 |
only与rules对比以下表格对比了only与rules的主要区别:
| 特性 | only | rules |
|---|---|---|
| 灵活性 | 较低 | 较高 |
| 条件判断 | 不支持 | 支持 |
| 文件变化监听 | 不支持 | 支持 |
| 文件存在检查 | 不支持 | 支持 |
以下是一个综合示例,展示了如何使用only、except、rules与workflow配置Pipeline:
xxxxxxxxxxworkflow rulesif'$CI_COMMIT_BRANCH == "main"' whenalwayswhennever
job1 onlymain excepttags scriptecho "Running on main branch"
job2 rulesif'$CI_COMMIT_BRANCH == "develop"' changesREADME.md whenmanualwhenalways scriptecho "Running on develop branch"
job3 rulesif'$CI_COMMIT_BRANCH == "feature"' existspackage.json whenmanualwhennever scriptecho "Running on feature branch with package.json"通过上述配置,可以实现灵活的Pipeline控制与动态作业触发。
创建一个项目 manage_zz, 在里面写个 .gitlab-ci.yml 文件,内容如下
xxxxxxxxxxstages# 指定运行的步骤,没有指定就顺序执行builddeploytestrebase
build1 tagsk8s stagebuild scriptecho "Do your build here"
test1 stagetest scriptecho "Do a test here"echo "For example run a test suite"
rebase stagerebase scriptecho "Do another parallel test here"echo "For example run a lint test"
deploy1 tagsk8s stagedeploy scriptecho "Do your deploy here"在另一个项目 LRUNWEB 的 .gitlab-ci.yml 里写上 trigger,内容如下
xxxxxxxxxxworkflow rulesif'$CI_PIPELINE_SOURCE == "push"' # 当为 push 的时候 whennever # 为 true 时,永远不执行whenalways # 否则永远执行
stages# 指定运行的步骤,没有指定就顺序执行builddeploytestrebase
build1 tagsk8s stagebuild scriptecho "Do your build here"
test1 stagetest scriptecho "Do a test here"echo "For example run a test suite"
rebase stagerebase scriptecho "Do another parallel test here"echo "For example run a lint test"
deploy1 stagedeploy trigger# 如果是 trigger 时,不需要 tags 和 script,要不然会报错 projectroot/manage_zz # 项目名称 branchmain # 分支 strategydepend # 状态同步注意:如果是 trigger ,不需要加 tags 和 script。要不然会报错
运行 LRUNWEB 项目,查看流水线。可以看到,在运行 Deploy 阶段的时候,运行了下游的 manage_zz 项目。
当下游项目运行成功时, Deploy 阶段也就成功了。

点击下游的流水线 id (#27)跳转到下游项目,可以看到下游也触发了流水线

点击下游的流水线 id (#27)跳转到下游项目,可以看到下游也触发了流水线。
我们也可以在 manage_zz 项目里,加上 workflow,只有当上游触发的时候才会执行该 pipeline,其他情况下不会执行,加上下面的代码就可以了
xxxxxxxxxxworkflow rulesif'$CI_PIPELINE_SOURCE == "pipeline"' # 只有当为 pipeline 时才触发,也就是上游在 trigger 里调度该项目 whenalways # 为 true 时,永远执行whennever # 为 false 时,永远不执行上面我们是触发不同项目之间的 ci,我们也可以在同一个项目下创建多个 ci 文件,然后去触发对应的 ci
创建两个目录,test1 和 test2,在两个目录下各创建一个 ci.yml 的文件
xxxxxxxxxxtest1`-----ci.yamltest2`-----ci.yaml.gitlab-ci.yamlREADME.md
文件内容如下
xxxxxxxxxxstages# 指定运行的步骤,没有指定就顺序执行builddeploytestrebase
build1 tagsk8s stagebuild scriptecho "Do your build here"
test1 tagsk8s stagetest scriptecho "Do a test here"echo "For example run a test suite"
rebase tagsk8s stagerebase scriptecho "Do another parallel test here"echo "For example run a lint test"
deploy1 tagsk8s stagedeploy scriptecho "Do your deploy here"在根项目的 .gitlab-ci.yml 里调用其他 ci 文件,如下
xxxxxxxxxxstages# 指定运行的步骤,没有指定就顺序执行buildtestbuild_test1build_test2
build1 tagsk8s stagebuild scriptecho "Do your build here"
test1 stagetest scriptecho "Do a test here"echo "For example run a test suite"
build-test1 stagebuild trigger include# 运行 test1 目录下的 ci.yml 文件localtest1/ci.yml # 相对路径 strategydepend # 状态同步 rules# 触发规则,test1 目录下的任何文件改变时触发changestest1/* # test1 下的任何文件发生改变就执行 whenalways
build-test2 stagebuild trigger include# 运行 test2 目录下的 ci.yml 文件localtest2/ci.yml # 相对路径 strategydepend # 状态同步 rules# 触发规则,test2 目录下的任何文件改变时触发changestest2/* # test2 下的任何文件发生改变就执行 whenalways然后在去 test2 目录下新增一个文件,看会不会触发
我创建了一个 hello.go 文件
xxxxxxxxxxtest1`-----ci.yamltest2`-----ci.yaml`-----hello.go.gitlab-ci.yamlREADME.md
在去查看流水线
发现只有 build-test2 触发了 ci,因为我们只在 test2 目录下新增了 hello.go 文件,test1 目录下的文件没有改变,所以不会触发 build-test1 的 ci
kubeconfig在 GitLab 管理中心 或项目的 Settings -> CI / CD -> Variables -> 展开 中,添加一个变量来存储你的 kubeconfig 文件。命名为 KUBECONFIG_CONTENT,这个变量存储你的 kubeconfig 的完整内容。
.gitlab-ci.yml以下是一个 .gitlab-ci.yml 文件示例,展示如何使用 bitnami/kubectl 并加载 kubeconfig 来与 Kubernetes 集群进行交互:
xxxxxxxxxxdeploy:image:name: bitnami/kubectl:1.18.19entrypoint: [""] # 重置镜像入口stage: deploybefore_script:# 设置 KUBECONFIG 环境变量,指向存储的 kubeconfig 文件- echo "$KUBECONFIG_CONTENT" > kubeconfig.yaml- export KUBECONFIG=$(pwd)/kubeconfig.yamlscript:- kubectl version --client- kubectl get pods --all-namespaces- kubectl apply -f deployment.yaml
docker-dind 服务xxxxxxxxxxdocker_image:stage: docker_imageimage: docker:26.1.4-cli-alpine3.20variables:DOCKER_HOST: tcp://docker:2375DOCKER_TLS_CERTDIR: ""services:- name: docker:26.1.4-dind-alpine3.20before_script:- export DOCKER_HOST=tcp://docker:2375- docker infoscript:- echo "I am in docker_image stage"- docker --version
在容器中使用docker命令,要在镜像内安装docker守护程序,要将主机的守护进程挂载到容器中。
例如,直接用户docker run方式启动的gitlab-runner可以这样挂载: -v /var/run/docker.sock:/var/run/docker.sock
在 Kubernetes 集群内的 gitlab CI 在构建镜像过程中,面临同样的问题。
xxxxxxxxxx$ docker build -t "${IMAGE}:${TAG}" .Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
xxxxxxxxxx# .gitlab-ci.yml 中指定docker镜像image: docker:latest
gitlab-runner在Kubernetes里安装的方法可以通过官方提供的chart来用helm3安装。官方chart的仓库地址为:https://gitlab.com/gitlab-org/charts/gitlab-runner,但这里有个问题就是无法配置宿主机的挂载目录,
根据gitlab-runner在docker模式下挂载目录的方法,并且结合官方文档,做如下改动即可支持挂载目录,修改templates/configmap.yaml文件,在"# Start the runner"前面增加如下代码:
xxxxxxxxxxcat >>/home/gitlab-runner/.gitlab-runner/config.toml <<EOF[[runners.kubernetes.volumes.host_path]]name = "docker-sock"mount_path = "/var/run/docker.sock"read_only = truehost_path = "/var/run/docker.sock"[[runners.kubernetes.volumes.host_path]]name = "cache"mount_path = "/cache"read_only = falsehost_path = "/data/gitlab-runner/cache"EOF
xxxxxxxxxxhelm pull bitnami/sonarqubehelm install sonarqube sonarqube/
xxxxxxxxxx[root@master ~]# helm install sonarqube sonarqube/NAME: sonarqubeLAST DEPLOYED: Wed Jul 6 18:56:58 2022NAMESPACE: cicdSTATUS: deployedREVISION: 1TEST SUITE: NoneNOTES:** Please be patient while the chart is being deployed **Your SonarQube site can be accessed through the following DNS name from within your cluster:sonarqube.cicd.svc.cluster.local (port 80)To access your SonarQube site from outside the cluster follow the steps below:1. Get the SonarQube URL by running these commands:LoadBalancer:NOTE: It may take a few minutes for the LoadBalancer IP to be available.Watch the status with: 'kubectl get svc --namespace cicd -w sonarqube'export SERVICE_IP=$(kubectl get svc --namespace cicd sonarqube --template "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}")echo "SonarQube URL: http://$SERVICE_IP/"ClusterIP:kubectl port-forward --namespace cicd svc/sonarqube 80:80 &echo "SonarQube URL: http://127.0.0.1/"NodePort:export NODE_PORT=$(kubectl get --namespace cicd -o jsonpath="{.spec.ports[0].nodePort}" services sonarqube)export NODE_IP=$(kubectl get nodes --namespace cicd -o jsonpath="{.items[0].status.addresses[0].address}")echo "SonarQube URL: http://$NODE_IP:$NODE_PORT/"2. Open a browser and access SonarQube using the obtained URL.3. Login with the following credentials below:echo Username: userecho Password: $(kubectl get secret --namespace cicd sonarqube -o jsonpath="{.data.sonarqube-password}" | base64 -d)
通过 gitlab 命令行访问
通过 python 访问
通过 curl 命令行访问
GITLAB_URL="https://gitlab.cd.xsio.cn"PRIVATE_TOKEN="glpat-7asHDvbNXBSyCvZDQgsC"project_id=2633job_id=1145492# List project jobs# curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs"curl --header "PRIVATE-TOKEN: "${PRIVATE_TOKEN} ${GITLAB_URL}"/api/v4/projects/"${project_id}"/jobs"# Get a single job# curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/8"curl --header "PRIVATE-TOKEN: "${PRIVATE_TOKEN} ${GITLAB_URL}"/api/v4/projects/"${project_id}"/jobs/"${job_id}""# Get a log file# curl --location --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/8/trace"curl --location --header "PRIVATE-TOKEN: "${PRIVATE_TOKEN} ${GITLAB_URL}"/api/v4/projects/"${project_id}"/jobs/"${job_id}"/trace"# Get job artifacts# curl --location --output artifacts.zip --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/42/artifacts"curl --location --output artifacts.zip --header "PRIVATE-TOKEN: "${PRIVATE_TOKEN} ${GITLAB_URL}"/api/v4/projects/"${project_id}"/jobs/"${job_id}"/artifacts"