找回密码
立即注册
搜索
发回帖 发新帖

6543

积分

0

好友

833

主题
发表于 11 小时前 | 查看: 3| 回复: 0

白板上画着两个框:左边是 GitLab,右边箭头指向 Runner。代码中枢有了,但没人干活。

GitLab Runner Docker executor 第12话插画:DevOps Flow 与 CI/CD 流水线

一、GitLab 是大脑,Runner 是手脚

「Runner 是什么?」

「执行器。你推代码,GitLab 说『有人推代码了』,Runner 就过来领任务、跑流水线,再把结果告诉 GitLab。」

「那不就是 CI 的工人?」

「对。GitLab 是大脑,Runner 是手脚。」

执行器主要有三种:

  • Shell executor:直接在宿主机跑,简单,但污染环境
  • Docker executor:每个任务起一个容器,干净隔离
  • Kubernetes executor:在 K8s 里跑,适合大规模

「我们用 Docker executor。每个流水线任务在独立容器里跑,不会因为上次任务留了垃圾文件就失败。」

GitLab Runner 三种 executor 对比:Shell、Docker、Kubernetes 隔离级别

二、启动 Runner

先创建配置目录:

sudo mkdir -p /srv/gitlab-runner/config

再启动 Runner 容器:

docker run -d --name gitlab-runner \
  --restart always \
  -v /srv/gitlab-runner/config:/etc/gitlab-runner \
  -v /var/run/docker.sock:/var/run/docker.sock \
  gitlab/gitlab-runner:latest

「为什么挂 docker.sock?」

「因为 Docker executor 要起容器。Runner 本身在容器里,它要调用外面的 Docker,就得挂这个 socket。」

「安全吗?」

「有一定风险。生产环境 Runner 要单独隔离。」

这个风险值得说得更具体一点,因为它经常被当成「配置细节」而忽略。挂上 /var/run/docker.sock 之后,Runner 容器内的进程可以:

  • 启动一个 -v /:/host 的容器,直接读写宿主机整个文件系统;
  • 启动一个 --privileged 的容器,进一步触及内核能力;
  • 读取宿主机上所有容器的环境变量,包括其他服务的密码。

换句话说:谁能改 .gitlab-ci.yml 并推到仓库,谁就等于拿到了宿主机 root。

加固手段按成本从低到高:

手段 效果
保护分支 + 限制谁能推流水线文件 最有效
Runner 单独一台 VM 缩小影响面
rootless Docker / Podman 不需要 root 的 socket
K8s executor 让集群 RBAC 和 Pod 安全策略兜底

「教学环境先跑通」不等于「生产可以这么干」。

三、注册 Runner(★ 这一步的规则变了)

在 Admin Area → CI/CD → Runners,点击 New instance runner:

  • Description:docker-runner-01
  • Tags:docker, linux, x86_64
  • 勾选 Run untagged jobs

创建后,GitLab 显示一个令牌:

glrt-xxxxxxxxxxxxxxxxxxxx

注意这个 token 的格式:glrt- 开头。这不是随便举的例子——它意味着 GitLab 已经把你引到了「新的注册工作流」上。

维度 旧:注册令牌 新:认证令牌
长什么样 一串十六进制,无前缀 glrt- 开头
在哪拿 Admin Area → Runners(全局令牌) 先点 New instance runner 创建 runner,创建完才给令牌
配置填在哪 register 命令一路问你 description、tags 在 UI 创建时就填好了
注册参数 --registration-token --token

为什么必须用新流程?GitLab 17.0 起,传统注册流程默认被禁用。如果还用旧方式,会拿到:

410 Gone - runner registration disallowed

这行报错看起来像「权限不够」,其实是你用了被废弃的流程。

所以,先看 token 前缀:glrt- 开头 = 新流程,用 --token;其他格式 = 旧流程,用 --registration-token。这类「工具还在、但使用方式已经变了」的改动,是自建平台最容易卡住的地方。遇到莫名其妙的失败,先搜一下这个版本的 Release Notes,比反复重试有效得多。

GitLab Runner 注册 token 变化:glrt 认证令牌与 410 Gone 报错

建议:能一行搞定,就别走交互式。

docker exec -it gitlab-runner gitlab-runner register \
--non-interactive \
--url "http://10.0.0.101" \
--token "glrt-xxxxxxxxxxxxxxxxxxxx" \
--executor "docker" \
--docker-image "alpine:latest"

两个好处:① 可复制、可脚本化;② 不会因为手滑选错——交互式流程里多按一次回车,可能就把 executor 选成了 shell。

交互式流程则是:

docker exec -it gitlab-runner gitlab-runner register

依次填:URL → token → description → tags → executor(docker)→ 默认镜像(alpine:latest)。

看到下面这行,说明注册成功:

Runner registered successfully.

刷新 GitLab 页面,能看到:

docker-runner-01   online   docker,linux,x86_64

「在线了。绿色就对了。如果灰色,说明连不上——检查 URL 和 token。」

四、config.toml

注册完成后,Runner 的配置会落在 /srv/gitlab-runner/config/config.toml 里,大概长这样:

concurrent = 1
check_interval = 0

[[runners]]
  name = "docker-runner-01"
  url = "http://10.0.0.101"
  token = "glrt-xxxxxxxxxxxxxxxxxxxx"
  executor = "docker"
  [runners.docker]
    image = "alpine:latest"
    privileged = false          # 不开特权,安全
    volumes = ["/cache"]

如果想提高并发,可以这样改:

sudo vim /srv/gitlab-runner/config/config.toml   # concurrent = 2
docker restart gitlab-runner

「改了配置都要重启。Runner 启动时读配置。」

五、验证:第一条流水线

在项目里加一个最简的 .gitlab-ci.yml:

stages:
  - test

hello:
  stage: test
  tags:
    - docker
  script:
    - echo "Hello from GitLab Runner"
    - uname -m
    - cat /etc/os-release | head -2

提交后,进 CI/CD → Pipelines,会看到任务从 pending 走到 running,再到 passed。

输出大概是:

Hello from GitLab Runner
x86_64
PRETTY_NAME="Alpine Linux v3.x"

「注意,这是 x86_64。因为 Runner 跑在 vm-gitlab 上,VM 是 x86_64。」

「所以 CI 构建的镜像是 x86_64,正好给私有云用。」

「对。这就是为什么 CI 要用私有云的 Runner,而不是你本地的 Mac。架构一致,构建出来的镜像直接能部署。」

GitLab CI/CD 骨架:从 push 到部署的 x86_64 链路

这不是偶然,是刻意的设计。看整条链路:

环节 架构 说明
你写代码的 Mac ARM64 只是编辑,不构建镜像
跑流水线的 Runner x86_64 构建在这里发生
私有 Registry x86_64 存的就是 Runner 构建出来的
部署目标 x86_64 和镜像架构一致

整条链路里,只有「写代码」是 ARM64,而它不产出镜像。所以后面所有环节都不会撞上架构不匹配。

六、常见问题

Q1:注册时提示 410 Gone - runner registration disallowed,怎么办?

这是「用了被废弃的旧流程」的典型症状,不是权限问题。

  1. (推荐)走新流程:New instance runner → 拿 glrt- 令牌 → 用 --token 注册;
  2. 临时启用旧流程:Admin Area → Settings → CI/CD,勾上 Allow runner registration tokens——权宜之计;
  3. 检查组/实例层级:token 从哪一级拿,决定 Runner 的可见范围。

判据:看 token 前缀。

Q2:Runner 显示 offline(灰色),怎么排查?

  1. 容器还在吗:docker ps | grep runner;
  2. 能不能访问到 GitLab:docker exec -it gitlab-runner curl -I http://10.0.0.101;
  3. token 对不对:看 config.toml;
  4. 看 Runner 日志:docker logs gitlab-runner。

最常见的原因:url 写成了 localhost——Runner 在容器里,localhost 是它自己。

Q3:改了 config.toml 为什么不生效?

因为 Runner 只在启动时读配置,改完要 docker restart gitlab-runner。

顺便提醒:concurrent 调大之前,先想清楚内存够不够——每个并发任务都会起一个构建容器。

Q4:可以让 Runner 只在特定分支跑吗?

那是 .gitlab-ci.yml 里控制的,不是 Runner 配置:

build:
  script: ...
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'

Runner 层控制「在哪台机器上跑」(tags),流水线层控制「什么时候跑」(rules)——两个维度别搞混。

Q5:为什么默认镜像选 alpine?

因为小。alpine 只有几 MB,ubuntu 有几十 MB。CI 里每次都要拉镜像,差距会累积成可观的时间。

但要注意:alpine 用 musl libc 和 BusyBox,某些依赖 glibc 的二进制跑不起来。这也是 docker exec 时要用 sh 而不是 bash 的原因。

建议:默认用 alpine 做轻任务,需要完整环境的任务单独指定 ubuntu 或 python:3.x 镜像。

七、下话

第 13 话:第一条流水线——lint + test + build。

老周把前面几话的 shellcheck、bats、docker build 全摆在桌上。

「你前面几话练的那些,今天要串成一条线。」

「一条线?」

「对。一条你不参与、也会自动跑的线。」

下话见。




上一篇:为什么王者荣耀不用微服务?游戏服务器拒绝微服务架构的深度剖析
下一篇:用 VirtualBox 在 Windows 11 上安装 Windows XP 虚拟机完整教程
您需要登录后才可以回帖 登录 | 立即注册

关闭

站长推荐上一条 /1 下一条

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-10-28 14:16 , Processed in 0.081223 second(s), 42 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表