[TOC]

0x00 前言简述

Q:我们常说的CI/CD是什么?

  • CI 为 Continuous Integration 的缩写持续集成,可以理解为代码变动提交后,自动执行代码编译、代码打包、代码测试的这么一个流程。
  • CD 对应多个英文名称:Continuous Deployment(持续部署)Continuous Delivery(持续交付)。可以理解为通过上一步的操作将生成部署包按照配置文件流程进行部署启动;

Q:什么是持续部署、交付?他有何作用?
答:先说说持续部署对于一个成熟的 CI/CD 的流程而言,代码变更经过编译、打包、测试之后的下一步就是部署环节。而持续交付一般是指,研发尽快地向客户交付,比如尽快实现功能上线,通过设计完善的 CI/CD 流程,一般可以实现持续交付的目标。

PS:对于上面提到的「持续」,可以理解为每完成一个完整的部分,就向下一个环节交付。


0x01 持续集成

1.GitLab-CI|Runner
1.1 基础介绍

Q:什么是GitLab-CI?
A:GitLab-CI是Gitlab官方提供的持续集成服务(GitLab8.0以后的版本是默认集成了GitLab-CI并默认启用的),它需要gitlab中配置注册runner,然后在仓库的根目录下新建.gitlab-ci.yml文件编写命令,并且在仓库的每次提交合并中将会触发构建;PS:当然还有其它的持续集成系统同样可以配合GitLab使用比如Jenkins主要针对于Java环境的项目,这里就不多说了;


Q:什么是GitLab-Runner?
A:GitLab-Runner就是一个用来执行软件集成脚本的,一般地GitLab-Runner是配合GitLab-CI进行使用的,GitLab里面的每一个工程都会定义一个属于这个工程的软件集成脚本,用来自动化地完成一些软件集成工作。当这个工程的仓库代码发生变动时,比如有人push了代码GitLab就会将这个变动通知GitLab-CI,此时GitLab-CI会找出与这个工程相关联的Runner,并通知这些Runner把代码更新到本地并执行预定义好的执行脚本。

示例:Runner就像一个个的工人,而GitLab-CI就是这些工人的一个管理中心,所有工人都要在GitLab-CI里面登记注册,并且表明自己是为哪个工程服务的。所以当相应的工程发生变化时 GitLab-CI就会通知相应的工人执行软件集成脚本的动作,如下图所示:

WeiyiGeek.GitLab-CI与Runner关系图

WeiyiGeek.GitLab-CI与Runner关系图

Q:GitLab-Runner分类两种类型说明?
两种类型指的是Shared Runner(共享型)和Specific Runner(指定型)

  • Shared Runner:是所有工程都能够用的并且只有系统管理员能够创建Shared Runner。
  • Specific Runner:这只能为指定的工程服务。拥有该工程访问权限的人都能够为该工程创建Shared Runner。


1.2 安装配置

GitLab-Runner安装配置此处有两种下载安装方式,这是由于考虑到国内的网络访问国外地址确实太慢而且容易下载失败,所以通常我们都是在国内的一些镜像源厂商处进行下载以及设置操作系统的更新源;

环境说明:

1
2
GitLab 服务器: 192.168.1.250 = gitlab.weiyigeek.top
Gitlab-Runner 服务器: 192.168.1.3

GitRunner安装配置流程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#方式1: GitLab官方安装脚本
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-ci-multi-runner/script.rpm.sh | sudo bash
yum install -y gitlab-ci-multi-runner
gitlab-ci-multi-runner register


#方式2:清华大学镜像站源进行安装Gitlab-Runner
cat > /etc/yum.repos.d/gitlab-runner.repo <<END
[gitlab-runner]
name=gitlab-runner
baseurl=https://mirrors.tuna.tsinghua.edu.cn/gitlab-runner/yum/el7
repo_gpgcheck=0
gpgcheck=0
enabled=1
gpgkey=https://packages.gitlab.com/gpg.key
END
sudo yum makecache
sudo yum list gitlab-runner --showduplicates #查看可安装版本
sudo yum install gitlab-runner -y
# 此处您可以安装指定版本 其中 12.3.5 即为指定的版本号
# yum install gitlab-runner-12.3.5-1.x86_64 -y

向GitLab-CI注册Runner流程如下:

  • Step1.由于向GitLab-CI注册一个Runner需要两样东西GitLab-CI的url和注册token所以我们首先需要在GitLab平台上得到该属性(管理中心->概览->Runner->手动设置SharedRunner);
    1
    2
    3
    4
    1.安装GitLab Runner
    2.在 Runner 设置时指定以下 URL: http://gitlab.weiyigeek.top/
    3.在安装过程中使用以下注册令牌: qupxfdPtuzCckymoSCUu
    4.启动 Runner!
  • Step2.在Gitlab-Runner 服务器中进行执行;
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    [[email protected] ~]$gitlab-runner register
    Runtime platform arch=amd64 os=linux pid=20709 revision=4c96e5ad version=12.9.0
    Running in system-mode.
    Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/):
    http://gitlab.weiyigeek.top/ #Gitlab地址
    Please enter the gitlab-ci token for this runner:
    qupxfdPtuzCckymoSCUu #gitlab-ci令牌
    Please enter the gitlab-ci description for this runner:
    [initiator]: TestRunner #Runner 描述
    Please enter the gitlab-ci tags for this runner (comma separated):
    TestRunner #Runner 标签
    Registering runner... succeeded runner=qupxfdPt #表示注册成功
    Please enter the executor: parallels, custom, docker, docker-ssh, docker+machine, docker-ssh+machine, kubernetes, shell, ssh, virtualbox:
    shell #执行方式
    Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!
  • Step3.注册完成之后GitLab-CI就会多出一条Runner记录,注意Type值有两种:shared 所有仓库都可以使用 / specific 只有指定的仓库可以使用 , 而type的类型由执行gitlab-runner register命令填入的token决定;
WeiyiGeek.

WeiyiGeek.

补充:不错当然您也可以在 /etc/gitlab-runner/config.toml 来注册相应类型的 Runner

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
$nano /etc/gitlab-runner/config.toml

#限制了整个GitLab Runner能并发处理job的数量
concurrent = 1
check_interval = 0

[session_server]
session_timeout = 1800

[[runners]]
name = "TestRunner"
url = "http://gitlab.weiyigeek.top/"
#注册生成的Runner 令牌
token = "5UmJ5uECw5k6H_phzeiW"
executor = "shell"
[runners.custom_build_dir]
[runners.cache]
[runners.cache.s3]
[runners.cache.gcs]

[[runners]]
name = "DockerRunner"
url = "http://gitlab.weiyigeek.top/"
token = "HrpstQA6eezWv5-9m5-d"
executor = "docker"
[runners.custom_build_dir]
[runners.cache]
[runners.cache.s3]
[runners.cache.gcs]
[runners.docker]
# 在这里需要添加上 harbor 的地址,才能允许 pull 私有 registry 的镜像
allowed_images = ["192.168.1.1/*:*"]
tls_verify = false
image = "alpine-node:latest"
privileged = false
disable_entrypoint_overwrite = false
oom_kill_disable = false
disable_cache = false
volumes = ["/cache"]
shm_size = 0

注意事项:

  • 1.特别注意concurrentworker数量无任何关系,所有worker的工作是受GitLab Runner控制的,如果concurrent值为1并且有一个worker已经在工作了,那么即使其他worker达到了可以工作的条件也只能“pending”。


1.3 命令参数

安装 Gitlab Runner 后有两个命令gitlab-ci-multi-runner和gitlab-runner,前者用于注册多个Runner而后者构建一个单实例runner;

gitlab-runner 命令参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
## 1.注册runner 会以引导的方式询问相关参数的设置-交互式
$gitlab-runner register

## 2.查看已经注册的runner
$gitlab-runner list
Runtime platform arch=amd64 os=linux pid=81864 revision=4c96e5ad version=12.9.0
Listing configured runners ConfigFile=/home/gitlab-runner/.gitlab-runner/config.toml

# 3.删除gitlab-runner相关配置
sudo gitlab-runner uninstall

# 4.安装并设置--user(例如设置为root)
sudo gitlab-runner install --working-directory /home/gitlab-runner --user root

# 5.临时采用root权限运行runner(坑多,在Gitlab-CI中由于采用的gitlab-runner用户常常操作文件时候提醒权限不足)
sudo gitlab-runner run

#6.将GitLab Runner安装为系统服务:
sudo gitlab-runner install -n "<service-name>" -u <user-name>

#7.启动服务
sudo gitlab-runner start -n "<service-name>"

GitLab Runner Commands 命令使用参考:https://docs.gitlab.com/runner/commands/README.html


1.4 基础使用

描述:假设我们在SecOpsDev项目中进行使用Gitlab-CI/CD,并且已经注册了Runner,管理中心->Runner->查看Runner标签:此处为TestRunner,然后点击编辑进行指派SecOpsDev项目;

WeiyiGeek.runnertags

WeiyiGeek.runnertags

(1)此时我们再在我们的SecOpsDev项目中建立一个.gitlab-ci.yaml文件,并且编写好后建议对其进行检测测试NewProject -> SecOpsDev -> CI Lint,示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#Path: secopsdev/.gitlab-ci.yml
#使用.gitlab-ci.yml配置你的项目,注意下面Tags是必须要指定的否则CI报错找不到Runner;
stages:
- test
- build
- deploy
#每次
before_script:
- echo "#Before script section" >> WeiyiGeek.txt
- echo "For example you might run an update here or install a build dependency"
- echo "Or perhaps you might print out some debugging details"

after_script:
- echo "#After script section" >> WeiyiGeek.txt
- echo "For example you might do some cleanup here"

test1:
stage: test
script:
- echo "(1) Do a test here - 正在进行代码测试 阶段1 "
- echo "For example run a test suite"
tags:
- TestRunner

test2:
stage: test
script:
- echo "(2) Do another parallel test here - 正在进行代码测试 阶段2 并行测试 "
- echo "For example run a lint test"
tags:
- TestRunner

build:
stage: build
script:
- echo "(3) Building the app - 正在对项目进行编译 "
tags:
- TestRunner

deploy:
stage: deploy
script:
- echo "(4) Deploy to staging server :" $url
- echo "(4) Deploy to staging server :" $(env)
environment:
name: staging
url: https://staging.weiyigeek.top
only:
- master
tags:
- TestRunner

WeiyiGeek.gitlab-ci.yaml

WeiyiGeek.gitlab-ci.yaml

(2)之后我们会在项目中的 CI-CD -> 流水线 | 作业 进行查看执行结果;

WeiyiGeek.流水线

WeiyiGeek.流水线

(3)Gitlab-CI执行详情结果:

WeiyiGeek.作业详情

WeiyiGeek.作业详情

(4)除此之外我们还可对CI/CD环境变量进行设置,并且运行到Runner环境中,设置路径如下: NewProject -> SecOpsDev -> CI/CD 设置 -> Expand (展开),然后重新执行deploy阶段在作业进行查看显示如下图所示;

WeiyiGeek.环境变量

WeiyiGeek.环境变量

(5)拉取的code会在Gitlab-Runner主机中,安装以下路径进行存放/home/gitlab-runner/builds/5UmJ5uEC/0/newproject/secopsdev/.git/

补充说明:

  • GitLab CI有三个默认阶段:1构建(build)、2测试(test)、3部署(deploy),我们将有一篇文章进行详细讲解。
  • Runner可以分布在不同的主机上,同一个主机上也可以有多个Runner。


1.5 Executor

下面我们来谈谈一个非常重要的话题Executor,上面我们在向gitlab-ci注册runner需要我们输入Executor;

1
Please enter the executor: parallels, custom, docker, docker-ssh, docker+machine, docker-ssh+machine, kubernetes, shell, ssh, virtualbox:

Shell Executor
描述:以宿主机(此处为Centos7系统)作为Runner(版本:12.9.0)的所有jobs的执行器。
Runner将会从远程仓库pull你的工程,工程的目录为:<working-directory>/builds/<short-token>/<concurrent-id>/<namespace>/<project-name>,如果你使用了cache,那么cache将会存在<working-directory>/cache/<namespace>/<project-name>

1
2
3
4
5
#Repo
/home/gitlab-runner/builds/5UmJ5uEC/0/WeiyiGeek/blog

#Cache
/home/gitlab-runner/cache/WeiyiGeek/blog

参考:https://docs.gitlab.com/runner/executors/shell.html


Docker Executor
描述:所有jobs的执行环境为指定的docker image所生成的container,每个job都会生成一个container并且在job结束后立即销毁。

  • - build和cache的存储

    Docker executor默认将所有的builds存储在/builds//(这里的路径是container里的路径,Runner配置文件config.toml里的build_dir字段可以重新指明build的目录,默认对应于宿主机的目录是在宿主机的docker volume下:/var/lib/docker/volumes//_data/),默认将所有的caches存储在container里的/cache目录(config.toml里的cache_dir字段可以重新指明cache的目录),注意build_dircache_dir指向的均是container里的目录,要想将container里的数据持久化,需要用到volumes字段,这个字段的使用和docker volume的使用是类似的,只需在config.toml[runner.docker]部分添加volumes = ["/cache", ":rw"]即可实现container里/cache目录数据的永久保存以及将host目录挂载到相应的container目录并具有读写的功能。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    [runners.custom_build_dir]
    [runners.cache]
    [runners.cache.s3]
    [runners.cache.gcs]
    [runners.docker]
    # 在这里需要添加上 harbor 的地址,才能允许 pull 私有 registry 的镜像
    allowed_images = ["192.168.1.1/*:*"]
    tls_verify = false
    image = "alpine-node:latest"
    privileged = false
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    volumes = ["/cache"]
    shm_size = 0
  • Pull policies

    当你使用dockerdocker+machine executors时,你可以通过设置pull_policy来决定Runner如何pull docker image。pull_policy有三种值:
    always —— Runner始终从远程pull docker image。
    if-not-present —— Runner会首先检查本地是否有该image,如果有则用本地的,如果没有则从远程拉取。
    never —— Runner始终使用本地的image。

  • Helper image

    当你使用docker, docker+machinekubernetes作为executor时,GitLab Runner将会使用特定的container来处理Git、artifacts 和cache 操作。通过在宿主机中键入以下命令:

    1
    2
    3
    4
    $ sudo docker images
    REPOSITORY TAG
    gitlab/gitlab-runner-helper x86_64-3afdaba6
    gitlab/gitlab-runner-helper x86_64-cf91d5e1

    当然,你也可以通过配置config.toml里的helper_image字段来让Runner使用你自己定制化的helper image。

Q:如何在job所对应的container里使用git clone命令?

答: 如果你想在job运行期间clone某些代码(如shell或python的脚本),首先要确保你的宿主机有权限clone代码,然后你就可以将你的secret挂载到container里

例如,你是通过ssh的方式克隆代码,并且你的ssh目录为home//.ssh,你就可以在config.toml文件里添加如下配置:

1
volumes = ["/home/x1twbm/.ssh:/root/.ssh:ro"]


1.6 缓存使用

该章节主要针对于Gitlab CI/CD 中的 Cache 两种机制进行学习和说明;

  • cache
  • artifacts

Q:为何要使用 Cache?它有什么目的?
A:在GitLab CI/CD 中在 pipeline 中的一些 job 可能会产生一些结果文件,Cache 机制的引入就是为了加快 job 执行的时间。Cache 在使用时制定一系列的文件或者文件目录,使得其在不同的 job 之间被缓存下来。这样当某一个 job 需要依赖于之前步骤产生的一些文件结果,Cache 就帮助我们在上一个 job 将产生的结果缓存下来并且在当前的 job 进行使用。


(1)Cache
描述:首先 cache 的定义范围可以全局定义即所有的 job 都会采用这个全局定义的 cache 设置, 当然每个 job 内也可以定义自己特有的 cache 来覆盖全局的配置
Cache 在使用上主要的配置有以下几种:

  • paths: 指定需要被缓存的文件路径(项目相对路径)
  • key: 在cache中不同 job 定义了不同的 key 时, 每个 job 都会有一个独立的 cache,不同的 key 下的缓存也不会相互影响,当 cache:key 结合 GitLab CI/CD 中预定义的参数可以有不同的效果,当 key 没有被特别定义的时候,默认为 default,所有没定义 key 的 cache 使用的是同一份 cache,会随着 job 的执行一直被覆盖;
  • policy: 如果有 cache 的配置此时每个 job 会在开始执行前将对应路径的文件下载下来,并在任务结束前重新上传,不管文件是否有变化都会如此操作(默认的配置 cache:policy为 pull-push 策略);但是如果我们已经知道某个 job 只是使用的其他 job 改变的文件,自身并无改变对应路径的文件,那么就不需要进行文件上传操作采用pull 策略即可,这样做的好处减少了不必要的操作,在一定程度上节约了时间

Q:如何进行 cache 继承?
答:如果在使用中有 job 大部分配置跟全局配置是一样的,但是部分不同,就可以采用继承的方式,而不必全部重写实际上类似于别名一样进行函数调用一样,首先需在cahe全局缓存中设置&global_cache,然后再job中进行调用击即可<<: *global_cache;

Q:如何禁用某个Job的Cache操作?
答:如果整个 pipeline 配置全局的 cache,意味着每个 job 在没有特殊配置的情况下会使用全局的配置。但是如果某某个 job 并不使用到 cache,包括缓存文件的上传和下载,那么可以进行如下配置对整个 job 的 cache 禁用,再job中配置cache: {}即不会收到全局缓存的影响:

Cache在runner中缓存的物理路径:

1
2
/home/gitlab-runner/cache/gitlab用户/项目名称/cache.zip
/home/gitlab-runner/cache/WeiyiGeek/blog/cache.zip

参数说明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#全局缓存 global_cache
cache: &global_cache
key: ${CI_JOB_NAME} #结合 GitLab CI/CD 中预定义的参数有不同的效果
# 缓存 node_modules/目录 下次构建不会删除
paths:
- node_modules/
policy: pull-push #默认对缓存文件进行拉取与更新

#局部缓存 local_cache
local_cache:
stage: build
cache: #如果在 job 内部也定义了 cache 配置,全局的配置就会被覆盖
key: ${CI_JOB_NAME}
policy: pull #使用了pull 策略不会在 job 结束后进行文件的上传操作
paths:
- node_modules/
- binaries/*.apk #在binaries 目录下以 .apk 结尾的所有文件以及 .config 文件会被缓存下来。

#Cache 的继承
inherit_cache:
cache:
# 继承全局配置
<<: *global_cache
# 仅覆盖 cache:policy 的配置
policy: pull


# Cache 的禁用
disable_cache
cache: {}

分布式 Cache 在 GitLab CI/CD 中,我们所使用的 runner 是以 docker 的形式运行不同的任务。普通的 cache 机制,其 cache 均存储在本地,所有如果两个 job 实际运行的位置是在不用宿主机上,其相互之间的缓存是无法共享的。

为了实现分布式 Cache,需要在配置 GitLab Runner 的 config.toml 的 [runners.cache]进行如下配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
[[runners]]
limit = 10
executor = "docker"
[runners.cache]
Type = "s3"
Path = "path/to/prefix"
Shared = true
[runners.cache.s3]
ServerAddress = "s3.example.com"
AccessKey = "access-key"
SecretKey = "secret-key"
BucketName = "runner"
Insecure = false

在以上的配置中,对应的 cache 的存储路径如下:http(s)://<ServerAddress>/<BucketName>/<Path>/project/<id>/<cache-key>,在配置,对应的存储 cache 服务器需要满足 s3 协议,当然也可以自建 cache 服务器

Cache 小实践:
(1).gitlab-ci.yml 配置以下配置中 job1 和 job3 使用了全局的 cache 配置,job2 独立定义了 cache 配置使用了 pull 策略

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
stages:
- test1
- test2
- test3

cache:
key: "$CI_COMMIT_REF_SLUG"
paths:
- Test.txt

job1:
stage: test1
script:
- cat Test.txt
- echo "aaaaaaaaaa" > Test.txt
- cat Test.txt
tags:
- base-runner

job2:
stage: test2
cache:
key: "$CI_COMMIT_REF_SLUG"
paths:
- Test.txt
policy: pull #关注点
script:
- cat Test.txt
- echo "bbbbbbbbbbb" >> Test.txt
- cat Test.txt
tags:
- base-runner

job3:
stage: test3
script:
- ls
- cat Test.txt
- echo "cccccccc" >> Test.txt
- cat Test.txt
tags:
- base-runner

(2) 执行结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#job1 结果
Checking cache for test-wer-1...
#首次检查缓存未存在进行创建缓存
$ echo "aaaaaaaaaa" > Test.txt
$ cat Test.txt
aaaaaaaaaa
Creating cache test-wer-1...
Test.txt: found 1 matching files
Uploading cache.zip to http://192.168.12.139:9000/runner/cache-path/project/1242/test-wer-1 #上传 cache 路径
Created cache
Job succeeded


#job2 结果
Checking cache for test-wer-1...
cache.zip is up to date #缓存进行了下载
Successfully extracted cache
$ cat Test.txt
aaaaaaaaaa
$ echo "bbbbbbbbbb" >> Test.txt
$ cat Test.txt
aaaaaaaaaa
bbb
Not uploading cache test-wer-1 due to policy # pull策略不上传缓存
Job succeeded


#job3 结果
Checking cache for test-wer-1...
cache.zip is up to date
Successfully extracted cache
$ cat Test.txt
aaaaaaaaaa
$ echo "ccccccccc" >> Test.txt
$ cat Test.txt
aaaaaaaaaa
ccccccccc
Creating cache test-wer-1...
Test.txt: found 1 matching files
22.txt: found 1 matching files
Uploading cache.zip to http://192.168.12.139:9000/runner/cache-path/project/1242/test-wer-1 #上传 cache 路径
Created cache
Job succeeded

总结:

  • job2 获取到缓存文件 Test.txt 的文件内容是 job1 执行后的结果,说明 job1 和 job2 之间实现了缓存共享
  • job3 获取到缓存文件 Test.txt 的文件与 job1 执行后内容一致而非 job2,这是因为 job2 执行后的结果没有进行上传
  • 特别注意的是 job1 在执行任务前获取到的 Test.txt 的文件与 job3 执行完的结果一致,这是因为这个 pipeline 我运行了多次,job1 获取的缓存是上一次 pipeline 中 job3 的执行后的缓存结果。说明 cache 在不同次 pipeline 之间也实现了共享


1.7 入坑问题解决

问题1.向Gitlab-CI进行注册Runner时候提示Failed to register this runner. Perhaps you are having network problems
问题关键字:

1
2
ERROR: Registering runner... failed runner=qRGh2M86 status=500 Internal Server Error
PANIC: Failed to register this runner. Perhaps you are having network problems

原因:因为 Gitlab 默认禁止了私有网段 IP 里的 API 请求,需要手动开启才行。
解决办法: 修改 gitlab 默认网络设置 或者 白名单以允许来自钩子和服务的对本地网络的请求(线上环境推荐)。
1
2
3
4
5
#此处以第一种方式为列
使用 root 用户从 web 端登录到 gitlab 管理中心 http://${ip}/admin 。管理中心 --> 设置 --> 网络 –> 外发请求
#设置如下
* 勾选 允许Webhook和服务对本地网络的请求
* 勾选 允许系统钩子向本地网络发送的请求

  • 补充 [2020年4月17日 22:53:44] 时间:

    如果点击 保存修改 之后就跳转到 Gitlab 500 错误的页面。
    尝试在管理中心修改其他设置保存时,也会出现 500 的情况。
    在安装 gitlab 的机器上查看一下日志。运行 gitlab-ctl tail 查看实时的日志。
    此时等到日志输出减慢的时候我们多按几下回车,然后就立即去点击 保存修改 按钮,这样就能捕捉到此刻的错误日志。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
==> /var/log/gitlab/gitlab-rails/production.log <==
Started PATCH "/admin/application_settings/network" for 10.0.30.2 at 2020-03-10 11:08:20 +0000
Processing by Admin::ApplicationSettingsController#network as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"[FILTERED]", "application_setting"=>
{"allow_local_requests_from_web_hooks_and_services"=>"[FILTERED]",
"allow_local_requests_from_system_hooks"=>"[FILTERED]", "outbound_local_requests_whitelist_raw"=>"",
"dns_rebinding_protection_enabled"=>"1"}}
Completed 500 Internal Server Error in 40ms (ActiveRecord: 14.5ms | Elasticsearch: 0.0ms)
OpenSSL::Cipher::CipherError ():
lib/gitlab/crypto_helper.rb:27:in `aes256_gcm_decrypt'
==> /var/log/gitlab/gitlab-rails/production_json.log <==
{"method":"PATCH","path":"/admin/application_settings/network","format":"html","controller":"Admin::
ApplicationSettingsController","action":"network","status":500,"error":"OpenSSL::Cipher::CipherError
: ","duration":40.08,"view":0.0,"db":14.47,"time":"2020-03-10T11:08:20.061Z","params":
[{"key":"utf8","value":"✓"},{"key":"_method","value":"patch"},{"key":"authenticity_token","value":"
[FILTERED]"},{"key":"application_setting","value":
{"allow_local_requests_from_web_hooks_and_services":"
[FILTERED]","allow_local_requests_from_system_hooks":"
[FILTERED]","outbound_local_requests_whitelist_raw":"","dns_rebinding_protection_enabled":"1"}}],"re
mote_ip":"10.0.30.2","user_id":1,"username":"root","ua":"Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87
Safari/537.36","queue_duration":2.55,"correlation_id":"9rvflpksdj2"}

错误关键信息: OpenSSL::Cipher::CipherError ():
错误原因: 应该是重新安装 Gitlab 之后的加密信息不对所致 或者 由于迁移导入项目后,没有导入原来的加密信息 /etc/gitlab/gitlab-secrets.json , 但是原来的加密信息文件我已经找不到了,后面发现可以直接重置就行了;
解决办法:

1
2
3
4
5
6
7
8
9
10
11
12
#命令行输入 gitlab-rails console ,然后输入ApplicationSetting.current reset_runners_registration_token! 即可,这样在保存修改的时候就不会再报 500的问题了。
╭─[email protected] ~
╰─# gitlab-rails console
--------------------------------------------------------------------------------
GitLab: 12.3.5 (2417d5becc7)
GitLab Shell: 10.0.0
PostgreSQL: 10.9
--------------------------------------------------------------------------------
Loading production environment (Rails 5.2.3)
irb(main):001:0> ApplicationSetting.current.reset_runners_registration_token!
=> true
irb(main):002:0> exit


  • 补充 [2020年3月14日 21:31:04] 时间:
    报错信息:
    1
    ERROR: Registering runner... failed runner=xxxxxxx status=couldn't execute POST against https://x.x.x.x/api/v4/runners: Post https://x.x.x.x/api/v4/runners: x509: cannot validate certificate for x.x.x.x because it doesn't contain any IP SANs
    原因:gitlab使用自签名证书时,注册时需要使用对应的ca根证书验证。
    解决方案:注册时也需要使用"--tls-ca-file"参数,指定自签名的ca根证书。


问题2.项目进行运行Gitlab-CI流水线上的时候报错:此作业被卡住,因为没有任何该项目指定标签的 runner 在线`
原因:由于我们再写用.gitlab-ci.yml配置时候未在各个阶段下加入指定的Runner标签;
解决办法1:

1
2
3
4
5
6
build:
stage: build
script: echo "Building the app"
#告诉 Runner 我们应用哪个标签
tags:
- TestRunner

解决方法2:运行未标记的作业进行勾选指示此runner是否可以选择无标记的作业,此时gitlab-ci.yaml将可以不用设置tags标签;

  • 补充 [2020年3月14日 21:31:04] 时间:
    报错信息:Post https://x.x.x.x/api/v4/runners: x509: certificate signed by unknown authority
    原因:注册runner时,如果设置了”–tag-list”,则”–run-untagged”默认为”false”,同时间.gitlab-ci.yml中的job未指定tag触发此报错。
    解决方案:注册时,”–run-untagged”参数设置为”true”;或者在已注册的runner中修改勾选" Indicates whether this runner can pick jobs without tags"或者.gitlab-ci.yml中的job指定tag。


问题3.Runner采用docker作为executor时,无法build docker image 提示dial unix /var/run/docker.sock: connect: permission denied
原因:gitlab-runner账号权限不足,不能访问/var/run/docker.sock。
解决方案:

1
2
3
4
5
6
#1.将gitlab-runner用户加入docker组
$usermod -aG docker gitlab-runner

#2.gitlab-runner加入的组出现docker即没问题
$groups gitlab-runner
gitlab-runner : gitlab-runner docker


问题4.Peer’s Certificate issuer is not recognized.
报错信息:fatal: unable to access 'https://gitlab-ci-token:[email protected]/root/cmop.git/': Peer's Certificate issuer is not recognized.
原因:gitlab-runner拉取代码时,使用https协议访问gitlab,需要验证。
解决方案:

1
2
3
4
5
6
7
#因runner运行时的执行者是gitlab-runner账户,需要在gitlab-runner账号下设置访问https类网站时,免验证
[[email protected] ~]# su - gitlab-runner
[[email protected] ~]$ git config --global http."sslVerify" false
#查看
[[email protected] ~]$ cat /home/gitlab-runner/.gitconfig
[http]
sslVerify = false


问题5. Couldn’t resolve host ‘gitlab.x.com’, 出现Runner无法连接网络的问题
报错信息:fatal: unable to access 'https://gitlab-ci-token:[email protected]/root/cmop.git/': Couldn't resolve host 'gitlab.x.com'
原因:executor = “docker”时,执行环境是1个容器,由于验证用的gitlab域名不能被dns解析,导致无法连接。
解决方案:

问题6.当我的Runner采用docker作为executor时,无法build docker image

信息错误:

1
2
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
time="2020-04-17T11:12:33Z" level=error msg="failed to dial gRPC: cannot connect to the Docker daemon. Is 'docker daemon' running on this host?: dial unix

这是个“dind(docker in docker)” 问题你可以将本地的docker socket绑定到container里来解决这个问题,具体方法是将volumes = ["/var/run/docker.sock:/var/run/docker.sock"]配置到config.toml文件里。


2.Drone

drone 英 /drəʊn/翻译为无人机(非正式);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
如何实现与gitlab互联

基于 Docker 的 CI/CD 工具 Drone 所有编译、测试的流程都在 Docker 容器中进行。

开发者只需在项目中包含 .drone.yml 文件,将代码推送到 git 仓库,Drone 就能够自动化的进行编译、测试、发布。

本文仅记录 Drone是如何跟Gitlab打通的过程。

由于Drone是基础Docker方式运行,所以需要有一个Docker环境。关于如何安装部署Docker这里就不细说了。

前要说明
由于drone 1.x版本跟0.8版本的变化也挻多,有些旧的参数已经弃用或者变更了,详细情况要参考官方文档。https://docs.drone.io/

1、配置gitlab applications:

登陆到Gitlab系统点击个人头像—-Settings—-Applications添加一个应用:
这里是一个变化,0.8版Redirect URL后面是跟:authorize ,而1.X版本使用:login

提交后就会自动生成以下ID和Key:

2、首先要拉取一个drone镜像:
通过docker search drone 可以看到很多相关的镜像,这里拉取第一个官方的镜像,大约63M左右,因为官方镜像也已经更新到了1.X版本,所以直接docker pull drone/drone就是1.X版的。

[[email protected] ~]# docker pull drone/drone
[[email protected] ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
helloworld latest 232ac0d24f85 21 hours ago 6.96MB
plugins/base multiarch 92bf59f52f26 23 hours ago 293kB
drone/drone latest 16646fab2afb 4 days ago 63.2MB

3、启动Drone服务

以下配置直接使用官网给出的示例;可以看到1.X版本跟之前的0.8版本有些地方,参数也有变化,以下这个配置是单机版的,就是server和agnet都整合运行在同一机器上,这个适合测试环境,或者使用量比较小的环境下。

docker run \
--volume=/var/run/docker.sock:/var/run/docker.sock \
--volume=/var/lib/drone:/data \
--env=DRONE_LOGS_DEBUG=true \
--env=DRONE_GIT_ALWAYS_AUTH=false \
--env=DRONE_GITLAB_SERVER=http://10.0.10.8 \
--env=DRONE_GITLAB_CLIENT_ID=09cb3f3bbdc607060f1fdb71b51e4a9e4db4c576955763a1a4efec078edf2d6b \
--env=DRONE_GITLAB_CLIENT_SECRET=8360a4e0d5697127f3e8a77440e884c3b0b93375c563cfaa407074d8b231c159 \
--env=DRONE_RUNNER_CAPACITY=3 \
--env=DRONE_SERVER_HOST=10.0.10.68 \
--env=DRONE_SERVER_PROTO=http \
--env=DRONE_TLS_AUTOCERT=false \
--publish=80:80 \
--publish=443:443 \
--restart=always \
--detach=true \
--name=drone \
drone/drone:latest

说明:

DRONE_GITLAB_SERVER :修改自己的gitlab仓库地址
DRONE_GITLAB_CLIENT_ID : 这个是在Gitlab里边配置的可参考上图
DRONE_GITLAB_CLIENT_SECRET : 同上当在gitlab中配置了一个applications就会自动生成ID,和SECRET
DRONE_SERVER_HOST :drone服务运行的Ip地址
DRONE_SERVER_PROTO :走哪种协议,这里直接使用http 即可,如果是外网能够访问的建议https.
DRONE_LOGS_DEBUG=true :开启Debug日志

当启动完Drone容器后再打开浏览器访问:http://10.0.10.68就会跳转到Gitlab页面,然后会提示授权。

授权完成后又会回到drone的界面了,如果Gitlab上有项目的就会把项目的信息同步过来。

至此,drone就可以实现Gitlab的连通了。

特别提醒

错误提示:

Login Failed. invalid character '<' looking for beginning of value

使用1.x版本的drone配置旧版本的gitlab(8.8.X)时遇到了一个错误,最后更新了gitlab版本到11.X后才能正常回调到drone的登陆页面。