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: 5scache.enabled: true(目录 /data/cache)、container.docker_host 指向 pod 内 dockerd 的 unix:///var/run/docker.sockhost.workdir_parent: /data/workdir。注册身份 .runner 落在 PVC 的 /data,不在这个 ConfigMap 里。

runner 通告以下 labels,在工作流里用 runs-on: 匹配:

label对应镜像
ubuntu-latestgitea/runner-images:ubuntu-latest
ubuntu-22.04gitea/runner-images:ubuntu-22.04
ubuntu-20.04gitea/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-backendremoteRef.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:3000GITEA_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=githubuses: 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 重启。

返回 infrastructure 总览

评论