使用 drone CI 已有小半年,在将原有项目的 CI 系统从 jenkins 向 drone 迁移的时候,也陆陆续续遇到了一些问题。在这段时间,也完成了使用官方插件到插件定制的转变,使得 drone CI 流程更贴合我们 devops 开发流程。通过这篇文章总结一下目前我们对 drone 进行的一些定制化开发以及使用技巧,由于 drone 官方的文档不是很详细,所以也希望通过这种方法来和其他使用 drone 的用户分享和交流使用经验。
在默认情况下,drone 会按照步骤执行,但是有时会遇到前后端在同一个 repo 的情况,这时使用并行构建就可以省去很多的构建时间。
构建流程:
在下面的示例里会展示一个如下流程:repo 中包含一个由 Java 写的服务以及一个 vue 前端项目,maven 构建和 npm 构建同时进行,maven 构建成功后会镜像 docker 镜像构建并上传镜像仓库,docker 构建成功后会镜像 k8s 部署,部署成功后会进行 vue 项目前端发布,在 k8s 部署成功并且前端发布成功后,进行钉钉构建成功同时,否则进行钉钉构建失败通知。
前端构建 ———————————— 前端发布 / / / / / 钉钉通知 / / / 后端构建 —— 镜像构建 —— k8s部署 ——————
.drone.yml
配置
kind: "pipeline" name: "default" steps: - name: "Maven编译" image: "guoxudongdocker/drone-maven" commands: - "mvn clean install" depends_on: [ "clone" ] - name: "构建镜像" image: "guoxudongdocker/drone-docker" settings: username: from_secret: "docker_user" password: from_secret: "docker_pass" dockerfile: "Dockerfile" repo: "registry-vpc.cn-shanghai.aliyuncs.com/guoxudong/test" registry: "registry-vpc.cn-shanghai.aliyuncs.com" tags: "${DRONE_BUILD_NUMBER}" depends_on: [ "Maven编译" ] - name: "Kubernetes 部署" image: "guoxudongdocker/kubectl" settings: config: "deploy/overlays/uat" timeout: 300 check: false depends_on: [ "构建镜像" ] - name: "前端构建" image: "guoxudongdocker/node-drone" commands: - "npm install" - "npm run build" depends_on: [ "clone" ] - name: "前端上传" image: "guoxudongdocker/node-drone" commands: - "do something" depends_on: [ "前端构建","Kubernetes 部署" ] - name: "钉钉通知" image: "guoxudongdocker/drone-dingtalk" settings: token: from_secret: "dingding" type: "markdown" message_color: true message_pic: true sha_link: true depends_on: [ "前端上传","Kubernetes 部署" ] when: status: - "failure" - "success"
在使用 drone 中遇到的最大问题就是,我们有很多项目都是在一个 repo 中有很多子项目,而每个子项目都是 k8s 中的一个服务,这时一个 .drone.yml
文件很难把所有的服务都囊括。而又不想每个子项目拉一个分支管理,当前的模式就很不合适。
针对这个问题,我们对 drone 进行了定制化开发,会在每次提交代码后,对新提交的代码和老代码进行比较,筛选出做了修改的子项目,然后对有修改的子项目尽心 CI ,其余的子项目则不进行发布。
而以上的方式仅适用于测试环境的快速迭代,生产环境则采用 tag 的模式,针对不同的子项目,打不同前缀的 tag ,比如子项目为 test1 ,则打 test1-v0.0.1
的 tag,就会对该子项目进行生产发布。
有修改的子项目
无修改的子项目
之前的 Kubernetes 发布只是将服务发布到 Kubernetes 集群,并不管服务是否正常启动。针对这个问题以及我们的 Kubernetes 应用管理模式,我们开发了 drone 的 Kubernetes 发布插件,该插件包括 kubectl
、 kustomize
、 kubedog
,来完善我们的 Kubernetes 发布 step 。
.drone.yml
steps: - name: Kubernetes 部署 image: guoxudongdocker/kubectl volumes: - name: kube path: /root/.kube settings: check: false # 该参数为是否开启子模块检查 config: deploy/overlays/uat # 这里使用 kustomize ,详细使用方法请见 https://github.com/kubernetes-sigs/kustomize timeout: 300 # kubedog 的检测超时 name: {your-deployment-name} # 如果开启子模块检查则需要填入子模块名称 ... volumes: - name: kube host: path: /tmp/cache/.kube # kubeconfig 挂载位置 trigger: branch: - master # 触发 CI 的分支
使用该插件会如果为测试构建,则会自动设置 docker 镜像 tag 为 DRONE_BUILD_NUMBER
;如果为生产构建(git tag),则叫自动设置 docker 镜像 tag 为 DRONE_TAG
,然后通过 kubectl apply -k .
进行部署,同时使用 kubedog
进行部署状态检查,如果服务正常启动则该 step 通过,如果超时或者部署报错则该 step 失败。
根据我们目前的开发模式,对 drone 插件进行了全方位的开发。由于 dockerhub 的镜像拉取经常超时,则将镜像推送到了我们自己的镜像仓库;对钉钉通知也进行了优化;同时也根据我们目前的开发语言进行了插件的开发,提供了基于 Java 、Python 以及 Node.js 的 drone 插件,基本可以满足我们现在的 CI 需求,但随着 drone 的深入使用,越来越多的问题将会暴露出来。后续将会不断解决遇到的问题,持续优化。