Skip to main content
☘️ Septvean's Documents
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

GitLab Runner 部署

服务器:

  • 192.168.101.201:GitLab CE
  • 192.168.101.202:GitLab Runner
  • 192.168.101.203:GitLab Runner

GitLab Runner 核心认知(先搞清楚)

GitLab / Runner / CI 的关系

.gitlab-ci.yml
GitLab(调度)
GitLab Runner(执行)
Executor(shell / docker / k8s)

⚠️ Runner ≠ GitLab

  • Runner 是“工人”
  • 可以部署在任意机器
  • 可以多个 Runner 对一个 GitLab

部署方式选择(重要)

Executor 场景 是否推荐
shell 简单 ❌ (污染宿主机)
docker 最常用
docker+machine 已淘汰
kubernetes 大规模
ssh 少见

👉 本文使用 shell executor + docker executor

宿主机是 AlmaLinux 9,使用 podman 代替 docker,使用 docker executor 部署,运行 docker 命令会报错

podman exec -it gitlab-runner docker version
/usr/bin/podman: error while loading shared libraries: libsubid.so.3: cannot open shared object file: No such file or directory

所以主要以 shell executor 部署。


Shell executor

下载 RPM 包

访问官网 https://packages.gitlab.com/runner/gitlab-runner

搜索 18.7.2,Distribution:el/9

找到 RPM 包:

  • gitlab-runner-18.7.2-1.x86_64.rpm
  • gitlab-runner-helper-images-18.7.2-1.noarch.rpm

点击上面的两个 RPM 的连接,然后点击右上角的 Download 下载 RPM 包

将这两个 RPM 包上传到服务器,保存:

  • 服务器:192.168.101.200
  • 路径:/data/files/rpms/gitlab-runner/18.7.2

安装 RPM 包

将 RPM 上传到服务器 192.168.101.202 和 192.168.101.203

安装或更新:

dnf install -y ./gitlab-runner-*.rpm

Docker executor

Docker 目录规划(强烈建议)

/data/gitlab-runner/
├── cache/      # CI 缓存
├── compose/    # docker-compose
└── config/     # Runner 配置
mkdir -p /data/gitlab-runner/{cache,compose,config}

docker-compose.yaml(核心)

文件:/data/gitlab-runner/compose/docker-compose.yaml

version: "3"

services:
  gitlab-runner:
    image: gitlab/gitlab-runner:v18.7.2
    container_name: gitlab-runner
    restart: always

    volumes:
      - /data/gitlab-runner/cache:/cache
      - /data/gitlab-runner/config:/etc/gitlab-runner
      - /var/run/docker.sock:/var/run/docker.sock

绑定 /var/run/docker.sockdocker executor 的关键

⚠️ 注意:挂载了 /var/run/docker.sock,使 Runner 可以直接利用宿主机的 Docker 守护进程,这是最常用的方式;若需更高的隔离性,可考虑 Docker-in-Docker。

启动 Runner 容器

# 拉取镜像
HTTP_PROXY=http://192.168.101.200:1080 HTTPS_PROXY=http://192.168.101.200:1080 podman pull gitlab/gitlab-runner:v18.7.2

# 启动
cd /data/gitlab-runner/compose
podman-compose up -d

检查:

podman ps

podman logs -f gitlab-runner

# 首次启动,报以下错误是正常的
# ERROR: Failed to load config stat /etc/gitlab-runner/config.toml: no such file or directory  builds=0 max_builds=1

注册 GitLab Runner(重点)

进入 CI/CD 配置页面

创建 Runner

Admin area -> CI/CD -> Runners -> Create instance runner

填写标签:

  • 如果用 RPM 包部署,建议使用 linux 标签
  • 如果用 Docker 容器部署,建议使用 docker 标签

创建完成之后,会给出提示:

注册 Runner

运行命令:

  • 服务器:192.168.101.202
# shell executor
rm -f /etc/gitlab-runner/config.toml
gitlab-runner \
    gitlab-runner register \
    --url http://192.168.101.201:7000 \
    --token glrt-UJAwY5U5B2arIh-riT6A9W86MQp0OjEKdToxCw.01.12125weuh

# docker executor
rm -f /data/gitlab-runner/config/config.toml
podman exec -it gitlab-runner \
    gitlab-runner register \
    --url http://192.168.101.201:7000 \
    --token glrt-YhHnYasZjvAxCclbzb9f7286MQp0OjEKdToxCw.01.121l1z4dk

注册过程

shell executor

Enter the GitLab instance URL (for example, https://gitlab.com/):
[http://192.168.101.201:7000]:
Verifying runner... is valid                        correlation_id=01KE52A09KBEPPGEVMM7DK538V runner=pvgww0NeJ
Enter a name for the runner. This is stored only in the local config.toml file:
[node-202.server.com]:
Enter an executor: ssh, parallels, virtualbox, docker, docker-windows, docker+machine, instance, custom, shell, kubernetes, docker-autoscaler:
shell
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!

Configuration (with the authentication token) was saved in "/etc/gitlab-runner/config.toml"

docker executor

Enter the GitLab instance URL (for example, https://gitlab.com/):
[http://192.168.101.201:7000]:
Verifying runner... is valid                        correlation_id=01KE53F4W2VTZFS8H45M336H5E runner=YhHnYasZj
Enter a name for the runner. This is stored only in the local config.toml file:
[86327c775580]: node-203.server.com
Enter an executor: shell, parallels, virtualbox, docker-windows, docker+machine, kubernetes, docker-autoscaler, custom, ssh, docker, instance:
docker
Enter the default Docker image (for example, ruby:3.3):
debian:trixie-slim
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!

Configuration (with the authentication token) was saved in "/etc/gitlab-runner/config.toml"

查看配置文件

shell executor

cat /etc/gitlab-runner/config.toml
concurrent = 1
check_interval = 0
shutdown_timeout = 0

[session_server]
  session_timeout = 1800

[[runners]]
  name = "node-202.server.com"
  url = "http://192.168.101.201:7000"
  id = 8
  token = "glrt-pvgww0NeJ1-bF_NGsAA7G286MQp0OjEKdToxCw.01.121rryw7l"
  token_obtained_at = 2026-01-04T17:53:59Z
  token_expires_at = 0001-01-01T00:00:00Z
  executor = "shell"
  [runners.cache]
    MaxUploadedArchiveSize = 0
    [runners.cache.s3]
    [runners.cache.gcs]
    [runners.cache.azure]

docker executor

cat /data/gitlab-runner/config/config.toml
concurrent = 1
check_interval = 0
shutdown_timeout = 0

[session_server]
  session_timeout = 1800

[[runners]]
  name = "node-203.server.com"
  url = "http://192.168.101.201:7000"
  id = 10
  token = "glrt-YhHnYasZjvAxCclbzb9f7286MQp0OjEKdToxCw.01.121l1z4dk"
  token_obtained_at = 2026-01-04T18:14:16Z
  token_expires_at = 0001-01-01T00:00:00Z
  executor = "docker"
  [runners.cache]
    MaxUploadedArchiveSize = 0
    [runners.cache.s3]
    [runners.cache.gcs]
    [runners.cache.azure]
  [runners.docker]
    tls_verify = false
    image = "debian:trixie-slim"
    privileged = false
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    volumes = ["/cache"]
    shm_size = 0
    network_mtu = 0

修改配置文件

shell executor 和 docker executor 通用配置

  • concurrent = 1 改为 concurrent = 2 (并发数,按需更改,如果每次 Runner 运行多个任务,则改为 4 或者更大)
  • request_concurrency = 2 添加到 [[runners]] 块中 (executor = "......" 的下一行)

docker executor 特别配置

  • privileged = false 改为 privileged = true
  • volumes = ["/cache"] 改为 volumes = ["/cache", "/var/run/docker.sock:/var/run/docker.sock"]
  • pull_policy = "if-not-present" 添加到末尾

重启 GitLab Runner

shell executor

systemctl restart gitlab-runner.service
systemctl status gitlab-runner.service

docker executor

podman stop gitlab-runner
systemctl start podman@gitlab-runner
podman ps
podman logs -f gitlab-runner

拉取镜像:

HTTP_PROXY=http://192.168.101.200:1080 HTTPS_PROXY=http://192.168.101.200:1080 podman pull docker.io/debian:trixie-slim

查看 Runner

192.168.101.202 / 203 都注册好之后,在 CI/CD Runners 页面可以看到状态


开机启动

# shell executor
systemctl enable gitlab-runner.service

# docker executor
systemctl enable podman@gitlab-runner

Podman Podman 设置 (重要‼️)

# 允许用户在无登录状态下运行
loginctl enable-linger gitlab-runner

# 设置密码
echo 'wR5zxK2R' | passwd --stdin gitlab-runner

# 禁止 jenkins 用户通过 SSH 登录
# 编辑 /etc/ssh/sshd_config.d/99-deny-users.conf
#   DenyUsers jenkins gitlab-runner
systemctl restart sshd

# 设置 sudo 权限
echo 'gitlab-runner ALL=(ALL) NOPASSWD: /usr/bin/podman,/usr/bin/docker' >> /etc/sudoers.d/gitlab-runner
chmod 400 /etc/sudoers.d/gitlab-runner

# 设置 UID 和 GID
usermod --add-subuids 100000-165535 --add-subgids 100000-165535 gitlab-runner

# 去重 & 排序
awk -F: '{ res[$1] = $0 } END { for (u in res) print res[u] }' /etc/subuid | sort | sudo tee /etc/subuid
awk -F: '{ res[$1] = $0 } END { for (u in res) print res[u] }' /etc/subgid | sort | sudo tee /etc/subgid

# 切换用户
su - gitlab-runner

# 检查配置
cat ~/.config/containers/containers.conf

# 如果配置文件不存在, 创建配置文件

# 强制 Podman 使用默认的 ulimit, 避免它尝试去设置过高的值
# 将其设置为一个 Jenkins 进程允许的值 (通常 4096 是比较安全的)
mkdir -p ~/.config/containers
cat > ~/.config/containers/containers.conf <<'EOF'
[containers]
default_ulimits = [ "nofile=1024:4096" ]
EOF

# 重置 podman
podman system migrate
podman system reset -f

# 查看镜像
podman images

# 拉取镜像
HTTP_PROXY=http://192.168.101.200:1080 HTTPS_PROXY=http://192.168.101.200:1080 podman pull custom/jdk:21.0.9-0

是否启用 privileged(是否允许 Docker in Docker)

如果要:

  • docker build
  • docker push
  • k8s 镜像构建

👉 必须 true


测试 Runner 是否正常

.gitlab-ci.yml 示例:

stages:
  - test

test-job:
  stage: test
  tags:
    - linux
  script:
    - echo "GitLab Runner is working"
    - docker version

⚠️ 注意:tags 必须与 Runner 的 Tags 一致 ‼️

Push 后应看到:

  • Runner 被选中
  • Job 成功执行

查看 Pipeline 和 Jobs

查看 Pipeline

手动触发 Pipeline:点击右上角的 New pipeline,再点击 New pipeline,即可。

触发成功后,可以看到 Pipeline 运行成功

查看 Job 运行情况

查看 Jobs


常见问题 & 坑(非常高频)

❌ 1. Job 一直 Pending

原因:

  • tag 不匹配
  • Runner 被 pause
  • Runner scope 错误(项目 / group)

检查:

gitlab-runner list

❌ 2. docker: command not found

原因:

  • 没挂 docker.sock
  • 没 privileged

❌ 3. 权限问题(docker.sock)

chmod 666 /var/run/docker.sock

或:

usermod -aG docker root

❌ 4. Runner 容器自己被 CI 杀掉

原因:

  • docker system prune
  • Runner 和 CI 用同一个 Docker

👉 生产建议 Runner 独立节点


生产最佳实践(非常重要)

Runner 与 GitLab 分离

  • GitLab:稳定
  • Runner:可随意扩缩

使用 Tag 控制 Runner

tags:
  - docker

一个 Runner ≠ 一个并发

concurrent = 4

固定 Runner 版本

image: gitlab/gitlab-runner:18.7.2

CI 镜像缓存

pull_policy = "if-not-present"

安全建议(容易被忽略)

⚠️ docker.sock = root 权限

等价于 宿主机 root

建议:

  • Runner 独立机器
  • 不对公网开放 GitLab Runner