控系統(tǒng):服務(wù)端容器化遷移與踩坑實戰(zhàn))
先交代一下背景。我這邊常年管著幾十臺虛擬機換來換去最容易翻車的往往是監(jiān)控系統(tǒng)本身——業(yè)務(wù)還沒遷過去監(jiān)控先失聯(lián)了。之前WGCLOUD監(jiān)控系統(tǒng)的server端一直是拿jar包直接在宿主機上跑的雖然也能用但每次換機器、升版本都得跟Java環(huán)境、端口占用、殘留進程較勁。后來干脆把server端塞進Docker容器整個遷移和回滾流程瞬間清爽了很多。這篇就把我用Docker部署WGCLOUD監(jiān)控系統(tǒng)server端的完整過程和踩坑經(jīng)驗整理出來給同樣打算容器化部署的朋友做個參考。1. 為什么我不用jar包硬跑而是把WGCLOUD server裝進容器WGCLOUD這類開源監(jiān)控系統(tǒng)服務(wù)端和客戶端的關(guān)系就像漁網(wǎng)和魚agent客戶端撒到各臺被監(jiān)控主機上負責采集CPU、內(nèi)存、磁盤、進程這些實時數(shù)據(jù)然后定時上報給server服務(wù)端server端把數(shù)據(jù)落庫、出圖、觸發(fā)告警最后通過Web界面呈現(xiàn)給你。這里說的server端就是監(jiān)控系統(tǒng)的“大腦”agent只是它的眼睛和耳朵。1.1 WGCLOUD服務(wù)端的部署形態(tài)jar包和容器哪個更適合你WGCLOUD的server端本質(zhì)上是一個Java應(yīng)用正式發(fā)布一般會提供打包好的jar包或者可執(zhí)行安裝包。傳統(tǒng)做法是直接在宿主機上裝JDK、跑jar包好處是結(jié)構(gòu)簡單壞處也明顯宿主機環(huán)境一旦被其他業(yè)務(wù)搞亂了最常見的就是JDK版本被覆蓋監(jiān)控系統(tǒng)第一個遭殃。用Docker部署server端的核心價值在于環(huán)境隔離和狀態(tài)可遷移。鏡像把JDK、依賴、配置文件全部固化到一個層里宿主機上有Oracle JDK還是OpenJDK、有沒有其他Java進程搶占9099端口跟容器完全無關(guān)。我實測下來從一臺機器把整個監(jiān)控server遷到另一臺只需要把容器和數(shù)據(jù)目錄搬過去五分鐘能搞定的程度。1.2 什么情況下我建議你還是用jar包說實話Docker部署也不是沒有代價。如果你只需要在固定一臺機器上部署一次、之后極少折騰那直接跑jar包反而更直接省去學習Docker的精力。但如果你的環(huán)境是虛擬化集群、經(jīng)常要擴縮容、想借這個機會把監(jiān)控server的部署也納入到通用的容器管理流程里那Docker部署就非常值得。我在切換過程中發(fā)現(xiàn)容器化之后最大的收益不是部署快其實第一次反而比jar包慢因為要先搞定鏡像和數(shù)據(jù)卷而是回滾變得極其簡單。jar包部署回滾要重新傳包、停服務(wù)、換包、再啟動容器部署回滾就一條命令換回舊鏡像數(shù)據(jù)完全不受影響。這是我最看重的點。2. 部署前的三張底牌鏡像來源、存儲目錄和端口規(guī)劃動手敲docker run之前有三件事必須想清楚否則后面大概率要返工鏡像從哪來、數(shù)據(jù)往哪存、端口怎么規(guī)劃。2.1 鏡像獲取官方維護版本優(yōu)先別亂用個人鏡像WGCLOUD官方發(fā)布頁會提供容器鏡像的獲取方式一般在Docker Hub的官方倉庫下就能搜到。我個人的習慣是只認官方倉庫維護的鏡像盡量不用第三方個人打包的版本。因為監(jiān)控系統(tǒng)里跑著的是關(guān)鍵業(yè)務(wù)數(shù)據(jù)來路不明的鏡像里萬一塞了點私貨你的服務(wù)器數(shù)據(jù)就全暴露了。另外鏡像標簽選擇上我建議避開latest這種滾動標簽。WGCLOUD升級頻率不低latest可能這段時間指代v3.x下個月就變成v4.x了你沒法控制哪天pull下來的到底是什么版本。最好是固定到具體的版本號標簽比如官方發(fā)布說明里標注的v3.x-rev數(shù)字這種格式方便后面做版本管理和回滾。2.2 存儲目錄容器可以被刪數(shù)據(jù)目錄必須焊死WGCLOUD server端默認使用自帶的H2數(shù)據(jù)庫所有監(jiān)控歷史數(shù)據(jù)、用戶配置、告警記錄都存在server安裝目錄下的data文件夾里。很多第一次用Docker部署的朋友會忽略這一點跑起來一個容器發(fā)現(xiàn)一切正常等到某天不小心刪了容器重啟監(jiān)控數(shù)據(jù)全部清零那才叫欲哭無淚。所以部署之前你先規(guī)劃好宿主機上的持久化目錄。我一般習慣創(chuàng)建這樣一個結(jié)構(gòu)/opt/wgcloud/ └── server/ └── data/ # 映射容器內(nèi)的數(shù)據(jù)目錄需要說明一下不同版本的鏡像容器內(nèi)數(shù)據(jù)目錄的具體路徑可能會略有差異有的版本叫/data有的可能掛在/app/server/data下這個以官方鏡像的說明為準。部署前建議先拉一次鏡像用docker inspect看一眼鏡像聲明的VOLUME路徑確認好再掛載避免數(shù)據(jù)卷映射到了一個空目錄。2.3 端口規(guī)劃9999是主端口別和別的服務(wù)打架WGCLOUD server端默認監(jiān)聽9999端口這個端口同時承擔著兩件事一是給瀏覽器訪問Web控制臺用二是接收所有agent上報的數(shù)據(jù)。也就是說只要這個端口通了agent的靈魂和Web的肉體現(xiàn)在就都綁在上面。我負責的環(huán)境里有不少舊系統(tǒng)喜歡用9999這種端口有的應(yīng)用默認就用它部署前一定要先確認ss -lntp | grep 9999如果端口被占你有兩個選擇一是在宿主機映射時換一個外部端口比如-p 9527:9999但這樣所有agent上傳數(shù)據(jù)地址也要改成9527改動面變大二是直接換一個空閑端口映射我更推薦前者外部端口換一下內(nèi)部容器端口保持默認agent那邊照樣配9999這樣agent配置不用動。端口規(guī)劃可以用下面這個表來提前記錄項目默認值我的規(guī)劃值說明Web控制臺端口99999999瀏覽器訪問http://宿主機IP:9999agent上報端口99999999agent主動連接server的9999端口數(shù)據(jù)目錄掛載/data(視版本)/opt/wgcloud/server/data持久化H2數(shù)據(jù)庫文件容器時區(qū)默認UTCAsia/Shanghai不設(shè)置的話告警時間會差8小時上面這個表格看著簡單但每一條我都吃過虧端口沖突是第一坑時區(qū)是第二坑數(shù)據(jù)卷是第三坑。接下來逐個說。3. 我的完整部署命令與參數(shù)拆解一次跑通的記錄當鏡像、存儲目錄、端口這三件事都定了部署命令本身反而沒什么玄學。我把自己實際用過的啟動命令貼出來逐條解釋為什么這么寫你可以直接抄作業(yè)但要把路徑和版本標簽換成你自己的。3.1 啟動命令逐行解析我的部署環(huán)境是一臺四核8G內(nèi)存的虛擬機宿主機系統(tǒng)是Ubuntu 20.04 LTSDocker版本是20.10.x。完整命令如下docker run -d \ --name wgcloud-server \ --restartalways \ -p 9999:9999 \ -v /opt/wgcloud/server/data:/data \ -e TZAsia/Shanghai \ --memory2g \ wgcloud官方倉庫鏡像:v3.x一行一行說。--restartalways這個必須加。監(jiān)控server本身就是基礎(chǔ)設(shè)施組件宿主機重啟之后容器必須自己拉起來。如果不加哪天機房斷電重啟你的監(jiān)控系統(tǒng)就忘了自己回來而且沒人發(fā)現(xiàn)因為連告警都發(fā)不出來了。-p 9999:9999剛才說過這個端口同時服務(wù)Web和agent。-v /opt/wgcloud/server/data:/data宿主機數(shù)據(jù)目錄映射到容器內(nèi)數(shù)據(jù)目錄。這里要注意的是宿主機上的data目錄如果有舊數(shù)據(jù)WGCLOUD啟動時會做一次數(shù)據(jù)兼容檢查。從舊版本鏡像升級時官方會提供數(shù)據(jù)庫升級說明操作前多看一眼別直接用新版本容器啟動舊數(shù)據(jù)不然可能引發(fā)數(shù)據(jù)庫結(jié)構(gòu)不匹配。-e TZAsia/Shanghai時區(qū)環(huán)境變量。國內(nèi)服務(wù)器務(wù)必加這個。如果不加容器內(nèi)Java虛擬機的默認時區(qū)是UTC你會發(fā)現(xiàn)監(jiān)控圖表里的時間比實際慢8個小時告警時間的判斷也會出偏差明明9點發(fā)的機器顯示凌晨1點。容器內(nèi)時區(qū)的影響是全局性的不只是顯示層問題。--memory2g限制容器最大內(nèi)存為2G。WGCLOUD server端整體屬于輕量級應(yīng)用官方建議server最低1G內(nèi)存但監(jiān)控的主機數(shù)量多起來比如上百臺agent上報、歷史數(shù)據(jù)保留周期長的時候內(nèi)存占用會往上走。限制2G是個比較穩(wěn)的中間值避免單個容器把宿主機內(nèi)存吃干。還有一個小細節(jié)如果你需要為JVM單獨設(shè)置Heap大小可以留意鏡像是否支持通過環(huán)境變量傳入Java參數(shù)。我一般不在這個層面折騰讓JVM自己根據(jù)容器內(nèi)存限制去自適應(yīng)實測更省心除非監(jiān)控規(guī)模特別大否則不需要手動調(diào)-Xmx。3.2 第一次啟動后的驗證清單容器跑起來之后別急著登錄Web頁面先按下面的順序做一輪驗證能幫你第一時間發(fā)現(xiàn)隱藏問題查看容器狀態(tài)和日志docker ps | grep wgcloud-server docker logs --tail100 wgcloud-server日志里應(yīng)當能看到server啟動完成的標志信息比如監(jiān)聽的端口號、初始化完成的提示等。檢查宿主機端口監(jiān)聽ss -lntp | grep 9999瀏覽器訪問http://宿主機IP:9999這一步正常能看到WGCLOUD的登錄頁。默認賬號是admin初始密碼是111111新版本第一次登錄會強制要求改密碼。這是WGCLOUD官方默認憑據(jù)如果你跑完登錄不進去多半是鏡像來源有問題或者數(shù)據(jù)目錄里殘留了舊數(shù)據(jù)。登錄后先看系統(tǒng)概覽頁是否自動出現(xiàn)了server本機的監(jiān)控數(shù)據(jù)。WGCLOUD有個特性server端會把自己當作一臺被監(jiān)控主機自動內(nèi)置了一個agent來上報自身狀態(tài)。如果你在Web界面能看到server自身的CPU、內(nèi)存曲線在跳動說明整個數(shù)據(jù)鏈路從采集到入庫到展示是通的這也說明server端部署成功了。順便說一句我見過有人在宿主機防火墻里忘了放行9999端口然后折騰了半天Web頁面打不開。Ubuntu上如果是ufw管理防火墻記得執(zhí)行ufw allow 9999/tcp如果是云主機安全組規(guī)則里也要放行。這個問題實在太過常見排查順序一定是從底往上先網(wǎng)絡(luò)通不通再容器活沒活最后才看應(yīng)用配置。4. 接入agent才是部署閉環(huán)從server端驗證整個監(jiān)控鏈路server端起來了只是上半場監(jiān)控系統(tǒng)的真正價值在于agent能不能穩(wěn)定上報數(shù)據(jù)。接入agent有兩件事需要注意一是agent配置的server地址IP或域名和端口要保持可達二是agent和server的版本要盡量保持在同一代。版本不一致在我實際運維中踩過不少次釘子后面展開說。4.1 agent下載、配置和啟動的標準化流程WGCLOUD的agent一般不用安裝解壓即用依賴有一個Java運行環(huán)境。在目標主機上執(zhí)行# 下載對應(yīng)版本的agent包傳到目標主機后解壓 tar -zxf wgcloud-agent-xxx.tar.gz cd wgcloud-agentagent的核心配置在conf目錄下我記不清具體配置文件名了但關(guān)鍵是改兩處一是server端的IP或域名二是上報端口。默認端口9999跟server端一致。有的版本里配置文件還分“私有IP”和“公網(wǎng)IP”兩個參數(shù)如果agent和server在同一個內(nèi)網(wǎng)段填內(nèi)網(wǎng)IP就行跨網(wǎng)段或走公網(wǎng)的話就填對應(yīng)的地址這個看你的網(wǎng)絡(luò)情況來定。改完配置后啟動agent常見的方式是執(zhí)行start.sh腳本。啟動后可以先看agent的本地日志確認它有沒有嘗試連接server端、連接是否成功。如果日志里出現(xiàn)連接超時或連接被拒絕先別急著懷疑server端口按這個順序排查在agent主機上ping server IP確認網(wǎng)絡(luò)層通。用telnet測9999端口通不通timeout 5 bash -c cat /dev/null /dev/tcp/server-ip/9999 echo port open如果是從外部網(wǎng)絡(luò)過來檢查安全組、防火墻。最后確認server端的容器日志里有沒有對應(yīng)agent的連接記錄。4.2 server端如何確認agent已經(jīng)接入agent啟動后間隔一小段時間WGCLOUD默認采集周期一般是一分鐘以內(nèi)server端Web界面左側(cè)的“主機管理”列表里就會陸續(xù)出現(xiàn)新主機。每臺新主機會帶上agent的IP、主機名、操作系統(tǒng)版本這些基本信息。此時點擊主機名能看到CPU、內(nèi)存、磁盤、網(wǎng)絡(luò)等監(jiān)控大項開始出圖。我每次接入新agent后都會做一次告警測試這比看圖靠譜得多。比如手動觸發(fā)一個“CPU占用率超閾值”的測試告警看server端能否在預(yù)期時間窗口內(nèi)彈出告警并成功推送通知。如果告警鏈路不通那agent就算接了上千臺也是白接等你服務(wù)器真宕機了才發(fā)現(xiàn)告警沒響那才叫慘。這里分享一個非常實用的經(jīng)驗把server和agent的時鐘校正做好。如果被監(jiān)控主機的時間跟server端時間偏差太大尤其是一些內(nèi)網(wǎng)機器常年不校時WGCLOUD部分版本會因為時間戳異常導致圖標亂跳甚至收不到數(shù)據(jù)。建議所有agent和server都配置NTP同步這算是我在生產(chǎn)環(huán)境緊盯的一條底褲。4.3 agent版本等于server版本這條紅線別破關(guān)于agent與server的版本匹配我再多寫幾行。WGCLOUD官方往往要求agent和server版本保持一致或者至少大版本號相同。具體原因大概是兩邊的通信協(xié)議和數(shù)據(jù)上報格式跟著版本走新版server可能加了新的資源監(jiān)控項舊版agent不認識自然就上報不了對應(yīng)數(shù)據(jù)反過來新版agent上報的數(shù)據(jù)格式舊版server解析不了日志里會各種異常。我在一次小版本混雜的場景中就遇到過server升到v3.xagent還是v2.x時代留下的包結(jié)果Web界面上主機狀態(tài)顯示正常但磁盤IO那一堆數(shù)據(jù)死活不出來。折騰半天才發(fā)現(xiàn)是agent版本太老字段對不上。從那之后我就定了一個規(guī)矩升級server的同時所有agent必須一并升級到配套版本哪怕麻煩一點也要統(tǒng)一否則一個環(huán)境里agent版本五花八門后面的坑只會越來越多。5. 升級、備份與起不來的舊坑容器部署運維筆記寫完第一版部署總結(jié)之后我又在實際運維中陸陸續(xù)續(xù)遇到了一些問題專門開這一章把升級流程、數(shù)據(jù)備份方法以及三種常見的啟動失敗場景記錄下來算是給前面的內(nèi)容打個補丁。5.1 數(shù)據(jù)備份停容器再拷目錄別圖省事WGCLOUD的監(jiān)控數(shù)據(jù)都落在H2數(shù)據(jù)庫文件里保證數(shù)據(jù)備份的最佳實踐是先停止容器再拷貝數(shù)據(jù)目錄。直接對運行中的容器的數(shù)據(jù)目錄執(zhí)行cp表面上看文件拷出來了但H2數(shù)據(jù)庫可能在落盤的瞬間有未寫完的事務(wù)備下來的可能就是一份損壞的數(shù)據(jù)??Х冗€沒煮完就把杯子拿走了杯里缺一口一回事。我的操作順序如下docker stop wgcloud-server cp -a /opt/wgcloud/server/data /opt/wgcloud/server/backup/data_$(date %Y%m%d_%H%M%S) docker start wgcloud-server注意容器重啟后Web頁面要等幾十秒才能訪問別誤以為又出故障了。備份文件建議保留最近兩到三個版本周期覆蓋掉到服務(wù)器上另外一個目錄去歸檔。5.2 升級容器版本的操作流程WGCLOUD升級和普通容器服務(wù)升級略有不同因為除了鏡像本身的更新還涉及數(shù)據(jù)目錄里數(shù)據(jù)庫文件的版本遷移。我一般按下面幾步操作備份按上面5.1的方法完整備份data目錄。拉新鏡像docker pull 新版本標簽先不急著停止舊容器。停舊起新停掉舊容器用完全相同的數(shù)據(jù)卷掛載和端口映射啟動新容器。觀察日志啟動后立刻docker logs -f wgcloud-server重點看有沒有數(shù)據(jù)庫結(jié)構(gòu)升級相關(guān)的日志輸出。WGCLOUD在檢測到舊版本數(shù)據(jù)時通常會自動做兼容性調(diào)整這一步可能需要一點時間期間不要隨意重啟容器。Web界面驗證登錄后確認歷史監(jiān)控數(shù)據(jù)還在、告警規(guī)則還在、主機列表沒有丟失。這里一定要提醒不要跳過備份直接升級。數(shù)據(jù)庫升級是不可逆操作一旦升級腳本執(zhí)行到一半失敗或者不兼容你手里又沒有備份那全部歷史監(jiān)控數(shù)據(jù)會直接葬送。我見過有人在測試環(huán)境升級翻車然后因為沒備份只能重頭再采一遍數(shù)據(jù)前幾個月的趨勢圖全沒了。5.3 容器起不來的三種典型故障從日志里找真相故障一容器啟動后立刻退出先看docker logs輸出常見的提示包括端口被占用、數(shù)據(jù)目錄權(quán)限不對、內(nèi)存不足被OOM殺掉。端口被占用分兩種情況宿主機上另一個進程占了9999或者有其他容器映射了同一端口。用docker ps -a檢查有沒有同名或同端口容器就行。數(shù)據(jù)目錄權(quán)限不對也發(fā)生過宿主機的data目錄如果屬主和容器內(nèi)進程不一致容器可能啟動報錯或?qū)懭胧?。最簡單的處理是把data目錄屬主改成普通用戶或者根據(jù)官方鏡像里聲明的用戶UID設(shè)置一致如果是root的鏡像改屬主為當前用戶基本就能解決。內(nèi)存不足方面我遇到過宿主機內(nèi)存本來就緊巴巴的容器啟動時分配不到足夠內(nèi)存直接被殺。建議優(yōu)先查看docker logs里有沒有OOM相關(guān)的關(guān)鍵字然后適當降低--memory限制或者給宿主機騰點內(nèi)存出來。故障二容器活著Web頁面卻打不開大概率是防火墻或安全組問題前面已經(jīng)給過排查順序。少數(shù)情況是容器內(nèi)啟動時間太長server還在初始化數(shù)據(jù)庫稍微等一會兒再刷頁面。不要一打不開就直接重啟容器重啟只會讓初始化過程從頭再來。故障三容器活著部分監(jiān)控圖表卻沒有數(shù)據(jù)這類問題最常見的原因是agent與server版本不一致或者agent的采集項在較新版本里調(diào)整了字段名。另一個常見原因是宿主機時間與agent時間偏差過大。優(yōu)先從這兩條線排查基本能覆蓋掉我遇到的大多數(shù)“有主機無數(shù)據(jù)”問題。最后再從我個人使用習慣的角度多嘴一句。容器化部署WGCLOUD server最爽的地方在于我可以隨時把監(jiān)控棧從一個宿主機平移到另一個宿主機中間不用關(guān)心JDK、環(huán)境變量這些瑣碎事。但容器化也意味著你必須對數(shù)據(jù)卷和版本管理更上心——容器的生命是短暫的數(shù)據(jù)才是長久的。每次操作前備份、確認版本、看日志這三件事做足了WGCLOUD server跑起來真的是個省心的監(jiān)控大管家。