LVM2(Logical Volume Manager, version 2)的前身是LVM,他是由Heinz Mauelshagen於1998年在HP-UX上開發。他當初為了解決unix上分割區空間分配的問題而設計出這個管理程式。有了LVM,我們可以動態的調整空間的大小,大大縮短置換硬碟所需的downtime。這個鬼才現在任職於Redhat,目前正主持幾個跟software raid相關的計畫。目前我們所接觸到的教學文件大多是LVM2,但是因為已經全面取代了舊版的的LVM,因此還是以LVM稱之。
LVM的基本架構
上圖引用自鳥哥的私房菜,是一個相當有助理解的架構圖。本文僅適合非常熟悉LVM架構的讀者做為快速複習使用;如果談到PV/LV/VG等名詞您還得停頓一下,本文可能對您毫無幫助。下表則是我自己整理的指令列表,但僅列出一些常用的commands。
Function | PV | VG | LV | |
新增 | pvcreate | vgcreate | lvcreate | |
刪除 | pvremove | vgremove | lvremove | |
擴大 | vgextend | lvextend | lvresize | |
縮小 | vgreduce | lvreduce | ||
變更屬性 | pvchange | vgchange | lvchange | |
掃描 | pvscan | vgscan | lvscan | |
詳列清單 | pvdisplay | vgdisplay | lvdisplay | |
匯入/匯出 | vgimport vgexport |
|||
移動 | pvmove | |||
附註: | 1. pvchange與lvchange非常少用,本文也不會提及。 2. lvextend與lvreduce可以完全由lvresize來取代。 3. LVM不具備redundent的功能。如果想要有備援機制,請改用raid或是raid搭配LVM。 4. 目前的開機管理程式均無法辨識LVM,請獨立出/boot便於開機。 |
設計一個實驗
藉由實做是理解LVM最好的方式。本實驗的流程與目的如下:
- 利用虛擬機器產生一個2G大小的硬碟用來產生LVM類型分割區
- 練習建立與刪除PV
- 練習建立與刪除VG
- 練習建立與刪除LV
- 在LV上建立檔案系統,並且動態改變LV以及檔案系統大小
- 實做LVM的snapshot功能並還原
- 以新硬碟取代舊硬碟
- 系統重灌或是硬碟轉移,LVM的轉移方案
我先前已經有一個2G的虛擬硬碟,我不想用fdisk慢慢組分割區,直接刪掉他的partiton table以利我們馬上就能使用:
dd if=/dev/zero of=/dev/hdb count=1接著利用fdisk產生四個分割區,假設分別是hdb{1,2,5,6},各為200M, 300M, 300M以及1200M。
把partition ID改成8e(LVM format)。改完後,別忘記更新核心的partition資訊:
partprobe /dev/hdb檢查一下核心是否已經更新partition table了:
cat /proc/partitions
major minor #blocks name 3 0 8388608 hda 3 1 8281476 hda1 3 2 104422 hda2 3 64 2097152 hdb 3 65 196024 hdb1 3 66 293328 hdb2 3 67 1 hdb3 3 69 293296 hdb5 3 70 1314400 hdb6如果能看到hdb的1,2,5,6號partition,那就表示可以進行下一步。
pv就是構成LVM最基本的元素,他可以是一整顆硬碟,也可以是一個partition。(實作上如果要把整顆硬碟加入LVM裡,還是建議至少做一個partition再加入)要把數個硬碟或是分割區加入PV裡,需要用pvcreate:
pvcreate /dev/hdb{1,5}把某個分割區從pv裡移除,使用pvremove:
pvremove /dev/hdb5查看現有的pv有哪些,可以用pvdisplay得知:
"/dev/hdb1" is a new physical volume of "191.43 MB" --- NEW Physical volume --- PV Name /dev/hdb1 VG Name PV Size 191.43 MB Allocatable NO PE Size (KByte) 0 Total PE 0 Free PE 0 Allocated PE 0 PV UUID OKTpgY-M2tF-KykI-xPB1-xJae-UMqI-XKvJ5U可以得知我們現在只有一個分割區加入到pv裡。我們把hdb{2,5}也加到pv裡,讓實驗繼續進行。
pvcreate /dev/hdb{2,5}
對於作業系統來說,vg相當於傳統硬碟的地位;把許多個傳統分割區加入pv裡,然後建立一個vg組成一個大的虛擬硬碟。現在我們建立一個名為myVG的vg,由hdb1及hdb2組成:
vgcreate myVG /dev/hdb{1,2}此時可以用vgdisplay以及vgscan觀察之:
--- Volume group --- VG Name myVG System ID Format lvm2 Metadata Areas 2 Metadata Sequence No 1 VG Access read/write VG Status resizable MAX LV 0 Cur LV 0 Open LV 0 Max PV 0 Cur PV 2 Act PV 2 VG Size 472.00 MB PE Size 4.00 MB Total PE 118 Alloc PE / Size 0 / 0 Free PE / Size 118 / 472.00 MB VG UUID VyMTQc-1Cuy-z2UG-jXyF-LFvx-vRY2-oQaJLd由上面資訊可以得知,我們只有一個vg叫做myVG,大小為472MB,為118個PE的大小,目前完全沒有PE被使用。
再把hdb5加入到這個vg裡:
vgextend myVG /dev/hdb5然後再使用vgdisplay/vgscan觀察變化。要把某個傳統分割區從vg裡開除,則使用vgreduce:
vgreduce myVG /dev/hdb1要把整個vg砍掉重練,就使用vgremove:
vgremove myVG為了後續的實驗,趕快恢復原狀吧:
vgcreate myVG /dev/hdb{1,2,5}
從一個vg裡建立一個lv,就好比從一顆硬碟建立分割區,你需要清楚的知道分割區從哪顆硬碟建立,以及分割區的大小。利用lvcreate建立lv:
lvcreate -L 500M -n myLV myVG也可以特別指定vg裡的某個pv:
lvcreate -l 125 -n myLV myVG /dev/hdb1上例表示使用myVG的其中一個pv的空間來建立lv,以-L指定大小,-l指定PE數量;預設1PE=4MB。需特別注意的是,lv一旦建立,想要使用lv則必須像是寫一個分割區一樣寫完整的路徑。以myLV而言,他的完整路徑將會是/dev/myVG/myLV或是/dev/mapper/myVG-myLV。
現在擴大lv成為600M:
lvextend -l +25 /dev/myVG/myLV上例會再從vg裡剩餘的空間去分配。同樣的,要縮減lv也很容易:
lvreduce -l -5 /dev/myVG/myLV如果-l後面沒有接正負號,則表示改變大小成指定值。由於lvextend只能接正值,lvreduce後面只能接負值,這兩個指令可以完全被lvresize取代,例如上面兩個例子完全等於:
lvresize -l +25 /dev/myVG/myLV
lvresize -l -5 /dev/myVG/myLV因此,往後的實作將只使用lvresize。為了使實驗繼續進行,我們把myLV的大小設定成600M吧:
lvresize -L 600M /dev/mapper/myVG-myLV
建立好lv(想像成建立好傳統的分割區)之後,就必須在上面搭載檔案系統以供使用。請把lv當成一個分割區一樣的來進行格式化吧!
mkfs.ext3 -L "myLV" /dev/mapper/myVG-myLV
mount -t ext3 LABEL=myLV /mnt截至目前,這個lv已經正式上線使用了。不過我們可以藉由vgdisplay以及df得知,其實myLV並沒有用到全部的可用空間。LVM最強大的功能之一,就是允許線上擴大容量。由於lv是底層,檔案系統在上層,因此要擴大檔案系統必須lv先擴大,filesystem再擴大。
想要擴張lv到最大容量,你可以查看vg剩餘多少PE然後擴大,或是直接擴大到全部可用範圍:
lvresize -l +100%FREE /dev/myVG/myLV或是指定完全使用某幾個pv:
lvresize -l +100%PVS /dev/myVG/myLV /dev/hdb{2,5}由此可見,LVM的運用非常強大,且自訂性極高。
擴充lv的容量之後,接著就可以擴充檔案系統:
resize2fs /dev/myVG/myLV [700M]如果不指定擴充大小,則resize2fs會自動擴充到全部可用範圍。
要縮減lv大小則與擴充相反--必須先縮小上層的filesystem,再縮小底層的lv。如果你不照此順序進行,lv上面的資料會全部付之一炬。縮減lv不支援線上進行,而且縮減到有寫入資料的部份也會造成檔案lost,必須小心為之:
umount /mnt依序縮減filesystem以及lv大小後,就可以掛載後正式上線工作。
fsck.ext3 -f /dev/myVG/myLV
resize2fs /dev/myVG/myLV 500M
lvresize -l -25 /dev/myVG/myLV
mount LABEL=myLV /mnt
Solaris的ZFS檔案系統擁有非常卓越的snapshot功能,雖然LVM的snapshot沒有Solaris那麼powerful,但是也是一樣功能強大且便於使用。snapshot目前僅支援lv,vg的snapshot功能還尚未實做出來。
快照檔其實就是一個lv,他會與檔案系統共用『未變更』的PE,因此snapshot必須與原本的lv在同一個vg裡面。
上圖引用自鳥哥的私房菜,說明了snapshot可以很小的原因就是與原本的lv共用未變更的PE。
他的大小約為想執行snapshot的lv的15%~20%的大小。檢查我們的lv大小:
lvdisplay | grep Size以我們的例子而言,我們的lv約750MB,製作一個snapshot約需要150MB,恰好目標5的末段我們縮減了檔案系統,vg也還有約156M的空間可以用。我們讓snapshot就坐在這156MB上:
lvcreate -L 156M -s -n `date +"%Y-%m%d".snap` /dev/myVG/myLV產生了具有日期為檔名的快照檔之後,可以以此作為系統還原備份之用。例如半年後想要回到snapshot的狀態,只要把該snapshot掛載上去就好。
umount /mnt雖然snapshot只佔有156MB的空間,但是對於核心而言,他就是一個lv的clone,因此你從df看到的大小是一樣的:
mkdir /mnt/{myLV,date}
mount /dev/myVG/2010-0505.snap /mnt/date
mount LABEL=myLV /mnt/myLV
/dev/mapper/myVG-myLV 591M 17M 545M 3% /mnt/myLV /dev/mapper/myVG-2010--0505.snap 591M 17M 545M 3% /mnt/date把snapshot給umount之後,再來進行一些測試!
umount /mnt/date以上,我們做的所有更動都會紀錄在snapshot檔裡,可以用lvdisplay /dev/myVG/2010-0505.snap來觀察:
for words in $(seq 1 1000000); do
echo 'I love peace world!!' >> abc.txt
done
cp -r /etc/httpd /mnt/myLV
--- Logical volume --- LV Name /dev/myVG/2010-0505.snap VG Name myVG LV UUID JDGmIg-m0qW-M0VK-Gem1-4bqA-DEyS-83FtbL LV Write Access read/write LV snapshot status active destination for /dev/myVG/myLV LV Status available # open 0 LV Size 600.00 MB Current LE 150 COW-table size 156.00 MB COW-table LE 39 Allocated to snapshot 13.32% Snapshot chunk size 4.00 KB Segments 1 Allocation inherit Read ahead sectors auto - currently set to 256 Block device 253:1請特別留意"Allocated to snapshot"已經佔了13.32%,由此可知LV的snapshot有個關鍵的要素:所容許的異動大小必須小於snapshot的大小。往後將此snapshot掛載,便可以取出製作快照前的檔案作為備援使用。snapshot被掛載的時候會停止紀錄變動,請非常留意。
刪除一個snapshot就是刪除一個lv:
lvremove /dev/myVG/2010-0505.snap
以上已經展示過LVM線上擴大檔案系統及lv的卓越能力,也展示過製作snapshot的功能,現在則是模擬淘汰一個快要壞掉的舊硬碟,換上一個又大又新的硬碟上去。我們假設舊硬碟是hdb1(200M),新硬碟是hdb6(1200M),首先必須把新硬碟加入:
pvcreate /dev/hdb6上述的指令顯示線上加入一個新硬碟到vg裡,然後把hdb1裡的PE都移動到hdb6裡,並且每隔2秒顯示詳細訊息:
vgextend myVG /dev/hdb6
pvmove -v -i 2 /dev/hdb1 /dev/hdb6
Finding volume group "myVG" Archiving volume group "myVG" metadata (seqno 4). Creating logical volume pvmove0 Moving 47 extents of logical volume myVG/myLV Found volume group "myVG" Updating volume group metadata Suspending myVG-myLV (253:0) with device flush Creating myVG-pvmove0 Loading myVG-pvmove0 table (253:1) Resuming myVG-pvmove0 (253:1) Creating volume group backup "/etc/lvm/backup/myVG" (seqno 5). Checking progress every 2 seconds /dev/hdb1: Moved: 14.9% /dev/hdb1: Moved: 34.0% /dev/hdb1: Moved: 46.8% /dev/hdb1: Moved: 57.4% /dev/hdb1: Moved: 66.0% /dev/hdb1: Moved: 76.6% /dev/hdb1: Moved: 89.4% /dev/hdb1: Moved: 100.0% Found volume group "myVG" Loading myVG-myLV table (253:0) Suspending myVG-myLV (253:0) with device flush Suspending myVG-pvmove0 (253:1) with device flush Resuming myVG-pvmove0 (253:1) Removing temporary pvmove LV Writing out final volume group after pvmove Creating volume group backup "/etc/lvm/backup/myVG" (seqno 7).由於是每隔兩秒顯示一次訊息,因此訊息很長。
vgreduce myVG /dev/hdb1最後的兩行指令,就是把hdb1完整的從LVM裡面拿掉,接著就是找個可以允許短暫downtime的時間,把舊硬碟抽走。別忘了新硬碟容量大多了,別忘了先把lv變大,在擴大filesystem!
pvremove /dev/hdb1
lvresize -l +100%FREE /dev/myVG/myLV
resize2fs /dev/myVG/myLV
假設今天想要換新的機器或是重灌系統,但是lvm裡面的資料還是要保留下來,我們該怎麼處理呢?大致的流程如下:
umount->vgchange(deactivate)->vgexport->系統重灌->vgimport->vgchange(activate)->mount
承續剛才的狀況:
umount /mnt/myLV
vgchange -a n myVG
vgexport myVG #可以藉由vgdisplay觀察是否有exported!
上述的指令便是停止vg的運作,因此所有在vg上的lv也都會全部終止運作,因此假設你在vg上切不只一個lv,則需要把所有掛載點都umount之後,vgchange才有可能終止活動。我終止這個vg並且匯出vg之後,關閉虛擬的os並開啟一個新的os,假設是SLES11好了;我們可以在SLES11上面利用vgdisplay找到這個vg:
vgimport myVG如此一來便可以順利完成轉移。
vgchange -a y myVG
mkdir /export
mount /dev/myVG/myLV /export
參考文獻:
1. Redhat Enterprise Linux系統管理寶典 進階篇(陳永昇),第八章
2. Logical Volume Manager(一)、(二)(林彥明)
3. RHEL3/4 之Logical Volume Manager(林彥明)
4. 鳥哥的私房菜:Logical Volume Manager
沒有留言:
張貼留言