gilab-runner源码阅读记录(一)

date
Dec 23, 2020
slug
gilab-runner源码阅读记录(一)
status
Published
tags
Go
summary
接之前的文章,单纯把整个流程调通了上到生产环境发现还是不满足所有需求。比如:不支持指定多个subnet和instance-type,导致的结果就是如果指定了subnet和instance-type,就只能在一个zone中请求spot实例,经常会出现没有相关资源的情况
type
Post

背景

接之前的文章,单纯把整个流程调通了上到生产环境发现还是不满足所有需求。比如:
  1. 不支持指定多个subnet和instance-type,导致的结果就是如果指定了subnet和instance-type,就只能在一个zone中请求spot实例,经常会出现没有相关资源的情况(capacity-not-available)。这时候所有CI请求就被block住了,因为没有新的机器可以运行,只能等已有任务跑完,复用已有的机器
  1. 既然是为了节省成本,当然选比较低配的机型,只要能跑通CI即可。但是有一些项目需要的资源是比较高的,我们选的机型是2C2G的机型,某些项目跑CI就会出现OOM(out of memory)的情况。
对于问题1,我们需要gitlab-runner支持配置多个subnet和instance-type,当拿不到机器的时候,就自动按照配置进行尝试,而不是傻等。
对于问题2,出现了就很难短时间解决,一旦出现此问题,对工作效率影响还是很大的。因为就算此时修改配置,重启runner,也不能保证之后该项目的任务可以分配到高配机器上。
如果不修改代码,只有2个方案:
一个是统一使用高配机型,这显然是不经济的,而且不解决根本问题,谁知道后续还有没有要求更高的项目呢?
另一个是碰到这种项目,就在gitlab后台进行runner的绑定并在项目级停用默认的runner,把这些项目绑定到一个高配的runner上。但是我们的工作流程是参考开源项目的流程,提交代码都是fork项目之后提pr的方式来进行的,针对每一个项目都要提工单,手动分配runner,很麻烦,也遭到了运维的反对,毕竟是额外的工作量。
所以我们需要runner能根据项目名称来修改docker-machine的参数,去请求高配的机型,且之后有该项目的CI任务过来,也要分配到高配的机型上面来运行。
其中docker-machine部分的修改比较容易,但是gitlab-runner的逻辑就比较复杂,这篇记录下runner的启动流程。

启动流程

gitlab-runner的启动(gitlab-runner run)流程依赖两个项目
可以稍微熟悉一下用法,其中golang-kardianos-service没啥详细文档,比较反人类,后面会着重提下
入口在项目目录的main.go中,Commands的注册是通过各个包的init()方法完成的,具体之后执行逻辑可根据运行的命令找到具体的包,我们要找的是 gitlab-runner run 命令,所以找到commands包
commands包的init()方法在 commands/multi.go 文件中,我们可以看到,实际执行的逻辑是 RunCommand.Execute() 方法
其中利用golang-kardianos-service项目,把逻辑封装成了Service,下一步执行逻辑在 RunCommand.Start()方法中
RunCommand.Start() 另启动了一个 goroutine 来运行实际逻辑,并把控制权转给了 RunCommand.runWait() 方法,实际运行的逻辑在 RunCommand.run() 方法中,至此,启动流程完成
gilab-runner源码阅读记录(一)

© oddcc 2020 - 2024