公司之前一直在使用 Jenkins+Gitlab 作为 CI/CD 工具, Jenkins 非常强大,它完成了几乎所有 CI/CD 的工作,并且应用于整个团队有好长一段时间了。但是随着公司服务容器化的推进, Jenkins 的一些弊端也凸显了出来:
- 重量级:Jenkins 功能十分齐全,几乎可以做所有的事情。但是这也是他的一个弊端,过于重量级,有时候往往一个小的修改需要改动许多地方,升级\下载插件后需要进行重启等。
- 升级不易:在一些安全 Jenkins 相关的安全漏洞被公开后,我们会对 Jenkins 进行升级,但这也不是一件容易的事。之前就出现过升级\重启后,所有 job 丢失,虽然我们所有项目配置都是以 Jenkinsfile 的形式统一存储,但是每个 job 都需要重新重新创建,包括每个 job 的权限。
- 权限控制复杂:这其实也是 Jenkins 的一大优势,可以精确控制每个用户的权限,但是需要花费更多时间去配置,时间长了也会出现权限混乱的问题。
- UI界面:虽然有 Blue Ocean 这样的插件来展示 pipeline ,但是还是没有从根本改变它简陋的 UI 界面。
总结:其实就是公司嫌占用内存大,运行在容器中,jenkins+gitlab在构建时共占20多G内存,而drone+gitea在构建时共占2G左右,所以要换drone+gitea,那我怎么办,我一打工人我怎么办,开始我的面向百度部署……
Drone 是一款基于 Docker 的 CI/CD 工具,所有编译、测试、发布的流程都在 Docker 容器中进行
开发者只需在项目中包含 .drone.yml 文件,将代码推送到 git 仓库,Drone 就能够自动化的进行编译、测试、发布。
drone 目前支持四种 git 托管服务(github, gitlab, gogs, gitea) 而 drone-server 预先知晓了对应托管服务的 API,drone 的很多功能比如拉取 git repo list/add webhook to repo 都是通过这些 API 完成的。
还有 drone 并不维护 user 这个概念,它把 user 的管理委托具体的托管服务。以 gitea 为例,我们在登录 drone 时,实际上相当于 drone 把用户名密码传给了gitea(委托鉴权)。同样由于这个原因,激活某个 repo 的构建(给repo加webhook) 能否成功取决于你这个账号在 gitea 里是不是该 repo 的管理员。
这篇主讲概念挺易懂,记录一下
功能灵活强大:构建、测试、发布、部署,你想干什么都可以,一套系统全搞定
兼容性好:支持所有 SCM、所有平台、所有语言
环境部署简单:原生支持 Docker 容器,启动两个容器就完成了部署,其它构建、测试、部署工具在使用时会自动从 docker 仓库拉取
扩展性强:强大的插件系统,丰富的插件可以免费使用,也可以自定义
配置简单:正如官方宣传的那样,“configuration as a code”,所有功能、步骤、工具、命令,一个 yaml 配置文件全搞定
维护简单:直接复用 SCM 的账号体系和权限管理,无需注册用户、分配权限
| 角色 | 作用 | |
|---|---|---|
| Drone | 服务中心 | 前台小妹, 24小时跟进客户(Gitea)的新需求(.drone.yml), 然后把需求(.drone.yml)通知打工人(runner) 来干活 |
| Gitea | 客户 | 准备好代码、和配置单(.drone.yml) |
| drone-runner | 打工人 | 打工人根据清单里不同的零件(容器)生产产品, 再交付给服务中心(Drone) |
- Server:为Drone的管理提供了Web页面,用于管理从Git上获取的仓库中的流水线任务。
- Runner(Agent):一个单独的守护进程,会轮询Server,获取需要执行的流水线任务,之后执行。
- drone-runner不是必选的,官方不推荐吧runner和server安装在一个实例上
mkdir -p /data/mysql/{conf,data,logs}
vim /data/mysql/conf/my.cnf
[mysqld]
port=3306
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
symbolic-links=0
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
init_connect='SET NAMES utf8
default-storage-engine=INNODB
character_set_server=utf8mb4
innodb_default_row_format=DYNAMIC
innodb_large_prefix=ON
innodb_file_format=Barracuda
innodb_log_file_size=2G
chmod 777 /data/mysql/logs/
docker run -itd --name mysql -p3306:3306 -v /data/mysql/conf/:/etc/mysql/conf.d -v /data/mysql/data/:/var/lib/mysql -v /data/mysql/logs/:/var/log/ -eMYSQL_ROOT_PASSWORD="mysql123456" mysql:5.7
docker exec -it mysql /bin/bash -c 'cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime'
———————————————————————————已有库执行操作———————————————————————————————
docker exec -it mysql /bin/bash
mysql -uroot -pmysql123456
create database gitea default charset 'utf8mb4';
grant all on *.* to 'gitea'@'%' identified by 'gitea';
flush privileges;
mkdir -p /data/gitea/data/
vim /data/gitea/gitea.yaml
version: '3'
networks:
gitea:
external: false
volumes:
gitea:
driver: local
services:
server:
image: gitea/gitea:1.17.1
container_name: gitea
environment:
- USER_UID=1000
- USER_GID=1000
- DB_TYPE=mysql
- DB_HOST=172.17.0.1:3306
- DB_NAME=gitea
- DB_USER=gitea
- DB_PASSWD=gitea
restart: always
networks:
- gitea
volumes:
- /data/gitea/data/:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- '10800:3000'
- '2221:22'
docker-compose -f /data/gitea/gitea.yaml up -d
容器启动后,通过域名或IP+端口的方式访问,进行初始配置,并创建drone应用
设置——>应用——>创建应用:
客户端ID:
c256df8a-e8b1-4adb-acd4-125585f744b4
客户端密钥:
gto_c5lwzx7sl2hcueing7fj76akbe5m4gmb5df57keeagwb3mctjdfa
应用名称:
drone
重定向 URI:
http://drone.***.cn/login
生成共享密钥:
# openssl rand -hex 16
LFS_JWT_SECRET = qTBmOJDyX2opTIGVh70IOty5VteR-SI2LDKh2tyU090
Drone部署需要安装docker-server(Drone 与流行的源代码控制管理提供商无缝集成) WEB界面和docker-runner守护进程执行器
创建一个共享密钥,用于drone-runner和drone-server之间的通信
[root@master drone]# openssl rand -hex 16
MH3HMzA7KC_frJunGTcDAw8Nx5druSqsKlwZDTI_GCI
部署drone-server
可参考:https://docs.drone.io/server/reference/
mkdir -p /data/drone/data/
docker run \
--volume=/data/drone/data:/data \
--env=DRONE_GITEA_SERVER=http://gitea.***.cn \ # GitLab 服务器 url,默认https://github.com
--env=DRONE_GITEA_CLIENT_ID=c256df8a-e8b1-4adb-acd4-125585f744b4 \ # GitLab oauth 客户端 ID(必填项)
--env=DRONE_GITEA_CLIENT_SECRET=gto_c5lwzx7sl2hcueing7fj76akbe5m4gmb5df57keeagwb3mctjdfa \ # GitLab oauth 客户端 ID(必填项)
--env=DRONE_RPC_SECRET=MH3HMzA7KC_frJunGTcDAw8Nx5druSqsKlwZDTI_GCI \ # 验证服务器和运行器之间的 rpc 连接(drone-server和drone-runner连接时必填项)
--env=DRONE_SERVER_HOST=http://drone.***.cn \ # 验证服务器和运行器之间的 rpc 连接(drone-server和drone-runner连接时必填项)
--env=DRONE_SERVER_PROTO=http \ # drone服务使用的协议 (必填项)
--env=DRONE_REGISTRATION_CLOSED=true \ # 禁止用户注册
--env=DRONE_OPEN=false \
--env=DRONE_ADMIN=root \
--env=DRONE_USER_CREATE=username:root,admin:true \ # Drone管理员用户创建
--publish=7120:80 \
--publish=7121:443 \
--restart=always \
--detach=true \
--name=drone \
drone/drone:2.13.0
drone启动参数很多,下面解释下:
# DRONE_GITLAB_SERVER: GitLab 服务器 url,默认https://github.com
# DRONE_GITLAB_CLIENT_ID: GitLab oauth 客户端 ID(必填项)
# DRONE_GITLAB_CLIENT_SECRET: GitLab oauth 客户端密码 (必填项)
# DRONE_RPC_SECRET: 验证服务器和运行器之间的 rpc 连接(drone-server和drone-runner连接时必填项,用于连接Server和Runner之间,两者需一致)
# DRONE_SERVER_HOST: 提供drone服务主机名或 IP 地址 (必填项)
# DRONE_SERVER_PROTO: drone服务使用的协议 (必填项)
# DRONE_USER_CREATE: Drone管理员用户创建
部署drone-runner
可参考:https://docs.drone.io/runner/docker/configuration/reference/
docker run --detach \
--volume=/var/run/docker.sock:/var/run/docker.sock \
--env=DRONE_RPC_PROTO=http \
--env=DRONE_RPC_HOST=http://drone.***.cn \
--env=DRONE_RPC_SECRET=MH3HMzA7KC_frJunGTcDAw8Nx5druSqsKlwZDTI_GCI \
--env=DRONE_RUNNER_CAPACITY=2 \
--env=DRONE_RUNNER_NAME=my-first-runner \
--env=DRONE_RUNNER_CAPACITY=5
--publish=7122:3000 \
--restart=always \
--name=runner \
-e DOCKER_API_VERSION=1.39 \
drone/drone-runner-docker:1.8.2
drone-runner启动参数很多,下面解释下:
# DRONE_RPC_PROTO: 用于连接 Drone 服务器的协议
# DRONE_RPC_HOST: 提供 Drone 服务器的主机名
# DRONE_RPC_SECRET: 用于向 Drone 服务器进行身份验证的共享密钥(用于连接Server和Runner之间,两者需一致)
# DRONE_RUNNER_CAPACITY: 限制运行器可以执行的并发管道的数量
# DRONE_RUNNER_NAME: 设置runner的名字
验证drone-runner是否连接上drone-server(successfully pinged the remote server):
# docker logs -ft runner
2022-10-25T11:06:52.308205454Z time="2022-10-25T11:06:52Z" level=info msg="starting the server" addr=":3000"
2022-10-25T11:06:52.321089697Z time="2022-10-25T11:06:52Z" level=info msg="successfully pinged the remote server"
2022-10-25T11:06:52.321109106Z time="2022-10-25T11:06:52Z" level=info msg="polling the remote server" arch=amd64 capacity=2 endpoint="http://drone.***.cn" kind=pipeline os=linux type=docker
浏览器访问drone-server Web界面(http://192.168.30.33:7118),点击继续Continue,自动跳转gitlab,授权即可进入drone
进入可看到gitlab所有项目,选择一个项目,进入点击activate 激活进入项目即可
如果要支持导入,需要在conf/app.ini文件中增加如下配置
[migrations]
ALLOW_LOCALNETWORKS = true
[webhook]
ALLOWED_HOST_LIST = 10.10.9.208/16
# docker-compose restart
mkdir -p /data/registry/data
mkdir /root/registry-auth
yum -y install httpd-tools
htpasswd -Bbn bob pwd@123 > /root/registry-auth/htpasswd
创建镜像服务器容器加载身份验证:docker run -d -p 7123:5000 --restart=always --name registry -v /data/registry/data:/var/lib/registry -v /root/registry-auth/:/auth/ -v /root/registry:/var/lib/registy -e "REGISTRY_AUTH=htpasswd" -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry REALM" -e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd" registry
docker tag jenkins/jenkins:lts 192.168.30.33:5000/jenkins:v1
docker push 192.168.30.33:5000/jenkins:v1
vim /etc/docker/daemon.json # 配置私有仓库地址
{
"insecure-registries": ["192.168.30.33:5000"], # docker客户端将https请求更改为http请求,不然会报错:Error response from daemon: Get https://192.168.220.125:5000/v2/: http: server gave HTTP response to HTTPS client
"registry-mirrors": ["https://leo12tew.mirror.aliyuncs.com"]
}
systemctl daemon-reload
systemctl restart docker
docker push 192.168.30.33:5000/jenkins:v1
部署registry私有仓库遇到的报错:
一、配置私有仓库后,docker启动不了,报错log:
Nov 3 15:55:10 jhsc_tool_01 polkitd[725]: Registered Authentication Agent for unix-process:31811:19363709 (system bus name :1.1387 [/usr/bin/pkttyagent --notify-fd 5 --fallback], object path /org/freedesktop/PolicyKit1/AuthenticationAgent, locale zh_CN.utf8)
Nov 3 15:55:10 jhsc_tool_01 polkitd[725]: Unregistered Authentication Agent for unix-process:31811:19363709 (system bus name :1.1387, object path /org/freedesktop/PolicyKit1/AuthenticationAgent, locale zh_CN.utf8) (disconnected from bus)
这里报错我遇到的是 /usr/lib/systemd/system/docker.service 文件中已添加私有仓库地址
ExecStart=/usr/bin/dockerd --insecure-registry 192.168.30.33:5000
而我又在 /etc/docker/daemon.json 中添加私有库地址,这两个添加一个即可
"insecure-registries": ["192.168.30.33:5000"],
二、docker报错:Get https://registry-1.docker.io/v2/: x509: certificate has expired or is not yet valid
这个错误一般都是本地系统时间错误导致报错证书过期
ntpdate cn.pool.ntp.org
APP_NAME = 鲸核
RUN_MODE = prod
RUN_USER = git
[repository]
ROOT = /data/git/repositories
[repository.local]
LOCAL_COPY_PATH = /data/gitea/tmp/local-repo
[repository.upload]
TEMP_PATH = /data/gitea/uploads
[server]
APP_DATA_PATH = /data/gitea
DOMAIN = http://gitea.***.cn/
SSH_DOMAIN = gitea_ssh.***.cn:7119
#SSH_DOMAIN = 192.168.30.33:7119
HTTP_PORT = 3000
ROOT_URL = http://gitea.***.cn/
DISABLE_SSH = false
SSH_PORT = 22
SSH_LISTEN_PORT = 22
LFS_START_SERVER = true
LFS_JWT_SECRET = MH3HMzA7KC_frJunGTcDAw8Nx5druSqsKlwZDTI_GCI
OFFLINE_MODE = false
[database]
PATH = /data/gitea/gitea.db
DB_TYPE = mysql
HOST = 172.17.0.1:3306
NAME = gitea
USER = gitea
PASSWD = gitea
LOG_SQL = false
SCHEMA =
SSL_MODE = disable
CHARSET = utf8mb4
[indexer]
ISSUE_INDEXER_PATH = /data/gitea/indexers/issues.bleve
[session]
PROVIDER_CONFIG = /data/gitea/sessions
PROVIDER = file
[picture]
AVATAR_UPLOAD_PATH = /data/gitea/avatars
REPOSITORY_AVATAR_UPLOAD_PATH = /data/gitea/repo-avatars
DISABLE_GRAVATAR = false
ENABLE_FEDERATED_AVATAR = true
插件参考:https://plugins.drone.io/
kind: pipeline
type: docker
name: deployment
clone:
disable: true
steps:
- name: backend image build
image: alpine/git
commands:
- echo 你好...
我们构建下载的那些包是可以存在本地磁盘的,所以不需要每次都去下载。可以参考Drone的缓存插件:drone-volume-cache,将下载的包缓存到磁盘中,下次再构建的时候就不需要下载了,从而提高构建速度。
在Drone的项目配置页面,会看到Badges选项(本人并未使用)

把里面的内容复制出来,添加到项目的README.md文件头部,这样我们就可以在Gitea项目页面中看到当前流水线的状态,就像右上角红框中显示的那样。
提交代码时通过备注增加[CI SKIP]跳 例: git commit –m “first commit [CI SKIP]”
Drone 天生就省去了各种账户\权限的配置,直接与 gitlab、github、gitea、Bitbucket 这样的源码管理系统操作源代码的权限一致。
项目——>设置——>可见性(将仓库设为私有——>更新仓库设置)——>签名验证设置(提交者: 信任与提交者匹配的签名——>更新仓库设置)
1、Web 钩子 测试推送一直失败
2、项目根目录还没有 .drone.yml 文件
Delivery: Post "http://drone:80/hook?secret=3yXXUv0mKyEZWNi3CGCDQLyBxTVTE7i8": read tcp 172.22.0.5:38650->172.22.0.4:80: i/o timeout
用docker logs 命令查看到 drone 容器的日志
{
"commit":"556017b3f889b768e5f69ae164091fef9baa50a3",
"error":"Not Found",
"event":"push",
"level":"warning",
"msg":"trigger: cannot find yaml", # 没有找到 .yml 文件
"ref":"refs/heads/master",
"repo":"root/demo",
"time":"2021-04-27T08:00:32Z"
}
访问 Drone 自动跳转到 Gitea授权这一步时候, 报错:授权失败。
那是因为 Drone 的 DRONE_SERVER_HOST 配置错误导致授权失败,正确应该是 能被外部访问的主机名(有端口带端口), 要注意, 你即使你改正确了, 注意缓存、没有新容器等问题
docker logs 容器 查看日志确认,url是否正确
{
"acme":false,
"host":"www.wulaoye.top:8080",
"level":"info",
"msg":"starting the http server",
"port":":80",
"proto":"http",
"time":"2021-04-27T07:37:56Z",
"url":"http://www.wulaoye.top:8080"
}
Error response from daemon: client version 1.40 is too new. Maximum supported API version is 1.39
是因为docker的版本问题, 所以你别管管是啥, 宿主机、容器等 ENV 都要设置一下 DOCKER_API_VERSION=1.39 环境变量, 另外容器配置不会因为 docker-compose restart 重启命令就会重新加载配置, 要用 up 命令, 该命令会检测配置变动, 重新加载配置
解决方案一:
# docker version
Client:
Version: 18.09.1
API version: 1.39
Go version: go1.10.6
Git commit: 4c52b90
Built: Wed Jan 9 19:35:01 2019
OS/Arch: linux/amd64
Experimental: false
Server: Docker Engine - Community
Engine:
Version: 18.09.1
API version: 1.39 (minimum version 1.12)
Go version: go1.10.6
Git commit: 4c52b90
Built: Wed Jan 9 19:06:30 2019
OS/Arch: linux/amd64
Experimental: false
# vim /etc/profile
export DOCKER_API_VERSION=1.39 # 添加
# source /etc/profile
解决方案二:运行容器时加参数
-e DOCKER_API_VERSION=1.39
kind: pipeline
type: docker
name: test-admin
clone:
disable: false
steps:
- name: "构建test-admin可执行文件"
image: golang:1.18-alpine
environment:
GOPROXY: https://goproxy.cn,direct
volumes:
- name: mount
path: /testtest
commands:
- go mod tidy
- go build -o test-admin main.go
- ls
- pwd
- rm -rf /testtest/*
- mv /drone/src/* /testtest
- name: build-start
image: appleboy/drone-ssh # SSH工具镜像
settings:
host: 192.168.30.33 # 远程连接地址
username: root # 远程连接账号
password:
from_secret: ssh_password # 从Secret中读取SSH密码
port: 22 # 远程连接端口
command_timeout: 5m # 远程执行命令超时时间
script:
- cd /www/ # 进入宿主机构建目录
- ls # 更改为可执行脚本
volumes:
- name: mount
host:
path: /www/tmp