Golang 从零开始搭建自动部署平台,一键部署基础服务
前言
为什么要做
公司用到的中间件和用到的组件超级多,JDK、Nginx、Docker、Rabbitmq、Harbor、Mysql、pgsql、MinIO……大概有 20 多个,虽然写了部署文档,直接复制粘贴就能部署,但是每次都得折腾差不多 5-6 个小时左右,而且这期间得一直盯着,和组里另一个运维(已经奏了😭)聊天的时候,他是这么说的:“来公司的别的没学会啥,复制粘贴倒是变得很熟练了😂”
做了一段时间之后,总感觉每次都这么折腾很没有意义,纯属浪费时间,就决定要把这个过程自动化
为什么不选择 Ansible
在运维(网工也有)自动化部署里面,有着非常好用的工具——Ansible ,那么为什么还是要自己折腾一番,自己单独搞一套出来捏?考虑按照优先级有以下几点
- 想做一些定制化的东西,用 Ansible 不大好弄
有一些定制化的需求,如果是自己开发就很好做,但是用 Ansible 就不大好整,随便举几个例子
1、公司的软件仓库非常慢(共享 20Mbps 带宽,和镜像仓和代码仓还有一堆服务器共用,在开发提交代码、CI/CD 传镜像和客户服务器下载镜像的时候下载会非常慢,其实很多时候,折腾的几个小时里面,大部分时间都是在等下载(几十k/s)……)
希望能够实现一套机制,有源仓库(公司仓库,云上自建、可靠)和镜像仓库(加速仓库,不一定可靠),优先从镜像仓库下载,如果所有的镜像仓库失效,再回退到源仓库下载
2、部署完成后,根据部署是否成功,给指定的员工在企业微信发送通知,发送通知需要先请求一个接口获取 Token ,再传参,参数里面包括有工号,用 Ansible 的话不大好确定参数
- 部署的脚本常常会调整,希望能够简化调整的流程
部署的脚本有时候会有一些小的调整,因为经常上新业务,总是会引入各种中间件,或者是对里面的配置进行修改(举例来说,比如 MySQL 里面因为程序没有做自动建表,需要部署 MySQL 的时候建表),用 Ansible ,每次修改都要去改压缩包,然后 sftp 传到公司软件仓,很麻烦
- 依赖 Python 环境,一些发行版对 SELinux 有要求,不够“一键”
华为 OpenEuler 22.03 LTS SP3,部署的时候会提示需要去关一下 SELinux,也就是说还得手动去每台机器操作去,偷懒程度不够
说到不够“一键”,经常需要根据客户提供服务器的情况,调整软件部署情况,一台机器有一台机器的部署方法、三台机器有三台机器的部署方法,给七台机器有七台机器的部署方法,如果用 Ansible ,按照安装软件写 yaml 文件里面的节点,比如下面这样,填写配置文件也很麻烦
[nginx] |
- 我愿意折腾 Golang,做这个非常好玩(自己来实现一个岂不是非常有趣,很有成就感,也能趁这个机会学到很多东西)
思路
分三端,运维端、服务器端、执行端,C/S 架构(前端现在还不大熟,所以暂时不用 B/S 😂)
运维端:主要是三部分(Component 组件、Solution 解决方案、Action 执行脚本)
- Component 组件:描述如何安装某个组件,比如部署 Nginx、部署 ClickHouse 之类的,数据库的话一般也包含建表、改密码、调优这些环节,都自动化
- Solution 解决方案:是多个组件的组合,比如标准化部署(组件固定)数据库服务器的流程
- Action 执行脚本:通过组件(或/和)解决方案的组合生成出来的,最终在客户端的服务器上执行的脚本
脚本的编写格式参考 GitHub Action 来弄,之前写 Action ,感觉很好写,舒服,Component/Solution 使用 Git 管理
服务器端:校验 Action 有效性,执行端企业微信消息推送中转,鉴权(运维端、执行端。不能让谁都能拿到 Action 和操作不是)
执行端:从服务器端获取 Action 并在客户的服务器上运行,负责安装指定的软件
运维端
主要是使用 Golang + Fyne + SQLite
界面展示
组件界面
查看&加载组件&新增组件
点击展开/收合图片
点击展开/收合图片
组件示例。由上面看到的生成组件功能生成,也可以手动填写(有删改,Solution 和 Action 和这个的感觉相似,不再展示):
# API 版本 |
解决方案
解决方案是由组件构成的在某一台机器上安装所有需要的软件的组件集合,新增解决方案的话,就是选择由哪些组件去组成这个解决方案,就像搭积木一样,模块化
点击展开/收合图片
Action
选择操作系统和架构,组合要使用的组件和解决方案,填充里面的变量(如果)有,然后就可以去执行了
点击展开/收合图片
挑战
之前没弄过 YAML ,小小的折腾了一下,不是很难,用的 github.com/gookit/config/v2/yamlv3
这个库,使用说明很到位,执行端也是用的这个库,也支持从远程读取 YAML ,挺好用的
服务器端
使用 Go + Gin + MySQL
挑战
基本上没啥挑战,做 YAML 的校验是在这里做的
执行端
使用 Go + tview + SQLite
界面展示
点击展开/收合图片
点击展开/收合图片
补充一张部署成功之后的通知截图
点击展开/收合图片
挑战
这里的 UI 叫做 TUI (Terminal UI),和 Fyne 一样,UI 是运行在主线程的,会阻塞主线程,所有的执行逻辑,消息传递都需要自己开协程去做这个事情,Fyne 那边框架帮忙把这个事情做好了,而 tview 这边就需要自己手动处理这个事情,需要使用好 Goroutine 和 Channel ,比如上面的界面,界面是跑在主线程,左边的终端消息处理组件和右侧的执行总体进度消息传递组件单独跑在两个协程里面,命令执行器单独跑在一个协程里面,命令执行器调度下载、插件、shell 执行组件,向终端消息组件和总体进度消息组件传递运行状态,消息处理组件收集到消息之后会根据消息的紧要程度给消息上色,折叠过长的消息等等处理,写入日志并在 TUI 上渲染
后续想做的改进
运维端使用了 Fyne ,由于 Fyne 使用了比较高版本的 OpenGL,导致对低版本的 Windows 、没有显卡的服务器和远程桌面支持不大好(PS 启动不了,但是可以用 pal1000/mesa-dist-win 解决),目前考虑是准备用 Wails ,需要去学下前端
执行端的话,想做成 web 控制的,B/S 架构,点点鼠标来部署,从中心服务器端拉取配置,然后就不需要运维端,也是要学前端
所以是准备抽空搞搞前端咯