/ Rancher

玩腻了Jenkins,也来玩玩Drone CI

一般一提起持续集成,很多人都会说“我们也在实施持续集成,有个Jenkins集群”之类的。这里面隐含着两个信息:持续集成与持续集成系统好像是一件事,这个是我个人最不同意的点,后面我会专门写一篇文章来分析持续集成最核心的“秘密”;另外一个信息就是持续集成系统主流就是使用Jenkins,其它的选择不太多。其实选择还真不少,比如,从早期的CruiseControl到TeamCity、Jenkins、Bamboo,以及TW的Go pipeline,再到最近流行的CI服务Travis CI、CodeShip、Circle CI,甚至GitLab 也集成了pipeline的功能。这些工具不少我使用过和研究对比过,有些是收费服务,有些是收费产品,有些是开源项目。最后我在自己产品上选择了相对金钱和精力投入相对较低的Drone CI。

我选择Drone CI有几个原因。第一,当然Drone是免费的开源项目,可以私有部署。然后,我比较喜欢Travis的配置方式,只需在代码里加上一个yml配置文件即可配置pipeline,比较简单而且可以版本化配置,Drone也是同样的方式(这也是我之前比较讨厌Jenkins的地方,当然,Jenkins 2之后也支持Jenkinsfile来定制pipeline了)。其次,我现在比较迷Docker,管理部署比较方便,而Drone完全是基于Docker容器的。

安装Drone

说了这么多,下面来看看如何运行一个Drone服务。其实很简单,既然Drone本身是基于Docker的,当然运行它也是通过Docker了。用docker-compose的方式来安装一个server和一个agent的话,就是这样:

version: '2'

services:
  drone-server:
    image: drone/drone:0.7
    ports:
      - 80:8000
    volumes:
      - /var/lib/drone:/var/lib/drone/
    restart: always
    environment:
      - DRONE_OPEN=true
      - DRONE_HOST=${DRONE_HOST}
      - DRONE_GITHUB=true
      - DRONE_GITHUB_CLIENT=${DRONE_GITHUB_CLIENT}
      - DRONE_GITHUB_SECRET=${DRONE_GITHUB_SECRET}
      - DRONE_SECRET=${DRONE_SECRET}

  drone-agent:
    image: drone/drone:0.7
    command: agent
    restart: always
    depends_on:
      - drone-server
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - DRONE_SERVER=ws://drone-server:8000/ws/broker
      - DRONE_SECRET=${DRONE_SECRET}

如果使用Rancher的话,那就更简单了,只需从Catalog选择Drone,然后填上相应的参数启动就好了,剩下的就交给Rancher了。当然如果你需要更多自定的配置或者想把配置方案版本化下来,你可以在Rancher里设置好,从Stack的YAML视图里复制docker-compose的配置文件。

用户管理

Drone的用户系统是依赖于版本控制系统(VCS)的,它支持Github、GitLab、Gitea、Gogs、Bitbucket和Coding。通常如果Drone是外网可访问的,那么建议把DRONE_OPEN设为false。可以通过DRONE_ADMIN来设置管理员的用户名,比如:

DRONE_OPEN=false
DRONE_ADMIN=zbcjackson,johnsmith

除了在启动参数设置管理用户外,Drone并没有提供用户管理的图形界面,但是可以使用Drone的命令行工具来管理,像这样添加用户

drone user add octocat

需要注意的是只有DRONE_ADMIN里设置的管理员才可以管理用户。

添加项目

和Travis一样,添加仓库就相当于Jenkins里添加项目了,当然仓库的根目录下得有.drone.yml文件。

登录后,Drone会从VCS获得所有你有权限的仓库,然后只需将对应的仓库开关打开就行。
drone-select-repos

选择仓库后,就可以在主界面上看到已经选择的仓库了。
drone-enabled-repositories

配置文件.drone.yml

配置文件.drone.yml其实是Drone实现了一个docker-compose文件的超集。你可以像这样定义pipeline

pipeline:
  backend:
    image: golang
    commands:
      - go get
      - go build
      - go test

  frontend:
    image: node:6
    commands:
      - npm install
      - npm test

这个pipeline里有2个步骤,一个编译并测试后端,一个测试前端。是不是很简单,很直观?有没有发现这里每个步骤都使用了Docker镜像?对了,每个步骤都是运行在一个Docker容器中的。我觉得这是Drone最好玩的地方。

后面我会详细解释Drone里面的概念和玩法。这里我先对Drone吐一下嘈,任何东西一定有啥让你不爽的地方:

  • Drone的界面实在是做的很糟糕,经常基面会卡死没反应,或者很慢。Drone使用了text/event-stream来更新构建的日志和服务器事件,所以我猜这里可能有内存泄漏。
  • Drone有个插件可以用来发布Docker镜像,但是我碰到几次镜像构建错误时,导致发布步骤出错,引起构建的状态一直处在运行,而不会标记为失败。这会导致Server觉得Agent好像都被占用,而把后面的构建都pengding,还有可能把这个步骤的Log给删了,实在无语。我不得不去改Drone的数据库,然后重启Agent。我觉得Server在处理步骤或插件异常时没有保护好Server的状态,这个Docker插件的异常处理也有些问题。
Jackson Zhang

Jackson Zhang

Odd-e敏捷教练,主要涉及组织,团队,产品,技术,工程实践等,曾为多家知名企业提供教练与培训服务。译有《用户故事与敏捷方法》,《.NET单元测试的艺术》和《实例化需求说明》。擅长工程实践(如测试驱动开发,单元测试,重构,持续集成等),产品探索(Impact Mapping,Pretotyping,Lean Startup等)与团队协作。zbcjackson AT gmail.com

Read More