
1. 為什么GPFS排故日志收集值得單獨拎出來講做過HPC存儲運維的人都有一個共識GPFS現(xiàn)稱IBM Storage Scale但圈內(nèi)人還是習(xí)慣叫GPFS出問題的時候最怕的不是故障本身而是故障現(xiàn)場被破壞、日志收集不全、事后復(fù)盤時發(fā)現(xiàn)關(guān)鍵信息缺失。我見過太多次這樣的情況——集群突然出現(xiàn)IO hang管理員第一反應(yīng)是重啟節(jié)點結(jié)果重啟完一切恢復(fù)正常但根因永遠找不到了。下一次故障再來還是抓瞎。GPFS作為一套分布式并行文件系統(tǒng)它的日志來源非常分散有內(nèi)核態(tài)的、有用戶態(tài)的、有管理節(jié)點的、有計算節(jié)點的、有IB/RoCE網(wǎng)絡(luò)層的、有存儲后端RAID控制器的。不同層面的日志格式、存放路徑、收集方式都不一樣。如果沒有一套標準化的收集流程排故時就會陷入知道要看什么但找不到在哪的窘境。這篇內(nèi)容要解決的核心問題就一個當GPFS集群出現(xiàn)各類異常時如何系統(tǒng)化、標準化、無遺漏地收集排故所需的全部日志。適合誰來參考一線存儲運維工程師、HPC集群管理員、以及需要對接廠商支持但不想被反復(fù)要求再抓一次日志的同行。我會把常見的故障場景分類針對每類場景給出具體的日志收集清單、命令、路徑和注意事項讓你在故障現(xiàn)場能像執(zhí)行checklist一樣操作不慌不亂。2. GPFS日志體系的全景拆解2.1 日志的三大來源層次GPFS的日志不是集中在一個目錄里的它橫跨了三個層次每個層次的日志解決不同維度的問題。第一層是GPFS自身的日志。這包括/var/adm/ras/目錄下的mmfs.log系列、/var/mmfs/下的各種狀態(tài)文件、以及通過mmfsadm dump系列命令動態(tài)抓取的運行時信息。這一層直接反映GPFS文件系統(tǒng)本身的行為——inode分配、鎖管理、token管理、磁盤租約、配額等。第二層是操作系統(tǒng)層面的日志。GPFS深度依賴內(nèi)核模塊mmfs、mmfslinux、tracedev等所以dmesg、/var/log/messages或/var/log/syslog、journalctl的輸出至關(guān)重要。很多GPFS的panic、hung task、OOM都和內(nèi)核態(tài)有關(guān)。第三層是硬件與網(wǎng)絡(luò)層的日志。包括IB交換機的性能計數(shù)器、網(wǎng)卡的統(tǒng)計信息、RAID控制器的事件日志、SAN交換機的zone配置和錯誤計數(shù)。這一層往往被忽略但實際排故中有相當比例的GPFS故障最終定位到網(wǎng)絡(luò)丟包或存儲鏈路抖動。注意三層日志的收集順序有講究。建議先抓第一層和第二層的瞬時狀態(tài)因為可能被覆蓋或丟失再從容收集第三層的硬件日志。2.2 關(guān)鍵日志文件與目錄速查下面這張表是我自己整理并反復(fù)使用的速查表建議收藏日志/目錄路徑內(nèi)容說明適用場景/var/adm/ras/mmfs.log.latest當前GPFS主日志所有GPFS異常/var/adm/ras/mmfs.log.previous上一次輪轉(zhuǎn)的日志故障后節(jié)點被重啟/var/adm/ras/mmsysmonitor.log系統(tǒng)監(jiān)控日志節(jié)點狀態(tài)異常/var/adm/ras/mmfsadm.log管理命令執(zhí)行記錄追溯誰做了什么操作/var/mmfs/gen/mmsdrfs集群配置描述文件配置比對/var/mmfs/gen/mmfsdb集群數(shù)據(jù)庫快照集群元數(shù)據(jù)恢復(fù)/tmp/mmfs/臨時dump文件動態(tài)抓取的診斷數(shù)據(jù)/var/log/messages系統(tǒng)綜合日志內(nèi)核態(tài)異常dmesg輸出內(nèi)核環(huán)形緩沖區(qū)OOM、hung task、驅(qū)動報錯2.3 日志輪轉(zhuǎn)機制與收集時機GPFS的mmfs.log.latest默認在達到一定大小后會輪轉(zhuǎn)為mmfs.log.previous舊的previous會被覆蓋。這意味著如果你不及時收集關(guān)鍵證據(jù)可能在幾小時內(nèi)就消失了。我踩過最慘的一次坑是一個客戶集群在凌晨3點出現(xiàn)IO超時管理員早上9點才通知我等我連上去的時候mmfs.log.latest已經(jīng)被后續(xù)的正常日志沖刷得面目全非previous里也只有部分殘留。所以我的原則是故障確認后的第一件事不是分析而是保全現(xiàn)場。具體做法是立即把所有相關(guān)節(jié)點的/var/adm/ras/目錄整體打包復(fù)制到一個安全位置再慢慢分析。3. 按故障場景分類的日志收集實操3.1 場景一集群無法掛載或文件系統(tǒng)mount失敗這是最常見的入門級故障但排查起來涉及的面并不少。當mmmount或mount命令失敗時你需要按以下順序收集第一步確認集群狀態(tài)。在所有節(jié)點上執(zhí)行mmgetstate -a把輸出完整保存。如果節(jié)點狀態(tài)是down或arbitrating說明集群層面就有問題。第二步抓取核心日志。在管理節(jié)點和問題節(jié)點上分別執(zhí)行# 打包GPFS核心日志 tar czf /tmp/gpfs_logs_$(hostname)_$(date %Y%m%d%H%M).tar.gz \ /var/adm/ras/mmfs.log.latest \ /var/adm/ras/mmfs.log.previous \ /var/adm/ras/mmsysmonitor.log \ /var/adm/ras/mmfsadm.log # 抓取集群配置 mmfsadm dump config /tmp/mmfs_dump_config_$(hostname).txt mmlscluster /tmp/mmlscluster_$(hostname).txt mmlsconfig /tmp/mmlsconfig_$(hostname).txt第三步檢查內(nèi)核日志。執(zhí)行dmesg | grep -i mmfs重點看有沒有mmfs:開頭的錯誤信息。常見的如mmfs: Failed to load module、mmfs: cannot allocate memory等。第四步檢查文件系統(tǒng)描述文件。/var/mmfs/gen/mmsdrfs是集群的憲法如果這個文件損壞或版本不一致mount必然失敗。收集時務(wù)必保留。實操心得mount失敗時很多人會反復(fù)嘗試mount命令這是大忌。每次失敗的mount嘗試都會在日志中產(chǎn)生新的記錄可能覆蓋掉第一次失敗時的關(guān)鍵信息。正確做法是失敗一次后立即停止收集完日志再分析。3.2 場景二IO性能驟降或hang住這類問題最棘手因為集群可能看起來正?!?jié)點狀態(tài)up文件系統(tǒng)mount著但應(yīng)用就是讀寫不動。這時候日志收集要覆蓋性能和阻塞兩個維度。GPFS層面的收集# 抓取當前所有GPFS線程棧 mmfsadm dump threads /tmp/mmfs_threads_$(hostname)_$(date %s).txt # 抓取等待隊列信息 mmfsadm dump waiters /tmp/mmfs_waiters_$(hostname)_$(date %s).txt # 抓取鎖和token狀態(tài) mmfsadm dump locks /tmp/mmfs_locks_$(hostname)_$(date %s).txt mmfsadm dump tokens /tmp/mmfs_tokens_$(hostname)_$(date %s).txt這幾個dump命令抓取的是瞬時快照建議間隔30秒連續(xù)抓3次這樣可以看出等待隊列是在增長還是在消化。操作系統(tǒng)層面的收集# 進程狀態(tài) ps -eLf /tmp/ps_elf_$(hostname).txt # IO統(tǒng)計 iostat -x 1 5 /tmp/iostat_$(hostname).txt cat /proc/diskstats /tmp/diskstats_$(hostname).txt # 網(wǎng)絡(luò)統(tǒng)計 netstat -s /tmp/netstat_s_$(hostname).txt ip -s link /tmp/ip_link_$(hostname).txt網(wǎng)絡(luò)層的收集如果用了IB或RoCE# IB性能計數(shù)器 perfquery /tmp/perfquery_$(hostname).txt ibstat /tmp/ibstat_$(hostname).txt # RoCE統(tǒng)計 ethtool -S roce_interface /tmp/ethtool_roce_$(hostname).txt注意mmfsadm dump threads的輸出可能非常大幾千行但這是定位IO hang最關(guān)鍵的證據(jù)。它能告訴你GPFS的內(nèi)核線程卡在哪個函數(shù)上——是在等鎖、等磁盤、還是等網(wǎng)絡(luò)。3.3 場景三節(jié)點意外宕機或panic節(jié)點宕機后如果配置了kdump第一優(yōu)先級是拿到vmcore。如果沒有kdump那就只能靠日志回溯。宕機前的日志保全# 從其他正常節(jié)點收集宕機節(jié)點的最后狀態(tài) mmgetstate -a /tmp/mmgetstate_all.txt mmdiag --node 宕機節(jié)點名 /tmp/mmdiag_node.txt # 檢查是否有core dump ls -la /var/crash/ 2/dev/null ls -la /var/adm/ras/ | grep -i coreGPFS的crash日志GPFS自身也有crash log機制通常在/var/adm/ras/下會有mmfs.core.*或mmfs.crash.*文件。這些文件需要用mmfsadm工具解析mmfsadm dump core /var/adm/ras/mmfs.core.xxxxx /tmp/mmfs_core_analysis.txt系統(tǒng)層面的回溯# 最后一次啟動的日志 journalctl -b -1 /tmp/journalctl_prev_boot.txt # 如果有kdump ls -la /var/crash/*/vmcore實操心得節(jié)點panic后如果集群配置了自動重啟節(jié)點可能在幾分鐘內(nèi)就重新加入了集群。這時候mmfs.log.latest會被新的啟動日志覆蓋。所以必須在節(jié)點重啟完成前從其他節(jié)點遠程抓取該節(jié)點的日志或者確保日志是集中收集的。3.4 場景四磁盤或存儲子系統(tǒng)報錯GPFS底層依賴NSDNetwork Shared DiskNSD又依賴本地磁盤或SAN LUN。當磁盤出現(xiàn)壞道、RAID降級、或SAN鏈路抖動時GPFS層面會報disk error或NSD server unavailable。GPFS層面的收集# NSD狀態(tài) mmlsnsd -X /tmp/mmlsnsd_X.txt mmfsadm dump nsd /tmp/mmfs_nsd_dump.txt # 磁盤錯誤統(tǒng)計 mmdiag --disk /tmp/mmdiag_disk.txt存儲層面的收集# 本地磁盤SMART信息 smartctl -a /dev/sdX /tmp/smartctl_sdX.txt # RAID控制器日志以常見的MegaRAID為例 storcli /c0 show events /tmp/storcli_events.txt storcli /c0 /eall /sall show /tmp/storcli_drives.txt # SAN HBA統(tǒng)計 systool -c fc_host -v /tmp/fc_host_stats.txt多路徑狀態(tài)multipath -ll /tmp/multipath_ll.txt注意存儲層的日志收集往往需要額外的工具storcli、sas3ircu、smartctl等建議在集群部署階段就把這些工具裝好別等故障了才發(fā)現(xiàn)沒有。4. 日志收集的自動化與標準化4.1 為什么需要自動化手動收集的問題很明顯故障時人手忙腳亂、容易遺漏、不同人收集的內(nèi)容不一致、廠商支持要反復(fù)催。我經(jīng)歷過最夸張的一次一個IO性能問題來回折騰了兩周就是因為每次收集的日志都不完整廠商支持每次看完都說還缺XXX。后來我寫了一個腳本把常見故障場景的日志收集全部自動化。效果立竿見影——第一次提交就給全了廠商支持的響應(yīng)速度直接快了一倍。4.2 腳本設(shè)計的核心思路腳本的設(shè)計原則是分層收集、場景可選、輸出規(guī)范。具體來說分層GPFS層、OS層、網(wǎng)絡(luò)層、存儲層分開收集每層一個子目錄場景可選通過參數(shù)指定故障類型mount/io/panic/disk腳本自動決定收集哪些內(nèi)容輸出規(guī)范統(tǒng)一打包成gpfs_diag_hostname_timestamp.tar.gz方便傳輸和歸檔下面是一個簡化版的核心框架#!/bin/bash # gpfs_log_collector.sh # 用法: ./gpfs_log_collector.sh 場景 輸出目錄 # 場景: mount | io | panic | disk | all SCENARIO${1:-all} OUTDIR${2:-/tmp/gpfs_diag_$(hostname)_$(date %Y%m%d%H%M%S)} HOSTNAME$(hostname) mkdir -p ${OUTDIR}/{gpfs,os,network,storage} collect_gpfs() { echo [*] Collecting GPFS logs... cp /var/adm/ras/mmfs.log.latest ${OUTDIR}/gpfs/ 2/dev/null cp /var/adm/ras/mmfs.log.previous ${OUTDIR}/gpfs/ 2/dev/null cp /var/adm/ras/mmsysmonitor.log ${OUTDIR}/gpfs/ 2/dev/null cp /var/adm/ras/mmfsadm.log ${OUTDIR}/gpfs/ 2/dev/null mmfsadm dump config ${OUTDIR}/gpfs/dump_config.txt 21 mmgetstate -a ${OUTDIR}/gpfs/mmgetstate.txt 21 mmlscluster ${OUTDIR}/gpfs/mmlscluster.txt 21 mmlsconfig ${OUTDIR}/gpfs/mmlsconfig.txt 21 mmlsnsd -X ${OUTDIR}/gpfs/mmlsnsd.txt 21 } collect_os() { echo [*] Collecting OS logs... dmesg ${OUTDIR}/os/dmesg.txt 21 cp /var/log/messages ${OUTDIR}/os/ 2/dev/null journalctl -b ${OUTDIR}/os/journalctl_current.txt 21 ps -eLf ${OUTDIR}/os/ps_elf.txt 21 cat /proc/meminfo ${OUTDIR}/os/meminfo.txt 21 cat /proc/loadavg ${OUTDIR}/os/loadavg.txt 21 } collect_network() { echo [*] Collecting network logs... ip -s link ${OUTDIR}/network/ip_link.txt 21 netstat -s ${OUTDIR}/network/netstat_s.txt 21 if command -v ibstat /dev/null; then ibstat ${OUTDIR}/network/ibstat.txt 21 perfquery ${OUTDIR}/network/perfquery.txt 21 fi } collect_storage() { echo [*] Collecting storage logs... cat /proc/diskstats ${OUTDIR}/storage/diskstats.txt 21 multipath -ll ${OUTDIR}/storage/multipath.txt 21 if command -v smartctl /dev/null; then for disk in /dev/sd[a-z]; do smartctl -a ${disk} ${OUTDIR}/storage/smartctl_$(basename ${disk}).txt 21 done fi } # 按場景執(zhí)行 case ${SCENARIO} in mount) collect_gpfs; collect_os ;; io) collect_gpfs; collect_os; collect_network ;; panic) collect_gpfs; collect_os ;; disk) collect_gpfs; collect_storage ;; all) collect_gpfs; collect_os; collect_network; collect_storage ;; *) echo Unknown scenario: ${SCENARIO}; exit 1 ;; esac # 打包 cd /tmp tar czf ${OUTDIR}.tar.gz $(basename ${OUTDIR}) echo [] Done. Output: ${OUTDIR}.tar.gz4.3 腳本使用的注意事項這個腳本看起來簡單但有幾個坑我踩過第一權(quán)限問題。很多GPFS的dump命令需要root權(quán)限腳本必須以root運行。但有些集群禁止root直接登錄這時候需要用sudo并且確保sudoers配置允許執(zhí)行這些命令。第二命令不存在的情況。不是所有節(jié)點都裝了smartctl、storcli、perfquery這些工具。腳本里用command -v做了檢查但實際使用中建議在集群部署階段就統(tǒng)一安裝。第三輸出目錄的空間。dmesg和journalctl的輸出可能很大如果/tmp空間不足會失敗。建議輸出到有足夠空間的分區(qū)或者加一個空間檢查。第四時間戳的精度。多個節(jié)點同時收集時時間戳精度到秒就夠了。但如果要做跨節(jié)點的時間線關(guān)聯(lián)分析建議用date %s.%N精確到納秒。實操心得腳本寫好后別等到故障了才第一次運行。建議在測試環(huán)境模擬各種故障場景驗證腳本能正常收集。我見過太多故障時腳本跑不起來的情況原因五花八門——路徑不對、權(quán)限不夠、命令缺失。5. 常見問題與排查技巧實錄5.1 日志收集過程中的典型問題問題一mmfsadm dump命令hang住不返回這種情況通常說明GPFS內(nèi)核模塊本身已經(jīng)處于異常狀態(tài)。解決辦法是加超時timeout 30 mmfsadm dump threads /tmp/threads.txt 21如果30秒還沒返回說明dump機制本身被阻塞了這時候只能靠dmesg和/proc下的信息。問題二日志文件太大傳輸困難mmfs.log.latest在繁忙集群上可能達到幾百MB甚至GB級別。傳輸前建議先壓縮并且只保留故障時間窗口附近的內(nèi)容# 提取最近2小時的日志 awk -v start$(date -d 2 hours ago %Y-%m-%d %H:%M) $0 start mmfs.log.latest mmfs_recent.log問題三多節(jié)點日志時間不同步這是分布式系統(tǒng)排故的經(jīng)典問題。如果各節(jié)點NTP沒同步日志時間戳對不上根本無法做因果分析。收集日志的同時務(wù)必收集各節(jié)點的時間狀態(tài)timedatectl /tmp/timedatectl_$(hostname).txt ntpq -p /tmp/ntpq_$(hostname).txt問題四廠商支持要求再抓一次這通常是因為第一次收集的日志不完整或格式不對。為了避免反復(fù)建議在提交前自己先檢查一遍GPFS日志有沒有、dmesg有沒有、時間窗口對不對、有沒有壓縮包密碼保護。我一般會附一個README說明收集了什么、故障現(xiàn)象是什么、時間點是什么。5.2 日志分析的核心思路收集只是第一步分析才是重頭戲。我的分析順序通常是先看時間線從mmfs.log.latest中找到第一個ERROR或FATAL出現(xiàn)的時間點再看關(guān)聯(lián)在那個時間點前后dmesg里有沒有對應(yīng)的內(nèi)核報錯然后看狀態(tài)mmfsadm dump的輸出里線程棧、等待隊列、鎖狀態(tài)是否異常最后看硬件如果前面都正常再查網(wǎng)絡(luò)和存儲層的計數(shù)器這個順序的邏輯是從軟件到硬件、從高層到低層。因為大部分問題在GPFS層面就能定位不需要一上來就查硬件。5.3 常見錯誤信息速查表錯誤信息可能原因進一步排查方向mmfs: Disk error on NSD xxx磁盤故障或鏈路抖動查smartctl、multipath、SAN日志mmfs: Token conflict detected集群分裂或網(wǎng)絡(luò)分區(qū)查網(wǎng)絡(luò)連通性、mmfs.log中的token記錄mmfs: Inode allocation failedinode耗盡或元數(shù)據(jù)損壞查mmlsinode、文件系統(tǒng)使用率mmfs: Quota exceeded配額超限查mmlsquota、用戶配額設(shè)置mmfs: Failed to mount配置不一致或日志損壞查mmsdrfs、mmfs.log.latesthung taskin dmesg內(nèi)核線程阻塞查mmfsadm dump threadsOOM killerin dmesg內(nèi)存不足查GPFS pagepool配置、系統(tǒng)內(nèi)存注意這張表只是快速索引實際排故中錯誤信息往往更復(fù)雜需要結(jié)合上下文。比如Token conflict可能是網(wǎng)絡(luò)問題也可能是節(jié)點時鐘不同步導(dǎo)致的。6. 日志收集的長期策略與經(jīng)驗沉淀6.1 建立集中式日志歸檔單次故障的日志收集是戰(zhàn)術(shù)建立長期的日志歸檔機制才是戰(zhàn)略。我的建議是在集群里部署一個集中式的日志收集服務(wù)所有節(jié)點的GPFS日志、系統(tǒng)日志實時或定時推送到一個中心存儲。這樣即使節(jié)點宕機、日志被覆蓋中心存儲里還有備份。實現(xiàn)方式可以很簡單用rsyslog或syslog-ng把/var/log/messages轉(zhuǎn)發(fā)到中心用cron定時打包/var/adm/ras/目錄。復(fù)雜一點可以用ELK或類似方案做結(jié)構(gòu)化存儲和檢索。6.2 定期做日志健康檢查就像定期體檢一樣日志系統(tǒng)也需要定期檢查。我一般每個月做一次檢查各節(jié)點的/var/adm/ras/目錄空間是否充足檢查日志輪轉(zhuǎn)是否正常檢查集中收集服務(wù)是否在運行抽查幾個節(jié)點的日志時間戳是否同步這些檢查花不了多少時間但能在關(guān)鍵時刻救命。6.3 把排故經(jīng)驗固化成文檔每次排故結(jié)束后我都會花半小時寫一個簡短的復(fù)盤記錄故障現(xiàn)象、收集了哪些日志、最終根因是什么、下次遇到類似問題應(yīng)該先看什么。這些記錄積累起來就是團隊最寶貴的知識庫。我個人的體會是GPFS排故這件事工具和腳本只占30%經(jīng)驗和思路占70%。同樣一份日志新手可能看不出問題老手一眼就能定位。而這個眼力就是靠一次次實戰(zhàn)和復(fù)盤練出來的。所以別嫌麻煩每次故障都認真收集、認真分析、認真記錄半年下來你就會發(fā)現(xiàn)自己排故的速度和準確率有質(zhì)的飛躍。最后分享一個小技巧在集群的每個節(jié)點上放一份排故日志收集checklist的打印版貼在機柜上。故障時不用想照著清單一項項做就行。這個習(xí)慣幫我避免了很多次事后才發(fā)現(xiàn)漏了關(guān)鍵日志的尷尬。