戰(zhàn):基于Docker Compose搭建SQL審核平臺(tái)并接入三種數(shù)據(jù)庫(kù))
做數(shù)據(jù)庫(kù)運(yùn)維的同學(xué)應(yīng)該都有這種體會(huì)公司里一旦過了幾十個(gè)開發(fā)、幾百?gòu)埍頂?shù)據(jù)庫(kù)變更就開始失控了。開發(fā)提了一條SQL過來到底是好是壞、有沒有索引失效、會(huì)不會(huì)鎖表全靠DBA肉眼去“人肉審計(jì)”。更麻煩的是執(zhí)行完沒留痕、想回溯找不到記錄、賬號(hào)權(quán)限也分不清楚誰(shuí)動(dòng)了哪張表。Archery就是來解決這個(gè)問題的它是一個(gè)開源的SQL審核查詢平臺(tái)把“提交SQL、規(guī)則校驗(yàn)、DBA審核、在線執(zhí)行、結(jié)果回滾、日志審計(jì)”整條鏈路全部Web化支持MySQL、PostgreSQL、ClickHouse等多種數(shù)據(jù)庫(kù)而且全部操作留痕。這篇教程我想把從零開始用Docker Compose把它完整部署起來、再把三種數(shù)據(jù)庫(kù)實(shí)例接入的過程一步步講清楚。整個(gè)實(shí)操下來你會(huì)發(fā)現(xiàn)這東西部署起來并沒有想象中復(fù)雜反而是實(shí)例接入和權(quán)限配置更值得花心思。1. Archery核心價(jià)值與方案選型思路1.1 Archery到底解決了什么問題先說一個(gè)真實(shí)場(chǎng)景。早些年我在一家電商公司做DBA每周最頭疼的事情就是收開發(fā)發(fā)來的SQL變更申請(qǐng)通常是Excel或者聊天消息寫得亂七八糟。“給xx表加個(gè)索引”“某條UPDATE忘寫WHERE了能幫我回滾嗎”這種消息天天有。人工審核有兩個(gè)致命問題第一不可追溯。SQL到底是誰(shuí)提交的、什么時(shí)候執(zhí)行的、執(zhí)行前有沒有人審過全靠郵件和聊天記錄出事只能靠猜。第二規(guī)則不一致。同一個(gè)DBA今天心情好放過了一條沒走索引的SQL明天另一個(gè)DBA審核時(shí)直接打回。開發(fā)完全不知道標(biāo)準(zhǔn)是什么流程形同虛設(shè)。Archery的定位就是把這件事標(biāo)準(zhǔn)化。它不是一個(gè)GUI工具而是一個(gè)“平臺(tái)”核心功能包括SQL審核內(nèi)置規(guī)則引擎對(duì)提交的SQL做語(yǔ)法解析、索引分析、規(guī)范校驗(yàn)比如檢測(cè)到全表DELETE、無(wú)WHERE條件的UPDATE、大表DDL等高風(fēng)險(xiǎn)操作會(huì)直接攔截或告警。工單流轉(zhuǎn)開發(fā)提交SQL后生成工單DBA在Web界面審核通過后可以手動(dòng)執(zhí)行、定時(shí)執(zhí)行執(zhí)行過程自動(dòng)記錄。查詢能力開發(fā)可以在線查詢但管理員可以控制查詢權(quán)限、限制返回行數(shù)、敏感字段脫敏。審計(jì)日志誰(shuí)在什么時(shí)間執(zhí)行了什么SQL一律留痕。多數(shù)據(jù)庫(kù)支持當(dāng)前主流的MySQL、PostgreSQL、ClickHouse都能接入這也是這篇教程選這三種數(shù)據(jù)庫(kù)的原因。拿它和其他開源方案橫向比一比平臺(tái)SQL審核工單流程多數(shù)據(jù)庫(kù)支持查詢/脫敏社區(qū)活躍度Archery強(qiáng)完整MySQL/PostgreSQL/ClickHouse等支持高Yearning中完整主要MySQL部分中CloudBeaver弱無(wú)多種支持但不克制中Kebinet中部分主要MySQL不支持低Archery的優(yōu)勢(shì)在于“審核流程查詢審計(jì)”是一條完整的閉環(huán)而不是只做了其中某一個(gè)點(diǎn)。這也是我當(dāng)年最終選它的核心理由。1.2 為什么選擇Docker Compose部署Archery自身是基于Django開發(fā)的Web應(yīng)用依賴的東西不算少Python運(yùn)行時(shí)、系統(tǒng)庫(kù)、MySQL它自己的元數(shù)據(jù)庫(kù)、Redis緩存和異步隊(duì)列、Django Q異步任務(wù)調(diào)度再加上各類數(shù)據(jù)庫(kù)驅(qū)動(dòng)和工具包。如果用裸機(jī)部署光是把這些依賴在干凈環(huán)境里裝一遍就能消耗掉大半天時(shí)間。更崩潰的是不同版本的Python和MySQL之間還有兼容性問題換個(gè)機(jī)器就是一場(chǎng)新的災(zāi)難。用Docker Compose部署的好處非常直接環(huán)境隔離所有依賴都封裝在鏡像里宿主機(jī)上裝了什么亂七八糟的Python、庫(kù)都不影響。一條命令拉起docker compose up -d搞定不再需要手寫初始化腳本。升級(jí)回滾方便鏡像版本切來切去配合數(shù)據(jù)卷掛載數(shù)據(jù)還在。三個(gè)角色一個(gè)鏡像Archery容器可以按啟動(dòng)參數(shù)分成web、task、scheduler不同角色實(shí)際部署時(shí)可以用一個(gè)鏡像跑多個(gè)容器。當(dāng)前這套部署方案的整體架構(gòu)大致是這樣的web容器Django應(yīng)用本體提供Web界面和API端口默認(rèn)8080。task容器異步任務(wù)執(zhí)行器處理SQL執(zhí)行、工單狀態(tài)變更等后臺(tái)任務(wù)。scheduler容器定時(shí)任務(wù)調(diào)度負(fù)責(zé)周期性的清理、巡檢、統(tǒng)計(jì)等任務(wù)。MySQL容器Archery的系統(tǒng)元數(shù)據(jù)庫(kù)存放用戶、實(shí)例、工單、規(guī)則等數(shù)據(jù)。Redis容器緩存與異步隊(duì)列。搞清楚這個(gè)架構(gòu)后面看docker-compose配置文件就不會(huì)一頭霧水了。2. 環(huán)境準(zhǔn)備與前置條件2.1 Docker與Docker Compose的安裝檢查工欲善其事必先利其器。不管你是Linux服務(wù)器還是Windows/macOS筆記本先把Docker環(huán)境跑起來。LinuxCentOS/Ubuntu/Debian我建議直接用官方腳本安裝簡(jiǎn)潔省事curl -fsSL https://get.docker.com | bash systemctl enable --now docker docker --version裝完Docker之后確認(rèn)一下Compose插件docker compose version現(xiàn)在新版Docker都自帶Compose V2插件不需要單獨(dú)裝docker-compose這個(gè)獨(dú)立二進(jìn)制了。如果執(zhí)行報(bào)錯(cuò)說明版本太老建議把Docker升級(jí)到20.10以上。Windows / macOSWindows上首推Docker Desktop。但很多人在安裝后啟動(dòng)時(shí)遇到過一個(gè)問題提示virtualization support not detected或者虛擬化支持沒有檢測(cè)到容器根本跑不起來。這個(gè)問題一般不是Docker的鍋而是宿主機(jī)的虛擬化開關(guān)沒開排查路徑按這個(gè)順序來打開任務(wù)管理器 - 性能 - CPU確認(rèn)“虛擬化”這一項(xiàng)是不是“已啟用”。如果顯示“已禁用”需要進(jìn)BIOS開啟Intel VT-x或AMD-V。這一步網(wǎng)上各種教程寫得很多我不展開。確認(rèn)Windows功能里“適用于Linux的Windows子系統(tǒng)”和“虛擬機(jī)平臺(tái)”兩個(gè)選項(xiàng)都勾上了然后重啟。如果依然報(bào)錯(cuò)打開PowerShell管理員執(zhí)行wsl --version確認(rèn)WSL2內(nèi)核是否完整。Windows下如果Docker Desktop實(shí)在啟動(dòng)不了還有一個(gè)保底方案用WSL2里裝Docker Engine。但那是另一個(gè)話題本節(jié)的目標(biāo)是先確認(rèn)Docker和Docker Compose兩條命令能正常輸出版本號(hào)。驗(yàn)證環(huán)境是否就緒docker info docker compose version兩個(gè)命令不報(bào)錯(cuò)就可以繼續(xù)了。2.2 資源規(guī)劃與端口規(guī)劃Docker部署雖然省事但資源需求不能忽視。Archery本身是Java都不用的輕量級(jí)應(yīng)用但它要同時(shí)跑MySQL和Redis還要執(zhí)行一些SQL審核任務(wù)所以資源底線不能太低。我的建議是節(jié)點(diǎn)角色最低配置推薦配置單機(jī)部署本教程4核8GB內(nèi)存8核16GB內(nèi)存磁盤50GB100GB以上為什么內(nèi)存要求不低因?yàn)镸ySQL系統(tǒng)庫(kù)本身就要吃內(nèi)存加上Django進(jìn)程、Redis緩存以及執(zhí)行審核任務(wù)時(shí)的臨時(shí)開銷8GB以下會(huì)明顯感覺卡頓工單提交多了還可能OOM。端口規(guī)劃也比較重要。Archery的Web端口默認(rèn)是8080系統(tǒng)庫(kù)MySQL默認(rèn)3306Redis默認(rèn)6379。這幾條端口在部署前就要想清楚服務(wù)默認(rèn)端口用途注意點(diǎn)Archery Web8080瀏覽器訪問平臺(tái)宿主機(jī)端口可映射為自定義端口系統(tǒng)MySQL3306存儲(chǔ)Archery元數(shù)據(jù)如果宿主機(jī)已有MySQL建議改映射端口Redis6379緩存與異步隊(duì)列內(nèi)網(wǎng)使用不建議暴露公網(wǎng)本機(jī)如果已經(jīng)有服務(wù)占用這些端口docker compose啟動(dòng)時(shí)會(huì)報(bào)port is already allocated。我的習(xí)慣是如果宿主機(jī)3306已經(jīng)被MySQL占用就把容器里的MySQL映射到13306:3306完全不影響Archery內(nèi)部通信因?yàn)槿萜髦g走的是Docker網(wǎng)絡(luò)不依賴宿主機(jī)端口映射。2.3 工作目錄與數(shù)據(jù)目錄規(guī)劃部署前最好先規(guī)劃一個(gè)干凈的工作目錄把配置、數(shù)據(jù)、日志都放在一個(gè)地方后面對(duì)比排查會(huì)省很多事。mkdir -p ~/archery cd ~/archery在這個(gè)目錄下我們會(huì)創(chuàng)建docker-compose.yml同時(shí)會(huì)有兩個(gè)數(shù)據(jù)卷目錄mysql-data和redis-data分別掛載系統(tǒng)庫(kù)的MySQL數(shù)據(jù)和Redis持久化數(shù)據(jù)。這樣即使容器刪了重建數(shù)據(jù)也不會(huì)丟。我的工作目錄結(jié)構(gòu)大概是這樣的~/archery ├── docker-compose.yml ├── mysql-data/ └── redis-data/Docker的細(xì)節(jié)很多人容易忽略一定要把數(shù)據(jù)卷掛載出來。不掛載的話容器刪了數(shù)據(jù)就沒了Archery里面的用戶、工單、實(shí)例配置全部歸零那種感覺比環(huán)境沒裝好還要崩潰。3. 從零部署編寫并啟動(dòng)docker-compose3.1 獲取Archery部署文件與鏡像版本選擇部署Archery之前先到它的GitHub Releases頁(yè)面拿到最新的release包。二進(jìn)制包里除了Docker配置文件還包括初始化SQL腳本、Dockerfile、示例配置等。我習(xí)慣把整個(gè)release包解壓到剛才的~/archery目錄里官方推薦的做法是保留它自帶的docker-compose.yml再按需修改。鏡像的話官方Docker Hub有構(gòu)建好的鏡像倉(cāng)庫(kù)名一般是hhyo/archery。我建議直接使用官方鏡像不要自己從頭構(gòu)建。自己構(gòu)建要拉Python、編譯依賴、裝MySQL客戶端、裝ClickHouse驅(qū)動(dòng)一套下來耗時(shí)很久而且配置容易出錯(cuò)。直接用官方鏡像省去這些繁瑣步驟。拉鏡像的命令docker pull hhyo/archery:latest如果網(wǎng)絡(luò)拉取比較慢可以考慮配置國(guó)內(nèi)鏡像加速器這個(gè)按自己的網(wǎng)絡(luò)環(huán)境處理即可。3.2 編寫docker-compose.yml核心配置逐行解讀這里我給出一個(gè)經(jīng)過我實(shí)際驗(yàn)證可用的docker-compose.yml這個(gè)文件同時(shí)也適合多數(shù)中小型團(tuán)隊(duì)直接抄作業(yè)version: 3.8 services: archery: image: hhyo/archery:latest container_name: archery-web restart: unless-stopped ports: - 8080:8080 environment: MYSQL_HOST: mysql MYSQL_PORT: 3306 MYSQL_USER: archery MYSQL_PASSWORD: ArcheryPass2024 MYSQL_DATABASE: archery REDIS_HOST: redis REDIS_PORT: 6379 TZ: Asia/Shanghai volumes: - ./data:/app/data depends_on: - mysql - redis mysql: image: mysql:8.0 container_name: archery-mysql restart: unless-stopped ports: - 13306:3306 environment: MYSQL_ROOT_PASSWORD: RootPass2024 MYSQL_DATABASE: archery MYSQL_USER: archery MYSQL_PASSWORD: ArcheryPass2024 TZ: Asia/Shanghai command: - --character-set-serverutf8mb4 - --collation-serverutf8mb4_unicode_ci volumes: - ./mysql-data:/var/lib/mysql redis: image: redis:7 container_name: archery-redis restart: unless-stopped ports: - 16379:6379 volumes: - ./redis-data:/data各個(gè)配置的作用我逐條解釋一下archery 服務(wù)核心應(yīng)用容器。端口8080映射到宿主機(jī)瀏覽器訪問http://localhost:8080就是Archery的登錄頁(yè)。MYSQL_環(huán)境變量*告訴Archery去連哪臺(tái)MySQL。這里的mysql是compose網(wǎng)絡(luò)內(nèi)的服務(wù)名Docker內(nèi)部的DNS會(huì)自動(dòng)解析到這個(gè)MySQL容器不需要寫IP。REDIS_環(huán)境變量*同理指定Redis服務(wù)地址。depends_on保證MySQL和Redis先于Archery啟動(dòng)。但這里有個(gè)坑MySQL容器起來不等于數(shù)據(jù)庫(kù)初始化完成所以后面首次啟動(dòng)后需要等幾秒鐘再初始化Archery。mysql 服務(wù)Archery的系統(tǒng)庫(kù)。ports映射我用的是13306:3306避免和宿主機(jī)已有的MySQL沖突。同時(shí)指定了utf8mb4字符集避免中文亂碼。redis 服務(wù)緩存和消息隊(duì)列。3.3 首次啟動(dòng)與初始化從拉取鏡像到創(chuàng)建管理員配置完成后第一次啟動(dòng)不要急著直接初始化按這個(gè)順序操作第一步啟動(dòng)容器cd ~/archery docker compose up -d這個(gè)命令會(huì)依次拉取鏡像并啟動(dòng)三個(gè)容器。第一次拉取可能需要一段時(shí)間取決于網(wǎng)絡(luò)。啟動(dòng)后用docker compose ps查看狀態(tài)docker compose ps看到三個(gè)容器狀態(tài)都是Up說明容器層面沒問題了。第二步等MySQL初始化完成MySQL容器首次啟動(dòng)時(shí)需要初始化數(shù)據(jù)目錄和系統(tǒng)表這個(gè)過程通常需要10到30秒。直接執(zhí)行下面的命令確認(rèn)MySQL能正常連上docker exec -it archery-mysql mysql -uarchery -pArcheryPass2024 -e select 1;如果能返回1說明數(shù)據(jù)庫(kù)已經(jīng)可用。如果報(bào)連接失敗等一下再試。第三步初始化Archery系統(tǒng)表并加載數(shù)據(jù)Archery的release包中自帶初始化腳本通常位于sql/目錄下。把release包里的init.sql文件復(fù)制到容器中執(zhí)行或者直接用docker exec進(jìn)入容器執(zhí)行遷移docker exec -it archery-web python3 manage.py migrate這一步會(huì)創(chuàng)建Archery運(yùn)行所需的全部數(shù)據(jù)表。如果執(zhí)行時(shí)報(bào)錯(cuò)說連不上MySQL大概率是MySQL還沒準(zhǔn)備好重新執(zhí)行一次即可。隨后加載初始化數(shù)據(jù)docker exec -it archery-web python3 manage.py dbshell sql/init.sql初始化數(shù)據(jù)會(huì)寫入內(nèi)置規(guī)則、默認(rèn)資源組、管理員賬號(hào)等基礎(chǔ)數(shù)據(jù)。第四步創(chuàng)建超級(jí)管理員docker exec -it archery-web python3 manage.py createsuperuser按提示輸入用戶名、郵箱、密碼建議用戶名直接用admin密碼設(shè)置復(fù)雜一點(diǎn)。這一步創(chuàng)建的賬號(hào)是超級(jí)管理員可以登錄平臺(tái)做所有配置。第五步訪問平臺(tái)瀏覽器打開http://localhost:8080用剛創(chuàng)建的超級(jí)管理員賬號(hào)登錄??吹降卿涰?yè)說明整套系統(tǒng)已經(jīng)跑起來了。到這里Archery的部署已經(jīng)完成。很多教程會(huì)在這里收尾但實(shí)戰(zhàn)中真正花時(shí)間的往往是后面的實(shí)例接入和權(quán)限配置這也是接下來我要重點(diǎn)展開的部分。4. 系統(tǒng)配置與三種數(shù)據(jù)庫(kù)實(shí)例接入4.1 登錄后臺(tái)后的基礎(chǔ)配置用超級(jí)管理員登錄Archery之后第一件事不是急著加數(shù)據(jù)庫(kù)實(shí)例而是把系統(tǒng)的整體配置過一遍。進(jìn)入“系統(tǒng)管理”-“系統(tǒng)配置”建議優(yōu)先調(diào)整以下幾項(xiàng)平臺(tái)名稱改成自己公司的名稱開發(fā)人員登錄后知道進(jìn)的是哪個(gè)平臺(tái)。工單超時(shí)時(shí)間設(shè)置一個(gè)合理的審核超時(shí)限制避免工單被DBA遺忘。郵箱SMTP配置如果希望工單提交、審核時(shí)有郵件通知這里必須配置。沒有郵件服務(wù)可以先跳過不影響核心流程。LDAP/LDAP對(duì)接公司有統(tǒng)一認(rèn)證的話可以對(duì)接小團(tuán)隊(duì)可以暫時(shí)忽略?;A(chǔ)配置完成后接下來就是重頭戲把三種數(shù)據(jù)庫(kù)實(shí)例接入進(jìn)來。Archery的實(shí)例管理入口在“實(shí)例管理”-“新增實(shí)例”。接入的過程雖然界面相似但每種數(shù)據(jù)庫(kù)在權(quán)限和連接參數(shù)上有些細(xì)微差異逐個(gè)來說。4.2 接入MySQL實(shí)例最順手也最需要細(xì)心MySQL是Archery支持得最完善的數(shù)據(jù)庫(kù)類型也是絕大多數(shù)團(tuán)隊(duì)的第一選擇。新增實(shí)例時(shí)關(guān)鍵參數(shù)這樣填數(shù)據(jù)庫(kù)類型選MySQL實(shí)例名稱建議用“環(huán)境業(yè)務(wù)角色”的命名方式比如生產(chǎn)-訂單庫(kù)-主庫(kù)主機(jī)地址與端口填MySQL實(shí)例所在的IP和端口。這里必須是Archery容器能訪問到的地址不能填localhost否則Archery連的是它自己的容器網(wǎng)絡(luò)連不到你的MySQL。這是新手最容易踩的坑。數(shù)據(jù)庫(kù)賬號(hào)與密碼Archery連接MySQL執(zhí)行審核和執(zhí)行操作需要一個(gè)專用的賬號(hào)不要直接用root。建議按下面的SQL創(chuàng)建一個(gè)賬號(hào)CREATE USER archery% IDENTIFIED BY YourPass2024; GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, INDEX, CREATE VIEW, SHOW VIEW, PROCESS, SUPER ON *.* TO archery%; FLUSH PRIVILEGES;這里為什么需要PROCESS和SUPER權(quán)限因?yàn)锳rchery做SQL審核時(shí)需要獲取當(dāng)前數(shù)據(jù)庫(kù)的線程列表和會(huì)話信息以便判斷當(dāng)前是否存在長(zhǎng)事務(wù)、鎖等待等高危場(chǎng)景。沒有這兩個(gè)權(quán)限功能會(huì)部分失效。測(cè)試連接填完參數(shù)后點(diǎn)擊“測(cè)試連接”Archery會(huì)嘗試連接目標(biāo)庫(kù)并校驗(yàn)賬號(hào)權(quán)限。如果提示連接失敗優(yōu)先檢查網(wǎng)絡(luò)連通性和賬號(hào)權(quán)限。MySQL接入完成后建議提交一條最簡(jiǎn)單的SELECT查詢工單驗(yàn)證一遍完整流程開發(fā)提交查詢申請(qǐng)DBA審核通過執(zhí)行并返回結(jié)果。流程走通說明這個(gè)實(shí)例真正可用了。4.3 接入PostgreSQL實(shí)例注意schema與權(quán)限PostgreSQL在復(fù)雜查詢、地理信息等場(chǎng)景下非常受歡迎Archery對(duì)它的支持也比較成熟。新增實(shí)例時(shí)類型選PostgreSQL主機(jī)端口默認(rèn)填5432。接入PostgreSQL時(shí)有三個(gè)細(xì)節(jié)需要特別留意第一賬號(hào)權(quán)限模型和MySQL完全不同。PostgreSQL使用“角色”體系建議為Archery單獨(dú)創(chuàng)建專用角色CREATE USER archery WITH PASSWORD YourPass2024; GRANT CONNECT ON DATABASE yourdb TO archery; GRANT USAGE ON SCHEMA public TO archery; GRANT SELECT ON ALL TABLES IN SCHEMA public TO archery; GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO archery;如果還要執(zhí)行DDL需要額外授予相應(yīng)的權(quán)限。很多人在這里圖省事直接給了超級(jí)用戶權(quán)限我不推薦一是審計(jì)留痕會(huì)混淆操作者二是一旦賬號(hào)被濫用影響范圍太大。第二schema的選擇。PostgreSQL默認(rèn)是public但很多業(yè)務(wù)會(huì)自建schema。在Archery實(shí)例配置中指定正確的schema否則會(huì)出現(xiàn)“表不存在”的問題。第三驅(qū)動(dòng)兼容性。Archery通過psycopg2連接PostgreSQL如果實(shí)例是PostgreSQL 12以上版本驅(qū)動(dòng)一般沒問題。如果是老版本建議升級(jí)Archery鏡像到最新版本避免驅(qū)動(dòng)兼容性報(bào)錯(cuò)。4.4 接入ClickHouse實(shí)例分析場(chǎng)景的另類玩法ClickHouse接入Archery的場(chǎng)景通常是大數(shù)據(jù)部門做OLAP分析開發(fā)需要跑一些查詢但這些查詢可能很重會(huì)對(duì)ClickHouse集群造成壓力。這時(shí)候用Archery做審核和限流就非常有價(jià)值。新增ClickHouse實(shí)例時(shí)關(guān)鍵配置和MySQL/PostgreSQL略有不同數(shù)據(jù)庫(kù)類型選ClickHouse端口ClickHouse有HTTP端口默認(rèn)8123和Native端口默認(rèn)9000Archery通常走HTTP端口。填8123即可不需要填9000。賬號(hào)權(quán)限ClickHouse的權(quán)限控制比較特殊可以為Archery單獨(dú)建一個(gè)賬號(hào)只授予只讀權(quán)限并根據(jù)需要限制查詢的內(nèi)存和超時(shí)。CREATE USER archery IDENTIFIED WITH plaintext_password YourPass2024; GRANT SELECT ON *.* TO archery;如果ClickHouse開啟了readonly1Archery執(zhí)行查詢不會(huì)有問題但執(zhí)行DDL或INSERT類工單會(huì)被拒。這是正常的ClickHouse的生產(chǎn)環(huán)境通常也是這種安全模式。ClickHouse接入有一個(gè)特別值得注意的點(diǎn)Archery的審核規(guī)則是基于MySQL語(yǔ)法規(guī)則設(shè)計(jì)的ClickHouse的SQL語(yǔ)法和一些函數(shù)跟MySQL有差異。所以ClickHouse實(shí)例的“審核”能力會(huì)比MySQL弱一些更多是流程管理和查詢權(quán)限控制。這一點(diǎn)在團(tuán)隊(duì)內(nèi)推廣的時(shí)候要提前說明避免開發(fā)誤以為CRC代碼審查層面的規(guī)則也能完全覆蓋ClickHouse。4.5 資源組與用戶權(quán)限讓合適的人做合適的事實(shí)例接入完成后還差最后一步把實(shí)例和用戶綁定到資源組。Archery的權(quán)限模型是“用戶 - 資源組 - 實(shí)例”只有把用戶加入某個(gè)資源組用戶才能在該資源組下的實(shí)例上提交工單或發(fā)起查詢。進(jìn)入“資源組”頁(yè)面新增一個(gè)資源組比如“訂單業(yè)務(wù)組”然后把剛才接入的三個(gè)實(shí)例都加入這個(gè)資源組再把開發(fā)人員和DBA賬號(hào)加入進(jìn)來。注意用戶權(quán)限分兩種DBA角色可以審核和執(zhí)行工單權(quán)限較大嚴(yán)格控制人數(shù)。開發(fā)角色只能提交工單和發(fā)起查詢不能審核自己的工單。我見過很多團(tuán)隊(duì)部署完Archery所有賬號(hào)都給超級(jí)管理員權(quán)限結(jié)果審計(jì)日志完全失去意義。規(guī)范的做法是超級(jí)管理員只留1到2個(gè)人其余人都按角色分配DBA負(fù)責(zé)審核開發(fā)負(fù)責(zé)提交。5. 常見問題與排查技巧實(shí)錄5.1 高頻問題速查表把這幾年用Archery過程中遇到的典型問題整理成一張速查表部署時(shí)遇到問題可以直接對(duì)照問題現(xiàn)象可能原因解決方法Docker Desktop啟動(dòng)失敗提示virtualization support not detected宿主機(jī)虛擬化沒開啟或WSL2未正確安裝進(jìn)BIOS開啟VT-x/AMD-V開啟“虛擬機(jī)平臺(tái)”和WSL2功能docker compose up報(bào)端口已占用宿主機(jī)端口被已有服務(wù)占用修改docker-compose.yml中的端口映射Archery容器啟動(dòng)后立刻退出環(huán)境變量配置錯(cuò)誤或MySQL還沒就緒docker logs archery-web查看日志確認(rèn)MYSQL_HOST、MYSQL_PASSWORD正確python3 manage.py migrate報(bào)連接MySQL失敗MySQL尚未完成初始化或者M(jìn)YSQL_HOST配置錯(cuò)誤等待MySQL就緒后重試確認(rèn)容器間使用服務(wù)名通信新增實(shí)例測(cè)試連接失敗網(wǎng)絡(luò)不通、賬號(hào)權(quán)限不足、端口填錯(cuò)從Archery容器內(nèi)ping目標(biāo)實(shí)例檢查賬號(hào)權(quán)限和端口連接MySQL 8.0時(shí)報(bào)認(rèn)證協(xié)議錯(cuò)誤目標(biāo)庫(kù)的認(rèn)證插件是caching_sha2_passwordArchery驅(qū)動(dòng)不支持創(chuàng)建賬號(hào)時(shí)指定IDENTIFIED WITH mysql_native_password BY 密碼工單提交后一直處于等待執(zhí)行狀態(tài)task容器沒起來或Redis沒連上檢查task容器狀態(tài)確認(rèn)Redis環(huán)境變量配置正確ClickHouse實(shí)例能查但執(zhí)行DDL失敗賬號(hào)只讀權(quán)限或ClickHouse只讀模式按需調(diào)整賬號(hào)權(quán)限或在ClickHouse配置中關(guān)閉readonly頁(yè)面中文亂碼系統(tǒng)庫(kù)字符集不是utf8mb4在MySQL容器啟動(dòng)命令中增加--character-set-serverutf8mb45.2 實(shí)操中踩過的幾個(gè)大坑坑一容器名和實(shí)例地址混為一談新增MySQL實(shí)例的時(shí)候如果你填的是localhost:3306從Archery容器內(nèi)部訪問到的不是宿主機(jī)的MySQL而是容器自己。宿主機(jī)上的數(shù)據(jù)庫(kù)要從容器內(nèi)訪問需要填宿主機(jī)的內(nèi)網(wǎng)IP或者把端口映射出來用宿主機(jī)IP訪問。這個(gè)細(xì)節(jié)是新手最常見的失誤菜鳥教程里幾乎沒人提。坑二MySQL 8.0的認(rèn)證插件兼容問題MySQL 8.0默認(rèn)的認(rèn)證插件是caching_sha2_password但Archery內(nèi)置的MySQL驅(qū)動(dòng)在某些版本下對(duì)它有兼容問題表現(xiàn)為“測(cè)試連接失敗”或者“認(rèn)證插件不支持”。解決方案是創(chuàng)建專用賬號(hào)時(shí)顯式指定CREATE USER archery% IDENTIFIED WITH mysql_native_password BY YourPass2024;這個(gè)坑我在第一次部署時(shí)折騰了將近一個(gè)下午最后查驅(qū)動(dòng)源碼才定位到?,F(xiàn)在每個(gè)環(huán)境接入MySQL我都直接用這個(gè)寫法省事很多??尤萜鲉?dòng)順序?qū)е鲁跏蓟ocker-compose的depends_on只保證服務(wù)啟動(dòng)順序不保證MySQL“可用”。如果MySQL容器還在初始化數(shù)據(jù)目錄Archery就已經(jīng)開始連數(shù)據(jù)庫(kù)必然報(bào)錯(cuò)。init時(shí)不要急先用docker logs archery-mysql查看MySQL日志看到類似ready for connections的日志再執(zhí)行Archery的遷移命令。坑四忘掛載數(shù)據(jù)卷有同事把Archery部署在測(cè)試環(huán)境用了一個(gè)月后來為了升級(jí)鏡像刪掉容器結(jié)果所有配置、工單、審計(jì)記錄灰飛煙滅。Archery的元數(shù)據(jù)全在系統(tǒng)MySQL里如果MySQL容器沒有把數(shù)據(jù)目錄掛載到宿主機(jī)刪容器刪數(shù)據(jù)。所以我強(qiáng)烈建議在部署開始時(shí)就把數(shù)據(jù)卷掛載做好這比任何高級(jí)配置都重要。5.3 日常維護(hù)與備份建議Archery上線之后日常維護(hù)主要圍繞三件事第一定期備份系統(tǒng)庫(kù)。Archery的元數(shù)據(jù)庫(kù)是整個(gè)平臺(tái)的“大腦”所有用戶、實(shí)例、工單、審計(jì)記錄都在里面。我的習(xí)慣是每天凌晨用mysqldump做一次全量備份保留7天。命令行可以直接寫在宿主機(jī)cron里docker exec archery-mysql mysqldump -uarchery -pArcheryPass2024 archery /backup/archery_$(date %F).sql第二觀察容器狀態(tài)。上線初期最容易出現(xiàn)task容器內(nèi)存飆升的情況尤其是大量工單同時(shí)執(zhí)行時(shí)。用docker stats看一眼實(shí)時(shí)資源如果內(nèi)存持續(xù)偏高考慮給task容器加上內(nèi)存限制。第三升級(jí)前先看變更記錄。Archery迭代速度還算快但每次升級(jí)數(shù)據(jù)庫(kù)表結(jié)構(gòu)可能都有變化。升級(jí)前一定先備份然后用新鏡像啟動(dòng)一個(gè)測(cè)試容器驗(yàn)證沒問題再替換生產(chǎn)環(huán)境。直接在生產(chǎn)環(huán)境硬升級(jí)萬(wàn)一數(shù)據(jù)遷移腳本有問題工單和審計(jì)記錄很可能出問題。結(jié)尾一個(gè)老DBA的心里話最后再分享一點(diǎn)個(gè)人經(jīng)驗(yàn)。Archery這套系統(tǒng)部署起來不難難的是讓它真正在團(tuán)隊(duì)里落地。我第一次部署的時(shí)候流程跑通了但開發(fā)根本不樂意用覺得在Web上提SQL比直接連數(shù)據(jù)庫(kù)麻煩多了。后來我們做了兩件事扭轉(zhuǎn)了局面一是把審核規(guī)則和開發(fā)團(tuán)隊(duì)公開對(duì)齊讓規(guī)則透明二是讓DBA在工單里寫清楚駁回原因不搞一言堂。工具是死的流程是活的。Archery能把“數(shù)據(jù)庫(kù)變更”這件高風(fēng)險(xiǎn)的事變得有章可循但真正讓它發(fā)揮價(jià)值還是靠團(tuán)隊(duì)一起把規(guī)范立起來。希望這篇教程能幫你少走一些彎路少踩幾個(gè)坑。