まだプログラマーですが何か?

プログラマーネタ中心。たまに作成したウェブサービス関連の話も https://twitter.com/dotnsf

タグ:lvm

最近、VM を扱う機会が多くなりました。何度も色んなパーティショニング要件で Linux をインストールしている中で、これまでちゃんと理解してなかった VG(Volume Group) と LV(Logical Volume) についても理解が深まりました。そのアウトプットの1つとして、ルートディレクトリの容量を無限に増やすことができるような形で Linux VM(VM でなくても OK)を作るための手順等を紹介しようと思い、まずはその前提知識となる VG / LV についてまとめてみます。


【「ルートディレクトリ容量を増やせるようにする」とは?】
Linux に慣れる前に使っていると、最初のうちはあまり深く考えずに VM 等で Linux 環境を用意して使い続けることになり、どこかのタイミングで特定のディレクトリにデータが集まりすぎてディスクが足りなくなってしまう、という経験はないでしょうか?

例えば MySQL データベースとして使っていると、(デフォルト設定だと)そのデータは /var/lib/mysql/ 以下に溜まっていきます。データを多く扱ううちにこのフォルダ以下に大量のファイルが溜まっていくことになります。 また(WordPress のような形も含めて)httpd サーバーとして多くのデータを扱っていると、/var/www/html/ 以下に多くのファイルが溜まっていくことになります。このようにあらかじめ容量に注意すべきディレクトリが分かっている場合は、そのディレクトリに大容量ディスクをマウントして使うとか、その上で LV 化(後述)しておいて後から容量追加できるようにしておく、といった準備が可能です。

問題はそのような大容量が必要なディレクトリ(上述の例だと /var/lib/mysql や /var/www/html )が事前にわからない場合です。最初はそもそも多くのデータを使うつもりもなく作った環境を、後から当初想定していなかった用途でも利用するようになって、あらかじめ容量を拡張できるような準備をせずに使い始めることもあると思っています。しかもこの場合だと利用開始時点では「どのディレクトリに多くのデータが集まるのかもわからない」ので、事前に準備できることがあるとすれば「/(ルートディレクトリ)の容量を後から動的に追加」できるようにしておく必要があります。

特定のサブディレクトリ以下ではなく、ルートディレクトリ自体が拡張可能になっていれば「後からディスクが足りなくなる」ことへの不安はかなり解消されると思っています。


【PV と VG と LV の関係】
以下、"PV", "VG", "LV" という用語を使います。まずはこれらの意味を簡単に紹介します:

PV(Physical Volume): 物理ボリューム
後述する「論理的なボリューム」に対比する意味での「物理的なボリューム」です。論理的なボリュームでは複数のディスクをまとめて1つのディスクであるかのように扱うのに対し、物理的なボリュームでは複数のディスクを(パーティショニングすることはあっても)1つにまとめて扱うのではなく、あくまで1つのディスクは1つとして取り扱う考え方です。厳密には1つの物理ディスクをパーティショニングして1つまたは複数の空間(=ボリューム)として扱います。「論理ボリューム」という考え方をしないのであれば「1つの物理ディスク内の1パーティション=1つの物理ボリューム」です。

VG(Volume Group): ボリュームグループ
PV とは逆に、複数のディスクであっても論理的に1つのディスクとしてみなす、という考え方です。この論理的なディスクをボリュームグループ (Volume Group) と呼びます。

複数の物理的なディスクをまとめて1つの VG を定義します。VG には後からディスクを動的に追加することもでき、そのサイズは追加したぶんだけ増えます。

LV(Logical Volume): 論理ボリューム
Linux のファイルシステムはマウントと呼ばれる仕組みで複数のディスクを1つの空間にマッピングすることができます。この考え方は物理ディスクだけでなく、論理ディスクにも適用できます。

物理ディスク同様に、複数のディスクからなる論理的な1台のディスクをパーティショニングしてマウントすることになります。この論理的なパーティションが論理ボリューム(LV) となり、LV を管理する方法を LVM (Logical Volume Manager) と呼びます。


【2つの物理ディスクを使った場合の比較】
2つの物理ディスク(/dev/sda 容量は 100GB と /dev/sdb 容量は 200GB)を使って Linux マシンを構築するケースを想定し、PV で作る場合と LV で作る場合を比較します。

PV で(というか、LV を使わずに)ルートディスクを作る場合、/dev/sda に1つのパーティション /dev/sda1 を作ってルート(/)にマウントすると仮定すると、100GB のディスク容量を持つファイルシステムが作れます:
2025090501


一方、LV(論理ボリューム)では物理的なサイズやとは関係なく、論理的に定義した空間の容量として考えます。例えば /dev/sda1 を1つの VG とみなし、この VG 全体を1つの LV とみなしてパーティションを作り、このパーティションをルート(/)にマウントすることで 100GB の容量を持つファイルシステムとなります:
2025090502


ここまでだと結局どちらも 100GB の空間を持つファイルシステムが作られることになり、同じことのように見えてしまって、PV と LV の違いが分かりにくいと思います。違いを分かりやすくするためにもう1つ、別に「容量 200GB のディスク /dev/sdb」が手元にあると仮定します。

PV で考えると、この 200GB のディスク /dev/sdb は先ほどの 100GB のディスク /dev/sda とは完全に別のディスクという扱いになります。「容量が 100GB のディスクA」と「容量が 200GB のディスクB」という2つのディスクです。Linux の機能を使って、ディスクAをルートディスク(/)として、ディスクBを /home にマウントすることはできますし、その場合「両方合わせて 300GB」にはなります。しかしディスクAに余裕があったとしてもディスクBに余裕がなければ /home にデータを追加できなくなってしまいます:
2025090503


一方 LV で考えるとこの辺りを柔軟に考えることができるようになります。もともとディスクAをまるごと使って VG を作成していましたが、更にディスクBも同じ VG に追加することができます。この場合、この VG のサイズ(つまり LV のサイズ)は 300GB になります。ディスクBに(物理的な)余裕がなかったとしても、ディスクAに余裕があれば LV にデータを追加可能です。仮にディスクA、B両方の余裕がなくなってしまった場合も、更に別の物理ディスクCを VG に追加することで、動的に VG/LV を拡張することが可能です:
2025090504


1点注意が必要なのは、この論理的な LV の空間が linux のどのディレクトリにマウントされているかです。例えばルートディスクは別に存在していて、 この LV が /mnt にマウントされていた場合、/mnt 以下には最大 300GB のデータを格納することができますが、それ以外のディレクトリ(/usr など)はルートディスクの空きを意識する必要がある、という点です。

なお、1つの VG を1つの LV にする必要はありません。物理ディスクをパーティショニングする時のように、1つの VG から複数の LV に分けて使うことも可能です。



Linux では複数ディスクを論理的に扱う VG/LV という概念があることを説明しました。次回はこの考え方を使って、ルートディレクトリを LV で作り、後からルートディレクトリを拡張する具体的な手順を紹介予定です。




Linux を使っているとディスクのパーティショニングに頭を悩ませることがあります。最近の Linux ディストリビューションは賢くできていて、特に何も指定しなくてもデフォルト設定のまま導入をしていく中で全容量などから自動的に最適(と思われる)パーティショニングを特定して、分割した上で導入してくれます。

その自動判断されたパーティションの割り振り方が本当に最適な内容であれば理想なのですが、現実はそうでないことが多いです。ディスク全体ではまだ余裕があるのに、特定のパーティションだけが残り少なくなってしまうケースは珍しいとは思えません。かといって全部をルートパーティションにするというのも万が一の際に全てを失ってしまうことになって・・・ というトレードオフです。

ところで、CentOS は普通に導入すると、そのディスクパーティショニングには標準で LVM(Logical Volume Manager : 論理ボリューム管理) が適用されます。深く考えずにデフォルト設定のまま Enter キー連打で導入すると LVM のパーティションが出来上がるので、導入後に「あ、LVM だった」と気付く人もいると思います(少なくともここに一人・・ σ(^^;)。

この LVM は柔軟な割り当てができるようになっていて、専用ツールなどを使わなくても、パーティション割り当てを導入後でも比較的容易に(開始ポイントや終了ポイントを意識することなく、サイズの指定だけで)変更することができます。 今回はこの LVM のパーティションニングを動的に変更する手順を紹介します。

まず前提として、現在の LVM によるパーティション内容は以下のようになっているものとします:
ファイルシステムサイズ用途
/dev/mapper/VolGroup-lv_root4.0GBルートファイルシステム
tmpfs500MBスワップ領域
/dev/mapper/VolGroup-lv_var4.5GB/var にマウント

これを最終的には以下のようなパーティショニングに変更することを今回の目的とします。もちろんこの変更によって容量の減る /var 以下のディスクが足りなくなることはないものとします:
ファイルシステムサイズ用途
/dev/mapper/VolGroup-lv_root6.5GBルートファイルシステム
tmpfs500MBスワップ領域
/dev/mapper/VolGroup-lv_var2.0GB/var にマウント

以下その手順を紹介しますが、大まかにはこのような手順をとります:
(1) /dev/mapper/VolGroup-lv_var を縮小
(2) /dev/mapper/VolGroup-lv_root を拡大

逆の手順は成立しないことを理解してください。最初にいきなりルートファイルを拡大しようとしてもディスクそのものに未使用の領域がない限りは足りなくなります。まずはどこかを減らして余りを作り、その余りを別のパーティションに追加する、という順序が必要になります。

というわけで、まずは (1) を行います。パーティションの縮小は(そのパーティション先にもよりますが)シングルユーザーモードで起動する必要があります。システムを再起動し、Linux の起動画面になったら何かキーを押してd自動ブートのカウントダウンを止めます:
 lv2013101701

この画面で E キーを押して起動モードの編集画面に移動します。そして "kernel" で始まる行に移動して再度 E キーを押します:
lv2013101702

起動オプションの編集画面になるので、シングルユーザーモードを指定するために最後に " single" という文字を加えて Enter キーを押します:
lv2013101703

1つ前の画面に戻りました。この画面だとわかりにくいのですが、kernel 行の最後には " single" が追加されています。改めてこの kernel 行が選択されている状態で B キーを押して起動します。
lv2013101704

CentOS がシングルユーザーモードで起動しました。パスワードも不要です。
lv2013101705

改めて現在のパーティション状況を確認します。 / に 4.0GB、/var に 4.5GB 割り当てられています。ここから /var の 2GB を / に付け替えるのが今回の目的になります。/var はまだ 309MB しか使っていないので、少なくともこの時点では 2GB 減らしても問題はありません。
lv2013101706

まずはこのパーティションをアンマウントします:
 # umount /var

ファイルシステムのサイズ変更は resize2fs コマンドで行いますが、減らす場合はその前に fsck コマンドでディスクチェックを行う必要があります。今回の /var(/dev/mapper/VolGroup-lv_var) は ext4 フォーマットなので、具体的には以下のコマンドを実行します:
 # fsck.ext4 -f /dev/mapper/VolGroup-lv_var

チェック後に resize2fs コマンドでパーティションサイズを変更します(最後の "2G" が変更後のパーティションサイズです):
 # resize2fs /dev/mapper/VolGroup-lv_var 2G

続けて論理ボリュームのサイズも 2G に変更します。確認メッセージが表示されたら y キーを入力します:
 # lvreduce -L 2G /dev/mapper/VolGroup-lv_var

最後に変更後のパーティションを改めて /var にマウントします:
 # mount -t ext4 /dev/mapper/VolGroup-lv_var /var

ここまでの一連のコマンドのスクリーンショットはこんな感じです:
lv2013101707

試しにこの段階で一度パーティション状態を確認しておきます。確かに 4.6GB あった /var が 2.0GB に減っていることが確認できます:
lv2013101708

では今度は /var で減らした分を /(/dev/mapper/VolGroup-lv_root) に追加割り当てします。増やす場合はアンマウント/マウントの必要がないのでより簡単です。 / は現在の 4.0GB に、追加する 2.5GB を加えるので、パーティションサイズとしては 6.5GB を指定することになります:
 # lvextend -L 6.5G /dev/mapper/VolGroup-lv_root

続けてファイルシステムとしてのサイズも変更します:
 # resize2fs /dev/mapper/VolGroup-lv_root

これで / パーティションのサイズ変更は完了です。確認してみるとたしかに増えています(画面上では 6.4GB になってますが・・)。一連のコマンドのスクリーンショットはこんな感じです:
lv2013101709

LVM を使っていなくても動的なパーティション変更ができないわけではないのですが、専用のツールを使って別システムから起動したり、サイズ調整に必要なパラメータが頻雑だったりと面倒です。その点 LVM だとサイズだけを意識するだけでいいので楽ですね。


このページのトップヘ