ARTICLE DETAIL

资讯详情

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

Archery Docker化部署:统一纳管MySQL、PostgreSQL与ClickHouse的SQL审核

Archery Docker化部署:统一纳管MySQL、PostgreSQL与ClickHouse的SQL审核 如果你的工作环境也像我们一样从最开始只有一套MySQL慢慢扩张到MySQL、PostgreSQL、ClickHouse并存那SQL审核这件事绝对会从“偶尔看一眼”变成“每天被追着问”。上个月我实在不想继续在群里一条条收SQL、再人肉判断风险抽了一个周末把Archery用Docker方式部署起来把三套数据库全部纳管进去。这篇文章就是把从零配置Archery的完整过程、我自己在用的compose文件、接入三种数据库实例时踩过的坑写下来给正在选型或者卡在部署阶段的同学一份可以照抄的作业。1. Archery不是单容器先把服务组成和部署思路捋清楚1.1 Archery到底解决什么问题先说结论Archery是一个开源的SQL审核查询平台简单理解就是给DBA和开发团队提供了一个web页面所有SQL工单在这里提交、审核、审批、执行、回滚同时还能做在线查询和数据字典。相比直接用命令行连数据库或者写一堆自制脚本去收集SQL它的价值在于把流程固化下来谁在什么时间提交了什么SQL谁批准的执行成功还是失败全部有记录。在只有一个MySQL实例的时候靠人肉审核还能勉强维持。可一旦引入PostgreSQL做业务分析库、ClickHouse做日志和指标存储问题就来了每种数据库的客户端不一样审核规范不一样回滚方案更不一样。如果每个库都搞一套审核流程维护成本会直接爆炸。Archery的思路是统一入口通过插件化方式对接不同的数据库类型至少在工单管理和查询入口上做到收敛。1.2 Archery的四个核心部件Archery不是一个孤零零的Web进程这一点很多人第一次部署时会忽略。从架构上看一套可用的Archery至少包含四部分Web服务核心基于Django框架开发提供管理后台和API。官方镜像名是hhyo/archery所有审核工单、权限、数据字典、用户体系都在这里。元数据库Archery自身产生的配置、工单记录、用户信息需要落库。官方默认使用MySQL 5.7不要图新鲜换成8.0后面我会讲原因。缓存/异步队列用Redis。工单执行、SQL查询异步化、celery任务调度都依赖它丢了或者连不上会导致大量按钮点了没反应。SQL审核引擎这是MySQL审核能力的核心。Archery通过goInception对MySQL做语法检查、索引分析、执行计划模拟、回滚语句生成。很多部署教程把它漏了结果就是工单提交后一直卡在“审核中”。理解了这四部分再去看部署方案就不会被各种compose文件绕晕。所谓Docker部署Archery本质上是把上面四个组件各自跑成容器并让它们之间网络互通。1.3 为什么推荐Compose而不是直接docker run我知道有的人习惯用Docker命令逐个启动容器一个docker run加一堆-e参数看起来很直接。但Archery这套服务涉及容器间互相访问如果逐个启动你得手动建一个bridge网络再控制启动顺序MySQL/Redis要先起Web后起还要处理数据卷挂载和重启策略。稍有不慎容器启动顺序错了Archery起来后连不上元数据库日志刷屏。Docker Compose的价值在于把整个服务编排写进一个YAML文件里up -d一条命令拉起全部依赖关系用depends_on声明网络直接用服务名互联日志一起滚动查看。对多实例部署和后续迁移也更友好。下面所有步骤都基于Compose方式展开。2. 环境准备镜像版本、目录规划、端口分配一次定好2.1 Archery版本镜像怎么选Archery的版本演进比较快1.9.x和2.x的部署方式差异很大。如果看官方仓库最新的release是2.x系列镜像标签也主要围绕这个版本。我的建议是如果没有特殊历史包袱直接用2.x的稳定版本镜像。原因有三点2.x的权限模型、资源组管理比1.x清晰多数据库实例纳管时更好用。官方compose文件默认针对2.x网上能找到的避坑文章也基本以2.x为准。1.x的goInception连接配置相对繁琐2.x在后台界面直接填地址就行。镜像拉取时注意Archery官方镜像是hhyo/archery后面的tag按实际版本填。如果你不知道具体版本号可以先docker pull hhyo/archery:latest然后看镜像环境变量。但生产环境不建议长期锁latest等文章最后我会说升级的坑。2.2 Docker Compose环境检查清单动手之前先确认你本机的Docker环境满足要求。我遇到过不少部署失败纯粹是环境问题。第一Docker版本。18.06以上基本可用20.10以上更稳。用docker version看Server端API版本太老的话compose里的version: 3语法可能不支持。第二Docker Compose是否单独安装。现在新版Docker Desktop自带docker compose子命令Linux上可能是docker-compose独立二进制。两种情况写法略有差异但YAML内容一致。我后面统一用docker compose命令。第三内存和磁盘。Archery整套服务MySQL元库RedisgoInceptionWeb跑起来后空闲状态下内存占用在2GB左右工单并发高时会涨到3GB以上。磁盘预留20GB以上比较稳因为不只容器镜像还有MySQL元数据增长和上传的SQL附件、导出文件。第四端口占用情况。先确认8000、4000、3306、6379这四个端口没有被本机其他服务占用。如果3306被本机MySQL占了compose里元数据库就别暴露宿主机端口或者换一个映射端口。2.3 目录、端口、账号的规划表在写compose文件前先把以下信息在工作区固定下来后面会反复用到。我用了一个统一的数据目录/data/archery你也可以按自己习惯改。项目规划值说明部署目录/data/archery/挂载卷统一放在这里元数据库数据目录/data/archery/mysql持久化MySQL元数据库Redis数据目录/data/archery/redis持久化Redis缓存数据上传文件目录/data/archery/uploadArchery的SQL附件、查询导出文件Web端口8000Archery管理后台访问端口goInception端口4000审核引擎端口可在容器内互联元数据库账号archery / archeryArchery连接MySQL元数据库用Redis库编号0Archery默认使用db0账号密码只是示例生产环境务必改强密码。还有一点要提前确认Archery连接的是元数据库MySQL和被审核的生产MySQL实例是两码事不要搞混。元数据库是存Archery自身配置的生产数据库实例是后面手动添加到平台里的。3. 部署过程写Compose、起容器、初始化、登录后台3.1 一份可直接使用的docker-compose.yml下面这份compose文件是我实际部署时精简过的版本注释标出了每个服务的作用。你把这部分存成/data/archery/docker-compose.yml即可。version: 3 services: mysql: image: mysql:5.7 container_name: archery-mysql environment: - MYSQL_ROOT_PASSWORDarchery - MYSQL_DATABASEarchery - MYSQL_USERarchery - MYSQL_PASSWORDarchery - TZAsia/Shanghai volumes: - /data/archery/mysql:/var/lib/mysql restart: always redis: image: redis:6 container_name: archery-redis volumes: - /data/archery/redis:/data restart: always goinception: image: hanchuanchuan/goinception:latest container_name: archery-goinception ports: - 4000:4000 restart: always archery: image: hhyo/archery:2.0.1 container_name: archery ports: - 8000:8000 environment: - DB_HOSTmysql - DB_PORT3306 - DB_USERarchery - DB_PASSWORDarchery - DB_NAMEarchery - REDIS_HOSTredis - REDIS_PORT6379 - REDIS_DB0 - TZAsia/Shanghai volumes: - /data/archery/upload:/opt/archery/upload depends_on: - mysql - redis restart: always这里解释几个关键点避免你照着写好后一头雾水MySQL 5.7不是顺手选的。Archery的Django ORM和底层SQL语句是针对5.7的语法和认证方式调过的。MySQL 8.0默认的caching_sha2_password认证插件会让Archery在启动时连接报错。虽然可以通过改default_authentication_plugin规避但没必要在第一步给自己挖坑。goInception为什么要暴露4000端口。Archery容器和goInception容器在同一个compose网络里其实不映射宿主机也能通过goinception:4000互访。我这里映射出来是为了方便本机用mysql -h127.0.0.1 -P4000做审核引擎连通性测试。depends_on不是万能的。它只能保证容器启动顺序不能保证MySQL已经初始化完成。Archery启动时如果MySQL还没ready容器会连不上并报错。后面我会给出处理办法。3.2 启动容器与检查状态在/data/archery目录下执行docker compose up -d这时候用docker ps能看到四个容器都处于Up状态。如果某个容器起不来重点看对应容器日志docker logs archery最常见的情况是Archery容器先启动了而MySQL还没初始化好日志里出现Cant connect to MySQL Server。别慌这个不是配置错误等MySQL完全ready后手动重启Archery即可docker restart archery判断MySQL是否ready有个很简单的方法docker exec -it archery-mysql mysql -uarchery -parchery -e select 1能返回1就说明元数据库可以连接了。3.3 数据库初始化和创建管理员Archery的镜像一般会在容器启动时自动执行migrate把Django所需的数据表初始化到元数据库。但如果你手动重启过容器或者镜像版本没有自动执行迁移逻辑就需要手动补一步docker exec -it archery python3 manage.py migrate注意观察输出看到一排OK就是成功。如果提示表已存在也不影响Django迁移具备幂等性。接着创建管理员用户docker exec -it archery python3 manage.py createsuperuser按提示输入用户名、邮箱、密码。我建议不要用admin/admin这种默认账号哪怕只是内网使用也至少换一个强一点的密码。Archery 2.x还有一个安全设置项会在你首次登录后引导修改默认admin密码一并处理掉。3.4 登录后台并配置goInception审核引擎浏览器访问http://你的服务器IP:8000用刚创建的管理员账号登录。登录后先别急着加数据库实例第一件事是配置goInception地址。在Archery后台左侧菜单找到“系统设置”或“参数配置”里面有一项是审核引擎相关设置需要填写goInception的地址。由于Archery和goInception在同一个compose网络里这里填容器服务名goinception和端口4000即可不需要填宿主机IP。填完后建议在Archery上找一个测试SQL提交工单看审核结果是否能正常返回。如果审核状态一直停留在“审核中”大概率是goInception地址填错或者容器之间网络不通。可以用下面命令从Archery容器内测试到goInception的连通性docker exec -it archery bash -c ping goinception如果ping不通检查compose文件里goInception服务是否真的叫这个名以及是否和Archery在同一个网络里。4. 把MySQL、PostgreSQL、ClickHouse实例接入Archery4.1 先搞懂Archery里的资源组、实例、数据库三层关系很多新手在接入数据库时直接把实例信息填进去然后发现列表里看不到或者工单无处提交原因是没有理解Archery的层级模型。它从上到下分三层资源组你可以理解为一个隔离域或项目组不同团队用不同资源组互相看不到对方的实例和工单。实例对应一个真实的数据库连接比如一个MySQL 5.7实例、一个PostgreSQL 14实例、一个ClickHouse集群。数据库实例下面的具体库。比如同一个MySQL实例上挂了orders、users、inventory三个库Archery里可以分别管理。所以流程是先创建资源组再在组下面添加实例然后为实例添加数据库。缺了任何一个环节工单都提不起来。4.2 接入MySQL审核、执行、查询一条链路MySQL是Archery支持最完整的数据库类型审核、执行、回滚、查询都能走通。先在左侧菜单“资源组”里新建一个测试组比如叫core-db。然后进入“实例管理”点击新增类型选择MySQL填写真实生产库或测试库的连接地址、端口、账号、密码。建议用一个专用的只读DDL受限账号而不是拿root直接配进去。填完先别保存点“测试连接”。Archery会通过后台去ping这个MySQL实例。这里有个常见问题如果Archery容器和目标MySQL不在同一网络填localhost或127.0.0.1肯定连不上要填目标MySQL所在主机在Docker网络里可达的IP或者同网段的容器名。实例添加成功后在实例详情里给该MySQL实例添加业务数据库。比如添加app_order库然后回到首页“SQL审核”选择资源组和实例就能看到库里所有表结构可以提交SQL工单了。提交工单后Archery会调用goInception做语法检查、索引优化建议、执行计划分析。如果SQL存在风险界面上会标红并给出具体原因比如“使用了select *”或者“影响行数过大”。审批通过后可以在工单详情页执行SQL执行完还能生成回滚语句。整条链路我实测下来跑一个DDL工单从提交到回滚语句生成十秒内基本能完成。4.3 接入PostgreSQL查询和工单的边界要心里有数PostgreSQL实例的接入同样在“实例管理”里新增类型选择PostgreSQL。很多人在这一步会困惑为什么我填了正确的PG地址和端口测试连接还是失败大部分问题出在PG的连接权限配置上。Archery连PG走的是普通libpq协议目标PG服务器的pg_hba.conf必须允许来自Archery容器IP网段的连接并且账号要有访问目标schema的权限。如果拿不准先在PG宿主机上用psql -h pg_ip -U user -d db测一遍能连上再回Archery填。PostgreSQL的审核能力和MySQL不完全一样。Archery的goInception只深度支持MySQL所以对PG工单更多是语法层面的校验、DDL执行和查询操作。回滚语句生成对PG基本不可用这一点团队里要提前达成共识不要让开发误以为PG的update也能像MySQL那样自动生成逆向脚本。实际使用中我把PostgreSQL主要定位成两个用途一是开发自助查询通过Archery在线查询PG中的数据避免他们直连生产库二是DDL变更走工单留痕执行前人工review。至于复杂SQL的调优建议还是得靠PG自己的EXPLAIN ANALYZE和DBA人工判断。4.4 接入ClickHouse查询场景为主别指望它做回滚ClickHouse接入Archery时实例类型选择ClickHouse连接信息填写ClickHouse所在地址。这里要特别注意端口选择。ClickHouse的HTTP接口默认8123原生TCP接口默认9000还有MySQL兼容协议在9004。Archery不同版本对不同协议的适配程度不一样如果你填9000测试不通就试试8123或者看Archery官方的连接驱动说明。ClickHouse的定位是列式分析数据库本身不支持事务性更新和删除虽然有变通语法。因此Archery里对ClickHouse的能力边界要明确核心场景是查询。我在接入手账时设了一条规矩ClickHouse实例配置在Archery中主要用于给数据分析师和研发提供一个在线查询入口SQL工单只承接建表、加字段这类DDL操作禁止通过Archery执行大范围的ALTER或DELETE。接入后建议在Archery在线查询里跑几个常见SQL比如SELECT * FROM system.tables LIMIT 10确认查询链路通。同时验证下结果集导出功能他们用Archery查ClickHouse日志时经常需要导出这一步能省掉不少邮件往来。4.5 用一个真实工单验证全流程三套数据库都接入后我习惯用一个最小的真实工单把链路完整走一遍确认不是只“能连上”而是“能干活”。以MySQL为例建一个company_dev资源组往里面加一个测试MySQL实例选择test_db库提交一条简单DDLALTER TABLE t_user ADD COLUMN remark varchar(255) DEFAULT NULL COMMENT 备注;看工单的状态变化提交后系统自动审核审核通过后我作为管理员审批然后点击执行执行成功后查工单详情里的回滚语句。如果这一条链路走通说明goInception、Archery Web、元数据库、MySQL目标实例四者之间的连接和权限都没问题。PostgreSQL和ClickHouse也分别提交一条只读查询工单和DDL工单验证即可。全程走完大概半小时半小时换后续几周安稳使用很值。5. 上线一周后排障、备份、升级要注意的事5.1 容器起不来的常见原因和排查顺序第一周最容易遇到的是服务器重启后Archery打不开。排查顺序我建议固定下来先docker ps看容器是否都在运行再看Archery日志最后手动重启一次。如果容器处于Exited状态大概率是restart: always没有生效或者容器启动时依赖的MySQL/Redis还没就绪。这时先启动MySQL和Redis再重启Archery通常能解决。还有一个高频问题元数据库的磁盘满了。Archery跑一段时间后工单历史、SQL执行记录、慢查询日志都会写进MySQL元数据库。如果/data/archery/mysql所在的磁盘分区满了Archery页面会各种奇怪报错。建议在规划目录时就把这个目录放在大容量磁盘上并且给容器加上--log-opt max-size50m类似的日志大小限制避免容器日志无限膨胀。5.2 数据持久化和备份策略Archery这套服务的数据核心是MySQL元数据库和upload目录里的附件。Redis缓存丢了影响不大最多celery任务重跑。备份逻辑很简单每天定时用mysqldump把元数据库导出到另一个目录或对象存储。以compose里MySQL容器为例docker exec archery-mysql mysqldump -uarchery -parchery --databases archery /data/backup/archery_$(date %F).sqlcrontab里加一条凌晨任务即可。upload目录用rsync同步到备份盘。恢复时先把新环境的MySQL容器跑起来再把dump文件导入然后启动Archery容器连上去就行。5.3 升级版本时的操作路径Archery迭代很快新版本会修复权限漏洞和工单流程bug。升级不要直接docker compose pull up -d我建议按这个顺序来备份元数据库和upload目录拉取目标版本镜像比如hhyo/archery:2.0.1换成一个新tag改好compose文件docker compose up -d启动新容器观察日志确认migrate自动执行成功登录后台跑一个测试工单验证功能回归。升级后如果发现某些菜单项变成英文或样式错乱优先清理浏览器缓存和Redis缓存。我遇到过升级后工单列表一直转圈docker exec -it archery-redis redis-cli flushall清一下就恢复了。5.4 资源占用和性能体感部署一周后我特意看了资源占用四个容器加起来接近3GB内存其中Archery Web和goInception是大头。如果服务器内存只有4GB不建议再塞其他重型服务。体感上最影响性能的是在线查询大结果集。开发在Archery里查出十万行数据导出时Web容器内存会明显上涨。解决办法是在Archery系统设置里调整查询返回行数上限或者限制单次导出数据量。我设的是单个查询最多5万行导出最多10万行对日常排查日志已经够用。整个部署过程中我最想强调的一点是Archery这类平台的价值不在功能多炫而在把所有SQL操作变成可追溯的工单流。我自己部署时走了不少弯路最开始的compose文件里漏掉了goInception导致MySQL审核一直不可用后来又因为MySQL元数据库用了8.0镜像启动就报认证错误。把这些记录下来希望能让你省掉这些重复劳动。如果你现在正在纠结部署方案直接按这篇文章的compose起步然后根据自己的网络环境和安全要求改账号密码就行。
返回列表