본문 바로가기

웹 운영/운영 구축

[PV, VG, LV] LV 분할하여 Ubuntu /var 용량 확장하기

728x90

프로젝트에서 mongodb 를 사용하던 중, Data Insert 시에 DB 가 down 되는 상황이 발생해서, 로그를 확인해보니 다음과 같았다. 

 

 

{"s":"F",  "c":"CONTROL",  "id":6384300, "ctx":"ftdc","msg":"Writing fatal message","attr":{"message":"terminate() called. An exception is active; attempting to gather more information\n"}}
{"s":"F",  "c":"CONTROL",  "id":6384300, "ctx":"ftdc","msg":"Writing fatal message","attr":{"message":"DBException::toString(): FileStreamFailed: Failed to write to interim file buffer for full-time diagnostic data capture: /var/lib/mongodb/diagnostic.data/metrics.interim.temp\nActual exception type: mongo::error_details::ExceptionForImpl<(mongo::ErrorCodes::Error)39, mongo::AssertionException>"}}

 

 

/var/lib/mongodb/diagnostic.data 쪽은 mongodb 에서 data 를 저장하는 쪽인데, 해당 부분에서 AssertionException 이 발생한 것이다. 용량이 의심되어서 df -h 명령어로 용량 현황을 살펴보니, /var 경로의 용량이 100% 로 가득차서 발생하는 문제임을 발견했다. 현재 VM 에 600GB 스토리지를 함께 발급받았었기 때문에, 이를 사용하기 위해 현재 상황을 살펴보았다.

 

 

$ lsblk
NAME                 MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda                    8:0    0  100G  0 disk
├─sda1                 8:1    0    1M  0 part
├─sda2                 8:2    0    1G  0 part /boot
└─sda3                 8:3    0   99G  0 part
  ├─rootvg-root_lv   253:2    0   45G  0 lvm  /
  ├─rootvg-tmp_lv    253:3    0   12G  0 lvm  /tmp
  ├─rootvg-var_lv    253:4    0   25G  0 lvm  /var
  └─rootvg-swap_lv   253:5    0   16G  0 lvm  [SWAP]
sdb                    8:16   0  600G  0 disk
└─sdb1                 8:17   0  600G  0 part
  ├─vg001-appdata_lv 253:0    0  600G  0 lvm  /appdata
sr0                   11:0    1 1024M  0 rom

 

 

처음보면 뭔 상황인지 잘 모르겠으나, 확실한건 600G 짜리 디스크가 존재하고, 이는 전혀 사용중이지 않음을 알 수 있다 (df 명령어들로 통해 확인 가능). 이쯤에서 PV, VG, LV 에 대해 이해해보고 가면 좋다.

 

 

 

* PV, VG, LV 에 대하여

 

 

PV 와 VG 와 LV 의 관계



PV : Physical Volume
> 물리적 디스크 그 자체 혹은 물리적인 파티션을 말한다
> /dev/sda1, /dev/sdb1 이런 공간들은 실제 디스크 내부의 파티션이다.
> PV 위에서 논리적 볼륨을 구성한다

 


VG : Volume Group
PV 들을 묶는다. 여러개의 PV 들을 논리적으로 묶어놓은 Pool (여러 PV 들을 합쳐서 하나의 큰 Storage Pool 만듬)
> 가령, VG001 은 sda1 과 sdb1을 합쳐서 만든 볼륨 그룹
> rootvg 같은건 Volume Group 이다. 

> lsblk 명령어에 실질적으로 등장하진 않는다. LV들의 소속을 보여줄 뿐이다.

 


LVM : Logical Volume Management
> 디스크 관리 방식 중 하나, 물리 디스크를 논리적으로 나누고, 그들을 묶기도 하여 효율적으로 공간을 관리하고 확장하기 위한 수단



<예시>

 

 

sda                    8:0    0  100G  0 disk
├─sda1                 8:1    0    1M  0 part
├─sda2                 8:2    0    1G  0 part /boot
└─sda3                 8:3    0   99G  0 part
  ├─rootvg-root_lv   253:1    0   45G  0 lvm  /
  ├─rootvg-tmp_lv    253:2    0   12G  0 lvm  /tmp
  ├─rootvg-var_lv    253:3    0   25G  0 lvm  /var
  └─rootvg-swap_lv   253:4    0   16G  0 lvm  [SWAP]



> 다 폴더 별로 관리되는 것 같음, 그래서 이 폴더는 이 공간에! 이런 느낌
> 위 그림을 보면, sda 내부에 sda1,2,3 는 PV 로, 파티션 물리 볼륨이다 (sda 가 실제 디스크)
> sda3 라는 공간은, 4가지 LV 가 분리되어서 담당한다 (이 때 남는 공간은 그냥 sda3 에게 할당되어 있는 듯)
> sda3 라는 공간은, 또한 rootvg 의 일부이다. rootvg 가 사용하는 PV 들 중 하나인 것
> rootvg 내부에 생성된 LV 들은 rootvg-{}-lv 들로, PV 에 배치된다
> 그니까 PV 에게 담당 LV 를 지정하는 구조가 아니라, PV 들이 모여 VG 이 되고, VG 안에서 LV 들을 만듬 (위 그림이랑 같이 이해)
> PV 는 자동으로 담당되는 LV 들이 생김!

 

 

 

* 문제 상황

 

 

/var 의 용량이 부족하므로, 600G 의 디스크 파티션 내에서 새로운 LV 를 생성해 /var 에 추가해주는 방식을 생각해 보았다. PV 가 다르더라도, /var 라는 공간에 같이 할당될 수 있을 것이라 생각했다 (참고로 결론은 불가능하다). 

 

 

맨 위에 lsblk 상황을 보면 새 디스크에는 이미 sdb1 이라는 PV, vg001 이라는 VG 이 만들어졌고, 600G 모두 vg001-lv 라는 생성되어 있는 LV에 할당되어 있다. 따라서 이 LV 를 줄인 다음에 새 LV 를 만든 후 /var 에 마운트를 해주면 될 것 같다 (600GB 의 LV 에서 100GB 를 떼어내려 함)

 

 

1. 데이터 백업 (혹시 모르니 데이터를 백업했다, 완료시 간단히 삭제하면 되므로)

 

 

> 디스크 관련 작업이나 DB 관련 작업을 한다면 무조건 백업 해두는게 좋다. "에이 설마.." 싶긴 했는데 이번에도 역시 필요했다 ㅋㅋㅋㅋ 정말 꼭 필수이다.

> 기존 사용하던 계정의 홈 디렉토리가 /appdata 였는데, 이거는 또 디스크 LV (/vg001-appdata_lv) 에 마운트 된 채로 발급되었다. /vg001-appdata_lv 는 우리가 100GB 를 떼어내고 싶은 LV 이므로, unmount 를 해야 한다. 따라서 현재 /appdata 에 있는 데이터 백업을 진행한다

 

> cp 를 하면 특수 파일 복사에 한계가 있다고 해서, rsync 명령어를 사용했다
> $ sudo rsync -avh --progress /appdata/ /{백업데이터_경로}/ 
>>  -a 는 권한, 심볼릭 링크, 타임스태프 등을 모두 복사, -vh 는 출력모드 설정, -progress 는 진행 상태 표시

 



2. unmount 및 기존 LVM 볼륨 축소 진행

 

 

> 디스크에 마운트 되어 있던 /appdata 를 언마운트한다. (참고로 이 때 /appdata 내부에서 실행된 프로세스들은 모두 종료되어야 한다. 작은 작업이 아닌 것)

> $ sudo umount /appdata

>> /appdata 라는 공간에 마운트된 File System 이 있다면 모두 해제하는 명령어

>> 참고로 unmount 를 진행하면 기존 /appdata 는 당연히 빈공간이 된다. 기존 데이터들은 appdata_lv 에 있기 때문이다.

 

> 중요한 건 파일 시스템을 먼저 축소하고, LV 의 크기를 축소해야 한다 (내가 여기에서 좀 꼬인듯 하다. 아래 나온다) - 파일시스템을 반드시 먼저 줄여야 한다고 함
> $ sudo resize2fs /dev/vg001/appdata_lv 500G (100기가를 줄임)

>> /appdata_lv 에서 생성한 File System 의 크기를 500GB 로 줄인다 (File System 과 Volume 시스템과는 다른 것인듯)
> $ sudo lvreduce -L -100G /dev/vg001/appdata_v (LV 자체를 줄임)
>> /appdata_lv 의 LV 자체의 크기를 500GB로 줄인다 

 

 


3. 새 LVM 생성

 


> $ sudo lvcreate -L 100G -n new_lv vg001 

>> vg001 VG 내에 새로운 new_lv LV 를 생성하고, 이 LV 에 100G 를 할당한다

> 이 때, 용량이 100G 불가능하다는 오류가 뜰 수 있는데, 이럴 때는 extent 단위로 환산하면 된다 (99 기가 남았는데 100기가로 할당 이런 문제라서 그런 걸 수도 있음)
> ex:: $ sudo lvcreate -l 25599 -n new_lv vg001 (나도 이런 식으로 하긴 함)

> 여기까지 됐다면 아래와 같은 상황이 된 것

 

 

sdb                    8:16   0  600G  0 disk
└─sdb1                 8:17   0  600G  0 part
  ├─vg001-appdata_lv 253:0    0  500G  0 lvm  /appdata
  ├─vg001-new_lv 253:0    0  100G  0 lvm  

 

 

 

4.  생성한 LVM 을 /var 에 할당

 

 

> $ sudo mount /dev/vg001/new_lv /var
>> /var 경로에 새로 만든 new_lv LV 를 추가적으로 mount 해준다.
> 진행하고 확인해보니, 추가된 것이 아니라 기존 LV 를 (rootvg-var_lv) 를 빼고 새 LV mount 하는 현상이 확인되었다 (이중 mount 는 안되는 것 ㅠㅠ)
> 따라서 그냥 용량을 가장 많이 차지하는 /var/lib 에 새 LV 를 마운트해줬다

>> 심볼릭 링크로 공간들이 존재하기 때문에, /var 라는 공간은 rootvg 에 마운트되어 있지만, 그 안에 /var/lib 라는 공간만은 더 넓은 vg001 에 마운트 되어 있는 형태가 가능한 것
> 그리고 기존에 있던 /var/lib 는 백업해 두었고 , 새로운 공간의 /var/lib 에 다시 넣어줬다 (이 때도 rsync 사용)

 

 

 

* 이후 벌어진 일들 (can't read superblock on /dev/~)

 

 

이제 다시 처음에 LV 축소를 위해 unmount 해줬던 /appdata-lv 를 다시 mount 해줘야 기존 profile 설정 및 해당 계정의 데이터들이 복원되는데, 문제가 발생했다.

 

 

$ sudo mount /dev/vg001/appdata_lv /appdata
mount: /appdata: can't read superblock on /dev/mapper/vg001-appdata_lv.

$ sudo xfs_repair /dev/mapper/vg001-appdata_lv   # 구글링 혹은 GPT 가 위 에러 발생시 repair 해보라고 함
xfs_repair: error - read only 0 of 512 bytes

 

 

위와 같은 오류들이 지속 발생한다. 매우 해결하는데 오래 걸렸고, 웬만한건 다 시도해본 것 같다 (-t xfs 등). 결론은 실제로 vg001-appdata_lv 가 손상되었다는 것으로 결론을 내릴 수밖에 없었다. 지금 리뷰하며 생각해보면, resize 만 하고 lvreduce 를 안했던 것 같다!! 그래서 xfs 시스템이 손상됐던 것 같다.

 


어쨌든 아무리해도 안되었으므로, (천만다행으로 appdata 를 백업해놨었음..) 그냥 기존 appdata_lv 를 삭제하고 새로 만들어줬다.
이 때, appdata_lv 를 굳이 xfs 로 만들 필요 없는 것 같아서 (알아보니 DB쪽에 적합하다고 함) ext4 형태의 파일 시스템으로 다시 생성하고 100G 를 할당하여, /appdata  에 다시 mount 하니 정상적으로 mount 되었다. 완성된 lsblk 의 모습은 아래와 같았다.

 

 

$ lsblk
NAME                 MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda                    8:0    0  100G  0 disk
├─sda1                 8:1    0    1M  0 part
├─sda2                 8:2    0    1G  0 part /boot
└─sda3                 8:3    0   99G  0 part
  ├─rootvg-root_lv   253:2    0   45G  0 lvm  /
  ├─rootvg-tmp_lv    253:3    0   12G  0 lvm  /tmp
  ├─rootvg-var_lv    253:4    0   25G  0 lvm  /var
  └─rootvg-swap_lv   253:5    0   16G  0 lvm  [SWAP]
sdb                    8:16   0  600G  0 disk
└─sdb1                 8:17   0  600G  0 part
  ├─vg001-appdata_lv 253:0    0  100G  0 lvm  /appdata     ## 새로 만든 appdata_lv
  └─vg001-var_lv     253:1    0  100G  0 lvm  /var/lib    ## 새로 만든 var_lv
sr0                   11:0    1 1024M  0 rom

 

 

sdb1 에 PV 내에 남은 400G 가 존재하고, 필요할 때 sdb 디스크 파티션을 새로 하거나, 혹은 LV 들 증설을 하면 될 것 같다. appdata 백업해둔 내용들은 역시 rsync 를 통해서 복원해주니 정상적으로 복원되었다. 

 

 


* 마운트 내용을 fstab 에 추가 및 주요 시스템 restart



/etc/fstab 은 서버가 기동될 때 (세션 시작이 아닌, 종료 후 시작) 파일 시스템들을 확인하여 대상 경로들과 파일 시스템들을 mount 하기 위해 사용되는 파일로, 없으면 파일 시스템이 아무 마운팅도 하지 않은 상태로 초기화된다. 따라서 fstab 에 다음과 같이 추가 후 저장해 두었다 

 

 

/dev/mapper/vg001-appdata_lv   /appdata                            ext4            defaults        0 0
/dev/mapper/vg001-var_lv            /var/lib                                ext4            defaults        0 0 
## 0 0 은 백업 옵션들인데, 안한다고 설정한 것 (자세히는 추후 알아보자)

 


서버 재부팅 후에도 정상적으로 mount 되었으며, /var 를 중심으로 실행되는 docker, nginx, mysql, mongod 를 다시 켜줘보니, 모든 Data 들이 그대로이며 정상적으로 동작하는 것이 확인되었다 (추가 마운트 후 복원해준 /var/lib 데이터들이 다 정상적으로 동작한다는 뜻).  appdata 역시 정상적으로 연계되었으므로 성공적으로 디스크 증설 성공하였다

 

$ df -h 
/dev/mapper/rootvg-var_lv      25G  8.9G   15G  39% /var     (약 60% 감소)
/dev/mapper/rootvg-tmp_lv      12G   41M   12G   1% /tmp
/dev/mapper/vg001-var_lv       98G   15G   79G  16% /var/lib 
/dev/mapper/vg001-appdata_lv   98G   12G   82G  13% /appdata

 


참고로 위 내용은 이전 후 현재 마운팅 포인트들의 용량들을 보여준 것이다. /var 는 기존의 /var/lib 를 사용하지 않으므로 100% 에서 39% 사용으로 감소하였고, /var/lib 라는 새로운 마운팅 포인트가 생겼으며, /appdata 와 함께 당장은 넉넉한 100GB 의 용량이 할당되었음을 알 수 있다.

 

 


* 다하고 남은 궁금증

 


> Volume 들과 파일 시스템? 이거의 연관 관계를 잘 모르겠음. ext4, ext3, xfs 이런 파일 시스템들..
> 적진 않았지만, docker 따위가 var 및 var/lib 내부에 많은 데이터를 사용하고 있기 때문에, 기존 /var/lib 를 청소 (모두 삭제) 하는데에는 실패하였다 .완전히 깔끔하게 하려면 docker 를 재설치하는 것이 깔끔해보였다.

 

 

 

 

 

 

 

 

끝!

728x90