以前,我的一些 Project 的部署流程基本都是纯手动的。
1、push to the repository (GitHub / Bitbucket)
2、connecting via SSH to server
3、clone the repository
4、install dependencies
5、stop old service and run the new project
之后,我在合作项目中接触到了持续集成
、流水线
的概念,使得一个应用程序从构建、部署、测试到发布整个过程实现自动化,觉得甚是好用,便决定在自己的项目中尝试一把CI
。
本文将较为全面地介绍Drone
的概念、安装、使用和一些可能遇到的坑。
Drone
Drone is a self-service Continuous Delivery platform for busy development teams.
Drone
是一个Golang
技术栈的CI
解决方案,功能和Jenkins
之类的CI
工具类似。
优点
- Golang 编写,镜像体积小,搭建容易,运行时占用资源小
- 支持主流代码托管平台
Webhook
沟通 - 构建运行时采用
image
优先,保证在不同平台的构建结果一致 - 支持插件化,提供强大的功能支持
- 现代化
UI
设计,操作简单明了
缺点
- 年轻,常改版
- 官方的各种文档写的太烂了
- 功能和完善程度不及一些老牌 CI
架构
由 1 台 Server 通过Webhook
跟代码托管平台做沟通,接收到事件后启动Runner
来处理 Server 上产生的任务。Runner
可以在同一台主机上,也可以分散在多台不同的主机上。
核心概念
pipeline
pipeline
可以帮助完成自动化软件交付过程中的步骤,例如启动代码构建、运行自动化测试以及部署到测试或生产环境。pipeline
的执行由源代码储存仓库repository
触发。代码更改会触发Webhook
从而与Drone
沟通,后者便开始运行相应的pipeline
。
pipeline
的种类不止一种,例如:
- Docker:在临时的 Docker 容器中执行命令,保证在不同平台的构建结果一致
- exec:直接在主机上执行 shell 命令而不隔离,对于不支持容器(如 macOS)的操作系统和体系结构,此运行程序尤其有用
- ssh:使用 ssh 协议在远程服务器上执行 shell 命令
platform
使用platform
配置目标操作系统和体系结构,并将pipeline
路由到适当的运行器。如果未指定,则系统默认为Linux amd64。
workspace
Drone
会自动创建一个临时卷,称为工作区,在其中 clone repository。工作区是管道中每个步骤的当前工作目录。
steps
steps
定义为一系列的 shell 命令。这些命令在 git 仓库的根目录(工作区)中执行,工作区由管道中的所有步骤共享。
一个特定的steps
由多个step
组成,供pipeline
执行,例如:
- clone、安装依赖、单元测试、生成静态文件、拷贝静态文件
condition
condition
决定了当前step
的触发条件。
触发条件有多种,例如:
- 根据 Branch:e.g. master/beta
- 根据 Event:e.g. push/pull_request
- 根据 Reference:e.g. refs/heads/feature-*
- 根据 Repository:e.g. octocat/hello-world
- 根据 Instance:e.g. drone.instance1.com/drone.instance2.com
- 根据 Status:e.g. success/failure
- 更多请参考文档
trigger
trigger
决定了当前pipeline
的触发条件。
触发条件有多种,基本和condition
一致。
安装 & 使用
Server
1、创建 OAuth 应用(以 Bitbucket 为例)
在 Bitbucket 上新建一个 OAuth 应用,Callback URL 填写 Server 配置的登陆地址 http(s)://{{drone_host}}/login,权限配置如图所示:
点击 Save 后获取 Key 和 Secret 以用于Drone
授权访问 Bitbucket resources。
2、启动 drone
Docker 启动非常容易,我使用Docker Compose
,配置 docker-compose.yml 如下:
version: '3'
services:
drone-server:
image: drone/drone:1
ports:
- 5000:80
volumes:
- /var/lib/drone:/data # SQLite 数据库存储地址
restart: always
environment:
- DRONE_BITBUCKET_CLIENT_ID={{DRONE_BITBUCKET_CLIENT_ID}} # 刚才获取的 Key
- DRONE_BITBUCKET_CLIENT_SECRET={{DRONE_BITBUCKET_CLIENT_SECRET}} # 刚才获取的 Secret
- DRONE_RPC_SECRET={{DRONE_RPC_SECRET}} # 可由 openssl rand -hex 16 命令生成
- DRONE_SERVER_HOST=drone.fix.moe
- DRONE_SERVER_PROTO=https
# - DRONE_LOGS_TRACE=true # 日志追踪
执行 docker-compose up -d,启动 drone-server。
3、同步仓库信息 & 激活代码库
如果步骤二没有问题,在浏览器打开 http(s)://{{drone_host}}/ 并授权登陆,完成后即可获得所有当前账号在 Bitbucket 内所拥有的代码库列表。
这时候账号下的项目都是未激活状态,需要点击面板上项目右边的 ACTIVATE 进行激活:
配置好后点击 SAVE 保存即可。经过这几个操作,Drone
已经激活了对相应代码库的Webhook
事件监听。
至此为止Drone
本体的安装基本上完成了,后续只需要配置Runner
便可让pipeline
顺利执行。
Runner
服务器部分配置完成后,如果没有单独安装和运行Runner
,服务器上所有触发的事件都会是 Pending 状态(不要问我怎么知道的)。
1、安装
Runner
的安装方法见官方文档。Runner
也有不同的类型,这里我用Exec Runner
举例:
$ curl -L https://github.com/drone-runners/drone-runner-exec/releases/latest/download/drone_runner_exec_linux_amd64.tar.gz | tar zx
$ sudo install -t /usr/local/bin drone-runner-exec
2、配置
Exec Runner
需要手动在 /etc/drone-runner-exec/config 创建一个配置文件:
DRONE_RPC_PROTO=https
DRONE_RPC_HOST=drone.fix.moe
DRONE_RPC_SECRET={{DRONE_RPC_SECRET}} # 和上文 drone-server 填写一样
DRONE_LOG_FILE=/var/log/drone-runner-exec/log.txt # log 存储目录,需要自行建立
DRONE_RUNNER_CAPACITY=2 # limits the number of concurrent pipelines that a runner can execute
DRONE_RUNNER_NAME=drone-runner
DRONE_RUNNER_PATH=/usr/local/bin:/usr/bin:/usr/sbin:/sbin # sets the PATH variable for all pipeline steps
DRONE_TRACE=true # 日志追踪
3、启动服务
$ drone-runner-exec service install
$ drone-runner-exec service start
cat /var/log/drone-runner-exec/log.txt
如果日志中有 msg="successfully pinged the remote server",则表明服务启动成功。
结合 .drone.yml 使用
在项目的根目录加入 .drone.yml 文件。以部署本博客为例,原本手动部署流程于本文最上方所示。
---
kind: pipeline
type: exec
name: deploy-master
platform:
os: linux
arсh: amd64
steps:
- name: copy
commands:
- cp -rf ./ /srv/fix.moe
- name: install
commands:
- source /root/.nvm/nvm.sh
- cd /srv/fix.moe
- npm install
- name: run
commands:
- source /root/.nvm/nvm.sh
- export PM2_HOME=/root/.pm2
- cd /srv/fix.moe
- pm2 stop fix.moe
- pm2 delete fix.moe
- pm2 start npm --name fix.moe -- run start
trigger:
branch:
- master
event:
- push
ok,现在测试一下,对博客做修改,commit
,push
一气呵成!
0 error(s), 0 warning(s) -> (虽然失败了 N 次)
踩坑
-
跑流水线无法运行,提示 Pending
- 检查
Runner
日志,是否成功连接 Server - 检查
Server
数据库文件是否成功创建 - 检查
.drone.yml
配置参数是否正确,type 是否与Runner
type 一致 - 关于 Pending,可以看下官方的一篇帖子:Builds are Stuck in Pending Status。
- 检查
-
跑流水线时终止在 xxx: command not found
- pipeline 运行时的 PATH 不同于用户自身的 PATH,需要在配置文件中设置好 DRONE_RUNNER_PATH
- 根据开发者的回答,commands 默认使用 /bin/sh
-
pm2
提示 Spawning PM2 daemon with pm2_home=/drone/xxx/.pm2- 想让
Drone
尝试连接到默认的 daemon path(守护进程路径),需运行 export PM2_HOME=/root/.PM2 ,就可以列出在根目录下运行的进程。
- 想让
-
使用 source xxx.sh 命令提示 source: command not found
- 在 Ubuntu 里,/bin/sh 默认使用 /bin/dash,而 /bin/dash 不支持 source 命令,如果要使用该命令可尝试以下命令:
$ ls -l `which sh` # /bin/sh -> dash $ sudo dpkg-reconfigure dash # Select "no" when you're asked $ ls -l `which sh` # /bin/sh -> bash
- 在 Ubuntu 里,/bin/sh 默认使用 /bin/dash,而 /bin/dash 不支持 source 命令,如果要使用该命令可尝试以下命令: