在Kubernetes上执行Drone CI/CD

介绍

之前曾使用 docker rundocker-compose 的方式部署过Drone服务,方法比较简单。最近一段时间一直在学习Kubernetes,正好研究一下如何在Kubernetes上部署Drone实现CI/CD。

相比之前在Docker下部署的Drone server-agent 模式,在Kubernetes上运行Drone可以简化我们的部署,其中最大的改进就是不再需要单独的去维护 agent 服务了,Drone会创建一个Kubernetes Job来执行相应的Pipeline。

这个Kubernetes Job会生成一个Pipeline Controller容器。来负责编排管道步骤、收集结果、并向Drone服务器回调通知。

不过,目前在Kubernetes上运行Drone服务仍然是实验性的,官方并不推荐在正式的生产环境中来部署。


实践

注意事项

我通过 Deployment 在VBox虚拟机上的Kubernetes环境中分别部署Gitea和Drone服务。其中有几点需要注意:

  • 为了便于测试,指定 Service 使用 type: NodePort 来绑定主机端口;
  • 由于使用本地环境部署的原因,并没有使用 traefik + host 的方式来设置虚拟域名,关键是在本地环境下gitea的webhook无法通过虚拟域名来执行回调而触发Drone的Pipeline,所以只能使用IP方式;
  • 先部署Gitea服务,其中的 nodePort 不需要手动指定,使用随机端口号即可;
  • 部署Drone服务时,需要手动指定 nodePort 一项,因为在设置环境变量 DRONE_SERVER_HOST 时需要该端口;
执行

gitea安装配置页面,以下几项需要注意:

创建一个简单的 .drone.yml 文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
kind: pipeline
name: default
clone:
disable: true
steps:
- name: test_drone
image: alpine:3.9
commands:
- echo "show hello world by drone"
- echo $(pwd)
- sleep 10

当执行git提交后,Drone容器中的部分日志记录如下:

1
2
3
4
5
{"commit":"6ef0d3355007823ab03c6c1a8ca7ba41bb7c304e","event":"push","level":"debug","msg":"webhook parsed","name":"hello","namespace":"abc","time":"2019-07-10T13:08:24Z"}
{"commit":"6ef0d3355007823ab03c6c1a8ca7ba41bb7c304e","event":"push","level":"debug","msg":"trigger: received","ref":"refs/heads/master","repo":"abc/hello","time":"2019-07-10T13:08:24Z"}
{"build-id":2,"level":"debug","msg":"kubernetes: creating job","repo-id":1,"stage-id":2,"stage-name":"default","stage-number":1,"time":"2019-07-10T13:08:24Z"}
{"build-id":2,"level":"debug","msg":"kubernetes: successfully created job","repo-id":1,"stage-id":2,"stage-name":"default","stage-number":1,"time":"2019-07-10T13:08:25Z"}
{"fields.time":"2019-07-10T13:08:25Z","latency":351766213,"level":"debug","method":"POST","msg":"","remote":"10.244.0.1:50176","request":"/hook?secret=Gfz8OUgBscs2wySUiQZsTRdqDCqK6GBc","request-id":"1Np3FAx2JZldpFOFBkNsnn2jgD1","time":"2019-07-10T13:08:25Z"}

可以看到其中关键的两步:

  • "build-id":2 -- "msg":"kubernetes: creating job"
  • "build-id":2 -- "msg":"kubernetes: successfully created job"

查看自动创建的Job:

1
2
3
$ kubectl -n cicd get job
NAME COMPLETIONS DURATION AGE
drone-job-2-cnbmdfdlov2wqkcsg 1/1 43s 56s

查看相应的Pod:

1
2
3
4
$ kubectl -n cicd get pods
NAME READY STATUS RESTARTS AGE
drone-deploy-77fb9ff86d-w8q9s 1/1 Running 0 17m
drone-job-2-cnbmdfdlov2wqkcsg-c8m56 0/1 Completed 0 5m37s

查看Drone UI中的构建情况:

分析

查看该Pod的详细描述:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
➜ kubectl -n cicd describe pods drone-job-2-cnbmdfdlov2wqkcsg-c8m56
Name: drone-job-2-cnbmdfdlov2wqkcsg-c8m56
Namespace: cicd
...
...
Status: Succeeded
IP: 10.244.1.121
Controlled By: Job/drone-job-2-cnbmdfdlov2wqkcsg
Containers:
drone-controller:
Container ID: docker://8a2e413b84fe6d9dd361cc17b82881f888ff7376605c83bea0714cd5e439523c
Image: drone/controller:1.2.1
Image ID: docker-pullable://drone/controller@sha256:3a57ab277657525b1cfe464d8f38501a4454a5db3d20ca7e56052330df2ec523
Port: <none>
Host Port: <none>
State: Terminated
Reason: Completed
Exit Code: 0
Started: Wed, 10 Jul 2019 02:14:44 +0800
Finished: Wed, 10 Jul 2019 02:14:57 +0800
...
...

可以看到在该Pod内部自动创建了一个基于 drone/controller 镜像的容器来执行Pipeline。

自动移除Jobs

默认情况下,执行完成后的Kubernetes Jobs不会自动从系统中清除,主要是为了便于对Pipeline执行过程中报错的故障排查。

如果需要实现自动清理,这里我找到了两种方式,可以深入的去了解一下:

  1. 设置Kubernetes的 TTLAfterFinished 特性,这也是Drone官方给出的解决方法
  2. 通过第三方的工具来实现:lwolf/kube-cleanup-operator: Kubernetes Operator to automatically delete completed Jobs and their Pods

注意事项

需要为Drone创建相应的ServiceAccount权限。否则会报如下错误:

1
jobs.batch is forbidden: User "system:serviceaccount:default:default" cannot create resource "jobs" in API group "batch" in the namespace "default"

配置流程则直接按照Drone文档中的方法操作即可。

相关参考

坚持原创技术分享,您的支持将鼓励我继续创作!
如有疑问或需要技术讨论,请留言或发邮件到 service@itfanr.cc