GitLab Runner
是一个开源项目,用于运行您的作业并将结果发送回GitLab
。它与GitLab CI
一起使用,GitLab CI
是GitLab
随附的开源持续集成服务,用于协调作业。
shared
:运行整个平台项目的作业(gitlab
)
group
:运行特定group
下的所有项目的作业(group
)
specific
:运行指定的项目作业(project
)
locked
:无法运行项目作业
paused
:不会运行作业
由于服务都进行了容器化,所以,我们的gitlab-runner也是用docker容器来运行的。
想要在CI/CD中使用Docker命令,你可以通过如下三种方式进行:
第一种,通过shell execotor可以不必将你的gitlab-runner以docker的方式运行,同时,需要你将gitlab-runner加入到docker组,这样gitlab-runner就可以执行docker的命令了。
第二种,Docker in Docker的方式需要docker container获取privilege的权限。他的含义是①executor的类型是docker②runner通过docker提供的镜像来执行docker命令。dockers镜像需要拥有所有的docker工具,并且以privilege的模式在镜像的上下文中执行docker命令。
在这种模式下官方推荐需要使用TLS,查看:GitLab.com shared runners.
第三种,可以不用priviledge
的方式,就是Docker socket binding
的方式。这种方式是通过将宿主机 /var/run/docker.sock
挂载到容器的 /var/run/docker.sock
上,这样,gitlab-runner
中执行的docker
命令最终会在宿主机上的docker daemon
中执行。
我们这篇文章也主要是介绍这种方式。
首先,我们通过gitlab-runner
的docker
镜像运行gitlab-runner
:
docker run -itd --restart=always --name gitlab-runner \
-v /data/gitlab-runner/config:/etc/gitlab-runner \
-v /var/run/docker.sock:/var/run/docker.sock \
gitlab/gitlab-runner:latest
在上面的命令中, 我们进行了两处挂载:
-v /data/gitlab-runne/config:/etc/gitlab-runner
:这个挂载是将gitlab-runner
的配置文件挂载到宿主机上,这样我们可以通过修改宿主机上的这个配置文件对gitlab-runner
进行配置
-v /var/run/docker.sock:/var/run/docker.sock
:这个挂载是将宿主机上的docker socket
挂载到了容器内,这样容器内执行的docker
命令会被宿主机docker daemon
最终执行。
当容器运行后,我们需要将这个runner
注册到gitlab
的ci/cd
上,runner
有几种类型,我们这里选择针对单个项目的runner
,在gitlab
页面选择相关的项目,左侧菜单栏选择settings
->CI/CD
,进入页面,点击Runners
的Expand
按钮,进入到如下页面:
左侧的Specific runners
下面有俩个重要的信息,一个是URL
,就是gitlab
的url
,另一个是token
,我们获取到这两个信息后,通过如下命令进入到要注册的runner
的容器内部:
#gitlab-runner是运行的容器的名称
docker exec -it gitlab-runner bash
在容器内部,我们执行如下命令:
gitlab-runner register
这个命令会进入一个流程,让你相继输入如下信息:
URL
:gitlab
给你的url
,从前面那一步获取的token
:gitlab
给你的token
,从前面那一步获取的executor
的类型:这里选择输入docker
image
:一个包含了docker
工具命令的镜像,runner
会利用这个镜像执行docker
命令,这里我填写的是docker:23.0.1
(不过由于我们使用的是Docker socket binding
的方式,所以不会使用这个镜像的docker
工具,输入的docker
命令会直接在宿主机上的docker daemon
中执行)tags
:这个信息很重要,是gitlab pipeline job
选择runner
的标志。此外还要填写描述信息等,这些根据情况填写就行了。
无交互式注册可以在容器外部通过docker命令进行:
docker run --rm -v /data/gitlab-runner/config:/etc/gitlab-runner gitlab/gitlab-runner register \
--non-interactive \
--executor "docker" \
--docker-image alpine:latest \
--url "http://192.168.220.20:1180/" \
--registration-token "_HSstx8BzrWbLfo8n8XB" \
--description "test" \
--tag-list "test" \
--run-untagged="true" \
--locked="false" \
--access-level="not_protected"
docker run --rm -v /data/gitlab-runner/config:/etc/gitlab-runner gitlab-runner register
:使用 docker run
命令运行一个 gitlab-runner register
命令,该命令用于在 GitLab Runner 上注册一个新的 runner。
--rm
选项表示在容器退出时,自动清除挂载的卷。在Docker容器退出时,默认容器内部的文件系统仍然被保留,以方便调试并保留用户数据。因此,可以通过--rm
命令,让容器在退出时,自动清除挂在的卷,以便清除数据。
-v /data/gitlab-runner/config:/etc/gitlab-runner
选项将主机上的 /data/gitlab-runner/config
目录挂载到容器中的 /etc/gitlab-runner
目录。
--non-interactive
:以非交互模式运行,不会提示用户输入。
--executor "docker"
:指定使用 docker
执行器。
--docker-image alpine:latest
:指定使用 alpine:latest
镜像,因为alpine:latest镜像十分的轻量。
--url "http://192.168.220.20:1180/"
:指定 GitLab 实例的 URL。
--registration-token "_HSstx8BzrWbLfo8n8XB"
:指定用于注册 runner 的注册令牌。
--description "test"
:为 runner 指定描述。
--tag-list "rouyi-runner,vue3"
:为 runner 指定标签,可以指定多个用‘,’隔开。
--run-untagged="true"
:允许 runner 运行未标记的作业。
--locked="false"
:指定 runner 不被锁定。
--access-level="not_protected"
:指定 runner 可以访问未受保护的作业。
用以上任意一种方法注册完成后,你的gitlab
项目中就会出现类似下图的runner
了:
这个时候,我们还需要注意两个配置的地方:
这个文件已经通过挂载的方式出现在我们宿主机上的挂载目录中,比如我的gitlab-runner
的挂载目录就是 /data/gitlab-runner/config
(前面我们运行gitlab-runner
的时候指定的)。
这时使用流水线测试发现gitlab-runner
中执行docker
命令失败,没能在宿主机上的docker daemon
中执行。
这需要我们在宿主机上编辑这个目录下的config.toml
,然后重启gitlab-runner
服务就行。基本上,我们执行gitlab-runner register
执行注册之后,还是需要编辑一下这个文件来实现宿主机和gitlab-runner容器的docker.sock挂载连接、gitlab实例的URL访问地址和两个镜像拉取策略 ,目前我的这个文件的结构如下:
#config.toml
concurrent = 1
check_interval = 0
[session_server]
session_timeout = 1800
[[runners]]
name = "first-register-runner"
url = "http://192.168.220.20:1180/"
#如果GitLab实例的URL无法被Runner使用,你可以配置一个clone_url。
#例如,防火墙可能会阻止Runner访问URL。如果Runner可以访问IP地址为192.168.1.23的节点,则将clone_url设置为http://192.168.1.23。
#这样,Runner就可以通过防火墙了
clone_url = "http://192.168.220.20:1180/" #添加了这行
token = "Qags9AEyCbKLHHdZ1a5r"
executor = "docker"
[runners.custom_build_dir]
[runners.cache]
[runners.cache.s3]
[runners.cache.gcs]
[runners.cache.azure]
[runners.docker]
tls_verify = false
image = "alpine:latest"
privileged = false
disable_entrypoint_overwrite = false
oom_kill_disable = false
disable_cache = false
#allowed_pull_policies 和 pull_policy 是GitLab Runner的配置文件config.toml中的两个参数。
allowed_pull_policies = ["if-not-present"] #添加了这行
#allowed_pull_policies 参数指定了允许的镜像拉取策略, pull_policy 参数指定了镜像拉取策略。
pull_policy = ["if-not-present"] #添加了这行
#在这种情况下,它们都被设置为“if-not-present”,这意味着如果本地没有镜像,则拉取镜像。
volumes = ["/var/run/docker.sock:/var/run/docker.sock","/cache"] #编辑了这行
shm_size = 0
上面需要添加/编辑的内容已经上面用#号标出
这个文件的产物就是一个pipeline
。pipeline
描述了gitlab
上某个项目的CI/CD
流程,pipeline
会在代码提交、代码合并之后触发运行(当然你也可以手动触发它)。他涵盖的概念也很多,基本结构是:
1、stages
,这个字段标志了这个pipeline
包含几个阶段。每个stage
可以包含多个job
,同一个stage
的job
可以并行执行。
2、job
,job
的名字可以自定义,每个job
里面可以包含多个执行脚本。
下面来看一下我的这个示例文件的结构:
stages:
- docker_image
- deploy
build-job: # This job runs in the build stage, which runs first.
stage: docker_image
tags:
- image_builder
- docker_image
script:
- cd Bt.Financing
- docker build -t xxx.xxx.xxx:9050/wallee/financing:latest .
- docker push xxx.xxx.xxx:9050/wallee/financing:latest
- docker rmi xxx.xxx.xxx:9050/wallee/financing:latest
deploy-job1: # This job runs in the deploy stage.
stage: deploy # It only runs when *both* jobs in the test stage complete successfully.
tags:
- docker_runner
script:
- docker stop financing
- docker rm financing
- docker rmi xxx.xxx.xxx:9050/wallee/financing:latest
- docker pull xxx.xxx.xxx:9050/wallee/financing:latest
- docker run -d -p 5008:5008 --name financing -v $HOME/Logs/financing:/app/Logs xxx.xxx.xxx:9050/wallee/financing:latest
deploy-job2: # This job runs in the deploy stage.
stage: deploy # It only runs when *both* jobs in the test stage complete successfully.
tags:
- docker_runner
script:
- docker stop financing
- docker rm financing
- docker rmi xxx.xxx.xxx:9050/wallee/financing:latest
- docker pull xxx.xxx.xxx:9050/wallee/financing:latest
- docker run -d -p 5008:5008 --name financing -v $HOME/Logs/financing:/app/Logs xxx.xxx.xxx:9050/wallee/financing:latest
那基本上到这一步,你的一个初步的gitlab的CI/CD就完成了。