如何使用 drone 进行持续集成

什么是 Drone

Drone 是一个现代化的持续集成和持续交付平台,使忙碌的团队能够自动构建、测试和发布工作流。使用 Drone 的团队发布软件的频率更高,bug更少。1

人话:Drone 是一个轻量级的 jenkins ,可以简单的实现软件的流水线化测试、编译、部署。并且可以和 gitlab github gogs gitea 轻松的结合到一起。

前提

本文对读者作出以下假设:

  • 具有较为丰富的 git 使用经验
  • 可以熟练的操作某种 git 服务平台,如 gogs、github、gitlab …. 本文以gogs为例
  • 具有一定的 linux 和 docker 的知识储备和操作经验
  • 或许也会使用 docker-compose
  • 或许懂一点 k8s

环境配置:

  • 本文使用 Gogs 为例
  • drone 为当前最新版:1.8.x

本文涉及到的工程文件:https://github.com/alex-techs/drone-tutorial

本文链接:https://println.org/url/ODQ=

原理

个人观点,仅供参考

参与角色

角色 功能
用户 Gogs
Drone Server Drone 主服务,提供Web界面
Drone Runner 我理解为实现各种操作的适配器,例如ssh、docker、k8s操作
Drone Agent 操作宿主机 Docker API 的代理程序
Docker Server 宿主机的 Doker 程序

image-20200709162255567

安装

整个 Drone 体系都是基于docker运行的,所以无需安装,拉下几个镜像即可。当然也可以等运行的时候自动处理。

这里只是列出这些镜像和说明其作用

  • 主服务
docker pull drone/drone
  • docker操作代理
docker pull drone/agent
  • ssh runner

ssh runner 为例

docker pull drone/drone-runner-ssh

配置

没什么配置,只是几个docker的启动参数而已。

server

参数 作用
DRONE_GOGS_SERVER 要连接的 GOGS 服务器地址
DRONE_GIT_ALWAYS_AUTH 在克隆公共repo时依然进行身份认证
DRONE_RPC_SECRET DRONE 主服务对外接口的密钥,调用所有接口均需要提供
DRONE_SERVER_HOST DRONE 主服务启动时监听的地址,类似 server_name 的概念
DRONE_SERVER_PROTO DRONE 主服务启动时的协议,http , https,非必须
DRONE_DEBUG 默认false,是否输出debug日志,非必须
DRONE_PROVIDER 服务提供者,声明是 gogs,非必须
DRONE_DATABASE_DATASOURCE 声明主服务使用的数据源,非必须
DRONE_DATABASE_DRIVER 声明主服务使用的数据库驱动,非必须
DRONE_GOGS_SKIP_VERIFY 是否强制使用TLS与gogs建立链接,默认false,非必须

agent

参数 作用
DRONE_RPC_SERVER 即 DRONE_SERVER_HOST
DRONE_RPC_SECRET 即 DRONE_RPC_SECRET
DRONE_DEBUG 默认false,是否输出debug日志,非必须
DOCKER_HOST 宿主机 docker 的 json api 默认监听的地址
DRONE_RPC_PROTO DRONE 主服务启动时的协议,http , https

ssh-runner

参数 作用
DRONE_RPC_PROTO 即 DRONE_SERVER_PROTO
DRONE_RPC_HOST 即 DRONE_SERVER_HOST
DRONE_RPC_SECRET 即 DRONE_RPC_SECRET

其它参数大全:https://docs.drone.io/server/reference/

如何使docker监听 tcp 2375 端口

DOCKER_HOST 需要这个值

编辑宿主机的 /usr/lib/systemd/system/docker.service 文件

找到:

 ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

修改为:

 ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H fd:// --containerd=/run/containerd/containerd.sock

重新加载 service 缓存

systemctl daemon-reload

重启docker

systemctl restart docker

启动

环境变量

export GOGS_URL="http://1.1.2.3:2048"
export DRONE_HOST="0.0.0.0"
export DRONE_SECRET="xh1HJLO2yfandlwjeHdsL3Kklwheour89"
export DOCKER_HOST="tcp://`docker network inspect --format='{{range .IPAM.Config}}{{.Gateway}}{{end}}' bridge`:2375"

server

docker run -d \
    --volume=/var/lib/drone:/data \
    --env=DRONE_GOGS_SERVER=${GOGS_URL} \
    --env=DRONE_RPC_SECRET=${DRONE_SECRET} \
    --env=DRONE_SERVER_HOST=${DRONE_HOST} \
    --env=DRONE_SERVER_PROTO=http \
    --publish=3005:80 \
    --restart=always \
    --name=drone \
    drone/drone

agent

docker run -d \
    --env=DOCKER_HOST=${DOCKER_HOST} \
    --env=DRONE_RPC_SERVER=http://drone-server \
    --env=DRONE_RPC_SECRET=${DRONE_SECRET} \
    --restart=always \
    --name=drone-agent \
    --link drone:drone-server \
    drone/agent

ssh-runner

docker run -d \
  -e DRONE_RPC_HOST=drone-server \
  -e DRONE_RPC_SECRET=${DRONE_SECRET} \
  --restart always \
  --name runner \
  --link drone:drone-server \
  drone/drone-runner-ssh

使用 Web 界面管理构建

如果你正确的启动了上述的几个镜像,那么你打开浏览器,输入IP:3005 可以进入到 DRONE主服务的web管理界面的登陆界面,账号密码为 DRONE_GOGS_SERVER 设置的 Gogs 服务器的账号密码。

注意:防火墙一定要开放3005端口,否则是无法访问到 Drone 的

主界面:

当你的Gogs加入了新的项目,可以使用 SYNC 按钮同步到 Drone 中来

image-20200710090528175

为新工程开启构建

保护设置为,如果勾选 Protected,则不会自动进行构建,需要手动点击允许。

更新:设置公开之后无需登录即可查看项目构建状态。私有则必须登录才可以

image-20200710092645980

Save之后将会自动生成 Gogs WebHook,但是它生成的地址未经转换,直接是 DRONE_HOST 拼接了 /hook,那就会产生一些问题

  1. 我们配置地址为0.0.0.0是为了公网可访问,那它生成这样的地址要上哪里发回调。我们要手动改成浏览器中可以访问的那个地址,例如:http://xxx.org:3005/hook

    无论你配置的什么地址,都应该亲自来 Gogs 中看一看,是否是可访问的地址

    image-20200710093643951

  2. 如果我们配置的 DRONE_HOST 是 127.0.0.1/ 那么它将会生成这样的地址,暂时先不关注端口的话,就只有多了个/的问题。按常理来讲多一个/不会影响请求效果,但是Drone会受影响,要手动去掉/,修改为正确地址才可以。例如:http://xxx.org:3005/hook

    image-20200710093815148

  3. 配置完成后你需要点铅笔符号,拉到最下面,有一个 Test Delivery ,点击下去观察是否可以成功推送。

    如果是这样,那就要重新检查你的 Webhook 域名配置了。

    image-20200710094911258

项目详情界面

image-20200710091938754

书写 .drone.yml 配置文件

Hello World

在你的项目根目录,新建 .drone.yml 并写入以下内容

kind: pipeline
name: default
steps:
    -   name: Hello World
        image: centos
        commands:
            - echo Hello World
Key 含义
kind 默认为 pipeline
type 这里没有用到,标志本次构建使用的 runner 类型,默认是 docker 即默认使用Docker Runner
name 因为drone支持同时书写多个构建任务,所以需要为本任务起个名字
steps 数组结构,流水线化的构建步骤
steps.images 本步骤运行在哪个docker镜像中,该镜像必须存在于 docker hub 中
steps.commands 构建过程中,将会依次执行的命令,如果命令退出码非0,将会终止构建本次构建

提供 JSON 版本来辅助理解数据结构。当然也可以直接使用json,因为json是合法的yml格式

{
    "kind": "pipeline",
    "name": "default",
    "steps": [
        {
            "name": "Hello World",
            "image": "centos",
            "commands": [
                "echo Hello World"
            ]
        }
    ]
}

Drone 配置文件除 yml 和 json 之外,还可以使用 jsonnet,官方示例:https://docs.drone.io/pipeline/scripting/jsonnet/

一次大胆的尝试

cat >.drone.yml<

Gogs

image-20200710103206262

Drone

image-20200710103405063

image-20200710103716309

image-20200710103924129

注:如果你的构建一直处于等待开始状态,也就是齿轮转圈不成功也不失败。你就要检查一下 agent 容器是否正确的启动和drone 主服务是否能正确的链接到 agent 容器中了。一般来说是主服务没有链接上,一直在等待 agent。

关于秘密

为新工程开启构建 一节已经略微解释过秘密的作用。本节主要描述如何使用秘密

新建秘密

为什么我们要定义一个叫做 log-path 的值,而不是password等真的秘密。一会儿你就知道了

image-20200710110347778

添加完成

image-20200710110444166

在 .drone.yml 中使用秘密

修改 Hello World 时建立的 .drone.yml,使用 from_secret 来取出秘密的值

cat >.drone.yml<

我们加入了 environment 组,该组的作用是在运行的容器内预先设置一些环境变量。并且建立了几个环境变量。

重点: VARPATH是直接明文,LOGPATH 则是使用了 from_secret 并输入了我们刚才在web界面上新建的秘密的key。

所以可以简单的理解 from_secret 是为了从秘密读取某个key,from_secret 除了 environment 之外,也可以应用于任意的字段中。

注:一般的shell命令使用一个$来获取变量,而 commands 使用$$ 是因为 yml 会解析$,并且替换为yml变量值,使用两个$$转义则可以保持原文。

验证

image-20200710112713961

注:因为无法看到原文,所以使用password举例的话并不能验证是否正确。使用一个目录来 ls 则可以判断是否真的读取到了秘密的值

Runner

管道可帮助您自动执行软件交付过程中的步骤,例如启动代码生成、运行自动测试以及部署到暂存环境或生产环境。管道执行由源代码存储库触发。代码更改会触发运行相应管道的 Drone 的 Webhook。其他常见触发器包括自动计划或用户启动的工作流。通过将文件放在 git 存储库的根目录来配置管道。yaml 语法设计为易于阅读和表达,以便查看存储库的任何人都可以理解工作流。

本例使用刚才启动的 ssh runner,其它runner的使用可参考官方示例https://docs.drone.io/pipeline/overview/

npm init
npm install helloworld

cat >.drone.yml<

注:

  1. 这里的 password 我们使用的就是从秘密中获取到的
  2. 也可以使用 ssh_key 来链接,但是我们启动 ssh runner 时并未映射key文件,所以使用密码进行演示。
  3. npm init 是为了让项目转换成npm项目,以演示 npm 等命令,并非必须
  4. PATH设置这个值是我的 node安装目录,为了让 commands 中的 npm 可以正确执行。你可以换成你自己的node安装路径
  5. 这次配置了多个 step,drone 也将会在ssh链接到的主机中依次执行这些命令。

执行结果

image-20200710135012935

image-20200710135107129

执行正确,构建完成。

image-20200710135930241

复合构建任务

我们在 Hello World 中提到过,是可以书写多个构建任务的。原理是利用 yml 可以使用 --- … 拼接多个文件的特性,简单的可以理解为 .drone.yml 可以是多个 .drone.yml 拼起来的。

示例:将我们的 Hello World 和 ssh runner 任务拼起来,同时执行。

---
kind: pipeline
name: Hello World
steps:
    -   name: Hello World
        image: centos
        environment:
            VARPATH: /var
            LOGPATH:
                from_secret: log-path
        commands:
            - echo $${VARPATH}
            - echo $${LOGPATH}
            - ls $${LOGPATH}

---

kind: pipeline
type: ssh
name: Ssh-Runner

server:
    host: xxxxx.org
    user: root
    password:
        from_secret: password

steps:
    -   name: list
        commands:
            - ls /var
    -   name: npm
        environment:
            PATH: "$$PATH:/opt/node-v14.3.0-linux-x64/bin/"
        commands:
            - pwd
            - node --version
            - npm version
            - npm install
...

每一对---中间,就是一个构建任务。... 表示结束,可省略。

效果

image-20200710142452894

image-20200710142522447

使用 docker-compose 编排容器

本文不对 docker-compose 进行讲解,可前往官网学习。

这份文件的作用与启动一节的ssh命令效果一致。其中的DOCKER_HOST 需要根据实际的值来进行替换

cat >docker-compose.yml<

插件

Drone 还有相当丰富的插件可以使用,示例:https://docs.drone.io/plugins/overview/

并不像其它的软件一样提供插件开发的api,drone 插件的原理就是运行docker镜像。在容器启动时自动加载step中写入的环境变量或命令。你可以完全将插件可以将它当作一种 step。

原理简单,不再赘述。

我们最终的代码结构

.
├── .git
│   └── ...
├── node_modules
│   └── helloworld
│       └── ...
├── .drone.yml
├── package-lock.json
└── package.json

补充

在 Settings 页面的底部,可以生成一个小图标链接,标志当前工程的最近一次构建状态。b格满满hhhhh

一瞬间成就感就来了hhhhh,感觉花两天时间研究 drone 是超值的

总结

我们已经学会了 drone 的安装、配置、基本使用,也知道了如何使用drone进行自动构建和排查出现的问题,学到了“秘密”的使用方法,还学会了一个 ssh runner 和执行多个构建任务。

那么现在我们就可以实现在代码更新后自动操作远程主机,更新、测试、编译、部署,实现基本的持续集成。

但是Drone 的能力,远不止于此。

你可能感兴趣的:(ci,持续集成,持续交付,docker,docker-compose)