文章目录
devops工作流与基础实现
1. Devops工作流
没啥用的前戏介绍
DevOps是一组过程、方法与系统的统称,用于促进开发、技术运营和质量保障(QA)部门之间的沟通、协作与整合。
---- 维基百科
一般来说项目软件从零到最终交付, 大概分为以下几个阶段: 规划、编码、构建、测试、发布、部署和维护。
瀑布模型
对应步骤及其工种
这三个阶段,即开发,测试,布署. 是早期所采用的软件交付模型,称之为“瀑布(Waterfall)模型”。
但需求是会不断变化的, 产品也会不断提出问题的, 瀑布式开发难以满足. 于是软件开发团队引入了新概念: “敏捷开发”.
敏捷开发
敏捷开发其实简单来说,就是把大项目变成小项目,把大时间点变成小时间点. 拆分功能, 将每个需求变为小项目, 不断的进行"开发-测试",美名其曰 "持续".
敏捷开发大幅提高了开发团队的工作效率,让版本的更新速度变得更快。可以帮助更快地发现问题, 风险会更小.
但是问题点依旧, 虽然提升了软件开发的效率和版本更新的速度, 但仅限于开发环节, 部署运维依旧未改变.
DevOps
简介
从目标来看,DevOps就是让开发人员和运维人员更好地沟通合作,通过自动化流程来使得软件交付整体过程更加快捷和可靠。
DevOps 其实包含了三个部分:开发、测试和运维。换句话 DevOps 希望做到的是软件产品交付过程中IT工具链的打通,使得各个团队减少时间损耗,更加高效地协同工作。
这几年云计算技术突飞猛进, 虚拟化、容器、微服务等等, 都为DevOps提供了很好的前提条件.
开发环境和部署环境都可以更好地隔离了,减小了相互之间的影响。
微服务:
就是将原来黑盒化的一个整体产品进行拆分(解耦),从一个提供多种服务的整体,拆成各自提供不同服务的多个个体.
虚拟化:
它从硬件上,将一个系统“划分”为多个系统,系统之间相互隔离,为微服务提供便利。
容器:
在操作系统上划分为不同的“运行环境”(Container),占用资源更少,部署速度更快。
CICD
这种开发模式下带来的新问题是, 如何确保运维上线的即时, 那就是CI和CD。
- CI(持续集成):
- 是指多名开发者在开发不同功能代码的过程当中,可以频繁的将代码行合并到一起并切相互不影响工作。
- CD(持续交付与持续部署):
- 基于某种工具或平台实现代码自动化的构建、测试和部署到线上环境以实现交付高质量的产品
- 持续部署在某种程度上代表了一个开发团队的更新迭代速率。
开发只需要关注代码, 业务逻辑, 测试脚本, 然后提交到代码仓库.
后续测试, 发布, 部署都由自动化脚本完成, 减少运维工作量, 避免人为失误.
DevOps平台
而DevOps平台的搭建可通过如下工具进行实现
项目管理(PM):Jira
代码管理:GitLab
持续集成(CI):GitLab CI
镜像仓库:VMware Harbor 私服nexus
容器:Docker
容器平台: Rancher
镜像扫描:Clairctl
编排:Kubernetes
服务注册与发现:etcd
脚本语言:python
日志管理:EFK
系统监控:prometheus
Web服务器:Nginx
数据库:MySQL redis
负载均衡:Nginx。
产品和UI图:蓝湖
公司内部文档:Confluence。
报警:推送到工作群 企业微信 钉钉
技术选型
初期采取: gogs + drone + docker-compose
后期可采用: gitlab + Jenkins
2. Gogs + Drone 搭建
Gogs
Gogs 的目标是打造一个最简单、最快速和最轻松的方式搭建自助 Git 服务。使用 Go 语言开发使得 Gogs 能够通过独立的二进制分发,并且支持 Go 语言支持的 所有平台,包括 Linux、Mac OS X、Windows 以及 ARM 平台。(引之官网)
官网: https://gogs.io/
上下文
公司项目目前放在 githup 上, 有些奇怪
想往gitlab 上迁移, 奈何公司没有测试服务器, 个人服务器1核2G又不给力,权衡之下, 选择轻量级的 Gogs.
以下为自行搭建的过程, 后续可迁移至公司服务器中, 或升级使用 gitlab, 可当做经验
优缺点
语言:
gogs 国人开发基于go
gitlab 基于ruby
特点:
gogs:
安装简单, 功能简要够用, 对于小团队而言挺合适.
git 版本库, 问题管理, wiki
头像不能自定义(dog)
gitlab:
集成较强的 CICD 功能
功能全面, 适合大团队开发, 相对耗费资源(4G内存)
安装方式
- 源码安装, 需要安装 go 语言
- 使用 Gogs 的二进制包安装, 不需要安装go环境
- 使用 docker 安装
Drone
官网: https://docs.drone.io/server/overview/
简介
Drone 是一个基于Docker容器技术的可扩展的持续集成引擎,用于自动化测试、构建、发布。每个构建都在一个临时的Docker容器中执行,使开发人员能够完全控制其构建环境并保证隔离。开发者只需在项目中包含 .drone.yml文件,将代码推送到 git 仓库,Drone就能够自动化的进行编译、测试、发布。
可以与docker完美集成, 相对于Jenkins来说更加轻量, 可以配合 Gogs 来实现持续集成
- Drone 引入了Pipeline 的概念, 管道可以帮助我们自动化软件交付过程中的步骤, 例如启动代码构建, 运行自动化测试以及部署到测试或生产环境
- 通过 .drone.yml 文件放在 git 信息库的根目录来配置管道.
- Drone 通过多个 step 来完成一系列的指令.
步骤梳理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7gUXSMDj-1626946901190)(https://images1.tqwba.com/20200926/gpafwuflo4b.png)]
1. 开发人员向 git 仓库提交代码, 代码中必须包含 DockerFile 与 .drone.yml 文件
2. 分支进行代码更新时, Gogs会通过钩子同步通知 Drone
3. Drone 通过git 插件 clone 分支代码到容器-测试-编译-构建可执行文件-打包镜像-发布到registry仓库-部署至生产环境-发送邮件通知等, 这里可以使用很多插件,比如harbor,notify, 微信钉钉等
4. 构建的pipeline脚本是通过 .drone.yml 编排的
安装步骤
-
安装 drone
-
安装 Drone-runner
drone-runner
是执行pipeline
的服务, 对应编写.drone.yml
的type
.- 安装启动
drone-runner-ssh
- 安装启动
drone-runner-docker
- 安装启动
所以安装时最后统一安装管理, 这里使用 docker-compose
进行编排部署
可以使用 openssl rand -hex 16 生成秘钥
几个关键配置
DRONE_GOGS_SERVER
使用gogs 作为仓库存储, 不同的仓库需要设置不同的变量
DRONE_RPC_SECRET
与 agent 之间通信的秘钥, 一定要配置
DRONE_SERVER_HOST
设置 drone server 使用的host名称, 可以是ip+port
DRONE_SERVER_PROTO
使用的协议 http/https
DRONE_LOGS_TRACE
启动日志
DRONE_USER_CREATE
设置初始管理员
DRONE_OPEN
开启注册,此配置允许任何人自注册和登录系统
几个关键配置
DRONE_RPC_HOST
上面启动server时配置的host
DRONE_RPC_SECRET
通信秘钥, 跟server配置的要保持一致
DRONE_RUNNER_CAPACITY
可以同时执行的任务数
DRONE_RUNNER_NAME
一般设置为主机名
安装集成
二进制文件安装太麻烦了, 我这边直接使用docker安装的方式.
确保服务器中已安装 docker + docker-compose
创建配置文件夹
mkdir -p /etc/opt/cicd_data/drone
mkdir -p /etc/opt/cicd_data/gogs
cd /data/cicd
docker-compose.yml
编写docker-compose.yml
文件
version: "3.6"
services:
# gogs 服务镜像
gogs:
image: gogs/gogs
container_name: gogs
restart: always
ports:
- "10022:22" # ssh 端口
- "9999:3000" # gogs仓库
volumes:
- /data/docker_test/gogs:/data # gogs 挂载卷
# drone server 端
drone:
image: drone/drone:latest
container_name: drone-server
ports:
- "10080:80" # drone 服务:HTTP
- "10443:443" # drone 服务:HTTPS
volumes:
- /var/run/docker.sock:/var/run/docker.sock # 本地docker
- /data/docker_test/drone:/var/lib/drone/ # 挂载卷
restart: always
environment:
- TZ=Asia/Shanghai
- DRONE_OPEN=true
- DRONE_GOGS_SERVER=http://服务器host:9999/ # 不同的代码仓库对应不同的key, v: 服务器仓库地址
- DRONE_SERVER_HOST=服务器host:10080 # drone 的server端地址
- DRONE_SERVER_PROTO=http
- DRONE_LOGS_TRACE=true
- DRONE_LOGS_DEBUG=true
- DRONE_GOGS=true
- DRONE_PROVIDER=gogs # 代码仓库
- DRONE_RPC_SECRET=2cbdaab90813f3743dc700816a322c62 # 秘钥与runner一致
- DRONE_USER_CREATE=username:管理员账户,admin:true # 设置管理员账户, 与gogs一致, 否则无法使用缓存
# drone runner 端, 用于执行pipeline
drone-runner:
image: drone/drone-runner-docker:1
container_name: drone-docker-runner # docker 与 ssh 有不同的runner
restart: always
ports:
- 10082:3000 # 端口映射
depends_on:
- drone # server端先构建启动
volumes:
- /var/run/docker.sock:/var/run/docker.sock # 本机docker
environment:
- TZ=Asia/Shanghai
- DRONE_DEBUG=true
- DRONE_RPC_SECRET=2cbdaab90813f3743dc700816a322c62 # 秘钥与server端一致
- DRONE_RPC_HOST=服务器host:10080 # server端
- DRONE_RPC_PROTO=http
- DRONE_RUNNER_CAPACITY=2
- DRONE_RUNNER_NAME=drone-runner
配置mysql服务或容器
使用自家的mysql, 或者新建容器(我直接新建容器测试的)
mkdir -p /etc/opt/cicd_data/mysql/conf
mkdir -p /etc/opt/cicd_data/mysql/logs
mkdir -p /etc/opt/cicd_data/mysql/data
docker run --restart=always \
-p 3308:3306 --name gogs_mysql \
-v /etc/opt/cicd_data/mysql/conf:/etc/mysql \
-v /etc/opt/cicd_data/mysql/logs:/var/log/mysql \
-v /etc/opt/cicd_data/mysql/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=admin \
-e MYSQL_DATABASE=gogs \
-e MYSQL_USER=gogs \
-e MYSQL_PASSWORD=123456 \
-e TZ="Asia/Shanghai" \
-d mysql:5.7
构建
docker-compose up -d
# 输入 DRONE_SERVER_HOST 配置的地址, 就可以进入系统进行使用了
gogs设置
访问 gogs web页面, 进行数据库及基础设置
数据库类型:
mysql
数据库主机用户密码库等信息:
上面配置的mysql服务或容器地址 ip:3308
运行系统用户:
root
域名:
你的域名或ip
ssh端口:
1022
HTTP 端口:
9999
应用 url:
http://ip:9999/
配置管理员账户:
test_admin : test_admin
# 限制不能使用 admin 为管理员账号名
用户设置, 添加ssh秘钥
查看本机秘钥
cd ~/.ssh
cat id_rsa.pub
创建仓库并提交代码
略
drone 设置
- 访问drone web页面
服务器host:10080
- 使用 gogs 管理员账户登录
- 配置 settings - Webhooks
可以看到 gogs 仓库中项目已同步
- 进入gogs: 代码仓库 - 仓库设置 - 管理web钩子
可以测试推送结果及请求
- 配置 settings - Webhooks - trusted
使用挂载功能
设置 secrets (如有)
编写 .drone.yml 文件
对于 Drone 来说, 最核心的就是 .drone.yml
文件, 里面定义了所有的流程 step
下面以部署go项目为例
部署Go项目触发CI
使用以下文件需要提前定义 `drone secret`
DDTOKEN: 钉钉机器人token
REGISTRY_HUB_USER: dockerhub 用户名
REGISTRY_HUB_PWD: dockerhub 密码
SSH_HOST: 服务器地址
SSH_NAME: 服务器用户名
SSH_PWD: 服务器密码
.drone.yml
kind: pipeline
type: docker # 使用docker
name: demo-go # 指定项目名称
steps:
# 编译测试
- name: build
image: golang:alpine # 本项目是golang项目, 所以使用go镜像
pull: if-not-exists
environment:
GOPROXY: "https://goproxy.cn,direct"
CGO_ENABLED: "0" # 指定不使用cgo
volumes: # 临时卷
- name: gopath
path: /go
commands:
- go build # 执行编译命令
- go test
# 构建镜像
- name: publish
image: plugins/docker # 构建docker镜像专用镜像
pull: if-not-exists # 默认always,指定if-not-exists或never可以大幅度提高速度,pull在中国很费时
settings: # plugins/docker用到的相关配置
dockerfile: ./Dockerfile # dockerfile 所在地址
username:
from_secret: REGISTRY_HUB_USER # 指定的docker hub的用户名(前面配置)
password:
from_secret: REGISTRY_HUB_PWD # 指定的docker hub的密码(前面配置)
repo: 镜像仓库/test # 要推送构建的镜像名字
# registry: https://harbor.kikakika.com # 如果使用自建的镜像仓库,例如 Harbor,这里可以通过 registry 指定
tags: latest # docker的tag值版本号 latest
# 部署容器
- name: deploy
image: appleboy/drone-ssh # 需要登录ssh服务器, 进行镜像拉取部署
pull: if-not-exists
settings:
host:
from_secret: SSH_HOST # from_secret 敏感信息请使用 drone secret
port: 22
username:
from_secret: SSH_NAME
password:
from_secret: SSH_PWD
script:
- image=镜像仓库/go_vmp:latest
- docker pull $image
- docker rm -f go_vmp_server || true
- docker image prune -f
- docker run -d -p 8080:8080 -v /data/docker_test/go_vmp/log:/app/log --name go_vmp_server $image
# 钉钉通知
- name: dingtalk
image: guoxudongdocker/drone-dingtalk # 钉钉通知专用镜像
settings:
token:
from_secret: DDTOKEN # 钉钉的token(前面配置)
type: markdown
message_color: true
message_pic: true
sha_link: true
when:
status: [failure, success] # 不管成功与否都发通知
volumes:
- name: deps
temp: {}
- name: dockersock
host:
path: /var/run/docker.sock
trigger:
branch:
- master # master分支收到推送就触发
以上 yml 文件定义了4个step, 并在master分支上触发
build:
执行 test 与 build
publish:
构建镜像, 并发布至docker_bub 镜像仓库(后期可自建)
deploy:
拉取镜像仓库中的镜像, 删除旧容器, 运行新镜像.
dingtalk:
钉钉群通知, 无论成功还是失败.
踩坑点
配置文件重启
修改了 api.ini 文件后, 我们需要进行应用的重启来加载文件
但是重启后会有异常报错
原因:
应用使用的是docker进行启动
而api.ini文件在我们 web install 界面已经进行了修改, 把端口映射成了我们的容器的指定值(9000:3000).
但此时重启, 应用暴露的端口理应是3000, 可文件中是修改之后的9000, 所以出现异常
所以, 进入容器后, 修改 vi /data/gogs/conf/app.ini 文件
将 HTTP_PORT 改成 3000
然后再重启
ssh仓库clone
由于配置了域名, 导致clone出现问题, 配置要主要, 不要遗漏
由于宿主机的端口20被sshd占用, 所以我们gogs只能使用其他端口映射 gogs 容器的20端口.
因此, ssh仓库clone代码时会有 域名:端口 出现, 如果想要去除域名, 官网我没找到方法, 可以借鉴以下的方式:
https://discuss.gogs.io/t/ssh-git-clone-fatal-xxx-vscode-git-does-not-appear-to-be-a-git-repository/2594
https://www.jianshu.com/p/831d29b5d598
你的 SSH 根本不是直连 Docker 容器的,所以你不可能连得上,只能使用 HTTP/HTTPS 进行访问。除非运行 Gogs 的 Docker 容器 expose 端口 22,但是这样你宿主的 SSHD 就凉凉了。如果你尝试 expose 宿主的其它端口到 Docker 容器的端口 22 的话,应该还是可以通过 SSH 访问的。