我最早接触的持续集成工具是大名鼎鼎的 Jenkins,接手同事留下的一个单节点 Jenkins。由于没有太强烈的使用需求,体会不到 Jenkins 的强大,印象停留在 “麻烦” 两个字:需要给研发同事手动添加账号,然后用一个有很多很多方框的表单来设置权限。而 Drone CI 在账号权限方面就给人眼前一亮的感觉,直接集成代码仓库,和 Github Actions,Travis CI 等使用流程类似。另外,Drone CI 原生基于容器,插件直接做成镜像,这样写出来的 yaml 配置文件可以做到简短清晰。本文记录 Drone CI 使用过程中遇到的问题及解决方案,基于 1.6.1 版本,可能不适用于最新版本。
如有兴趣,可以看看我个人的 Drone CI 的运行效果:https://ci.annhe.net/annProg/chart。
安装
代码仓库为 Gitea,使用 Kubernetes 安装,参考配置如下。
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: drone-server-rbd-rbd1
spec:
accessModes:
- ReadWriteOnce
storageClassName: rbd
resources:
requests:
storage: 200Gi
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: drone-rbac
subjects:
- kind: ServiceAccount
name: default
namespace: default
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: drone-server
namespace: default
labels:
app: drone-server
spec:
replicas: 1
selector:
matchLabels:
app: drone-server
strategy:
type: RollingUpdate
# 由于挂载了 rbd,需要先销毁pod才能创建新的
rollingUpdate:
maxUnavailable: 1
maxSurge: 0
template:
metadata:
labels:
app: drone-server
spec:
containers:
- name: drone-server
image: cr.xxx.com/drone/drone:1.6.1
env:
- name: UPDATEAT
value: 2019-10-27-21:22
- name: DRONE_KUBERNETES_ENABLED
value: "true"
- name: DRONE_KUBERNETES_NAMESPACE
value: default
- name: DRONE_GITEA_SERVER
value: https://git.xxx.com
- name: DRONE_GITEA_CLIENT_ID
value: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
- name: DRONE_GITEA_CLIENT_SECRET
value: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- name: DRONE_SERVER_HOST
value: ci.xxx.com
- name: DRONE_SERVER_PROTO
value: https
- name: DRONE_USER_CREATE
value: username:root,admin:true
- name: DRONE_GIT_ALWAYS_AUTH
value: "true"
- name: DRONE_RPC_SECRET
value: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
- name: DRONE_LOGS_DEBUG
value: "true"
- name: DRONE_LOGS_TRACE
value: "true"
- name: DRONE_LOGS_PRETTY
value: "true"
- name: DRONE_GIT_IMAGE
value: cr.xxx.com/drone/git:latest
# 此镜像修复了 k8s 上 image pull policy 问题
# tag 为 latest 且未指定 pull policy 时,policy 为 always
- name: DRONE_KUBERNETES_IMAGE
value: cr.xxx.com/drone/controller:1.6.1-1
- name: DRONE_KUBERNETES_IMAGE_PULL
value: IfNotExists
ports:
- name: http
containerPort: 80
volumeMounts:
- name: data
mountPath: "/data"
volumes:
- name: data
persistentVolumeClaim:
claimName: drone-server-rbd-rbd1
restartPolicy: Always
---
kind: Service
apiVersion: v1
metadata:
name: drone-server-service
namespace: default
spec:
type: NodePort
selector:
app: drone-server
ports:
- protocol: TCP
port: 80
name: http
targetPort: 80
nodePort: 30000
然后使用 Ingress Nginx 做负载均衡,注意需要增大 proxy_read_timeout
的值,默认的 3s
对于 drone 的 api/stream
接口可能太短。
使用kaniko
我对 CI 的主要需求是做镜像,kaniko 这种不需要特权模式就能生成镜像的工具是很好的选择。使用 Drone CI 的 kaniko 插件,可以参考以下几点:
auto_tag
支持,参见 Github- 自动更新镜像仓库描述信息,参见 自动更新Harbor仓库的描述信息
- cache 支持,参见 Github
用 Drone CI 生成镜像的一个例子,可以看到 yaml 配置很简洁。
kind: pipeline
name: chart
steps:
- name: build
image: banzaicloud/drone-kaniko:0.5.1
settings:
repo: ann17/chart
auto_tag: true
username:
from_secret: username
password:
from_secret: password
问题记录
插件镜像不更新
安装部分 yaml 中有以下代码:
# 此镜像修复了 k8s 上 image pull policy 问题
# tag 为 latest 且未指定 pull policy 时,policy 为 always
- name: DRONE_KUBERNETES_IMAGE
value: cr.xxx.com/drone/controller:1.6.1-1
这里的修复方案针对 1.6.1
版本,新版本可能不存在此问题了。修复方案见 Github。使用此分支重新编译 drone-controller
。在 Drone 代码的 go.mod
中添加以下代码后重新编译。
replace github.com/drone/drone-runtime => github.com/ops-itop/drone-runtime k8s-pullpolicy
另外,如果不重新编译,也可以在 yaml 中手动指定 pull policy 来解决:
pull: always
但是对于 tag
为 latest
的镜像,自动设置为 always
才更合理。
secret管理
只能给 repo 添加 secret,secret 更改比较麻烦。考虑提issue,增加用户级别的 secret,比如,用户级别的 docker push password,当 repo 中未定义 docker push password,yaml
中又引用时,使用用户级别的 docker push password。但是搜索到一个 issue,见 drone/issues/1619 ,提出一个 Organization
级别的 secret
概念,被作者给否了,作者提出一个变通的方案:使用命令行批量设置 secret,代码如下。
drone repo ls | xargs -I{} drone secret add {} KEY VALUE
特定分支触发
以下示例,在 k8s-sidecar
分支 push
或者创建 tag
时触发 CI。
when:
ref:
- refs/heads/k8s-sidecar
- refs/tags/*
----或者用trigger
trigger:
ref:
- refs/heads/test
- refs/tags/*
参考资料
1. https://drone.io/
2. https://discourse.drone.io/t/drone-1-3-1-on-kubernetes-not-pull-latest-plugin-image/6088
3. https://docker-runner.docs.drone.io/configuration/conditions/
4. https://discourse.drone.io/t/execute-a-build-step-only-when-a-feature-branch-is-tagged-with-a-specific-pattern/1237/3
发表回复