ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Archery部署实践:基于goInception的SQL审核平台搭建与运维

Archery部署实践:基于goInception的SQL审核平台搭建与运维 1. 平台定位与部署思路拆解1.1 Archery到底解决了什么问题如果你维护过几台以上的MySQL一定有过这样的经历开发同学直接在聊天工具里甩过来一段SQL说“帮我在生产环境跑一下”。这段SQL到底是全表UPDATE还是DROP前没备份你心里完全没有底。人工看吧量大、枯燥、容易漏不看吧出事儿就是线上事故。Archery就是冲着这个场景来的。Archery是一套开源的SQL审核与执行平台基于Python Django开发前端用Vue做交互界面核心审核引擎用的是goInception。它把“开发提交SQL → DBA人工审核 → 线上执行 → 变更回滚”这条链路整个搬到了Web平台上所有操作留痕所有审核规则可配置。我最初接触它是因为团队里上线变更越来越多DBA一个人扛不住需要一个能让开发自己提交、自己看审核结果、流程上又能兜底的工具。Archery恰好做的就是这件事。它的适用人群很明确被SQL变更折腾过的DBA、需要规范化数据库操作流程的运维团队、以及受够了“线上裸奔执行”的后端开发。对中小团队来说它替代的是“人肉审核聊天窗口传SQL”的原始状态对大型团队来说它可以作为数据库变更管理的前置入口配合CMDB、审批系统一起用。1.2 核心组件与技术栈拆解Archery不是一个大而全的“数据库管理套件”它的架构思路很清晰核心由三部分组成。Web服务层Django Vue负责展示工单、管理用户、配置权限、展示审核结果。这一层本身不碰数据库变更只做流程编排和页面交互。审核/执行引擎层goInception这是Archery的关键所在。它本身是一个独立的服务监听在4000端口通过MySQL协议对外通信。你把一条SQL发给它它返回一条虚拟的结果集里面包含了语法检查结果、规范检查结果、执行影响行数、回滚语句等内容。Archery把goInception当成一个“审核后端”来调用自己不做SQL解析。存储层MySQL业务元数据库 Redis缓存和Celery的任务队列。Archery自身需要一套数据库来存工单、用户、实例配置、审核记录这套库通常叫archery库。Redis主要配合Celery做异步任务比如异步执行大工单、定时拉取慢查询、发通知等。这套架构里最值得说的一点是为什么选goInception而不是老版的Inception。Inception是去哪儿网开源的MySQL审核系统用C写的但后期维护力度不够对MySQL 5.7以上版本的支持跟不上。goInception是社区用Go语言重写的版本兼容Inception的协议和功能同时修复了很多Bug还支持MySQL 8.0。Archery从某个版本开始就把goInception作为默认推荐的审核引擎就是看中了它的活跃维护和更好的兼容性。1.3 部署方式选型Docker Compose优先Archery官方提供了两种部署路径一种是Docker Compose一种是源码安装。我的建议很直接如果网络条件允许、服务器能跑Docker优先用Docker Compose。原因不是源码安装有多难而是Archery依赖的东西比较多——Python环境、Node环境、Celery、Redis、goInception每一个都可能有版本兼容性问题。Docker Compose把这些依赖全部固化在镜像里你只需要关心一件事配置好环境变量然后把容器拉起来。我这次部署选的就是Docker Compose方案下面的内容也按照这个路线展开。当然如果服务器在内网离线环境拉不了镜像源码部署反而是更现实的选择。源码部署的核心是把Archery的依赖通过pip装到虚拟环境里再手动安装goInception二进制配置好Nginx和Supervisor。流程更繁琐但可控性更强。两种方式我都会提到对应的坑但主线以Docker Compose为准。2. 部署实操从环境准备到平台跑通2.1 前置条件与硬件规格建议Archery本身对硬件要求不高真正吃资源的是它管理的那一堆业务数据库。我在部署时用的是一台4核8G的云主机跑了Archery主容器、MySQL元数据库、Redis、goInception四个容器平时CPU使用率基本在10%以下。如果你的业务量比较大工单数量多、慢查询采集频繁建议8核16G起步主要是给MySQL元数据库和Celery留出余量。操作系统方面CentOS 7.9和Ubuntu 20.04/22.04都验证过没有问题。CentOS 7需要注意内核版本和Docker版本的兼容性老内核跑新版本Docker偶尔会踩到存储驱动的坑建议用Docker 20.10以上的稳定版本。软件依赖清单如下组件版本要求端口用途Docker20.10-容器运行时Docker Composev2.0-编排容器Archery镜像当前社区最新版8000Web服务MySQL元数据库5.7或8.03306存储平台数据Redis6.x6379缓存与任务队列goInception社区最新版4000SQL审核引擎2.2 docker-compose.yml配置详解拿到Archery的源码包后根目录下就有现成的docker-compose.yml。一般不需要大改但有几个配置项必须根据你的环境调整。核心环境变量如下services: archery: image: hhyo/archery:latest container_name: archery environment: - MYSQL_HOSTmysql - MYSQL_PORT3306 - MYSQL_USERarchery - MYSQL_PASSWORDarchery_password - MYSQL_DATABASEarchery - REDIS_HOSTredis - REDIS_PORT6379 - REDIS_PASSWORDredis_password - INCEPTION_HOSTgoInception - INCEPTION_PORT4000 ports: - 8000:8000 depends_on: - mysql - redis - goInception mysql: image: mysql:5.7 environment: - MYSQL_ROOT_PASSWORDroot_password - MYSQL_DATABASEarchery - MYSQL_USERarchery - MYSQL_PASSWORDarchery_password volumes: - mysql_data:/var/lib/mysql redis: image: redis:6 command: redis-server --requirepass redis_password goInception: image: hanbm/goInception:latest ports: - 4000:4000几个容易踩坑的点MYSQL_PASSWORD不要搞混。docker-compose.yml里有两处MYSQL_PASSWORD一处是在archery服务的environment里这是Web服务连接元数据库用的另一处是在mysql服务的environment里这是初始化MySQL容器时创建用户用的。两处必须保持一致否则Django启动时会因为连不上数据库而报错。Redis密码需要强制设置。如果Redis不设密码Archery默认配置反而会连接失败因为它的连接串里带了密码参数。所以就算你不在乎安全也建议设一个简单的密码省得到处改配置。端口冲突要提前确认。8000、3306、4000这三个端口都是Archery默认监听的端口。如果服务器上已经装了其他MySQL或者Redis建议把容器端口映射改掉比如3306映射成13306。2.3 容器启动与初始化流程配置好docker-compose.yml后按照下面的顺序操作。首先是拉取镜像并启动容器# 拉取镜像首次会比较慢预计5-15分钟 docker-compose pull # 启动所有服务 docker-compose up -d # 查看容器状态 docker ps正常的容器状态是四个容器都是Up。如果某个容器反复重启用docker logs 容器名看日志大部分问题都能从这里找到线索。接下来是数据库初始化和平台数据初始化。这一步比较关键很多人在部署Archery时卡在这里。打开Archery源码包的docs目录里面有一个初始化脚本说明。实际操作是这样# 进入archery容器 docker exec -it archery /bin/bash # 在容器内执行数据库迁移 python3 manage.py migrate # 生成初始化数据资源组、权限、配置项等 python3 /opt/archery/sql/init_sql.py # 退出容器 exit # 重启archery服务使配置生效 docker restart archerymigrate是Django的标准数据库迁移命令作用是把项目里的数据模型映射成真实的数据库表。init_sql.py是Archery项目提供的初始化脚本它会创建默认的资源组、管理员账号、系统配置项没有这步平台登录进去是空的连实例都没法添加。初始化完成后浏览器访问http://服务器IP:8000就能看到Archery的登录页面了。默认管理员账号是admin密码是admin首次登录后务必在右上角菜单里修改密码。注意如果你的网络环境无法直接访问8000端口需要在服务器安全组/防火墙里放行对应端口。另外Docker部署时默认没有配置HTTPS内网使用问题不大如果暴露在公网至少要在前面加一层Nginx做TLS终止不要裸奔。3. 接入业务数据库与核心功能配置3.1 实例管理把业务库注册进平台平台跑通之后第一件事就是把业务数据库接入进来。Archery的菜单里有个“实例管理”模块点进去可以添加实例。添加实例时需要填关键信息实例名称、数据库类型MySQL/Oracle、连接地址、端口、账号密码。这里的账号建议单独创建一个专用账号不要直接用root。我在生产环境是这样做的-- 在目标业务库上执行创建Archery专用账号 CREATE USER archery% IDENTIFIED BY 强密码; GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, INDEX, DROP, REFERENCES ON *.* TO archery%; GRANT SUPER, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO archery%; FLUSH PRIVILEGES;给这么多权限看起来有点吓人但这是Archery执行SQL和获取元数据所必需的。SUPER权限用于goInception执行某些特殊语句REPLICATION SLAVE用于获取Binlog信息以生成回滚语句。如果你对安全要求极高可以按需裁剪但结果可能是某些功能如回滚、在线执行用不了。添加实例成功之后还要把它关联到资源组。Archery的权限模型是“用户 → 资源组 → 实例/库”一个用户必须加入了某个资源组才有权限操作该资源组下关联的实例。默认的初始化脚本会创建一个叫“default”的资源组如果你的团队有DBA、开发、运维多个角色建议按照业务线拆分成多个资源组每个组设置不同的用户和审核流程。3.2 工单流程配置让审核规则真正生效实例接入后最核心的就是配置工单流程。Archery把SQL变更设计成工单模式流程大致是提交工单 → 系统自动调用goInception审核 → 审核人审批 → 执行人执行 → 记录结果。审核规则在哪里设置在“系统管理”里的“审核规则”菜单中。Archery内置了一百多条g语法检查规则比如“禁止SELECT *”、“禁止UPDATE不带WHERE”、“表名必须小写”、“索引数量限制”等。每条规则都可以单独开关也可以设置警告级别警告或错误。警告级别的SQL允许提交但高亮提示错误级别的SQL直接拦截。审批流怎么配Archery默认支持两级审批资源组管理审批和上线审核。在资源组里设置对应的审批人后工单提交时第一级由资源组管理员确认变更范围第二级由DBA或指定的审核员做技术审核。如果你的团队比较小可以简化成只要一级审批在系统配置里开启即可。执行权限怎么控制工单提交后谁有权限执行由资源组里的“执行人”决定。可以设置“仅DBA可执行”也可以设置“提交人自己执行”。我的建议是查询类工单SELECT让开发自己执行变更类工单INSERT/UPDATE/DELETE/DDL由DBA执行。这样既给了开发自由度又守住了变更的红线。3.3 goInception审核参数调优goInception虽然自带一套默认审核规则但实际使用中你会发现默认规则与团队习惯不一定匹配。比如默认规则禁止使用INSERT INTO ... VALUES多条批量插入但有些业务团队就是习惯这么写。这种规则如果不开调整会大量误报开发用起来很烦躁。goInception的配置不在Archery的Web界面上而是在goInception的配置文件里。使用Docker部署时一般通过环境变量或挂载配置文件来控制。我这边是把goInception的配置文件挂载出来的路径一般是/etc/inc.cnf核心参数包括# 审核规则开关comment是规则项的注释说明 check-autoincrement-name 1 check-column-charset 1 check-column-comment 1 check-column-default-value 1 check-column-type 1 check-dml-limit 1 enable-query-review 1 # 备份相关开关 enable-remote-backup 1 backup-host 业务库IP backup-port 3306 backup-user backup_user backup-password backup_password backup-database backup_db关于备份功能多说一句。goInception在执行DML语句时如果开启了备份会把涉及的行以BINLOG解析的方式倒进备份库。有了这份备份线上执行出问题后就能生成回滚语句。这是Archery做SQL变更时最重要的安全保障。备份库建议和业务库放在同一个MySQL实例上但用独立的database避免跨库业务复杂度。提示goInception配置修改后需要重启容器才能生效。建议用docker inspect goInception查看当前容器的挂载信息确认配置文件映射到了哪里而不是在容器里直接改文件否则容器重建后配置又丢了。4. 上线后运维从日志到慢查询到日常巡检4.1 日志体系与资源监控平台上线后第一件要做的事是配置日志。Archery的Django应用本身会把运行日志打到容器标准输出可以通过docker logs -f archery查看。但这样看日志太原始我建议把容器日志接入到统一的日志平台。如果不考虑引入ELK这类重量级方案至少用Docker自带的json-file驱动把日志按天切分并限制大小# 在docker-compose.yml中的archery服务增加 logging: driver: json-file options: max-size: 100m max-file: 3避免日志无限增长把磁盘写满这是个容易忽略的点。Docker日志如果不限制大小默认是无限增长的Archery在工单频繁时一天能产生几百MB日志半个月就会把磁盘撑爆。资源监控方面主要盯三个指标元数据库MySQL的连接数、Redis的内存占用、goInception的响应耗时。连接数飙升通常意味着有大量工单在并发执行这时可以调大Django数据库连接池参数Redis内存增长过快则要检查Celery队列是否积压goInception响应变慢往往是审核规则太多或SQL过于复杂导致的可以在配置里把不需要的规则关掉。4.2 慢查询采集与索引优化Archery内置了慢查询管理功能这是个容易被低估的模块。它支持自动采集MySQL慢日志并生成索引优化建议。配置方式在实例管理的“慢查询设置”里需要填慢查询日志的保存路径和阈值。生产环境中我先确认了MySQL开启了慢查询日志-- 在目标MySQL上设置慢查询参数 SET GLOBAL slow_query_log ON; SET GLOBAL long_query_time 2; SET GLOBAL slow_query_log_file /var/log/mysql/slow.log;Archery采集慢日志的逻辑很简单它定时读取慢日志文件把超过阈值的SQL解析进平台再调用goInception的索引分析功能生成优化建议。优化建议会显示在“慢查询管理”页面里比如建议在哪个表加什么索引、预计能提升多少效率。这里有个实际经验值得分享慢查询采集的机器和业务库之间要确保网络互通且账号要有读取慢日志的权限。我第一次配置时采集端始终拉不到数据排查半天发现是安全组规则更新后采集服务器与业务库之间的网络被隔断了。传输层不通一切配置都白搭。4.3 备份策略与升级注意事项Archery元数据库承载了所有工单记录、用户信息、权限配置这库一旦丢了平台上的历史记录就全没了。虽然工单在业务库执行时已经有goInception的备份库兜底但元数据库本身还是要做独立的备份策略。我在部署时用crontab做了一个简单的每日备份# 每天凌晨2点备份archery元数据库保留最近7天 0 2 * * * mysqldump -h127.0.0.1 -uarchery -p密码 archery | gzip /data/backup/archery_$(date \%Y\%m\%d).sql.gz 2 /data/backup/backup.log 0 3 * * * find /data/backup -name archery_*.sql.gz -mtime 7 -delete版本升级这件事也要提前规划。Archery的社区更新节奏不算太快但每次升级都可能涉及数据库表结构变更。升级前一定要做三件事备份元数据库、拉取新镜像、看官方Release Note里的SQL变更脚本。不要在业务高峰期升级我习惯选在变更窗口执行先升级测试环境验证一遍再动生产。5. 常见部署问题与排障实录5.1 容器层面的典型故障容器反复重启退出码为1这个现象最常见。先docker logs archery看输出通常有两种情况连不上元数据库或者Redis认证失败。连不上数据库时检查MYSQL_HOST是否指向了正确的容器名以及MYSQL_PASSWORD和mysql服务里创建的用户密码是否一致。Redis认证失败时检查REDIS_PASSWORD是否与redis服务的--requirepass参数一致。Redis连接超时如果所有服务都在同一个宿主机上理论上不应该出现这个问题但如果你把Redis独立部署了注意Archery的REDIS_HOST要填Redis所在主机的IP而不是容器名。Docker容器之间通过容器名互通跨主机就必须用IP加端口映射。goInception连不上工单审核直接失败Archery提交工单时如果报“Inception连接失败”大概率是INCEPTION_HOST配置不对。docker-compose部署时goInception容器的服务名就是goInceptionArchery容器内直接解析这个名称。如果你是源码部署就要填goInception所在机器的IP并确认4000端口没有被防火墙挡掉。5.2 登录认证与权限相关默认账号登录不进去新装好的Archery默认账号是admin/admin如果登录失败check一下是否执行了init_sql.py。这个脚本不光创建资源组还负责写入默认管理员账号。另一个可能性是Redis换了密码导致session失效Django的登录态会一直写不进Redis。用户看不到任何实例用户登录平台后左侧菜单里看不到实例或者提交工单时实例下拉框是空的。这个场景几乎都是资源组授权问题。Archery的设计是“先加资源组 → 把实例关联到资源组 → 把用户拉进资源组”少一步都不行。在“用户管理”里检查用户是否加入了正确的资源组以及该资源组是否关联了实例。执行工单时提示没有权限在资源组的配置里执行权限是与角色绑定的。普通开发默认是“提交人”DBA是“执行人”。如果开发自己提交工单后想自己执行需要资源组管理员把执行权限开放给“提交人”角色否则只能等DBA来执行。5.3 审核规则相关的排查经验提交SQL后审核结果为空或直接报错这种情况分两步排查。第一确认goInception容器是否正常运行尝试用MySQL客户端连一下goInception的4000端口mysql -h127.0.0.1 -P4000 -uroot -p能连上说明服务正常。第二检查SQL文本是否包含了goInception不支持的语法比如某些高级JSON函数、窗口函数的老版本兼容问题。遇到这种可以先在平台里跑一条最简单的SELECT 1验证基础链路通不通。审核规则改了不生效Archery的审核规则有两层Web界面的审核规则是“展示层”真正由goInception执行的规则在goInception的配置里。你在Archery的规则管理里开关了某项但goInception内部的配置文件没有对应调整审核结果就不会变化。修改goInception配置后记得重启容器。SELECT语句也被拦截Archery默认会拦截没有WHERE条件的UPDATE和DELETE这是对的。但有些团队希望连SELECT都能一键执行这时候在系统配置里调整“查询权限”就行。我建议保留SELECT的审批特别是涉及生产库的大表查询限制是全表扫描。5.4 部署排障速查表现象可能原因处理方法容器无法启动Exit 1数据库连接串错误或Redis密码错误检查环境变量两侧密码保持一致页面打开白屏静态文件未收集容器内执行python3 manage.py collectstatic工单提交失败报Inception错误goInception端口不通检查4000端口监听、防火墙配置慢查询页面没有数据业务库慢日志未开启设置globalslow_query_logON登录状态频繁失效Redis重启或密码变更检查Redis容器健康重启后session清空定时任务不执行Celery worker未运行进入容器启动celery worker或看docker logs审核规则与预期不符两层规则配置不一致同步修改goInception配置文件6. 使用Archery半年后的真实体会部署Archery只是第一步真正让它发挥价值的是工单流程的推广和执行。我在这套平台上线的头两个星期团队里最大的阻力其实是习惯问题——开发惯性很大还是喜欢直接扔SQL给DBA。后来我们定了个规矩所有线上变更没有Archery工单记录一律不执行聊天窗口里的SQL请求全部不响应。规矩执行了一周大家就都转到平台上了。有一个细节让我印象很深。老版本的Archery在执行某些DDL语句时如果表数据量特别大在线执行会锁表很久。goInception较新的版本对这部分做了优化但大表变更前我还是建议走“先在测试环境执行再用平台工单走流程”的做法。工单里的审批和回滚记录不仅是流程要求更是事后追溯的依据。如果你只是想把“别人发SQL让我执行”的状态做个规范化管理Archery的Docker部署半小时就能搞定如果你想把它当成数据库变更治理的基石那还要在规则配置、权限划分、备份策略上多花心思。但不管哪种目标这套平台都能显著降低你的人肉审核压力。根据我个人经验最值得投入时间的不是部署本身而是把审核规则和团队流程磨到顺手那是真正能节省日常沟通成本的地方。最后分享一个小技巧Archery平台里的数据库实例密码是加密存储的但加密密钥默认在配置里写死了。如果你部署后需要把平台交给别人维护建议把DJANGO_SECRET_KEY和加密相关的配置改成自己的随机值避免hash种子泄露导致密码可被逆向。这一步在初始化之后再做做晚了就得重新录入一遍实例密码。
返回列表