본문으로 바로가기

LVM ( Logical Volume Manage )

category Linux/Linux Server 2017. 8. 29. 20:12
  • LVM 이란?

물리적인 디스크를 논리적 볼륨그룹으로 구성해서 이 논리적인 볼륨그룹 내에 사용자가 원하는 크기 만큼의 논리볼륨을 할당하여 사용하는 방법으로, 여러 개의 디스크를 하나의 논리적인 볼륨그룹(VG)으로 구성할 수 있으며, 각 논리볼륨(LV)는 독립적이므로, 하나의 디스크에도 여러 가지의 파일 시스템을 설치할 수 있다. 또한 디스크의 용량증설이 요구 될 경우에도 볼륨그룹에 물리볼륨(PV)만 추가하여 용량증설이 가능하고, 데이터량이 감소하여 더 이상 많은 양의 저장공간이 필요 없는 경우, 볼륨그룹에 속한 물리볼륨 개수를 축소하여 용량 감소가 가능하다.




  • LVM 구성요소


  • 작동 방식
- PE (Physical Extent) : PV가 갖는 일정한 블록

디스크에 PV를 생성하게 되면, LVM은 주소를 지정할 수 있는 PE(Physical Extent)라는 단위로 각 물리 디스크를 나눈다. extent는 주소 0번부터 시작하여 1씩 증분하며 순차적으로 디스크에 할당되고, PE의 크기는 볼륨 그룹을 만들 때 구성할 수 있다. 그리고 각 PE의 크기는 default 값이 4MB이며, 이 값은 필요에 따라 볼륨 그룹을 생성 시 1MB에서 256MB 사이의 값으로 지정할 수 있다.
 
- LE (Logical Extent) : LV가 갖는 일정한 블록

디스크에 PV를 생성하고, 생성된 PV를 이용하여 VG(Volume Group)을 구성한 후 이 VG에 LV(Logical Volume)를 생성할 수 있다. LV의 기본 할당 단위를 LE(Logical Extent)라고 하는데, 이 LE는 PV 생성 시 나누어진 PE 영역과 Mapping된다. 따라서 PE의 크기가 4MB이면 LE의 크기도 4MB가 된다. 그리고 LV의 크기는 구성된 LE의 개수 또는 할당할 디스크 용량에 의해 결정된다. 

- LVM과 Data Access 

앞서 말한 바와 같이 LVM이 논리볼륨에 디스크 공간을 할당할 때 LVM은 주소 0에서 시작하여 각 디스크에 순차적으로 할당된 PE와 할당된 LE의 Mapping Table을 만든다. 따라서 LVM은 그림 9.3과 같이 실제 데이터가 물리 볼륨에 상주하는 위치와 상관없이 논리 볼륨을 Access 함으로써 데이터에 액세스 한다.

- Mirroring


미러링되거나 스트라이프된 논리 볼륨을 제외하고 각 LE는 하나의 PE에 매핑된다. 그러나 미러링된 논리 볼륨의 경우, 단일 또는 이중 미러링을 사용하는지에 따라 각 LE는 두 개 또는 세 개의 PE와 매핑된다. 예를 들어, 미러 사본이 하나인 경우에는 각 LE가 두 개의 PE에 매핑되는데 하나의 확장 영역은 원본에 대한 것이고 다른 하나는 미러 사본에 대한 것이다.



  • LVM 명령어
- LVM은 8 Exa Bytes 까지 지원 ( 64-bits CPU )

(B -> KB -> MB -> GB -> TB -> PB -> EB -> ZB -> YB)


-작업 순서

1) System Partition ID 변경(fdisk CMD) 

2) PV 생성(pvcreate CMD) 

3) VG 생성(vgcreate CMD) 

4) LV 생성(lvcreate CMD)

5) F/S 생성(mkfs CMD)

6) 마운트(mount CMD, /etc/fstab)


1) System Partition ID 변경

# fdsik /dev/sdc


Command (m for help): p


Disk /dev/sdc: 1073 MB, 1073741824 bytes

255 heads, 63 sectors/track, 130 cylinders

Units = cylinders of 16065 * 512 = 8225280 bytes


   Device Boot      Start         End      Blocks   Id  System

/dev/sdc1               1         130     1044193+  83  Linux


Command (m for help): t

Selected partition 1

Hex code (type L to list codes): L


 0  Empty           1e  Hidden W95 FAT1 80  Old Minix       bf  Solaris        

 1  FAT12           24  NEC DOS         81  Minix / old Lin c1  DRDOS/sec (FAT-

 2  XENIX root      39  Plan 9          82  Linux swap / So c4  DRDOS/sec (FAT-

 3  XENIX usr       3c  PartitionMagic  83  Linux           c6  DRDOS/sec (FAT-

 4  FAT16 <32M      40  Venix 80286     84  OS/2 hidden C:  c7  Syrinx         

 5  Extended        41  PPC PReP Boot   85  Linux extended  da  Non-FS data    

 6  FAT16           42  SFS             86  NTFS volume set db  CP/M / CTOS / .

 7  HPFS/NTFS       4d  QNX4.x          87  NTFS volume set de  Dell Utility   

 8  AIX             4e  QNX4.x 2nd part 88  Linux plaintext df  BootIt         

 9  AIX bootable    4f  QNX4.x 3rd part 8e  Linux LVM       e1  DOS access     

 a  OS/2 Boot Manag 50  OnTrack DM      93  Amoeba          e3  DOS R/O        

 b  W95 FAT32       51  OnTrack DM6 Aux 94  Amoeba BBT      e4  SpeedStor      

 c  W95 FAT32 (LBA) 52  CP/M            9f  BSD/OS          eb  BeOS fs        

 e  W95 FAT16 (LBA) 53  OnTrack DM6 Aux a0  IBM Thinkpad hi ee  EFI GPT        

 f  W95 Ext'd (LBA) 54  OnTrackDM6      a5  FreeBSD         ef  EFI (FAT-12/16/

10  OPUS            55  EZ-Drive        a6  OpenBSD         f0  Linux/PA-RISC b

11  Hidden FAT12    56  Golden Bow      a7  NeXTSTEP        f1  SpeedStor      

12  Compaq diagnost 5c  Priam Edisk     a8  Darwin UFS      f4  SpeedStor      

14  Hidden FAT16 <3 61  SpeedStor       a9  NetBSD          f2  DOS secondary  

16  Hidden FAT16    63  GNU HURD or Sys ab  Darwin boot     fb  VMware VMFS    

17  Hidden HPFS/NTF 64  Novell Netware  b7  BSDI fs         fc  VMware VMKCORE 

18  AST SmartSleep  65  Novell Netware  b8  BSDI swap       fd  Linux raid auto

1b  Hidden W95 FAT3 70  DiskSecure Mult bb  Boot Wizard hid fe  LANstep        

1c  Hidden W95 FAT3 75  PC/IX           be  Solaris boot    ff  BBT            

Hex code (type L to list codes): 8e

Changed system type of partition 1 to 8e (Linux LVM)


Command (m for help): p


Disk /dev/sdc: 1073 MB, 1073741824 bytes

255 heads, 63 sectors/track, 130 cylinders

Units = cylinders of 16065 * 512 = 8225280 bytes


   Device Boot      Start         End      Blocks   Id  System

/dev/sdc1               1         130     1044193+  8e  Linux LVM


Command (m for help): w

The partition table has been altered!


Calling ioctl() to re-read partition table.

Syncing disks 


2) PV 생성


[명령어 형식]

- PV 생성

# pvcreate /dev/sda1 

# pvcreate /dev/sda1 /dev/sdb1 /dev/sdc1 

# pvcreate /dev/sd[abc]1 

# pvcreate /dev/sda /dev/sdb /dev/sdc 


- PV 정보 확인

# pvs 

# pvscan 

# pvdisplay    (# pvdisplay /dev/sdc1)

# lvmdiskscan 


3) VG 생성


[명령어 형식]

- VG 생성

# vgcreate vg1 /dev/sdc1 /dev/sdd1 /dev/sde1 

# vgcreate vg1 /dev/sd[cde]1 


- VG 이름변경

# vgrename /dev/vg1 /dev/vg1_backup

# vgrename vg1 vg1_backup


-VG 정보 확인

# vgs

# vgscan

# vgdisplay   (# vgdisplay vg1)


4) LV 생성


[명령어 형식]

-LV 생성

# lvcreate -L 10G vg1            /* LV 이름 자동 생성 : lvol#(용량 10G) */

# lvcreate -L 1500M -n lv1 vg1 /* -L 숫자 용량 -n (name) 이름 지정 */

# lvcreate -L 1500 -n lv1 vg1    /* 용량 단위가 없으면 MB */

# lvcreate -l 60%VG -n lv1 vg1 /* -l 스트링입력 가능 */

# lvcreate -l 100%FREE -n lv1 vg1 /* 100%FREE 남은 공간 다 */


-LV 이름 변경

# lvrename /dev/vg1/lv1 /dev/vg1/lv2

# lvrename vg1 lv1 lv2           /* vg1(lv1 -> lv2) */ vg 다르면 같은 이름 존재 가능


-LV 정보 확인

# lvs 

# lvscan 

# lvdisplay 


5) F/S 생성


# mkfs.ext3 /dev/vg1/lv1


6) 마운트 작업


# mount /dev/vg1/lv1 /lv1


-물리적인 파티션 작업과 LVM 작업 비교


- LVM 삭제 

삭제는 생성의 역순으로 진행한다. 


[작업순서]

1) 마운트 풀기 (umount CMD, /etc/fstab)

2) LV 삭제(lvremove CMD)

3) VG 삭제(vgremove CMD) 

4) PV 생성(pvremove CMD)

 

1) 마운트 풀기

# umount /lv1


2) LV 삭제

# lvremove /dev/vg1/lv1


3) VG 삭제

# vgremove /dev/vg1


4) PV 삭제

# pvremove /dev/sda1


- LVM 용량 늘리기 / 줄이기


-용량 늘리기

용량을 늘릴땐 사용중인 lv를 umount 하지 않고도 이어 붙힐 수 있다. 


[작업순서]

1) VG안에 용량이 남았는지 확인후 없다면 새로운 디스크를 VG안에 추가시킨다.

2) VG안의 남은 용량을 LV로 추가시킨다.


새로운 디스크 : /dev/sdf1

# fdisk /dev/sdf1          /*  system partition ID 8e */

# fdisk -l | grep LVM    /* 확인 */

# pvcreate /dev/sdf1    /* PV로 설정 */

# vgextend vg1 /dev/sdf1    /* vg1으로 추가 */

# pvs                                /* 확인 */

# lvextend -l +100%FREE /dev/vg1/lv1    /* 남은용량 모두 lv1 으로 추가 */

# df -h /lv1 

# resize2fs /dev/vg1/lv1     /* 용량을 추가했음에도 df -h  명령어에 전과 같이 나오면 파일시스템을 다시 확인 */

# df -h /lv1  /* 확인 */


-용량 줄이기

(주의) 용량을 줄이기 위해서는 백업 과정을 거친다.

용량을 줄일때는 다른 사용자가 lv를 사용하고 있으면 안되기 때문에 umount 작업이 필요하다.

그리고 사용중인 공간 이상으로 줄이면 문제가 생기기 때문에 파일시스템 점검과 파일 시스템 용량을 줄이고 나서 

lv의 용량을 줄여야한다. 


[작업순서] 반드시 준수 

1) 파일 시스템 언마운트 (umount)

# umount /lv1

2) 파일 시스템 점검 (fsck -f , fsck.ext3 -f , e2fsck -f)

# e2fsck -f /dev/vg1/lv1 /* -f 강제로 실행한다.  이상이 없다면 실행하지 않아 강제로 실행시켜 점검한다.*/

3) 파일 시스템 용량 줄이기

# resize2fs -p /dev/vg1/lv1 700M 

4) LV 용량 줄이기

# lvreduce -L 700M /dev/vg1/lv1  /* 파일 시스템으로 줄인 용량만큼만 줄여야한다. */



# cp /etc/passwd /lv1/file1

[참고]데이터 백업

# mkdir -p /backup

# cd /lv1

# tar cvzf /backup/lv1.tar.gz .

# cd

# umount /lv1

[참고] fuser /* 사용중인 사람이 있다면 알림후 kill */

# fsck.ext3 -f /dev/vg1/lv1

# resize2fs -p /dev/vg1/lv1 2G

# lvreduce -L 2G /dev/vg1/lv1

# lvs

# mount /lv1 ; cd /lv1

# cat file1     /* 파일이 정상적인지 확인 */



- VG 안의 PV 를 새로운 PV로 교체

성능이 좋은 디스크로 교체하는 경우 또는 용량이 큰 디스크로 교체하는 경우에 기존의 PV에 저장된 내용을 새로운 PV로 옮겨야한다. 

기존 디스크 : /dev/sdf        디스크가 속해있는 VG : vg1

새로운 디스크 : /dev/sdg


# fdisk /dev/sdg     /* system partition id 8e 로 설정 */

# fdisk -l | grep lvm

# pvcreate /dev/sdg1    /* PV 설정 */

# pvs         /* 확인 */

# vgextend vg1 /dev/sdg1    /* vg1 에 장치 추가 */

# pvmove /dev/sdf1 /dev/sdg1        /* sdf1 -> sdg1 */

# pvs     /* 확인 */

  • LV - Striping 구성
- LVM Stripe : 하나의 PV를 사용하는 것이 아니라 PV에 분할 저장한다. 
- 특성 :  분할 저장되어있기때문에 읽을때 각 디스크마다 한번씩 I/O 가 발생되어 성능이 향상된다.
마찬가지로 분할 저장되어있기 때문에 하나의 디스크가 망가지면 모든 파일이 깨진다. 안정성은 떨어진다.

[명령어 형식]
# lvcreate -L 50G -i2 -I64 -n lv1 vg1    /* -I : 대문자 i */
-> -i 옵션: number of stripes
-> -I 옵션: stripe size(KB) - 기본값이 64KB
-> 2개의 PV에 걸쳐서 stripe 크기는 64KB 크기로 vg1에 lv1 구성

# lvextend -L +10G /dev/vg1/lv1  
# lvextend -l +100%FREEE /dev/vg1/lv1

[예]
vg1 에 /dev/sdc1(1G)  /dev/sdd1(1G) /dev/sde1(1G) 이 pv로 설정되어있다고 할때.

# lvcreate -L 1.5G -i 3 -n stripelv vg1
# pvs

 PV         VG   Fmt  Attr PSize    PFree  

  /dev/sdc1  vg1  lvm2 a-   1016.00M 504.00M

  /dev/sdd1  vg1  lvm2 a-   1016.00M 504.00M

  /dev/sde1  vg1  lvm2 a-   1016.00M 504.00M 

-> sdc1의 1G와 sdd1의 500M 를 사용하지 않고 모든 3개의 PV 모두 500M씩 사용되었다

[확장하기]stripe의 LV 확장시 저장되는 디스크의 개수를 파악하여 그 개수만큼 확장해주어야한다. 
# lvcreate -L 1.5G -i 3 -n stripelv vg1
.....
# pvcreate /dev/sd[fgh]1        /* 3개의 디스크를 추가한다 */
.....
# lvextend -L +1.5G /dev/vg1/stripelv 

  • LV Mirroring 구성
-LVM Mirroring :  안정성을 위해 같은 내용을 더 저장한다. 
- 특성 : read 성능은 높아지나 write 성능은 낮아진다. read는 두개의 디스크에 저장되므로 나눠서 I/O를 발생시켜 하나의 디스크가 
처리해야하는 I/O를 줄여주지만 같은 내용을 2번써야하므로 write 성능은 낮아진다.
같은 내용이 있으므로 디스크가 손상되어도 서비스에는 이상이 없다. 안정성이 높다. 

[명령어 형식]
# lvcreate -L 50G -m 1 -n lv1 vg1
-> -m 옵션: number of copies
# lvcreate -L 12G -m1 -n lv1 vg1 /dev/sdc1 /dev/sdd1

# lvextend -L +5G /dev/vg1/mirrorlv —nosync 

[예]
vg1 에 /dev/sdc1(1G)  /dev/sdd1(1G) /dev/sde1(1G) 이 pv로 설정되어있다고 할때.

# pvs

PV         VG   Fmt  Attr PSize    PFree   

  /dev/sdc1  vg1  lvm2 a-   1016.00M 1016.00M

  /dev/sdd1  vg1  lvm2 a-   1016.00M 1016.00M

  /dev/sde1  vg1  lvm2 a-   1016.00M 1016.00M 


# lvcreate -L 100M -m 1 -n mirrorlv vg1 ( # lvcreate -L 100M -m 1 -n mirrorlv vg1 /dev/sdc1 /dev/sdd1 )
# pvs

PV         VG   Fmt  Attr PSize    PFree   

  /dev/sdc1  vg1  lvm2 a-   1016.00M  916.00M

  /dev/sdd1  vg1  lvm2 a-   1016.00M  916.00M

  /dev/sde1  vg1  lvm2 a-   1016.00M 1016.00M 

 -> /dev/sdc1 과 /dev/sdd1 이 각각 100M 로 설정되었다. 
-m 1 이기 때문에 하나만 copy해서 만들었으므로 /dev/sde1의 용량은 변함없다.

[확장]
# lvextend -L +100M /dev/vg1/mirrorlv
# pvs 

V         VG   Fmt  Attr PSize    PFree   

  /dev/sdc1  vg1  lvm2 a-   1016.00M  816.00M

  /dev/sdd1  vg1  lvm2 a-   1016.00M  816.00M

  /dev/sde1  vg1  lvm2 a-   1016.00M 1012.00M

-> 미러링은 100M 확장하면 copy 된 디스크도 같은 용량이 확장된다. 

위에선 1개의 copy를 만들어 놨으므로 100M가 1번더, 총 200M가 할당된다. 


[연습 문제]

(ㄱ) 디스크 준비
/dev/sdc1(1G), /dev/sdd1(1G), /dev/sde1(1G), /dev/sdf1(1G), /dev/sdg1(1G), /dev/sdh1(1G)

(ㄴ) 생성과정
PV(pvcreate) -> VG(vgcreate) -> LV(lvcreate) -> F/S(mkfs.ext3) -> Mount(mount,/etc/fstab)

(ㄷ) 작업 시나리오
VG1(/dev/sdc1, /dev/sdd1, /dev/sde1)
LV1(1.5G)     ----> /lvm1 (마운트 포인터)
LV2(1.5G)     ----> /lvm2 (마운트 포인터)

VG2(/dev/sdf1, /dev/sdg1)
LV3(1G)       ----> /lvm3 (마운트 포인터)
LV4(1G)       ----> /lvm4 (마운트 포인터)

VG2에 /dev/sdh1 디스크 추가(vgextend, lvextend, resize2fs)
LV4(/lvm4) 용량(EX:1G) 모두 할당
reboot 후에 확인    -> ( /etc/fstab 에 설정)
(ㄹ) 삭제
언마운트(umount, /etc/fstab) -> LV 삭제(lvremove) -> VG 삭제(vgremove) -> PV 삭제(pvremove)

[참고] pvremove 명령어로 삭제 했지만 pvscan 결과에 표시가 나는 경우
# dd if=/dev/zero of=/dev/sdc1 bs=512 count=2   /* LVM  정보 자리에 null 처리 -> 강제로 날림 */
# pvscan

[정답]
(1) 디스크 준비
- 각 DISK를 PV로 생성한다.
# fdisk /dev/sdc    (/de/sdc1(System ID : 8e))
# fdisk /dev/sdd    (/de/sdd1(System ID : 8e))
# fdisk /dev/sde    (/de/sde1(System ID : 8e))
# fdisk /dev/sdf    (/de/sdf1(System ID : 8e))
# fdisk /dev/sdg    (/de/sdg1(System ID : 8e))
# fdisk /dev/sdh    (/de/sdh1(System ID : 8e))
# fdisk -l | grep LVM 

(2) PV 생성
# pvcreate /dev/sdc1   (# pvcreate /dev/sd[cdefgh]1)
# pvcreate /dev/sdd1
# pvcreate /dev/sde1
# pvcreate /dev/sdf1
# pvcreate /dev/sdg1
# pvcreate /dev/sdh1
# pvscan 
# pvdisplay
# pvs 

(3) VG 생성
# vgcreate VG1 /dev/sdc1 /dev/sdd1 /dev/sde1  (# vgcreate VG1 /dev/sd[cde]1)
# vgcreate VG2 /dev/sdf1 /dev/sdg1            (# vgcreate VG2 /dev/sd[fg]1)
# vgscan
# vgdisplay
# vgs
# pvs

(4) LV 생성
# lvcreate -L 1500M -n LV1 VG1    (# lvcreate -L 1.5G -n LV1 VG1)
# lvcreate -L 1500M -n LV2 VG1    (# lvcreate -l 100%FREE -n LV2 VG1)

# lvcreate -L 1000M -n LV3 VG2    (# lvcreate -L 1G -n LV3 VG2)
# lvcreate -L 1000M -n LV4 VG2    (# lvcreate -l 100%FREE -n LV4 VG2) 

# lvscan
# lvdisplay
# lvs

(5) 파일시스템 작업
# mkfs.ext3 /dev/VG1/LV1 
# mkfs.ext3 /dev/VG1/LV2 
# mkfs.ext3 /dev/VG2/LV3 
# mkfs.ext3 /dev/VG2/LV4 
# tune2fs -l /dev/VG1/LV1

(6) 마운트 작업
# mkdir /lvm1 /lvm2 /lvm3 /lvm4 
# mount /dev/VG1/LV1 /lvm1 
# mount /dev/VG1/LV2 /lvm2 
# mount /dev/VG2/LV3 /lvm3 
# mount /dev/VG2/LV4 /lvm4 
# vi /etc/fstab 
/dev/VG1/LV1            /lvm1                   ext3    defaults        1 2
/dev/VG1/LV2            /lvm2                   ext3    defaults        1 2
/dev/VG2/LV3            /lvm3                   ext3    defaults        1 2
/dev/VG2/LV4            /lvm4                   ext3    defaults        1 2


# df -h (# mount)

(7) 용량 늘리는 작업
# vgextend VG2 /dev/sdh1 
# lvextend -L +1000M /dev/VG2/LV4    (# lvextend -l +100%FREE /dev/VG2/LV4)
# resize2fs /dev/VG2/LV4

# df -h
/dev/mapper/VG1-LV1  1.5G   35M  1.4G   3% /lvm1
/dev/mapper/VG1-LV2  1.5G   35M  1.4G   3% /lvm2
/dev/mapper/VG2-LV3  985M   18M  918M   2% /lvm3
/dev/mapper/VG2-LV4  2.0G   18M  1.9G   1% /lvm4


(8) 재부팅
# init 6 (# reboot)

부팅 이후에 확인

# df -h
/dev/mapper/VG1-LV1  1.5G   35M  1.4G   3% /lvm1
/dev/mapper/VG1-LV2  1.5G   35M  1.4G   3% /lvm2
/dev/mapper/VG2-LV3  985M   18M  918M   2% /lvm3
/dev/mapper/VG2-LV4  2.0G   18M  1.9G   1% /lvm4


(9) 삭제 작업
# umount /lvm1
# umount /lvm2
# umount /lvm3
# umount /lvm4
# vi /etc/fstab
# df -h

# lvremove /dev/VG1/LV1    (# lvremove /dev/VG[12]/LV[12])
# lvremove /dev/VG1/LV2 
# lvremove /dev/VG2/LV3 
# lvremove /dev/VG2/LV4 
# lvscan

# vgremove VG1 
# vgremove VG2 
# vgscan

# pvremove /dev/sdc1       (# pvremove /dev/sd[cdefgh]1)
# pvremove /dev/sdd1 
# pvremove /dev/sde1 
# pvremove /dev/sdf1 
# pvremove /dev/sdg1 
# pvremove /dev/sdh1 
# pvscan


'Linux > Linux Server' 카테고리의 다른 글

SWAP  (0) 2017.08.31
RAID  (0) 2017.08.30
마운트 ( mount )  (0) 2017.08.28
파일 시스템( Filesystem)  (0) 2017.08.28
장치 인식과 파티션 작업  (0) 2017.08.27