CICD——gitea+drone部署

前言

公司之前一直在使用 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简介

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 的管理员。
这篇主讲概念挺易懂,记录一下

为什么使用 Drone 作为 CI/CD 工具

功能灵活强大:构建、测试、发布、部署,你想干什么都可以,一套系统全搞定
兼容性好:支持所有 SCM、所有平台、所有语言
环境部署简单:原生支持 Docker 容器,启动两个容器就完成了部署,其它构建、测试、部署工具在使用时会自动从 docker 仓库拉取
扩展性强:强大的插件系统,丰富的插件可以免费使用,也可以自定义
配置简单:正如官方宣传的那样,“configuration as a code”,所有功能、步骤、工具、命令,一个 yaml 配置文件全搞定
维护简单:直接复用 SCM 的账号体系和权限管理,无需注册用户、分配权限

Drone + Gitea 的 CI/CD 理解

角色 作用
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安装在一个实例上

Drone部署

mysql部署并创建库、用户

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;

部署gitea(docker-compose)

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及Runner

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

部署registry私有仓库

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

.drone.yml

插件参考: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的缓存插件:drone-volume-cache,将下载的包缓存到磁盘中,下次再构建的时候就不需要下载了,从而提高构建速度。

小技巧

在Drone的项目配置页面,会看到Badges选项(本人并未使用)
在这里插入图片描述

把里面的内容复制出来,添加到项目的README.md文件头部,这样我们就可以在Gitea项目页面中看到当前流水线的状态,就像右上角红框中显示的那样。

git提交代码如何让drone跳过本次提交,不执行pipeline

提交代码时通过备注增加[CI SKIP]跳 例: git commit –m “first commit [CI SKIP]”

Drone优化

权限管理

Drone 天生就省去了各种账户\权限的配置,直接与 gitlab、github、gitea、Bitbucket 这样的源码管理系统操作源代码的权限一致。

项目——>设置——>可见性(将仓库设为私有——>更新仓库设置)——>签名验证设置(提交者: 信任与提交者匹配的签名——>更新仓库设置)
在这里插入图片描述
在这里插入图片描述

故障记录

Web 钩子 测试推送一直失败

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"
}
.drone.yml构建失败

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

猜你喜欢

转载自blog.csdn.net/weixin_45373345/article/details/127497832