第9章 LVM応用とストレージデバイス調整
LPIC-2 204.2〜204.3 相当
中級の第3章ではLVMの基本概念(PV/VG/LV)を扱いました。ここでは、運用中によく使う応用操作と、ネットワーク越しにブロックストレージを利用するiSCSIを学びます。いずれも、単一サーバーの枠を超えたストレージ設計を行う上で欠かせない知識です。
LVスナップショット
LVMのスナップショットは、ある時点の状態を保持したまま、元のLVを使い続けられる機能です。バックアップ取得中の一貫性確保などに使われます。内部的にはCoW(Copy-on-Write)という仕組みで実現されており、スナップショット作成時点ではデータの実体はコピーされず、元のLVとスナップショットで同じブロックを共有します。その後、元のLV側でデータが変更されるたびに、変更前の元データだけがスナップショット用の差分領域に退避されるため、スナップショット作成直後の負荷は小さく済みます。
$ sudo lvcreate --size 1G --snapshot --name lv_snap /dev/vg01/lv_data
Logical volume "lv_snap" created.
# lv_data のスナップショット lv_snap を1GBの差分領域で作成
$ sudo lvremove /dev/vg01/lv_snap # 不要になったら削除
Do you really want to remove active logical volume vg01/lv_snap? [y/n]: y
Logical volume "lv_snap" successfully removed.
この行のこの値に注目: lvremoveは誤削除防止のため既定で確認プロンプトを出します。スクリプトから実行する場合は-y(--yes)を付けて確認をスキップできますが、対話的に実行する際は対象のLV名を必ず確認してからyを入力します。
yと答えてしまうと、そのLVの中のデータは失われます。日頃からLVのバックアップ(lvcreate -sによるスナップショットや、外部ストレージへの定期バックアップ)を取っておくことが、万が一の誤操作からの唯一の実効的なリカバリ手段です。lvremove自体には取り消し操作はありません。
lvsコマンドでSnap%列を定期的に確認し、枯渇しそうな場合は早めに削除するか、差分領域を拡張(lvextendをスナップショットLVに対して実行)する必要があります。
スナップショットを使ってLVを以前の状態に戻したい場合は、lvconvert --mergeでスナップショットを元のLVにマージ(ロールバック)できます。ただし、マージ操作はLVがアクティブでない(アンマウントされている)状態、あるいは次回の再起動時に行われるため、稼働中のシステムボリュームに対するロールバックには計画的なメンテナンス時間が必要です。
LVの容量拡張
LVMの大きな利点は、運用を止めずに容量を拡張できることです。ただし、LVを拡張しただけではファイルシステムのサイズは変わらないため、ファイルシステム側のリサイズも必要です。
$ sudo lvextend --size +5G /dev/vg01/lv_data # LVを5GB拡張
Size of logical volume vg01/lv_data changed from 20.00 GiB (5120 extents) to 25.00 GiB (6400 extents).
Logical volume vg01/lv_data successfully resized.
$ sudo resize2fs /dev/vg01/lv_data # ext4の場合
resize2fs 1.47.0 (5-Feb-2023)
Filesystem at /dev/vg01/lv_data is mounted on /mnt/data; on-line resizing required
The filesystem on /dev/vg01/lv_data is now 6553600 (4k) blocks long.
$ sudo xfs_growfs /mnt/data # xfsの場合(マウントポイントを指定)
data blocks changed from 5242880 to 6553600
この行のこの値に注目: lvextendのchanged from ... to ...行でLV自体の容量拡張が完了したことが分かりますが、この時点ではファイルシステムのサイズはまだ変わっていません。resize2fs/xfs_growfsを実行して初めて、OSから見える実際の空き容量が増えます。
2つのコマンドを毎回別々に実行するのは手間なので、lvextendには-r(--resizefs)オプションがあり、これを付けるとLVの拡張と、対応するファイルシステムのリサイズを1コマンドでまとめて実行できます。
$ sudo lvextend -r --size +5G /dev/vg01/lv_data
Size of logical volume vg01/lv_data changed from 25.00 GiB (6400 extents) to 30.00 GiB (7680 extents).
Logical volume vg01/lv_data successfully resized.
resize2fs 1.47.0 (5-Feb-2023)
The filesystem on /dev/vg01/lv_data is now 7864320 (4k) blocks long.
# LVの拡張とファイルシステムのリサイズを同時に実行(内部で適切なresize2fs/xfs_growfsを自動判定)
シンプロビジョニング(thin provisioning)
通常のLVでは、作成時に指定した容量がその場でVGから確保されますが、LVMには、実際の使用量に応じて必要な分だけ物理領域を割り当てる「シンプロビジョニング(thin provisioning)」の機能もあります。複数のLVで共有する「シンプール(thin pool)」を作成し、そこから見かけ上の容量が物理容量を超えるLVを切り出せます。
$ sudo lvcreate --type thin-pool --size 50G --name pool01 vg01
Logical volume "pool01" created.
$ sudo lvcreate --thin --virtualsize 200G --name lv_thin vg01/pool01
Logical volume "lv_thin" created.
# 物理プールは50GBしかないが、見かけ上200GBのLVを作成できる
この行のこの値に注目: どちらのコマンドも成功時はLogical volume "..." created.とだけ表示され、見た目上は通常のLV作成と変わりません。実際に物理容量以上の仮想サイズになっているかは、後述のlvs -o+data_percentなどで確認します。
同じ内容をsudo lvcreate -L 100G --thinpool thinpool vg_data(シンプール作成)、sudo lvcreate -V 500G --thin -n lv_thin vg_data/thinpool(仮想サイズを指定した実LV作成)のように書くこともでき、複数の仮想マシンのディスクイメージのように「最大容量は大きく確保しておきたいが、実際にはそこまで使われないことが多い」用途で特に容量効率を高められます。
便利な反面、シンプール自体の空き容量を監視していないと、複数のLVが実データで物理容量を使い切ってしまい(オーバーコミット)、書き込み不可に陥る危険があります。lvs -o+data_percent,metadata_percent などで使用率を定期的に確認する運用が欠かせません。
PVの追加とVGの拡張
運用を続けているとVG(ボリュームグループ)自体の空き容量が不足してくることがあります。その場合は新しい物理ディスクをPV(物理ボリューム)として初期化し、既存のVGに追加することで、システムを止めずに容量を拡張できます。LVMの各階層(PV・VG・LV)は独立して拡張できるため、「まず物理ディスクを追加してVGを広げ、次にLVを広げ、最後にファイルシステムを広げる」という順序を理解しておくと、容量不足への対応がスムーズになります。
$ sudo pvcreate /dev/sdf1 # 新しいディスクをPVとして初期化
Physical volume "/dev/sdf1" successfully created.
$ sudo vgextend vg01 /dev/sdf1 # VGに新しいPVを追加して拡張
Volume group "vg01" successfully extended
$ sudo vgs vg01 # VGの空き容量を確認
VG #PV #LV #SN Attr VSize VFree
vg01 2 3 1 wz--n- 250.00g 50.00g
この行のこの値に注目: vgsの#PVが2に増えていれば新しいディスクが正しくVGに組み込まれたことが分かります。VFree列が拡張直後に増えた分だけ、今後LVをさらに切り出せる余地があります。
逆にディスクをVGから外したい場合は、対象のPVにデータが残っていないことをpvmoveで他のPVへ退避してからvgreduceで切り離します。
pvmove・vgreduceはいずれも稼働中のシステムのストレージ構成そのものに手を加える操作です。移動先のPVに十分な空き容量があるか、退避が完全に終わってからvgreduceを実行しているかを必ず確認してください。事前にバックアップを取り、作業手順を検証環境で確認してから本番へ適用するのが安全です。
iSCSIの基礎
iSCSIは、SCSIコマンドをTCP/IPネットワーク越しにやり取りするプロトコルです。専用のストレージ機器を、あたかもローカルのディスクのように扱えるのが特徴です。
| 用語 | 役割 |
|---|---|
| ターゲット(Target) | ストレージを提供する側(サーバー) |
| イニシエータ(Initiator) | ストレージを利用する側(クライアント) |
| IQN | iSCSIの世界での機器の識別名 |
| LUN(Logical Unit Number) | 1つのターゲットが公開する論理ディスク単位の番号。1つのターゲットが複数のLUNを持つこともある |
$ sudo iscsiadm -m discovery -t sendtargets -p 192.168.1.100 # ターゲットを検出
192.168.1.100:3260,1 iqn.2024-01.com.example:storage01
$ sudo iscsiadm -m node --login # 検出したターゲットにログイン(接続)
Logging in to [iface: default, target: iqn.2024-01.com.example:storage01, portal: 192.168.1.100,3260]
Login to [iface: default, target: iqn.2024-01.com.example:storage01, portal: 192.168.1.100,3260] successful.
この行のこの値に注目: discoveryの結果に表示されるIQN(iqn.2024-01.com.example:storage01)を、その後のログイン操作で対象として使います。ログイン成功時のsuccessfulという表示を確認したら、lsblkやdmesgで新しく認識された/dev/sdXデバイスを確認します。
ログインに成功すると、通常のSCSIディスクと同様に /dev/sdX として認識されるため、その上にLVMやファイルシステムを重ねて通常のディスクと同じ手順で利用できます。認証が必要な環境ではCHAP(Challenge Handshake Authentication Protocol)を /etc/iscsi/iscsid.conf に設定し、無認可のイニシエータからの接続を防ぎます。
$ sudo iscsiadm -m node -T iqn.2024-01.com.example:storage01 -p 192.168.1.100 --logout
Logging out of session [sid: 1, target: iqn.2024-01.com.example:storage01, portal: 192.168.1.100,3260]
Logout of [sid: 1, target: iqn.2024-01.com.example:storage01, portal: 192.168.1.100,3260] successful.
# 特定のターゲットからログアウト(切断)
$ sudo iscsiadm -m node # これまでにdiscoveryで検出済みのノード(ターゲット)を一覧表示
192.168.1.100:3260,1 iqn.2024-01.com.example:storage01
この行のこの値に注目: -m node(引数なし)は、過去にdiscoveryしたことのあるノードの一覧であり、現在ログイン中かどうかは示しません。現在の接続状態を見たい場合はiscsiadm -m sessionを使います。
一度ログインしたターゲットは、既定ではnode.startup = automaticの設定により、次回のシステム起動時に自動的に再接続されます。手動接続のみにしたい場合は/etc/iscsi/iscsid.confや個々のノード設定でこの値をmanualに変更します。
iqn.年-月.ドメイン名を逆順にしたもの:任意の識別子という形式が一般的です(例: iqn.2024-01.com.example:storage01)。組織のドメインと登録年月を含めることで、世界中で一意な名前になるよう設計されています。LPIC-2試験でもこの命名規則の理解が問われることがあります。
multipath(device-mapper-multipath)で経路を冗長化するのが一般的です。1本のネットワーク経路やコントローラの故障だけでストレージ接続が失われないようにします。
ストレージデバイスのチューニング
iSCSIのようなネットワーク越しのストレージだけでなく、ローカルに接続されたディスクそのものの設定を調整・確認するためのツール群もLPIC-2 204.2の出題範囲に含まれます。
| コマンド | 用途 |
|---|---|
hdparm | 主にSATA/IDE(ATAPI含む)ディスクの設定確認・変更 |
sdparm | SCSI/SASデバイス向けの、hdparmに相当するパラメータ確認・変更ツール |
nvme(nvme-cliパッケージ) | NVMe SSDの情報取得・管理 |
fstrim | SSDに対して、使われなくなったブロックをまとめて通知するTRIMコマンドを発行する |
hdparmの主なオプションを整理します。
| オプション | 意味 |
|---|---|
-I | デバイスの詳細情報(型番、対応機能、シリアル番号など)を表示する |
-t / -T | 実際のディスク読み取り速度を簡易測定する(-tはディスクから直接、-Tはバッファキャッシュ経由の速度) |
-W | ディスクの書き込みキャッシュの有効・無効を切り替える |
-B | APM(Advanced Power Management)レベルを設定する(1に近いほど省電力優先、254に近いほど性能優先) |
-S | 一定時間アクセスがない場合にディスクをスピンダウン(回転停止)させるまでの時間を設定する |
$ sudo hdparm -I /dev/sda # デバイスの詳細情報を表示
Model Number: Samsung SSD 870 EVO 1TB
Serial Number: S6PWNJ0R123456
Firmware Revision: SVT03B6Q
Transport: Serial, ATA8-AST, SATA 1.0a, SATA II, SATA III
Write cache
Advanced Power Management feature set
$ sudo hdparm -tT /dev/sda # バッファキャッシュ経由/直接の読み取り速度を簡易測定
Timing cached reads: 18200 MB in 2.00 seconds = 9102.34 MB/sec
Timing buffered disk reads: 1580 MB in 3.01 seconds = 524.92 MB/sec
$ sudo hdparm -W 1 /dev/sda # 書き込みキャッシュを有効化(性能重視、電源断時のリスクは増す)
setting drive write-caching to 1 (on)
$ sudo hdparm -B 254 /dev/sda # APMレベルを254(性能優先、省電力機能をほぼ無効化)に設定
setting Advanced Power Management level to 0xfe (254)
$ sudo hdparm -S 240 /dev/sda # 一定時間アイドルでスピンダウンさせる(値の単位は既定で約5秒刻み)
setting standby to 240 (20 minutes)
この行のこの値に注目: -tTのTiming cached readsはメモリキャッシュ経由のため実ディスク性能を反映せず、Timing buffered disk readsのほうが実際のディスクI/O性能に近い値です。-W/-B/-S系の設定変更コマンドは、すべてsetting ... to ...という形式で変更後の値をそのまま返します。
hdparmの設定は誤用するとデータを失う可能性があります。-Wで書き込みキャッシュを有効にした状態で電源断が起きると、キャッシュ上にあった未書き込みのデータが失われることがあります。また-Sで頻繁にアクセスされるディスクに短いスピンダウン時間を設定すると、スピンアップ・ダウンの繰り返しでディスクの寿命を縮めたり、スピンアップ待ちによる予期しないI/O遅延を招いたりします。本番環境で変更する前には、対象デバイスと影響範囲を必ず確認してください。
sdparmは、hdparmがSATA/IDE系デバイスを主な対象とするのに対し、SCSI/SASデバイス(エンタープライズ向けストレージでよく使われる)のパラメータ確認・変更に使います。同じ「デバイスのパラメータを見る・変える」という目的でも、下位のプロトコルが異なるためコマンドが分かれています。
$ sudo sdparm --get=WCE /dev/sdb # SCSIデバイスのライトキャッシュ(Write Cache Enable)設定を確認
/dev/sdb: DELL PERC H730P Adp 4.30
WCE 1 [cha: y]
この行のこの値に注目: WCEの値が1であれば書き込みキャッシュが有効です。[cha: y]は、このパラメータが変更可能(changeable)であることを示しており、yでなければ--setによる変更ができません。
NVMe SSDの情報取得にはnvme-cliパッケージのnvmeコマンドを使います。
$ sudo nvme list # 認識しているNVMeデバイスの一覧
Node SN Model Namespace Usage Format
---------------- -------------------- ------------------------- ---------- -------- ------
/dev/nvme0n1 S6PWNJ0R123456 Samsung SSD 980 PRO 1TB 1 1.00 TB 512 B
$ sudo nvme id-ctrl /dev/nvme0 # コントローラの詳細情報(ベンダー、モデル名、シリアル番号など)
vid : 0x144d
sn : S6PWNJ0R123456
mn : Samsung SSD 980 PRO 1TB
fr : 5B2QGXA7
$ sudo nvme smart-log /dev/nvme0
critical_warning : 0
temperature : 35 C
available_spare : 100%
available_spare_threshold : 10%
percentage_used : 12%
data_units_read : 123456789
data_units_written : 987654321
media_errors : 0
この行のこの値に注目: nvme listのNode列がデバイスパス、id-ctrlのsn/mnがシリアル番号・モデル名です。smart-logのpercentage_usedはSSDの推定寿命消費率で、100%に近づくほど交換を検討すべきタイミングであることを示します。
この行のこの値に注目:percentage_usedはNAND(フラッシュメモリ)の消耗度合いの推定値で、0%が新品同様、100%に近づくほどメーカー保証の書き込み耐性に近づいていることを示します(100%を超えても即座に故障するわけではありませんが、信頼性低下の目安になります)。available_spareは不良ブロックの置き換え用に予備として確保されている領域の残り割合で、available_spare_thresholdを下回るとcritical_warningが立ちます。media_errorsは実際に検出された訂正不能なメディアエラーの累積数で、0以外かつ増加傾向にある場合は交換を検討すべきサインです。
$ sudo fstrim -av # マウント中の全対応ファイルシステムに対してTRIMを実行し、結果を表示
/mnt: 12.3 GiB (13212345678 bytes) trimmed on /dev/sdb1
SSDは、HDDと異なり「上書き」ではなく「消去してから書き込む」という特性上、OS側が使わなくなったブロックを事前に伝えておく(TRIM)ことで、書き込み性能の劣化を防げます。TRIMには2つの実行方式があります。
| 方式 | 特徴 |
|---|---|
discardマウントオプション | ファイル削除のたびに、その都度リアルタイムでTRIMコマンドを発行する。書き込み・削除のたびにオーバーヘッドが発生し、特に古いSSDファームウェアでは同期的なdiscard処理が遅く、性能に悪影響を与えることがある |
fstrimの定期実行(fstrim.timer) | 未使用ブロックをまとめてバッチ的に通知する。通常運用への性能影響が小さく済むため、多くのディストリビューションではこちらが既定で有効になっている |
この性能特性の違いから、常時discardを有効にするよりも、fstrim.timerによる週次程度の定期実行が推奨されることが多くなっています。
近年主流のNVMeは、従来のSATA接続で使われてきたAHCI(Advanced Host Controller Interface)とはプロトコルレベルで大きく異なります。
| 項目 | AHCI(SATA) | NVMe |
|---|---|---|
| 設計対象 | 回転するHDDのシーク遅延を前提に設計 | フラッシュストレージ専用に一から設計 |
| コマンドキュー | 1キュー、キュー深度は最大32程度(NCQ) | 最大65,536キュー、各キュー深度最大65,536 |
| 並列性 | 限定的 | CPUコアごとに専用キューを割り当てられるなど、大幅に並列化可能 |
この設計の違いにより、NVMeはAHCI接続のSATA SSDよりもレイテンシが低く、IOPS(1秒あたりの入出力操作数)も桁違いに高くなります。
SANの基礎知識
SAN(Storage Area Network)を構成する代表的なプロトコルには、それぞれ異なる位置づけがあります。
| プロトコル | 位置づけ |
|---|---|
| FC(Fibre Channel) | 専用の光ファイバー配線とFCスイッチによる、伝統的で高性能・低レイテンシなSANプロトコル。専用のHBA(Host Bus Adapter)が必要でコストは高いが、実績が豊富 |
| FCoE(Fibre Channel over Ethernet) | FCのフレームをイーサネット上でカプセル化し、既存のFCストレージ資産をイーサネット環境に統合するためのプロトコル |
| AoE(ATA over Ethernet) | ATAコマンドをイーサネットフレームに直接載せる、非常にシンプルな軽量プロトコル。IP層を使わないためルーティング不可 |
| iSCSI | SCSIコマンドをTCP/IP上でカプセル化する。既存の汎用イーサネット機器で構築できるためコストが低く、IPネットワークなのでルーティングも可能 |
性能・レイテンシの面では専用ハードウェアを使うFCが最も安定していますが、コストと構築の手軽さでは、既存のイーサネットインフラを流用できるiSCSIが選ばれる場面が多くなっています。
SANやマルチパス環境で個々のストレージデバイスを一意に識別するための識別子として、WWNとWWIDがあります。
| 識別子 | 意味 |
|---|---|
| WWN(World Wide Name) | Fibre Channel/SASの規格で定義された64bitのグローバル一意識別子。ポート単位のWWPN、ノード単位のWWNNなどに細分化される |
| WWID(World Wide Identifier) | Linuxのudev・multipath-toolsが、WWNを含む様々な下位プロトコルの情報から導出して内部的に扱う、より汎用的な一意識別子 |
同じ物理ディスク(1つのLUN)が複数の経路(パス)を通じて別々の/dev/sdXとして見えている場合でも、WWIDが同じであれば同一のディスクであると判別できます。この複数経路を束ねて1つの論理デバイスとして扱い、経路の冗長化を行うのがmultipath(device-mapper-multipath)です。
$ sudo multipath -ll
mpatha (36001405abcdef1234567890abcdef12) dm-2 DELL,MD32xxi
size=500G features='1 queue_if_no_path' hwhandler='1 alua' wp=rw
|-+- policy='round-robin 0' prio=50 status=active
| `- 4:0:0:1 sdb 8:16 active ready running
`-+- policy='round-robin 0' prio=10 status=enabled
`- 5:0:0:1 sdc 8:32 active ready running
この行のこの値に注目:先頭行のmpathaがmultipathデバイス名、括弧内の長い16進文字列がWWID、その後がベンダー・製品名です。優先グループごとに実際の物理パス(sdb・sdc)とその状態が表示され、prio=50でstatus=activeの経路が現在優先的に使われ、prio=10でstatus=enabledの経路はスタンバイとして待機し、アクティブ経路の障害時に自動的に昇格します。
デバイスファイル名/dev/sdXは再起動のたびに変わりうるため、永続的な参照には/dev/disk/以下のシンボリックリンクを使います。
| ディレクトリ | 基準 | 向いている用途 |
|---|---|---|
/dev/disk/by-id/ | デバイス自体のシリアル番号・WWNなど、デバイスに紐づく永続的な識別子 | 接続ポートやケーブルを差し替えても同じ物理ディスクを恒久的に指し続けたい場合(fstabの記述など) |
/dev/disk/by-path/ | そのデバイスに到達するための物理的な接続経路(PCIバス番号、SCSIターゲットIDなど) | 「特定のスロット・ポートに挿さっているディスク」を指したい場合(ディスク自体が交換される前提の運用など) |
SCSIデバイスから一意な識別子を取得するコマンドがscsi_idで、udevルールの中でby-idのシンボリックリンク名を生成する元データとしてよく使われます。
$ sudo /lib/udev/scsi_id -g -u /dev/sda
36001405abcdef1234567890abcdef12
-gはホワイトリスト化された(サポート対象として確認済みの)デバイスのみを対象にする既定動作、-uは出力を一意な識別子のみの1行に整形するオプションです。