實體主機資料碟掛載:確認路徑後才啟動服務
資料碟掛載失敗後,應用程式不一定會立即報錯。原本作為掛載點的 /srv/data 仍是系統碟上的一般目錄,服務可能繼續寫入,直到耗盡系統碟空間。掛載修復後,這批檔案又會被掛載上來的檔案系統遮住,留下兩份難以辨別的資料。上線驗收應確認路徑實際所在的檔案系統,而不只是檢查目錄是否存在。
一、先確認資料碟身分與操作範圍
本文以 Ubuntu Server 24.04 LTS,以及已建立 ext4 檔案系統的資料分割區為例,不進行分割或格式化。命令透過 SSH 在主機上執行;CloudSFP 的連線憑證可於付款後在控制台查看,若有多個位址,請使用第一個位址。
標準配備的兩顆 1TB NVMe 各自直接連接,沒有硬體 RAID。裝置編號不代表系統碟或資料碟的身分,也不能用來推斷備援關係。若已有軟體 RAID 或其他儲存層,應掛載上層的檔案系統,不可繞過該層直接掛載成員磁碟。
lsblk -o NAME,PATH,SIZE,TYPE,FSTYPE,UUID,MOUNTPOINTS
sudo blkid
findmnt -T /
findmnt -T /srv
綜合容量、檔案系統類型、現有掛載點與安裝紀錄,辨識目標分割區並記錄其 UUID。UUID 比裝置列舉名稱穩定,但不保證一定唯一:複製檔案系統時,也可能一併複製 UUID。發現重複時,應先解決識別衝突,不要直接寫入啟動設定。
以下變更應在資料碟投入業務使用前完成。已承載業務的主機必須先停止寫入,確認備份與還原方式;不得為了測試,直接卸載正在使用的檔案系統。
二、先試掛載,再登錄 fstab
建立空的掛載點,檢查其中是否已有檔案,也要檢查隱藏檔案。若目錄不是空的,先查明檔案來源,不要刪除或覆寫。
sudo mkdir -p /srv/data
sudo find /srv/data -mindepth 1 -maxdepth 1 -print
read -r -p 'Filesystem UUID: ' DATA_UUID
sudo blkid -U "$DATA_UUID"
sudo mount -t ext4 -o ro "UUID=$DATA_UUID" /srv/data
findmnt -M /srv/data -o TARGET,SOURCE,FSTYPE,OPTIONS,UUID
只有 blkid 的輸出與磁碟身分紀錄相符,才繼續執行掛載。首次以唯讀方式掛載是為了檢查內容,不是修復損壞檔案系統的方法。此處的 findmnt -M 檢查指定的確切掛載點;findmnt -T 則查找承載該路徑的檔案系統,資料碟未掛載時可能傳回根檔案系統,不能只因命令成功結束,就判定掛載正常。
確認來源與內容後,卸載唯讀掛載。先備份 /etc/fstab,再編輯檔案;不要重複加入同一個掛載點。範例中的 UUID 必須替換成剛才核對過的實際值:
UUID=<已核对的文件系统UUID> /srv/data ext4 defaults,nofail,x-systemd.device-timeout=15s 0 2
這行設定允許系統在磁碟缺失時繼續啟動。裝置等待上限是本例選用的 15 秒,不是交付或復原時間的承諾。若業務要求磁碟缺失時就阻止系統啟動,應另行設計啟動策略,不要直接照用 nofail。
sudo umount /srv/data
sudo cp -a /etc/fstab /etc/fstab.before-data-mount
sudoedit /etc/fstab
sudo findmnt --verify --verbose
sudo systemctl daemon-reload
sudo mount /srv/data
findmnt -M /srv/data -o TARGET,SOURCE,FSTYPE,OPTIONS,UUID
驗證失敗時,先修正設定,不要繼續掛載。只掛載目標路徑,避免一次掛載所有檔案系統而掩蓋其他設定問題。通過語法檢查也不代表裝置一定可用,仍須驗收實際掛載結果。
三、讓服務啟動相依於掛載
nofail 處理的是系統啟動行為,不負責應用程式安全。使用資料目錄的服務必須宣告掛載相依性。下列 app.service 代表實際存在的業務單元,應替換成真實名稱,並確認該單元確實會啟動寫入程序。
執行 sudo systemctl edit app.service,加入:
[Unit]
RequiresMountsFor=/srv/data
AssertPathIsMountPoint=/srv/data
RequiresMountsFor 會啟動存取此路徑所需的掛載,並建立啟動順序;斷言則用來拒絕「目錄存在,但不是掛載點」的狀態。兩者都無法識別錯誤的磁碟,也不能取代應用程式的資料一致性檢查,因此核對 UUID 與來源仍是獨立步驟。
sudo systemctl daemon-reload
sudo systemctl cat app.service
sudo systemctl show app.service -p Requires -p After
檢查覆寫設定是否生效,並確認應用程式實際使用的資料目錄位於 /srv/data 之下。若啟動指令碼另外將路徑導向其他位置,即使相依性正確,仍可能寫錯地方。排程工作、手動指令碼與其他服務不會自動繼承這些限制,必須分別檢查。
掛載成功後,再建立業務子目錄,並依實際服務帳號設定擁有者與權限。不要讓所有帳號都能寫入整個資料碟,也不要將憑證寫進掛載設定。
四、正式寫入前演練磁碟缺失與復原
演練應在尚無業務資料、也沒有進行中寫入的階段執行。先停止應用程式,再停止資料碟的掛載單元。/srv/data 對應的單元名稱可用 systemd-escape --path --suffix=mount /srv/data 核對,不要憑複雜路徑手動猜測。
sudo systemctl stop app.service
sudo systemctl stop srv-data.mount
sudo systemctl mask --runtime srv-data.mount
sudo systemctl start app.service
sudo systemctl status app.service srv-data.mount --no-pager
暫時遮罩掛載單元,是為了模擬掛載無法使用,避免啟動應用程式時自動重新掛載。預期結果是啟動失敗,且業務程序沒有執行。若卸載時提示忙碌,應查明是哪個程序占用;不要用強制卸載或延遲卸載繞過檢查。
此時檢查掛載點底下的 /srv/data 目錄是否出現新檔案。測試結束後,先解除遮罩,再恢復掛載:
sudo systemctl unmask --runtime srv-data.mount
sudo systemctl start srv-data.mount
findmnt -M /srv/data -o TARGET,SOURCE,FSTYPE,OPTIONS,UUID
sudo systemctl reset-failed app.service
sudo systemctl start app.service
只有來源相符,且應用程式通過健康檢查,才算復原完成。驗收結束時,必須確認暫時遮罩已解除。啟動相依性主要保護啟動階段,不是偵測執行期間磁碟故障的機制;後續仍需要應用程式的錯誤處理與監控。
五、留下可複核的上線紀錄
紀錄應包含磁碟身分、UUID、掛載點、檔案系統類型、fstab 變更、服務覆寫設定,以及磁碟缺失演練的結果。重新啟動驗收應安排在投入業務使用前,確認掛載先完成,服務才啟動;不能用當下單次手動掛載成功,取代啟動驗證。
若掛載後發現系統碟空間異常,先核對是否有被掛載遮住的舊檔案。應停止相關寫入,再安排檢查,不能在運作中卸載後直接刪除,更不能盲目合併掛載點底下的目錄與資料碟上的目錄。
最終通過條件是:來源正確、路徑確實已掛載、服務相依性生效、磁碟缺失時沒有誤寫,以及復原後通過健康檢查。掛載設定不提供備援,也不提供備份;這兩項仍須分別設計與驗收。
常見問題
資料碟掛載為何不直接使用裝置名稱?
裝置列舉順序可能改變,應使用已核對且唯一的檔案系統 UUID。複製檔案系統可能造成 UUID 重複,因此仍須以 lsblk、blkid 與 findmnt 比對來源。
fstab 設定 nofail 就能避免誤寫系統碟嗎?
不能。nofail 只讓系統在掛載失敗時繼續啟動。應用服務還須設定 RequiresMountsFor 與 AssertPathIsMountPoint,並核對掛載來源,避免資料碟缺失時寫入底層目錄。