gitea-runner · 集群内 Gitea 的自托管 Actions runner
gitea-runner 是为集群内 Gitea 实例提供的自托管 Gitea Actions runner,让 gitea.yldm.tech 仓库里的 .gitea/workflows/*.yaml 真正能跑起来。
它采用 gitea/runner:*-dind 镜像:该镜像自带 dockerd,runner 在同一个 pod 内用 Docker 容器拉起每个 job——没有独立的 runner controller,这一点和 github-runner 目录里基于 ARC 的 GitHub runner 不同。runner 是拉取式(pull-based)工作:它长轮询集群内的 Gitea 取队列任务,没有任何东西反向连入它,因此 ingress 默认全部拒绝。
部署形态
- Name
- 命名空间
- Description
- gitea-runner
- Name
- 工作负载类型
- Description
- StatefulSet(serviceName 为 gitea-runner,headless)
- Name
- 镜像
- Description
- gitea/runner:1.0.8-dind(kustomization.yaml 未单独管理 images,直接取容器 image)
- Name
- 副本数
- Description
- replicas: 1(每个 pod 注册为独立 runner,capacity=1 即一次只跑一个 job;扩并发就加 replicas)
- Name
- 安全上下文
- Description
- 容器 privileged: true(DinD 必须特权),pod seccompProfile: RuntimeDefault
- Name
- 端口
- Description
- cache 8088(actions/cache 服务端,监听 pod 自身 IP)
- Name
- 资源
- Description
- requests cpu 250m / memory 512Mi,limits cpu 8 / memory 12Gi
- Name
- 存储 data
- Description
- volumeClaimTemplate,storageClass nfs-client,20Gi,挂载 /data(放注册身份 .runner、cache、workdir)
- Name
- 存储 docker-storage
- Description
- volumeClaimTemplate,storageClass local-path,30Gi,挂载 /var/lib/docker(overlay2 必须节点本地,不能放 NFS)
- Name
- PVC 保留策略
- Description
- whenDeleted: Retain,whenScaled: Delete
PVC 保留策略有讲究:缩容时删除被移除副本的 PVC——否则残留的 local-path PVC 会把未来的 pod-N 重新钉回它曾经运行过的那个节点;而删除整个 StatefulSet 时保留 PVC(对 recreate 迁移是安全的)。
配置与依赖
runner 配置来自 ConfigMap gitea-runner-config(act_runner 0.6.x 的 config.yaml),以 read-only 挂载到 /etc/act_runner,由 CONFIG_FILE env 指向。关键项:runner.capacity: 1(一次一个 job)、timeout: 3h、长轮询 fetch_interval: 2s / fetch_timeout: 5s、cache.enabled: true(目录 /data/cache)、container.docker_host 指向 pod 内 dockerd 的 unix:///var/run/docker.sock、host.workdir_parent: /data/workdir。注册身份 .runner 落在 PVC 的 /data,不在这个 ConfigMap 里。
runner 通告以下 labels,在工作流里用 runs-on: 匹配:
| label | 对应镜像 |
|---|---|
| ubuntu-latest | gitea/runner-images:ubuntu-latest |
| ubuntu-22.04 | gitea/runner-images:ubuntu-22.04 |
| ubuntu-20.04 | gitea/runner-images:ubuntu-20.04 |
ConfigMap gitea-runner-dind 提供 /etc/docker/daemon.json,把集群内 registry 标为 insecure-registries(registry.registry.svc.cluster.local:5000,明文 HTTP)——CI 把多 GB 的 DNF 镜像推到这里,绕开 Cloudflare Tunnel 的 100MB 上传上限。
ExternalSecret gitea-runner-token 从 Vault 拉取注册 token(ClusterSecretStore vault-backend,remoteRef.key: gitea/runner,property registration_token),合成 Secret gitea-runner-token,刷新间隔 1h。token 是一次性消耗品:runner 首次启动用它换取持久身份写到 PVC 的 /data/.runner,此后不再读取——轮换 Vault 值只在需要重新注册(抹了 PVC 或在 Gitea 删了 runner)时才有意义。Vault 路径写法见 VAULT_SETUP.md(vault kv put secret/gitea/runner registration_token=...)。
env 关键项:GITEA_INSTANCE_URL=http://gitea-http.gitea.svc.cluster.local:3000、GITEA_RUNNER_REGISTRATION_TOKEN(来自上述 Secret)、GITEA_RUNNER_NAME(取 pod 名 metadata.name)、DOCKER_HOST=unix:///var/run/docker.sock(job 容器经此连入 pod 内 dockerd)。
依赖:集群内 Gitea(gitea-http.gitea:3000,拉任务、回传日志/产物)、Vault(注册 token)、集群内 registry(registry.registry:5000,推镜像)、外网 github.com(Gitea 侧 DEFAULT_ACTIONS_URL=github,uses: actions/checkout@v4 等从 github.com 拉取)。
访问与监控
Service 为 headless(clusterIP: None),仅为 StatefulSet 提供稳定 DNS——runner 是拉取式,没有谁需要连入它,service 暴露 cache 端口 8088(targetPort cache)但无 Ingress。
命名空间设有 ResourceQuota gitea-runner-quota(pods 10、requests.cpu 4 / memory 8Gi、limits.cpu 20 / memory 24Gi)与 LimitRange gitea-runner-limits(容器 max cpu 8 / memory 12Gi、min cpu 10m / memory 32Mi、default cpu 2 / memory 4Gi、defaultRequest cpu 250m / memory 512Mi)。注意 job 容器是 docker 子进程而非 k8s pod,不受 LimitRange 约束,只有 runner pod 本身受约束。本目录下无 ServiceMonitor、PrometheusRule、HPA、VPA、PDB。
网络策略
默认拒绝入站,按需放行出站:
| 策略 | 作用 |
|---|---|
| default-deny-ingress | 对所有 pod 拒绝全部 ingress |
| allow-same-namespace | 放行同命名空间内 pod 之间的 ingress 与 egress |
| allow-dns-egress | 出站到 kube-system 的 DNS(UDP/TCP 53) |
| allow-gitea-egress | 出站到 gitea 命名空间 TCP 3000(长轮询取任务、回传日志/产物,因 3000 非标准端口需单独放行) |
| allow-registry-egress | 出站到 registry 命名空间 TCP 5000(推镜像,集群内 5000 不在 80/443 默认放行范围) |
| allow-external-egress | 出站 0.0.0.0/0 的 TCP 80/443(拉 github.com actions 与 job 镜像),但排除云元数据端点 169.254.169.254/32 |
注意事项
overlay2 存储必须节点本地,绝不能放在 NFS PVC 上——因此 /var/lib/docker 由 local-path 的 volumeClaimTemplate 承载(镜像层在 pod/节点重启后得以保留,不必每次重新拉取)。代价:一旦绑定,该 PV 的 node affinity 会把 pod 钉到那个节点;若节点宕机,删掉这个 docker-storage PVC 让 pod 重新调度(cache 从头重建)。local-path 不强制 size 请求,悬空层会累积,若出现节点磁盘压力就 docker system prune。
扩容:每个 pod 一次只跑一个 job(runner.capacity: 1),抬高 replicas 增加并行 runner,每个都用同一个 Vault token 独立注册。
重新注册:删了 Gitea 里的 runner 或抹了 PVC 后,按 VAULT_SETUP.md 重新签发 token 覆盖 secret/gitea/runner,等 ESO 一小时内同步或手动 force-sync,再删 pod(kubectl delete pod -n gitea-runner gitea-runner-0)让它带新 token 重启。
gitea-runner-token ExternalSecret 一直不同步、pod 起不来。返回 infrastructure 总览