Kubernetes GitLab Runner 智能调度器
该项目实现了一个 Kubernetes MutatingWebhook,用于优化 GitLab Runner 在 Kubernetes 中的调度策略。它能够使 CI/CD 任务优先调度到上次执行任务的节点上,从而利用节点上已存在的缓存目录,显著提高构建速度。
背景
在 Kubernetes 中运行 GitLab Runner 时,默认的调度策略是将 Pod 分散到集群的不同节点上。但在 CI/CD 流程中,每个任务都需要下载依赖、构建代码等,这些操作可以通过缓存来加速。如果能够将任务调度到之前执行过相同任务的节点上,可以命中缓存,大幅缩短构建时间。
工作原理
- 当 GitLab Runner 创建新的 Pod 时,MutatingWebhook 会拦截该请求
- 检查该 Pod 是否包含缓存卷(通过卷名前缀
runner-cache
识别) - 查询该 Runner ID 上次被调度到的节点(存储在 ConfigMap 中)
- 向 Pod 添加节点亲和性(NodeAffinity),使其优先调度到上次执行过的节点
- Pod 调度后,通过 Pod 监控组件记录新的调度结果,以供下次任务使用
部署指南
前提条件
- Kubernetes 集群(1.16+)
- kubectl 命令行工具
- Docker(用于构建镜像)
- OpenSSL(用于生成证书)
构建镜像
# 克隆仓库
git clone https://git.treesir.pub/DevOps/k8s-hookrunner-scheduling.git
cd k8s-hookrunner-scheduling
# 构建 Docker 镜像
docker build -t your-registry/gitlab-runner-webhook:latest -f deploy/Dockerfile .
docker push your-registry/gitlab-runner-webhook:latest
部署到集群
- 修改镜像地址
# 修改 deploy/webhook-deployment.yaml 中的镜像地址
sed -i 's|gitlab-runner-webhook:latest|your-registry/gitlab-runner-webhook:latest|g' deploy/webhook-deployment.yaml
- 生成 TLS 证书并部署 Webhook
# 进入 deploy 目录
cd deploy
# 生成证书并创建 Secret
./generate-certs.sh
# 部署服务
kubectl apply -f webhook-deployment.yaml
- 验证部署
# 检查 Pod 是否运行正常
kubectl get pods -n kube-system -l app=gitlab-runner-webhook
# 检查服务是否正常
kubectl get service -n kube-system gitlab-runner-webhook
# 检查 WebhookConfiguration 是否存在
kubectl get mutatingwebhookconfigurations gitlab-runner-webhook
配置 GitLab Runner
确保 GitLab Runner 配置中 Pod 包含 Runner ID 标签。在 Runner 的 values.yaml
中,确保有以下配置:
runners:
config: |
[[runners]]
[runners.kubernetes]
[runners.kubernetes.pod_labels]
"gitlab.com/runner-id" = "{{ .RunnerID }}"
工作原理详解
-
Pod 调度记录:系统通过 Pod Informer 持续监控集群中的 Pod 调度情况,对于每个被调度的 GitLab Runner Pod,记录其 Runner ID 和被调度的节点名称。
-
历史记录存储:调度历史存储在 Kubernetes ConfigMap 中,以 Runner ID 为键,节点名为值。
-
亲和性注入:对于新建的 Pod,系统查询其 Runner ID 上次调度的节点,并添加节点亲和性(preferredDuringSchedulingIgnoredDuringExecution),权重为 100,使 Kubernetes 调度器优先将 Pod 调度到该节点上。
-
系统组成:
- WebHook 服务器:拦截 Pod 创建请求并注入节点亲和性
- 调度记录器:记录和存储 Pod 调度历史
- Pod 监控器:监控 Pod 调度事件,及时更新调度历史
定制开发
修改标签识别规则
如果你的 GitLab Runner 使用的不是默认标签,可以修改 pkg/webhook/mutate.go
中的常量定义:
// 修改为你的标签
const GitlabRunnerLabel = "your-custom-label"
修改缓存卷识别规则
如果你的缓存卷名称前缀不是 runner-cache
,可以修改以下常量:
// 修改为你的缓存卷名称前缀
const CacheVolumePrefixes = "your-cache-prefix"
贡献指南
欢迎提交 Pull Request 或提出 Issue 来帮助改进项目。