목록 보기
LVM 스냅샷 관리 기능 개발 후기 (1)
기타

LVM 스냅샷 관리 기능 개발 후기 (1)

글루시스
글루시스
2024년 6월 3일

장애 복구나 유실된 데이터 복원을 위해서 AnyStor는 이전부터 스냅샷 기능을 지원하였습니다. 그러나 스냅샷 생성과 확인은 가능할 뿐, 실제로 복원 등에 사용하기 위해서는 관리자가 CLI 명령어를 사용하여 데이터를 복원할 수밖에 없었습니다. 실제 복원 시에는 고객 서비스에 영향이 없도록 진행되어야 했기에 도입하기 까다로웠던 점도 있었습니다. 이번에 스냅샷 기능을 재편하게 되었는데, 스냅샷을 안정적으로 도입하기 위해서 거쳤던 테스트와 이슈 대응 방안에 대해서 살펴보겠습니다. 배경 설명 본 제품에서는 LVM 볼륨을 주로 다룹니다. LVM 볼륨의 프로비저닝 정책에 따라서 스냅샷의 종류도 나뉘게 되는데, 우선 볼륨의 프로비저닝 종류에 대해서 간략히 설명해 보겠습니다. 씬 프로비저닝(Thin Provisioning)된 볼륨 : 사용자에게 필요한 만큼의 스토리지 공간을 할당하되, 실제로는 사용한 만큼의 공간만 실제 스토리지에서 차지하는 방식입니다. 씩 프로비저닝(Thick Provisioning)된 볼륨 : 미리 정해진 크기의 스토리지 공간을 사용자에게 할당하는 방식입니다. 이 공간은 사용자가 실제로 사용하지 않더라도 할당된 크기만큼 스토리지에서 차지합니다. 스토리지 공간을 확보하는 데 있어서 보다 안정적이지만, 사용하지 않는 공간이 발생할 수 있어 스토리지 공간의 사용이 비효율적일 수 있습니다. 프로비저닝 된 볼륨에 따라서 스냅샷의 저장 방식도 바뀝니다. 씬 프로비저닝된 볼륨과 씩 프로비저닝된 볼륨에 대해서 약칭으로 각각 Thin 볼륨, Thick 볼륨으로 변경하여 설명하겠습니다. Thin 볼륨의 스냅샷: 원본 볼륨의 데이터를 공유하며, 자체 메타데이터 영역을 가지고 있습니다. 메타데이터 영역에는 스냅샷의 논리적 익스텐트와 물리적 익스텐트 간의 매핑이 저장되어 있습니다. 이를 통해 스냅샷은 원본 볼륨의 상태를 보존하고, 변경 사항을 추적하게 됩니다. Thick 볼륨의 스냅샷 : 원본 볼륨의 데이터를 복사하여 새로운 공간에 저장합니다. 원본 데이터의 완전한 복사본을 제공하지만, 스토리지 공간을 더 많이 차지하게 됩니다. 여기까지만 살펴봤을 때 차이점이 여럿 보입니다. Thin 볼륨은 저장 방식이 다르기 때문에, 스냅샷 또한 저장하는 방법이 다르게 보입니다. 실제로 Thin 볼륨은 스냅샷을 다음과 같은 구조로 저장합니다. :bulb: NOTE 물리적 익스텐트(Physical Extents: PE): 디스크의 섹터로 매핑된 물리적 할당 단위 논리적 익스텐트(Logical Extents: LE): 물리적 익스텐트로 매핑된 논리적 할당 단위 < Thin 볼륨 구조 > 위 구조를 보게 되면 Thin 볼륨과 스냅샷 볼륨은 공통의 데이터 볼륨을 공유합니다. 그렇기 때문에 많은 스냅샷을 생성할 수 있지만, 스냅샷을 삭제하더라도 여유 공간이 추가로 확보되지 않을 수도 있습니다. 데이터 볼륨 말고도 메타데이터 볼륨도 보이는데, 메타데이터 볼륨에서는 각 Thin 볼륨에 속한 데이터 볼륨을 추적합니다. 볼륨 그룹 별로 여러 씬 풀(Thin Pool)이 생성 될 수 있는데, 예비 메타데이터로 불리는pmspare 는 볼륨 그룹에 대해서 하나만 생성됩니다. 이 pmspare 는 볼륨 그룹 내의 모든 씬 풀(Thin Pool)의 메타데이터를 복구하기 위해서 사용됩니다. 씬 풀(Thin Pool) 은 약칭으로 Thin 풀로 변경하여 설명하겠습니다. 스냅샷 도입 전 테스트 스냅샷을 도입하기 전에 몇 가지 스냅샷 기능에 관한 테스트를 진행하였습니다. 진행하면서 있었던 고려 사항들을 공유드리고자 합니다. 1. Thin 풀 데이터 볼륨 저장 공간 확보 Thin 볼륨의 파일 시스템에서 파일을 삭제하면 일반적으로 씬 풀에 Free 블록을 다시 추가하지 않습니다. 파일 시스템에서는 삭제되었지만, 씬 풀에 적용되지 않은 경우, fstrim 을 통해서 물리적 공간을 Thin 풀에 복원할 수 있습니다. 비슷한 효과를 마운트 시에 옵션으로 처리할 수도 있는데, 마운트시에 discard 옵션으로 Thin 풀의 데이터 공간에 대한 자동 해제 옵션을 추가하여 데이터 볼륨의 저장 공간을 확보할 수 있었습니다. # Thin 볼륨 데이터 쌓기 dd if=/dev/zero of=/(mount_path)/fileN bs=4096 count=1000000

용량 확인

lvs LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert root anystor-e -wi-ao---- &lt44.00g
swap anystor-e -wi-ao---- 5.00g
ThinLV thinvpool Vwi-aotz-- 60.00g tp_thinvpool 58.33
tp_thinvpool thinvpool twi---tz-- 40.00g 87.51 3.28

데이터 삭제 후 재 마운트

mount 시에 -o discard 추가

mount -o discard /dev/mapper/thinvpool-ThinLV /(mount_path)

Thin 볼륨 데이터 쌓기

dd if=/dev/zero of=/(mount_path)/fileN bs=4096 count=1000000

용량 확인

lvs LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert root anystor-e -wi-ao---- &lt44.00g
swap anystor-e -wi-ao---- 5.00g
ThinLV thinvpool Vwi-aotz-- 60.00g tp_thinvpool 1.78
tp_thinvpool thinvpool twi---tz-- 40.00g 2.67 1.64 2. Thin 데이터 볼륨 공간 부족 자동 확장을 설정한 경우 데이터 공간이 부족해지기 전에 설정값에 따라서 씬 풀의 데이터 공간이 확장됩니다. 하지만 확장할 공간이 없고 씬 풀의 데이터 공간이 이미 100%인 경우에도 추가로 디스크를 증설해 준다면 이후에 수동으로 확장할 수 있습니다. 만약 자동 확장 시 볼륨의 물리적인 용량이 부족한 경우 확장에 실패하여 데이터 볼륨이 가득 차게 되는 경우가 있는데, 그 경우의 쓰기 동작을 설정할 수 있습니다. 데이터 볼륨에 여유 공간이 없는 경우, 큐 버퍼에 쓰기 명령을 넣었다가 확장이 완료되면 버퍼를 사용합니다. 기본 타임아웃(60초)이 지난 경우에는, 모든 쓰기 명령이 error 를 반환하게 됩니다. Thin 풀에서는 --errorwhenfull 옵션으로 Thin 풀이 가득 찼을 때, 큐 버퍼 사용 유무를 지정할 수 있습니다. # Thin 풀의 데이터 볼륨이 가득 찬 경우 lvs LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert root anystor-e -wi-ao---- &lt44.00g
swap anystor-e -wi-ao---- 5.00g
ThinLV thinvpool Vwi-aotz-- 60.00g tp_thinvpool 66.67
tp_thinvpool thinvpool twi---tzD- 40.00g 100.00 3.53

Thin 풀의 errorwhenfull 옵션으로 파일 시스템의 동작 결정

lvchange --errorwhenfull (y/n) thinvpool/tp_thinvpool Thin 풀이 가득 찼을 때 파일 시스템의 동작을 결정했다면, 다음으로는 Thin 풀의 수동 확장으로 용량을 확장할 수 있습니다. Thin 풀만 확장해 준다면, Thin 볼륨은 자동으로 확장됩니다. lvextend -L+(size) thinvpool/tp_thinvpool 3. Thin 풀 메타데이터 볼륨 공간 부족 Thin 풀 메타데이터의 볼륨이 작고, 스냅샷이 많은 경우 메타데이터 볼륨이 부족할 수 있습니다. 만약 Thin 풀 메타데이터의 볼륨이 가득 찬 경우 메타데이터의 볼륨이 손상될 수 있습니다. lvcreate -s -n snap1 vg1/thinvol ... lvcreate -s -n snap600 vg1/thinvol

lvs
thinvol vg1 Vwi-aotz-- 10.00g tp_thinpool 82.70
tp_thinpool vg1 twi-aotzM- 10.00g 84.81 100.00
메타데이터를 확인하고 복구하는 것은 파일 시스템에서 fsck/repair 를 실행하는 것과 유사합니다. Thin 풀의 메타데이터를 복구하는 방법 중 하나는 lvconvert --repair (vg)/(thinpool) 를 실행하는 것입니다, 이 동작에서는 pmspare 로 복구 메타데이터를 생성하고, 메타데이터를 교체할 수 있도록 유도합니다. 단순히 공간이 더 필요한 경우는 메타데이터 확장을 시도해 볼 수 있습니다. #lvs -a LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert

thinlv vg Vwi-aotz-- 10.00g thinpool 82.70
thinpool vg twi-aotzM- 10.00g 84.81 100.00
[thinpool_tdata] vg Twi-ao---- 10.00g
[thinpool_tmeta] vg ewi-ao---- 12.00m

#lvextend --poolmetadatasize +(size) vg/thinpool

#lvs -a LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert

thinlv vg Vwi-aotz-- 10.00g thinpool 82.70
thinpool vg twi-aotz-- 10.00g 84.84 28.04
[thinpool_tdata] vg Twi-ao---- 10.00g
[thinpool_tmeta] vg ewi-ao---- 60.00m
4. 메타데이터 장애 복구 실제 이용 시에는 메타데이터의 용량이 가득 찬 경우나, 디스크 장애 등의 사례에서 메타데이터가 손실되는 경우도 있었습니다. LVM 에서는 각각의 디스크가 동일한 볼륨 풀을 사용하고 있다면, 동일한 메타데이터를 디스크에 복사하여 사용하기 때문에, 디스크에 할당된 정보(PV 정보 등)을 제외하고 복사한다면 손쉽게 복구할 수 있습니다. 메타데이터 영역 중 디스크 정보에 해당하는 656Byte를 제외하고 1024KB까지 복사하여 손상된 디스크의 메타데이터를 복구합니다. # 메타데이터 장애 로그 Metadata location on /dev/sde at 109056 begins with invalid VG name. Failed to read metadata summary from /dev/sde Failed to scan VG from /dev/sde Couldn't find device with uuid 3C36Fc-B9Fc-7LGH-EoAO-0r2c-ECrl-GuWorB. Cannot restore Volume Group VGPB with 1 PVs marked as missing. Restore failed.

임시 파일 복사 (백업용)

dd if=/dev/sde of=/root/temp bs=1020k count=1

LVM 메타데이터 복사

dd if=/dev/sdd of=/dev/sde bs=1020k count=1 conv=notrunc

LVM PV Header만 다시 복사

dd if=/root/temp of=/dev/sde bs=656 count=1 conv=notrunc LVM 메타데이터에서는 어떤 데이터가 있는지 확인한다면, 조금 더 세부적인 이슈에 대응할 수도 있습니다. 한번 메타데이터에 대해서도 자세하게 살펴보겠습니다. LVM 의 메타데이터 4. 메타데이터 장애 복구 에서도 한 번 언급했던 LVM 의 메타데이터는 같은 볼륨 그룹 안의 물리 볼륨에 동일하게 저장되어 있습니다. 이번 장에서는 LVM 메타데이터가 어떻게 저장되어 있는지 LVM2의 소스코드와 디스크 덤프를 비교하면서 상세하게 살펴보겠습니다. 우선 덤프를 위해 샘플 메타데이터부터 위 글과 같이 /dev/sdd, /dev/sde 의 물리 볼륨을 가지는 볼륨 그룹 thick 과 논리 볼륨 thick_vol, 스냅샷 thick_snap 으로 구성해 보겠습니다. # pvs PV VG Fmt Attr PSize PFree /dev/sdd thick lvm2 a-- &lt50.00g 48.98g /dev/sde thick lvm2 a-- &lt50.00g &lt50.00g

vgs

VG #PV #LV #SN Attr VSize VFree thick 2 2 1 wz--n- 99.99g 98.98g

lvs

LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert thick_snap thick swi-a-s--- 12.00m thick_vol 0.00 thick_vol thick owi-a-s--- 1.00g 우선 디스크 덤프 후 보기 편하게 16진수로 변경한 다음 전체 구성을 한번 살펴보겠습니다. # cat sdd_hex

... 0000200: 4c41 4245 4c4f 4e45 0100 0000 0000 0000 LABELONE........ 0000210: a982 7799 2000 0000 4c56 4d32 2030 3031 ..w. ...LVM2 001 0000220: 4a6f 6c4f 5177 7833 4466 5033 756a 6e75 JolOQwx3DfP3ujnu 0000230: 776e 6435 4342 4735 6230 6747 5975 3874 wnd5CBG5b0gGYu8t 0000240: 0000 0080 0c00 0000 0000 1000 0000 0000 ................ 0000250: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 0000260: 0000 0000 0000 0000 0010 0000 0000 0000 ................ 0000270: 00f0 0f00 0000 0000 0000 0000 0000 0000 ................ 0000280: 0000 0000 0000 0000 0200 0000 0100 0000 ................ 0000290: 0000 0000 0000 0000 0000 0000 0000 0000 ................

...

0001000: 2af4 634e 204c 564d 3220 785b 3541 2572 .cN LVM2 x[5A%r 0001010: 304e 2a3e 0100 0000 0010 0000 0000 0000 0N>............ 0001020: 00f0 0f00 0000 0000 00a0 0100 0000 0000 ................ 0001030: 0007 0000 0000 0000 a181 917c 0000 0000 ...........|.... 0001040: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 0001050: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 0001060: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 0001070: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 0001080: 0000 0000 0000 0000 0000 0000 0000 0000 ................

...

001b000: 7468 6963 6b20 7b0a 6964 203d 2022 3266 thick (.id = "2f 001b010: 7559 4431 2d48 5856 792d 315a 3275 2d76 uYD1-HXVy-1Z2u-v 001b020: 797a 332d 7765 4530 2d6c 6553 4a2d 716e yz3-weE0-leSJ-qn 001b030: 6d79 784f 220a 7365 716e 6f20 3d20 3333 myxO".seqno = 33 001b040: 0a66 6f72 6d61 7420 3d20 226c 766d 3222 .format = "lvm2" 001b050: 0a73 7461 7475 7320 3d20 5b22 5245 5349 .status = ["RESI 001b060: 5a45 4142 4c45 222c 2022 5245 4144 222c ZEABLE", "READ", 001b070: 2022 5752 4954 4522 5d0a 666c 6167 7320 "WRITE"].flags. 001b080: 3d20 5b5d 0a65 7874 656e 745f 7369 7a65 = [].extent_size

... 메타데이터 정보가 여러 군데로 나눠서 저장되어 있는데, 크게 보자면 다음과 같이 구성되어 있는 것을 알 수 있습니다. < 디스크 덤프로 살펴보는 메타데이터의 구조 > 가장 처음 부분부터 소스코드와 함께 살펴볼까요? 0000200: 4c41 4245 4c4f 4e45 0100 0000 0000 0000 LABELONE........ 0000210: a982 7799 2000 0000 4c56 4d32 2030 3031 ..w. ...LVM2 001

cat lib/label/label.h

35 /* On disk - 32 bytes / 36 struct label_header ( 37 int8_t id[8] / LABELONE / 38 uint64_t sector_xl / Sector number of this label / 39 uint32_t crc_xl / From next field to end of sector / 40 uint32_t offset_xl / Offset from start of struct to contents / 41 int8_t type[8] / LVM2 001 */ 42 ) attribute ((packed)) 맨 처음 부분은 Label Header 입니다. Label Header 에서는 다음과 같은 정보를 정의합니다. < Label Header > LVM 이 사용하는 디스크라고 설

댓글 0

댓글을 작성하려면 로그인이 필요합니다.

댓글을 불러오는 중...