[리눅스 뻘짓 일기] 루트 파티션 변경 하기
LVM 파티션 재구성 및 GRUB 부트로더 복구 작업 기록
이 문서는 1TB 서버의 100GB LVM 루트 파티션 용량 부족 문제를 해결하기 위해 시스템 파티션을 재구성하고, 변경된 환경에 맞게 GRUB 부트로더를 복구한 전체 과정을 기술합니다.
1. 초기 문제 정의 및 해결 계획 수립
- 초기 상황: 1TB 디스크를 장착한 서버가 100GB 크기의 LVM(논리 볼륨)으로 루트(
/
) 파티션이 설정되어, IntelliJ Gateway 및 LXC 컨테이너 사용으로 인해 용량 부족 현상이 발생했습니다. - 초기 목표: 호스트 OS와 LXC 컨테이너의 스토리지를 분리하기 위해, 기존 LVM 볼륨 그룹(VG)을 확장하고 논리 볼륨(LV)을 분리하는 것을 목표로 설정했습니다.
- 기술적 한계: LVM 확장을 시도하는 과정에서, LVM의 기반이 되는 물리적 파티션(PV) 자체가 특정 크기에 묶여 있어 단순 확장이 불가능하다는 점이 확인되었습니다.
2. LVM 제거 및 파티션 재구성
단순 확장이 불가능하여, LVM을 완전히 제거하고 파티션 구조를 새로 설계하는 방식으로 계획을 변경했습니다.
2-1. 시스템 데이터 백업
- 상세 작업 내용: 파티션 변경 작업에 앞서, 데이터 손실을 방지하기 위해
rsync
를 사용하여 시스템 전체 데이터를 별도의 저장소에 백업했습니다.
단계 | 작업 내용 | 예시 명령어 |
---|---|---|
1 | 기존 LVM 볼륨 마운트 | sudo mount /dev/ubuntu-vg/ubuntu-lv /mnt/oldroot |
2 | 백업용 저장소 마운트 | sudo mount /dev/sdb1 /mnt/backup |
3 | 시스템 전체 복제 실행 | sudo rsync -aAXv --info=progress2 /mnt/oldroot/ /mnt/backup/ |
2-2. LVM 해체 및 파티션 재생성
- 상세 작업 내용: 데이터 백업 완료 후, 기존 LVM 구성을 역순으로 해체하고
parted
를 이용해 디스크 파티션을 물리적으로 재구성했습니다.
단계 | 작업 내용 | 예시 명령어 |
---|---|---|
1 | LVM 비활성화 | sudo lvchange -an /dev/ubuntu-vg/ubuntu-lv sudo vgchange -an ubuntu-vg |
2 | LVM 구성요소 제거 | sudo lvremove /dev/ubuntu-vg/ubuntu-lv sudo vgremove ubuntu-vg sudo pvremove /dev/nvme0n1p3 |
3 | Parted 실행 | sudo parted /dev/nvme0n1 |
4 | 기존 파티션 삭제 | (parted) rm 3 |
5 | 새 파티션 생성 | (parted) mkpart primary ext4 2048s 130G (parted) mkpart primary 130G 100% |
6 | 변경사항 저장 및 종료 | (parted) quit |
2-3. 시스템 복원 및 부팅 실패 발생
- 상세 작업 내용: 재구성된 130GB 파티션을 포맷하고, 백업해 둔 시스템 데이터를 복원했습니다. 이로 인해 파티션의 UUID가 변경되어 첫 부팅에 실패했습니다.
단계 | 작업 내용 | 예시 명령어 |
---|---|---|
1 | 새 파티션 포맷 | sudo mkfs.ext4 /dev/nvme0n1p2 (새로 생성된 파티션) |
2 | 새 파티션 마운트 | sudo mount /dev/nvme0n1p2 /mnt/newroot |
3 | 백업 데이터 복원 | sudo rsync -aAXv --info=progress2 /mnt/backup/ /mnt/newroot/ |
4 | 결과 확인 | 재부팅 시 initramfs 프롬프트로 진입 |
3. 최종 시스템 아키텍처 정의
초기 계획을 수정하여, 최종 시스템 아키텍처는 다음과 같이 정의되었습니다.
- 최종 목표 아키텍처:
- 호스트 OS:
/dev/nvme0n1
의 첫 130GB를 일반ext4
파티션으로 할당하여 루트(/
)로 사용. - LXC 컨테이너:
/dev/nvme0n1
의 남은 360GB와 다른 SSD의 250GB를 각각 물리 볼륨(PV)으로 만들어 하나의 볼륨 그룹(VG)으로 묶어 컨테이너 전용 LVM 스토리지 풀로 사용.
- 호스트 OS:
4. GRUB 부트로더 복구 작업
새로운 아키텍처에 맞게, 변경된 루트 파티션(130GB 일반 파티션)으로 시스템을 부팅시키기 위해 GRUB 부트로더 복구 작업을 수행했습니다.
4-1. 표준 복구 시도의 실패
- 상세 작업 내용: 부팅 실패의 원인인 UUID 불일치를 해결하기 위해,
chroot
환경에서 관련 설정 파일의 UUID를 수동으로 수정했으나update-grub
이 정상적으로 동작하지 않았습니다.
단계 | 작업 내용 | 예시 명령어 |
---|---|---|
1 | 새 UUID 확인 | sudo blkid /dev/nvme0n1p2 |
2 | 루트 파티션 마운트 | sudo mount /dev/nvme0n1p2 /mnt |
3 | 설정 파일 수정 | sudo nano /mnt/etc/fstab sudo nano /mnt/etc/default/grub |
4 | 결과 | update-grub 을 실행했으나 부팅 설정이 제대로 갱신되지 않음 |
4-2. 수동 부트 엔트리 작성으로의 전환
- 상세 작업 내용:
update-grub
의 자동 업데이트가 실패하자,40_custom
스크립트에 부팅 명령어를 직접 정의하여 강제로 부팅 메뉴를 생성하는 방식으로 전환했습니다.
단계 | 작업 내용 | 예시 명령어 |
---|---|---|
1 | 커스텀 스크립트 편집 | sudo nano /etc/grub.d/40_custom (chroot 환경 내부) |
2 | 부트 엔트리 코드 작성 | bash menuentry 'Manual Ubuntu Boot' { set root='hd0,gpt2' linux /boot/vmlinuz-generic root=UUID=<새 UUID> ro initrd /boot/initrd.img-generic } |
3 | 실행 권한 부여 | sudo chmod +x /etc/grub.d/40_custom |
4-3. chroot
환경 구축
- 상세 작업 내용:
grub-install
과 같은 시스템 복구 명령어를 올바르게 실행하기 위해, Live USB 환경에서 복구 대상 시스템으로 루트를 완벽하게 전환하는 가상 환경을 구축했습니다.
단계 | 작업 내용 | 예시 명령어 |
---|---|---|
1 | 루트 파티션 마운트 | sudo mount /dev/nvme0n1p2 /mnt |
2 | 시스템 디렉토리 바인드 | for d in dev dev/pts proc sys; do sudo mount --bind /$d /mnt/$d; done |
3 | UEFI 파티션 마운트 | sudo mount /dev/nvme0n1p1 /mnt/boot/efi |
4 | chroot 환경 진입 |
sudo chroot /mnt |
5 | EFI 변수 마운트 (chroot 내부) | mount -t efivars efivars /sys/firmware/efi/efivars |
4-4. 최종 오류 분석(트러블 슈팅)
fstab
과 /etc/default/grub
의 UUID를 올바르게 수정했음에도 update-grub
명령이 적용되지 않은 현상은, 시스템 복구 과정에서 발생할 수 있는 대표적인 '소리 없는 실패(silent failure)' 사례입니다. 명령어 자체는 오류 없이 실행된 것처럼 보이지만, 실제 결과물인 /boot/grub/grub.cfg
는 갱신되지 않은 것입니다.
가장 유력한 원인은 불완전한 chroot
환경 때문입니다.
update-grub
은 단순히 설정 파일을 읽어 텍스트를 교체하는 프로그램이 아니라, 실행되는 시점의 시스템을 동적으로 탐색하여 grub.cfg
를 '생성'하는 복잡한 스크립트입니다. 이 동적 탐색 과정이 실패하면, 명령어 자체는 오류 없이 끝나도 결과물은 갱신되지 않을 수 있습니다.
실패 과정 상세 분석:
- 설정 파일 수정: 저는
fstab
과/etc/default/grub
의 UUID를 새로운 루트 파티션의 것으로 정확히 수정했습니다. 이 단계의 작업은 올바르게 수행되었습니다. - 불완전한
chroot
환경: 하지만/dev
,/proc
,/sys
등의 필수 가상 파일 시스템을 현재 시스템과 연결(bind mount
)하지 않은 채chroot
환경에 진입했습니다. - 동적 탐색 실패:
chroot
내부에서update-grub
을 실행하자, GRUB의 하위 스크립트(주로/etc/grub.d/10_linux
)가 새로운 루트 파티션을 탐색해야 했습니다. 그러나 시스템의 장치 정보(dev
), 커널 및 프로세스 정보(proc
,sys
)에 접근할 수 없었기 때문에, 새로운 UUID를 가진 장치를 현재 시스템의 루트 파티션으로 발견하는 데 실패했습니다. - 결과: '소리 없는' 실패: 스크립트는 새로운 정보를 발견하지 못하자, 변경 전의 낡은 정보(캐시 또는 환경 변수에 남아있던 옛 LVM 경로 등)를 바탕으로
grub.cfg
를 생성하거나, 혹은 해당 부팅 항목의 업데이트 자체를 건너뛰었습니다. 이 과정에서 스크립트가 문법 오류 등으로 중단된 것이 아니므로, 셸에는 아무런 오류 메시지 없이 작업이 완료된 것처럼 보였습니다.
작업 관련 용어 및 개념 총정리
여기서 부터는 LVM 파티션 재구성 및 GRUB 부트로더 복구 과정에서 언급된 모든 기술 용어와 개념을 정리한 자료입니다.
1. LVM (Logical Volume Manager) 관련 개념
LVM은 물리적인 디스크를 추상화하여 유연하고 확장 가능한 스토리지 관리를 지원하는 기술입니다. 계층 구조를 가집니다.
- PV (Physical Volume / 물리 볼륨)
- 정의: LVM에서 사용할 수 있는 기본 단위로, 디스크 파티션(
_ /dev/nvme0n1p3_
)이나 디스크 전체를 LVM용으로 초기화한 것입니다. - 관련 명령어:
pvcreate
(PV 생성),pvremove
(PV 제거),pvs
(PV 목록 보기). - 작업 내용: 사용자는 기존 LVM을 해체하기 위해
pvremove
를 사용했으며, 새로운 컨테이너용 LVM을 만들기 위해 360GB와 250GB 파티션을 각각 PV로 만들었습니다.
- 정의: LVM에서 사용할 수 있는 기본 단위로, 디스크 파티션(
- VG (Volume Group / 볼륨 그룹)
- 정의: 하나 이상의 PV들을 묶어 하나의 큰 저장소 풀(Pool)로 만든 것입니다. (예:
ubuntu-vg
) - 관련 명령어:
vgcreate
(VG 생성),vgremove
(VG 제거),vgextend
(VG 확장),vgs
(VG 목록 보기). - 작업 내용: 사용자는 기존
ubuntu-vg
를vgremove
로 제거했으며, 두 개의 새로운 PV를 묶어 컨테이너용 VG를 새로 생성했습니다.
- 정의: 하나 이상의 PV들을 묶어 하나의 큰 저장소 풀(Pool)로 만든 것입니다. (예:
- LV (Logical Volume / 논리 볼륨)
- 정의: VG라는 저장소 풀에서 사용자가 필요한 만큼 할당받아 사용하는 논리적인 파티션입니다. 운영체제는 이 LV를 일반 파티션처럼 인식하고 사용합니다. (예:
ubuntu-lv
) - 관련 명령어:
lvcreate
(LV 생성),lvremove
(LV 제거),lvextend
(LV 확장),lvreduce
(LV 축소),lvs
(LV 목록 보기). - 작업 내용: 사용자가
lvreduce
를 잘못 사용하여 최초의 문제가 발생했으며, 최종적으로는 호스트 OS용 LV를 제거하고 컨테이너용 LV를 새로 생성하는 구조로 변경했습니다.
- 정의: VG라는 저장소 풀에서 사용자가 필요한 만큼 할당받아 사용하는 논리적인 파티션입니다. 운영체제는 이 LV를 일반 파티션처럼 인식하고 사용합니다. (예:
2. 파티션 및 파일 시스템 관련 개념
디스크를 나누고 데이터를 저장하는 방식과 관련된 용어입니다.
- 파티션 (Partition)
- 정의: 하드 디스크 드라이브나 솔리드 스테이트 드라이브의 논리적인 구획입니다. 운영체제는 이 구획을 별개의 디스크처럼 다룰 수 있습니다.
- 관련 도구:
parted
,fdisk
- 작업 내용:
parted
를 이용해 기존 LVM이 있던 파티션을 삭제하고, 호스트 OS용(130GB)과 컨테이너 LVM용(360GB) 파티션을 새로 생성했습니다.
- UUID (Universally Unique Identifier)
- 정의: 각 파티션이나 파일 시스템에 부여되는 고유한 식별자입니다. 디스크 순서가 바뀌어도 시스템이 정확한 파티션을 찾아갈 수 있도록 도와줍니다.
- 관련 명령어:
blkid
- 작업 내용: 파티션을 재생성하면서 UUID가 변경된 것이 최초 부팅 실패의 직접적인 원인이었습니다. 복구 과정에서
blkid
로 새 UUID를 확인하여 설정 파일을 수정하는 작업이 필수적이었습니다.
- 파일 시스템 (File System)
- 정의: 운영체제가 파일을 디스크에 저장하고 구성, 탐색, 검색하는 방법을 정의하는 구조입니다. (예:
ext4
,vfat
) - 관련 명령어:
mkfs.ext4
(ext4 파일 시스템 생성),resize2fs
(ext4 파일 시스템 크기 조정). - 작업 내용:
resize2fs
를 파일 시스템보다 논리 볼륨을 먼저 축소하여 문제가 발생했습니다. 복구 시에는mkfs.ext4
로 새 파티션을 포맷했습니다.
- 정의: 운영체제가 파일을 디스크에 저장하고 구성, 탐색, 검색하는 방법을 정의하는 구조입니다. (예:
- /etc/fstab
- 정의: 시스템 부팅 시 자동으로 마운트할 파티션과 파일 시스템의 정보를 담고 있는 설정 파일입니다. UUID를 기반으로 장치를 지정하는 것이 일반적입니다.
- 작업 내용: 파티션 재구성 후, 이 파일에 남아있는 과거의 UUID를 새로운 루트 파티션의 UUID로 수정하는 작업이 필요했습니다.
- rsync
- 정의: 파일과 디렉토리를 복사하고 동기화하는 강력한 유틸리티입니다. 권한, 소유권 등 속성을 그대로 보존하며 복제할 수 있어 시스템 백업 및 이전에 매우 유용합니다.
- 작업 내용: 파티션을 재구성하기 전 시스템 전체를 백업하고, 재구성 후 새 파티션에 시스템을 복원하는 핵심적인 역할을 수행했습니다.
3. 부팅 프로세스 및 복구 관련 개념
컴퓨터 전원이 켜지고 운영체제가 시작되기까지의 과정, 그리고 이를 복구하는 데 사용되는 용어입니다.
- UEFI (Unified Extensible Firmware Interface)
- 정의: 전통적인 BIOS를 대체하는 최신 펌웨어 인터페이스입니다. 더 빠른 부팅, 더 큰 디스크 지원, 보안 기능 강화 등의 장점을 가집니다.
- 작업 내용: 사용자의 시스템이 UEFI 기반이었기 때문에, GRUB 복구 시 EFI 파티션을 마운트하는 등 UEFI에 맞는 절차를 따라야 했습니다.
- ESP (EFI System Partition)
- 정의: UEFI 펌웨어가 운영체제 부트 로더를 찾고 로드하는 데 사용하는 특정 파티션입니다. FAT32(vfat) 파일 시스템으로 포맷되어 있으며, 부트로더 파일(`.efi)이 저장됩니다.
- 작업 내용:
chroot
환경에서grub-install
이 실패한 주된 이유는 이 ESP를/boot/efi
에 마운트하지 않았기 때문입니다.
- GRUB (GRand Unified Bootloader)
- 정의: 대부분의 리눅스 배포판에서 사용하는 부트 로더입니다. 운영체제 커널을 디스크에서 찾아 메모리에 로드하는 역할을 합니다.
- 관련 파일 및 명령어:
- /etc/default/grub: GRUB의 동작(커널 부팅 옵션, 타임아웃 등)을 제어하는 기본 설정 파일.
- /etc/grub.d/:
update-grub
실행 시 사용되는 스크립트들이 모여있는 디렉토리.40_custom
은 사용자가 직접 메뉴를 추가할 때 사용합니다. - /boot/grub/grub.cfg: 위 설정과 스크립트를 바탕으로
update-grub
이 최종적으로 생성하는 실제 부팅 설정 파일. (이 파일을 직접 수정해서는 안 됩니다.) - update-grub: 설정 변경 후, 이를
grub.cfg
에 반영하는 명령어. - grub-install: GRUB 부트로더 자체를 디스크의 부트 영역에 설치하는 명령어.
- initramfs (Initial RAM File System)
- 정의: 리눅스 커널이 부팅 과정 초기에 사용하는 임시 루트 파일 시스템입니다. 실제 루트 파일 시스템을 마운트하는 데 필요한 드라이버(LVM, RAID 등)를 포함하고 있습니다.
- 작업 내용: 부팅 실패 시 최종적으로 진입한 환경이 바로
initramfs
셸이었습니다. 이는 커널이 필요한 드라이버를 로드했지만, 최종 목적지인 루트 파일 시스템을 찾지 못했음을 의미합니다.
- chroot (Change Root)
- 정의: 특정 디렉토리를 임시 루트 디렉토리로 만들어, 현재 실행 중인 시스템과 격리된 환경에서 작업할 수 있게 하는 명령어입니다. 시스템 복구 시 Live USB로 부팅한 뒤, 고장 난 시스템의 파티션을 마운트하고 그 안으로 들어가 마치 정상 부팅된 것처럼 작업할 때 필수적으로 사용됩니다.
- 작업 내용: GRUB 복구의 모든 과정은 Live USB 환경에서
chroot
를 통해 새로운 루트 파티션으로 진입하여 이루어졌습니다.dev
,proc
,sys
,efi
등을 마운트하는 것은 성공적인chroot
환경 구축의 핵심입니다.