踐指南)
在實(shí)際運(yùn)維里Debian系統(tǒng)上做“raid5lvm”組合幾乎是中小型Linux服務(wù)器最常碰到的存儲方案之一。我剛接手某公司那臺文件服務(wù)器時(shí)前一位運(yùn)維留下的就是這套東西4塊數(shù)據(jù)盤做了RAID 5然后在上面疊加了一層LVM整個(gè)存儲池被切成了好幾個(gè)邏輯卷分別掛給項(xiàng)目目錄。RAID 5解決的是“多塊盤里壞一塊數(shù)據(jù)不丟”的問題LVM解決的是“容量不夠想在線擴(kuò)”的問題兩個(gè)軟件包mdadm和lvm2就能把幾塊普通硬盤變成一塊既冗余又靈活的存儲空間。這篇內(nèi)容適合自己折騰家用NAS的也適合剛接手生產(chǎn)服務(wù)器的運(yùn)維新人我會從設(shè)計(jì)思路講到具體命令再到故障處理盡量把每一步為什么這么做講清楚。1. 為什么偏偏是RAID 5LVM1.1 RAID級別的取舍我見過不少人一上來就問“RAID 5到底選幾塊盤”但事實(shí)上最重要的不是幾塊盤而是先想清楚你的場景到底吃哪一套冗余策略。RAID 0速度快但沒有冗余壞一塊盤全部數(shù)據(jù)清零適合純緩存類場景。RAID 1把數(shù)據(jù)完整復(fù)制兩份安全但有效容量直接打五折適合系統(tǒng)盤或者一兩塊盤的場景。RAID 10是鏡像加條帶性能和冗余平衡得很好但是最少4塊盤有效容量也只有一半。RAID 5則是把數(shù)據(jù)和校驗(yàn)信息分散寫在所有盤上允許壞一塊盤而不丟數(shù)據(jù)3塊盤就能用有效容量是n-1塊盤的容量。RAID級別最少盤數(shù)有效容量冗余能力典型場景RAID 02100%無緩存、臨時(shí)數(shù)據(jù)RAID 1250%1塊盤系統(tǒng)盤、小容量數(shù)據(jù)RAID 53(n-1)/n1塊盤文件服務(wù)、備份數(shù)據(jù)RAID 10450%每組1塊盤數(shù)據(jù)庫、高IO應(yīng)用我直接把RAID 5的容量公式放出來n塊盤做RAID 5有效容量 (n-1)/n × 總?cè)萘克?塊4T盤實(shí)際可用8T。這個(gè)公式在mdadm創(chuàng)建時(shí)也是這么計(jì)算的底層會把其中一塊盤的容量空間用作分布式校驗(yàn)。很多人第一次看到RAID 5的校驗(yàn)機(jī)制會疑惑“為什么壞一塊還能繼續(xù)讀寫”其實(shí)就是因?yàn)樾r?yàn)塊分散在每一塊盤上任何一塊盤的數(shù)據(jù)都能通過其它n-1塊盤恢復(fù)出來。RAID 5的寫性能要額外算校驗(yàn)所以隨機(jī)小塊寫入比RAID 10慢這是它天生的特點(diǎn)但順序讀寫和大多數(shù)文件服務(wù)器場景完全夠用。1.2 LVM為什么值得疊直接說RAID陣列本身有一個(gè)問題一旦創(chuàng)建容量基本是固定的。雖然mdadm支持在線擴(kuò)容但總歸要先加盤、再調(diào)整陣列操作粒度比較粗。而LVM是另一層抽象它把底層RAID陣列看成一個(gè)物理卷PV再把空間切割成一個(gè)個(gè)PE多個(gè)PE組成卷組VG最后從VG里劃分邏輯卷LV。關(guān)鍵就是LV可以在VG還有空閑的情況下隨時(shí)在線擴(kuò)大甚至縮小雖然縮小一般不建議在生產(chǎn)上隨便做。比如我做過的某單機(jī)項(xiàng)目中文件服務(wù)器起初LVM卷組里RAID 5陣列只有8T可用后來數(shù)據(jù)量漲到接近滿就加了盤把RAID擴(kuò)成更大的陣列VG的空間隨之變大然后lvextend把LV撐大文件系統(tǒng)在線resize幾乎沒停服務(wù)。這就是RAID 5LVM組合最值錢的點(diǎn)也是為什么它在Debian系服務(wù)器上這么流行。2. Debian部署前的基礎(chǔ)準(zhǔn)備2.1 硬件與軟件要求要在Debian下創(chuàng)建RAID 5LVM最少需要3塊獨(dú)立的硬盤注意是獨(dú)立硬盤而不是三塊邏輯分區(qū)。數(shù)據(jù)盤和系統(tǒng)盤最好分開不要把系統(tǒng)所在盤也加進(jìn)RAID否則系統(tǒng)盤掛了整個(gè)系統(tǒng)都起不來RAID冗余形同虛設(shè)。如果是家用NAS或者小型服務(wù)器建議4塊盤起步多出來的一塊用來做熱備盤spare平時(shí)不參與寫入一旦某塊盤故障會自動頂替上去開始重建這個(gè)后面細(xì)講。系統(tǒng)層面需要安裝兩個(gè)軟件包mdadm負(fù)責(zé)管理軟件RAID陣列l(wèi)vm2負(fù)責(zé)LVM層的邏輯卷管理。Debian下安裝很簡單一條命令就能裝好。裝完建議順手確認(rèn)一下兩個(gè)命令能正常執(zhí)行。apt update apt install -y mdadm lvm2 mdadm --version lvm version2.2 磁盤識別與盤符漂移做RAID之前最關(guān)鍵的準(zhǔn)備工作不是敲命令而是認(rèn)清楚哪塊盤是哪個(gè)物理設(shè)備。這個(gè)環(huán)節(jié)出錯(cuò)的代價(jià)極高把系統(tǒng)盤和數(shù)據(jù)盤搞混了做進(jìn)陣列系統(tǒng)分分鐘起不來。用lsblk看塊設(shè)備布局用fdisk -l看磁盤大小還可以用smartctl看序列號。更穩(wěn)妥的做法是用ls -l /dev/disk/by-id/查看所有磁盤的WWID或者廠商序列號不同廠商盤的命名格式不同但都能追溯到物理設(shè)備。生產(chǎn)環(huán)境里我習(xí)慣把每塊盤的盤位標(biāo)簽和/dev/disk/by-id/的鏈接對應(yīng)起來寫在一個(gè)小本子上避免開機(jī)盤符變化時(shí)憑感覺猜。經(jīng)驗(yàn)更豐富一點(diǎn)的話也要注意Debian的udev規(guī)則重啟后/dev/sdX這種盤符順序可能因?yàn)閮?nèi)核識別順序變化而徹底打亂。以前SATA盤少的時(shí)候還好現(xiàn)在NVMe和SATA混裝加上USB外接存儲盤符漂移幾乎是必然的。所以真正寫進(jìn)mdadm和fstab的時(shí)候絕對不要依賴/dev/sdX而是用UUID后面的配置會專門處理這個(gè)。還有一個(gè)細(xì)節(jié)數(shù)據(jù)盤建議直接用整塊盤設(shè)備不需要先分區(qū)。mdadm可以直接在整塊盤上創(chuàng)建陣列很多老教程會讓人先分區(qū)再mdadm多一層分區(qū)表反而增加復(fù)雜度而且分區(qū)表出錯(cuò)也會影響陣列識別。普通場景推薦整塊盤走到底。3. 創(chuàng)建RAID 5陣列3.1 mdadm的創(chuàng)建命令和參數(shù)確認(rèn)磁盤無誤后就可以創(chuàng)建RAID 5陣列。典型命令是這樣的假設(shè)我有四塊數(shù)據(jù)盤/dev/sdb、/dev/sdc、/dev/sdd、/dev/sde我準(zhǔn)備用前三塊做RAID 5第四塊做熱備盤。mdadm --create /dev/md0 --levelraid5 --raid-devices3 --spare-devices1 /dev/sdb /dev/sdc /dev/sdd /dev/sde命令說明--create是創(chuàng)建/dev/md0是陣列的設(shè)備名--levelraid5指定RAID級別--raid-devices3表示陣列由3塊組成--spare-devices1表示后面4個(gè)設(shè)備里第4個(gè)作為熱備盤。創(chuàng)建的時(shí)候還有一個(gè)重要參數(shù)叫做chunk size條帶大小它決定數(shù)據(jù)條帶化寫入時(shí)每個(gè)條帶塊的大小。mdadm默認(rèn)是512K但這個(gè)默認(rèn)值并不適合所有場景。如果存儲的是大量小文件比如代碼、配置目錄、數(shù)據(jù)庫日志建議把chunk size調(diào)小到64K或者128K小文件能更快地落盤。反過來如果主要存視頻、鏡像、備份數(shù)據(jù)這類大文件可以保持512K甚至用1M順序讀寫的吞吐更爽。在創(chuàng)建命令里加上chunk size參數(shù)mdadm --create /dev/md0 --levelraid5 --raid-devices3 --spare-devices1 --chunk128 /dev/sdb /dev/sdc /dev/sdd /dev/sde這里的128就是128K的意思。注意chunk參數(shù)不帶單位默認(rèn)就是K不需要寫成128K。3.2 等待同步和狀態(tài)檢查創(chuàng)建完RAID 5陣列后系統(tǒng)會立即開始后臺同步rebuild目的就是讓整個(gè)陣列進(jìn)入一致的冗余狀態(tài)。這個(gè)階段陣列還沒完全可用讀寫性能也會明顯下降不能急著格式化或者寫入數(shù)據(jù)。查看進(jìn)度用cat /proc/mdstat輸出里會看到類似這樣的內(nèi)容Personalities : [raid6] [raid5] md0 : active raid5 sde[4](S) sdd[3] sdc[1] sdb[0] 109572224 blocks super 1.2 level 5, 128k chunk, algorithm 2 [3/3] [UUU] [....................] resync 2.5% (2745856/109572224) finish18.7min speed19473K/sec它包含的關(guān)鍵信息有好幾處陣列狀態(tài)是active raid5三塊工作盤為[3/3] [UUU]熱備盤是sde 4 同步百分比resync以及預(yù)計(jì)完成時(shí)間finish和實(shí)時(shí)速度speed。同步速度默認(rèn)會限制避免把整機(jī)IO打滿等同步完成前不要做其它重IO操作。同步完成后可以再用詳細(xì)命令確認(rèn)mdadm --detail /dev/md0這條命令會列出陣列的成員盤狀態(tài)、chunk大小、同步進(jìn)度、壞塊數(shù)等完整信息。我習(xí)慣把它作為每次巡檢的第一條命令。3.3 陣列參數(shù)與完整性再補(bǔ)充一個(gè)容易踩坑的細(xì)節(jié)。創(chuàng)建時(shí)默認(rèn)的metadata版本是1.2這個(gè)沒問題但如果你在很老的Debian版本或者某些特殊引導(dǎo)環(huán)境下可能需要考慮metadata版本兼容性。99%的現(xiàn)代系統(tǒng)直接用1.2即可不用刻意改。寫操作時(shí)也可以考慮給陣列加bitmap也就是位圖文件mdadm --grow /dev/md0 --bitmapinternal內(nèi)部位圖的好處是系統(tǒng)異常斷電重啟后不需要對整個(gè)陣列做全量同步只需要對位圖標(biāo)記的“臟”區(qū)域做增量重建。這在生產(chǎn)環(huán)境里能省掉大把重建時(shí)間。我個(gè)人的建議是創(chuàng)建完成后順手加上。陣列層面的狀態(tài)顯示clean只表示元數(shù)據(jù)一致真正的數(shù)據(jù)一致性需要靠文件系統(tǒng)層面的檢查來兜底。Debian下可以定期對已掛載的ext4文件系統(tǒng)做只讀檢查e2fsck -fn /dev/vg_data/lv_projects-f是強(qiáng)制檢查-n表示只讀模式不會對文件系統(tǒng)做任何修改適合在線檢測。真正需要修復(fù)的時(shí)候才去掉-n但那時(shí)候最好先卸載或者維護(hù)窗口再操作。4. LVM疊加與容量管理4.1 PV、VG、LV三層邏輯LVM把存儲空間分成三層物理卷PV對應(yīng)整個(gè)底層塊設(shè)備這里是/dev/md0卷組VG是多個(gè)PV拼起來的大容量池邏輯卷LV是最終格式化和掛載使用的“虛擬分區(qū)”。創(chuàng)建PV很簡單pvcreate /dev/md0創(chuàng)建完可以用pvs或者pvdisplay看狀態(tài)。在這里我要特別提醒PV一旦直接建在/dev/md0上以后整個(gè)陣列就被LVM接管如果臨時(shí)想把陣列直接當(dāng)成普通塊設(shè)備就會多一步剝離操作但這不復(fù)雜后面如果想反悔可以用pvremove把PV信息清掉只要底層數(shù)據(jù)沒有格式化破壞就可以。然后創(chuàng)建VG并指定PE大小vgcreate vg_data /dev/md0PE物理擴(kuò)展塊是VG的分配單位默認(rèn)是4MiB。這個(gè)默認(rèn)值不需要動除非你有特別大量的小邏輯卷需求一般保持默認(rèn)即可。創(chuàng)建后再用vgs、vgdisplay確認(rèn)卷組容量vgdisplay能看到VG的可用空間。接下來創(chuàng)建LVlvcreate -L 4T -n lv_projects vg_data這里的-L 4T表示直接分配4T空間給這個(gè)邏輯卷。如果你想用VG的全部剩余空間可以寫成-l 100%FREE。我一般會留出10%左右的VG空間不分配作為未來的快照空間或者應(yīng)急擴(kuò)容儲備因?yàn)橐坏㎜V把VG占滿再想創(chuàng)建快照就沒有空間了。4.2 格式化與掛載LV建好后可以像普通分區(qū)一樣格式化。常見的文件系統(tǒng)是ext4如果新部署且數(shù)據(jù)不是特別敏感用xfs其實(shí)也推進(jìn)得很廣泛但Debian默認(rèn)工具鏈里ext4最順手下面的例子就用ext4。mkfs.ext4 /dev/vg_data/lv_projects格式化前再檢查一下確認(rèn)這個(gè)設(shè)備名字沒有拼錯(cuò)。格式化是不可逆的操作路徑寫錯(cuò)了真的會出事。掛載測試mkdir -p /data/projects mount /dev/vg_data/lv_projects /data/projects df -h能正??吹饺萘亢蛼燧d點(diǎn)說明這個(gè)LV工作正常。df -h會顯示容量約等于創(chuàng)建時(shí)指定的4T減去文件系統(tǒng)自身開銷。4.3 在線擴(kuò)展與快照擴(kuò)展容量是LVM相對傳統(tǒng)分區(qū)最爽的地方。假設(shè)存儲空間滿了我先給RAID陣列加盤把新盤加入陣列如果當(dāng)初留了熱備盤直接拔掉故障盤和加入新盤的重建流程都比較順暢。陣列擴(kuò)容完成后原來創(chuàng)建的PV大小會自動跟隨變化但VG不會自動把新增空間納入可用還要執(zhí)行pvresize /dev/md0 vgspvresize的作用就是刷新PV大小讓VG知道陣列容量變了。然后就可以擴(kuò)展LV和文件系統(tǒng)lvextend -L 2T /dev/vg_data/lv_projects resize2fs /dev/vg_data/lv_projects注意resize2fs只對ext4有效如果你當(dāng)初選擇xfs就改xfs_growfs這倆命令的參數(shù)形式完全不同。很多新手?jǐn)U容時(shí)文件系統(tǒng)忘了同步擴(kuò)展邏輯卷已經(jīng)變大但df看到的容量沒變就是這一步漏了。再額外講一下LVM快照??煺赵趥浞輬鼍袄锓浅S杏帽热缫谶\(yùn)行中的存儲上打一個(gè)一致的備份點(diǎn)就可以對LV做快照lvcreate -L 200G -s -n snap_projects /dev/vg_data/lv_projects快照創(chuàng)建時(shí)幾乎是瞬間完成的原理是寫時(shí)復(fù)制CoW原始數(shù)據(jù)塊發(fā)生變化前先把舊數(shù)據(jù)移到快照區(qū)所以快照只記錄增量變化不能用于長期備份只適合做短期一致性備份點(diǎn)。快照空間用完了快照會自動失效所以給快照分配的大小要比備份期間預(yù)計(jì)寫入的數(shù)據(jù)量稍大。5. 開機(jī)自動裝配與文件系統(tǒng)掛載5.1 生成mdadm配置并更新initramfs如果希望系統(tǒng)重啟后RAID陣列自動被識別必須保存陣列配置?,F(xiàn)在Debian里的mdadm配置通常寫在/etc/mdadm/mdadm.conf用如下命令把當(dāng)前陣列的信息追加進(jìn)去mdadm --detail --scan /etc/mdadm/mdadm.conf查看生成的內(nèi)容里面會有一行類似ARRAY /dev/md0 metadata1.2 namehostname:0 UUIDxxxx:xxxx:xxxx:xxxx這里的UUID是陣列的唯一標(biāo)識mdadm啟動時(shí)靠這個(gè)UUID而不是/dev/sdX去識別陣列所以盤符漂移不影響陣列裝配。配好之后還要更新initramfs因?yàn)閙dadm的配置要打進(jìn)初始內(nèi)存盤里系統(tǒng)引導(dǎo)階段才能識別update-initramfs -u這一步不能漏否則重啟時(shí)系統(tǒng)可能因?yàn)闊o法識別RAID而進(jìn)入initramfs提示符或者直接找不到根文件系統(tǒng)。5.2 fstab自動掛載文件系統(tǒng)掛載同樣不能依賴盤符要用UUID。先用blkid查到LV的UUIDblkid /dev/vg_data/lv_projects輸出會包含UUID然后編輯/etc/fstab加一行類似UUIDxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx /data/projects ext4 defaults,noatime 0 2這里的noatime是個(gè)很實(shí)用的掛載參數(shù)它可以關(guān)閉atime更新減少不必要的磁盤寫入。對SSD和機(jī)械盤都有好處。至于最后的兩個(gè)數(shù)字0表示不進(jìn)行dump備份2表示開機(jī)時(shí)按順序執(zhí)行fsck檢查。根分區(qū)一般是1其它數(shù)據(jù)分區(qū)可以用2。配置好fstab后建議先手動卸載再掛載驗(yàn)證一次umount /data/projects mount -a df -hmount -a會把fstab里所有未掛載條目都掛一遍如果這一條配置有錯(cuò)會立刻報(bào)出來不會拖到重啟才發(fā)現(xiàn)。這一步是驗(yàn)證fstab正確性的最佳實(shí)踐比直接重啟要安全得多。6. 故障場景與排查經(jīng)驗(yàn)6.1 RAID降級與壞盤處理做運(yùn)維的人最怕半夜收到監(jiān)控告警說RAID降級。RAID 5允許壞一塊盤但只要壞盤沒處理陣列就處于降級狀態(tài)性能會受影響而且萬一第二塊盤再出問題就是全盤皆輸。當(dāng)發(fā)現(xiàn)陣列降級第一步是確認(rèn)是哪塊盤出了問題mdadm --detail /dev/md0輸出里壞盤會標(biāo)記為removed或者faulty同時(shí)狀態(tài)變成[2/3] [UU_]。在確認(rèn)物理盤已替換或故障盤被標(biāo)記移除后把故障盤從陣列中移除mdadm /dev/md0 --fail /dev/sdd mdadm /dev/md0 --remove /dev/sdd然后插入新盤mdadm /dev/md0 --add /dev/sdf如果新盤被識別為陣列的缺口成員mdadm會自動開始重建數(shù)據(jù)。如果沒有熱備盤整個(gè)過程需要手動操作如果當(dāng)時(shí)留了熱備盤故障盤失效后熱備盤就會自動接管狀態(tài)直接進(jìn)入rebuild。所以我在2.1里的建議是4塊盤起步多出來那塊做熱備對白天忙碌或者半夜沒有運(yùn)維盯的場景特別有用。重建期間的/proc/mdstat會顯示resync或者recovery進(jìn)度速度一般受限于整機(jī)IO和盤本身能力。重建期間盡量避免在陣列上做高負(fù)載讀寫降低二次故障的風(fēng)險(xiǎn)。6.2 擴(kuò)容后文件系統(tǒng)不一致與檢查我在前面提過lvextend之后忘了resize2fs是常見坑。這個(gè)問題還有一個(gè)變種擴(kuò)容RAID陣列以后LV大小已經(jīng)變大了但文件系統(tǒng)是后來才想起來resize這時(shí)候不要慌直接重新跑一遍resize2fs /dev/vg_data/lv_projects就行resize2fs是冪等的已經(jīng)擴(kuò)展到目標(biāo)大小就不會重復(fù)動作。還有另一種情況是fstab掛載失敗系統(tǒng)啟動時(shí)直接進(jìn)入到緊急模式emergency mode。這種問題多數(shù)是因?yàn)閁UID變了或者mdadm.conf沒有正確更新導(dǎo)致陣列沒有裝配。排查順序先看blkid確認(rèn)設(shè)備UUID再看/etc/fstab里的UUID是否匹配再看mdadm.conf里的陣列UUID是否在最后看initramfs是否包含新配置。一般三步能定位90%的問題。定期做數(shù)據(jù)完整性檢查也是值得納入巡檢計(jì)劃的。對于一個(gè)已經(jīng)穩(wěn)定運(yùn)行的RAID 5陣列每季度做一次只讀的e2fsck檢查配合smartctl看各塊盤的SMART健康信息可以提前發(fā)現(xiàn)隱患避免被動的故障處理。6.3 性能與寫入策略不想把優(yōu)化寫成玄學(xué)只說幾個(gè)我實(shí)測下來最影響RAID 5體驗(yàn)的點(diǎn)。首先是RAID 5的隨機(jī)寫性能天然劣勢。因?yàn)槊繉懸淮螖?shù)據(jù)都要同步更新校驗(yàn)在小塊隨機(jī)寫入場景比如數(shù)據(jù)庫會很吃虧。如果應(yīng)用對隨機(jī)寫要求高應(yīng)該選RAID 10不要指望RAID 5通過參數(shù)調(diào)整變成快。RAID 5適合順序讀寫多、并發(fā)不算極端的場景。其次是write-back cache的設(shè)置。mdadm在較新內(nèi)核支持write-behind模式但通常要配電池保護(hù)卡或者UPS才能安全啟用否則突然斷電會造成數(shù)據(jù)不一致。沒有電池保護(hù)卡的普通服務(wù)器我建議保守一點(diǎn)不要強(qiáng)制加write-behind默認(rèn)的write-through策略雖然慢一點(diǎn)但穩(wěn)。最后是陣列同步速度限制??梢杂孟旅婷钫{(diào)整echo 50000 /proc/sys/dev/raid/speed_limit_min echo 200000 /proc/sys/dev/raid/speed_limit_max單位是KB/s這個(gè)調(diào)整只在當(dāng)前運(yùn)行期間有效重啟會恢復(fù)默認(rèn)。在預(yù)先規(guī)劃好的維護(hù)窗口里調(diào)高一點(diǎn)能加速重建但不建議在業(yè)務(wù)高峰調(diào)高反而拖垮整機(jī)IO。想長期修改可以寫在/etc/sysctl.d/里但我個(gè)人傾向只臨時(shí)調(diào)整重建設(shè)完就恢復(fù)默認(rèn)。我自己折騰過不少存儲組合RAID 5LVM在Debian上的這套流程算是性價(jià)比很高的“標(biāo)準(zhǔn)答案”。每次做這類操作我的個(gè)人習(xí)慣是先看圖再動手lsblk確認(rèn)一遍盤mdadm --detail確認(rèn)一遍陣列blkid確認(rèn)一遍文件系統(tǒng)三個(gè)命令各花幾秒鐘換取的是深夜不接報(bào)警電話的安穩(wěn)。還有一句必須有的話——RAID從來不是備份陣列的冗余只防硬件故障防不了誤刪和邏輯錯(cuò)誤真正重要的數(shù)據(jù)該做備份還是老實(shí)做多一層快照也只是增援部隊(duì)不是保險(xiǎn)箱。