Proxmox VE 8에서 9로 업그레이드
단일 노드 Proxmox VE 8.4 → 9.2 인플레이스 업그레이드를 준비부터 마무리 검증까지 실제 로그와 함께 단계별로 정리한 기록입니다.
홈랩에서 운영하던 단일 노드 Proxmox VE를 8.4에서 9.2로 업그레이드했습니다. 클러스터도 아니고 Ceph도 없는 단출한 구성이지만, 하이퍼바이저 OS 자체를 Debian Bookworm에서 Trixie로 올리는 메이저 업그레이드인 만큼 한 단계씩 신중하게 진행했습니다. 이 글은 그 과정을 준비, 점검, 실제 업그레이드, 마무리 검증, 그리고 업그레이드 직후 따라온 디스크 확장 작업까지 순서대로 정리한 기록입니다.
같은 환경(단일 노드, 외부 스토리지 분리, Ceph/PBS 없음)에서 업그레이드를 앞둔 분이라면 이 글의 흐름을 거의 그대로 따라가실 수 있을 것입니다. 다만 부트로더와 LVM 설정처럼 환경에 따라 갈리는 지점이 몇 군데 있는데, 그런 부분은 "왜 그렇게 판단했는지"까지 적어두려 합니다. 명령을 그대로 베끼는 것보다 판단 근거를 이해하는 쪽이 결국 더 안전하기 때문입니다. 메이저 업그레이드에서 가장 위험한 순간은 잘 모르는 명령을 자신 있게 실행할 때 찾아오곤 합니다.
업그레이드 대상과 범위 이해하기
가장 먼저 짚고 넘어가야 할 것은 "무엇을 업그레이드하는가"입니다. 이게 의외로 헷갈리는 지점입니다.
PVE 8 → 9 인플레이스 업그레이드는 베어메탈 위에서 돌아가는 Proxmox 호스트 OS 자체를 올리는 작업입니다. 그 위에 올라가 있는 VM이나 컨테이너는 업그레이드 대상이 아닙니다. 예를 들어 제 환경에는 Docker 컨테이너들을 돌리는 게스트 VM이 있는데, 이 VM 내부의 Docker나 그 안의 애플리케이션은 호스트 업그레이드와 무관합니다. 하이퍼바이저라는 한 겹의 OS만 바뀌는 것이지, 그 위에서 돌아가는 가상 머신들의 내부까지 바뀌는 것이 아니라는 점을 분명히 해두면 작업 범위가 명확해집니다. VM 입장에서 유일하게 영향을 받는 순간은 호스트가 재부팅되는 동안 잠깐 꺼졌다 켜지는 것뿐입니다.
업그레이드 자료를 찾다 보면 "Docker 패키지 충돌"에 관한 경고를 종종 보게 되는데, 이 경고는 호스트에 직접 Docker를 설치한 경우에만 해당하는 이야기입니다. Proxmox 호스트에 Docker를 직접 설치하면 Debian 기본 패키지와 Docker 공식 레포 패키지가 충돌해 업그레이드가 막힐 수 있습니다. 하지만 정석대로 호스트에는 Docker를 깔지 않고 VM이나 LXC 안에서만 돌리고 있다면 그런 단계는 전부 건너뛰어도 됩니다. 게스트 VM 안에서 도는 Docker는 호스트의 패키지 의존성과 완전히 분리되어 있기 때문입니다. 제 경우 호스트에 Docker가 없는지 다음 명령으로 확인했고, 아무것도 출력되지 않았습니다.
dpkg -l | grep -i docker
정리하면, 이 업그레이드에서 손대는 것은 하이퍼바이저 OS 한 겹뿐이고, 게스트들은 재부팅 시점의 정상 종료와 기동만 신경 쓰면 됩니다.
시작 전 준비사항
메이저 업그레이드는 준비가 8할입니다. 공식 위키도 "유효하고 검증된 백업은 항상 필수"라고 못 박고 있습니다. 준비 단계에서 챙겨야 할 항목들을 정리하겠습니다.
백업과 복원 테스트. 모든 VM/CT를 호스트와 분리된 외부 스토리지에 백업합니다. 여기서 핵심은 "분리"입니다. 업그레이드 대상 호스트 디스크에 백업을 두면, 그 디스크가 깨지는 순간 백업도 함께 사라지므로 의미가 없습니다. NAS, 외장 디스크, 별도 PBS 서버처럼 반드시 호스트 밖에 두어야 합니다. 그리고 백업은 "떴다"는 사실보다 "복원이 된다"는 사실이 훨씬 중요합니다. 열리지 않는 백업은 백업이 아니기 때문입니다. 가능하다면 업그레이드 전에 백업본 하나를 임시 VM으로 복원해보고, 실제로 부팅되는지까지 확인하는 것이 가장 안전합니다.
VM 백업은 GUI에서 각 VM → Backup → Backup now로 간단히 뜰 수 있고, CLI라면 다음과 같습니다. 업그레이드 직전에는 어차피 VM을 끌 것이므로 데이터 정합성이 가장 확실한 stop 모드를 권합니다. 이름은 stop이지만 강제 종료가 아니라 "정상 종료 → 백업 → 다시 켜기"를 자동으로 수행하는 모드라, 파일시스템이 일관된 상태에서 백업이 떠집니다.
vzdump --all --storage <백업저장소> --mode stop --compress zstd
디스크 여유 공간. 루트 파티션에 최소 5GB, 가급적 10GB 이상을 확보합니다. dist-upgrade 과정에서 새 패키지를 내려받아 풀어야 하므로 공간이 빠듯하면 중간에 막힐 수 있습니다. df -h /로 미리 확인하고, 부족하다면 오래된 ISO나 불필요한 백업을 먼저 정리합니다.
콘솔 접근과 터미널 멀티플렉서. IPMI/iKVM이나 물리 콘솔이 있으면 가장 좋습니다. 커널이 바뀌면서 NIC 이름이 변경되거나 부팅이 꼬여 SSH가 올라오지 않을 때를 대비하기 위함입니다. SSH만 가능한 상황이라면 반드시 tmux나 screen 같은 터미널 멀티플렉서 안에서 작업합니다. dist-upgrade가 한창 진행 중일 때 SSH가 끊겨 프로세스가 죽으면 패키지가 어중간하게 설치된 상태로 남아 복구가 까다로워지기 때문입니다. screen의 사용법은 단순합니다. 이름을 붙여 세션을 시작하고, 끊기면 같은 이름으로 다시 붙습니다.
screen -S upgrade # 세션 시작
# (이 안에서 업그레이드 명령 실행)
# 잠깐 빠져나올 때: Ctrl+a 누르고 떼고 d (detach)
screen -r upgrade # 재접속 후 복귀
Ctrl+a를 누른 뒤 손을 떼고 d를 누르면 세션은 백그라운드에서 계속 돌고, 나중에 screen -r upgrade로 그대로 복귀할 수 있습니다. SSH가 예기치 않게 끊겨도 작업이 살아남는다는 점이 핵심입니다.
현재 버전 확인. 업그레이드는 반드시 최신 8.4에서 출발해야 합니다. pveversion 결과가 8.4.1 이상이어야 하며, 아니라면 먼저 8.4 계열로 올립니다. 중간 버전에서 곧바로 9로 건너뛰는 것은 지원되지 않습니다.
apt update && apt dist-upgrade
pveversion
pve8to9 점검 스크립트로 사전 진단하기
Proxmox는 업그레이드 전후로 잠재적 문제를 짚어주는 pve8to9라는 점검 스크립트를 제공합니다. 이 스크립트는 점검만 하고 시스템을 바꾸지는 않습니다. 그래서 부담 없이, 그리고 자주 돌려야 합니다. 업그레이드 전에 한 번, 문제를 고칠 때마다 다시, 그리고 업그레이드가 끝난 뒤에도 돌립니다.
pve8to9 --full
제 환경에서 처음 돌렸을 때의 결과 요약은 다음과 같았습니다.
= SUMMARY =
TOTAL: 41
PASSED: 32
SKIPPED: 8
WARNINGS: 1
FAILURES: 0
FAILURES: 0이고 경고는 단 하나였습니다. 그 경고도 심각한 것이 아니라 "실행 중인 게스트 2개가 있으니 끄거나 옮기는 것을 고려하라"는 안내였습니다.
WARN: 2 running guest(s) detected - consider migrating or stopping them.
단일 노드에서는 게스트를 옮길 다른 노드가 없으므로, 업그레이드 직전에 정상 종료하는 것으로 이 경고를 해소하면 됩니다. 그리고 이 단계의 출력은 단순한 통과/실패 이상으로 유용했습니다. 환경에 따라 갈리는 두 가지 중요한 판단이 여기서 정리됐습니다.
첫째, LVM autoactivation 마이그레이션은 할 필요가 없었습니다. PVE 9부터는 LVM 게스트 볼륨의 자동 활성화 동작이 바뀌어, 공유 스토리지(예: 공유 iSCSI/FC LUN) 환경에서는 마이그레이션 스크립트를 돌려야 합니다. 여러 노드가 같은 LUN을 보는 구성에서 부팅 시 모든 게스트 볼륨이 무조건 활성화되면 충돌이 날 수 있기 때문입니다. 하지만 제 스토리지는 LVM 기반이 아니어서 해당 사항이 없었고, 스크립트도 이를 확인해주었습니다.
INFO: Check for LVM autoactivation settings on LVM and LVM-thin storages...
PASS: No problematic volumes found.
둘째, 부트로더 처리는 지금이 아니라 나중에 할 일이라는 신호를 받았습니다. 이게 가장 중요한 힌트였습니다.
INFO: Checking bootloader configuration...
SKIP: not yet upgraded, systemd-boot still needed for bootctl
즉 systemd-boot 관련 정리는 dist-upgrade 이후에 처리할 일이라고 스크립트가 직접 알려준 것입니다. 이 한 줄 덕분에 부트로더를 섣불리 건드리는 실수를 피할 수 있었습니다. 이 부분은 다음 절에서 더 깊이 다루겠습니다.
부트로더 구성을 정확히 파악하기
systemd-boot 처리는 잘못 건드리면 부팅이 깨지는 영역이라, 명령을 치기 전에 제 시스템이 정확히 어떤 방식으로 부팅하는지부터 확인했습니다. 인터넷에 흔히 도는 "systemd-boot는 찌꺼기니 그냥 지워라"라는 조언은 GRUB으로 부팅하는 시스템에서나 맞는 이야기이고, 모든 시스템에 적용되지 않습니다. 이 조언을 자기 시스템의 부팅 방식을 확인하지 않은 채 따라 했다가 부팅 불능에 빠지는 사례가 실제로 적지 않습니다.
먼저 bootctl status로 현재 부트로더를 확인했습니다.
Current Boot Loader:
Product: systemd-boot 252.38-1~deb12u1
이 시스템은 GRUB이 아니라 실제로 systemd-boot로 부팅하고 있었습니다. 그래서 단순히 apt remove systemd-boot를 했다간 부팅에 쓰는 부트로더를 날려버릴 수 있는 상황이었습니다. 다음으로 proxmox-boot-tool status로 한 단계 더 들어갔습니다.
System currently booted with uefi
85F1-F97D is configured with: uefi (versions: 6.8.12-13-pve, 6.8.12-20-pve, 6.8.12-30-pve)
여기서 uefi라는 표시는 proxmox-boot-tool이 systemd-boot 방식으로 ESP(EFI System Partition)를 관리하고 있다는 뜻입니다. 즉 이 시스템은 PVE ISO 설치 시 구성되는 표준적인 proxmox-boot-tool + systemd-boot 조합으로 부팅하는, 지극히 정상적인 구성이었습니다. ZFS-on-root를 secure boot 없이 UEFI로 설치하면 흔히 이 구성이 됩니다.
여기서 핵심을 이해해야 합니다. Debian Trixie에서는 systemd-boot 패키지가 더 잘게 쪼개졌습니다. 부팅에 실제로 쓰이는 EFI 바이너리는 systemd-boot-efi로, bootctl 도구는 systemd-boot-tools로 분리되고, systemd-boot라는 이름은 이제 메타패키지가 되었습니다. 이 메타패키지는 자기 자신이나 다른 패키지가 업그레이드될 때 끼어들어 부트로더 구성을 자동으로 바꾸는 훅(hook)을 담고 있습니다. proxmox-boot-tool이 부팅을 관리하는 시스템에서는 이 훅이 오히려 방해가 됩니다. 그래서 제거 대상은 부팅 바이너리가 아니라 이 메타패키지 하나입니다. 둘은 별개의 패키지이며, 메타패키지를 지워도 systemd-boot-efi와 systemd-boot-tools는 그대로 남아 부팅과 bootctl이 정상 동작합니다.
결론적으로 제 시스템은 PVE ISO로 설치한 표준 구성이고 systemd-boot를 손수 세팅한 적이 없으므로, 메타패키지 제거 대상이 맞습니다. 다만 그 처리는 dist-upgrade 이후에 pve8to9가 시키는 시점에 하는 것이 맞습니다. 이 시점에 미리 지우면 bootctl이 사라져 점검 자체가 곤란해지므로, 스크립트가 알려준 순서를 그대로 존중하기로 했습니다.
APT 레포지토리를 Trixie로 전환하기
준비와 점검이 끝났으면 레포지토리를 Trixie로 바꿉니다. 먼저 시스템이 최신 8.4 패키지 상태인지 다시 확인한 뒤, Debian 베이스 레포와 Proxmox 레포의 bookworm을 trixie로 치환합니다.
apt update
apt dist-upgrade
pveversion # 8.4.1 이상 확인
sed -i 's/bookworm/trixie/g' /etc/apt/sources.list
sed -i 's/bookworm/trixie/g' /etc/apt/sources.list.d/*.list
치환 후에는 남아있는 bookworm 항목이 없는지 반드시 확인합니다. 하나라도 남아있으면 그 레포에서 가져오는 패키지가 업그레이드되지 못해 의존성이 꼬일 수 있습니다.
grep -r bookworm /etc/apt/sources.list /etc/apt/sources.list.d/
아무것도 출력되지 않아야 정상입니다. 만약 bookworm 전용 레포가 남아 있다면 해당 줄 맨 앞에 #을 붙여 주석 처리합니다. 구독 키가 없어 no-subscription 레포를 쓴다면 enterprise 레포는 비활성화되어 있어야 하며, 둘을 혼용하면 안 됩니다. PVE 9는 새로운 deb822 형식(.sources 파일)을 권장하므로, 불안하다면 웹 UI의 Node → Repositories 패널에서 최종 상태를 눈으로 확인하는 것도 좋은 방법입니다. 마지막으로 apt update로 인덱스를 갱신하고 에러가 없는지 봅니다. 이 단계에서 에러가 보인다면 레포 설정이 잘못된 것이므로, dist-upgrade로 넘어가기 전에 반드시 먼저 해결해야 합니다.
dist-upgrade 실행과 설정 파일 머지 판단
이제 본 작업입니다. 반드시 screen이나 tmux 안에서 실행합니다.
apt dist-upgrade
이 단계의 소요 시간은 루트 파일시스템의 IOPS와 대역폭에 크게 좌우됩니다. 느린 HDD라면 한 시간 가까이 걸릴 수도 있고, SSD라면 몇 분 안에 끝납니다. 진행 중 apt-listchanges 화면이 뜨면 q로 빠져나오면 되고, 서비스 재시작 여부를 물으면 확신이 없을 때는 기본값을 택합니다. 어차피 마지막에 재부팅하면서 모든 서비스가 깨끗하게 다시 뜨기 때문입니다.
가장 신경 써야 할 부분은 설정 파일 머지 질문입니다. 패키지가 새 버전의 기본 설정 파일을 들고 오는데, 현재 파일과 다르면 어느 쪽을 쓸지 묻습니다. 직접 수정한 적 없는 파일은 maintainer 버전(Y)을 받는 게 일반적이지만, Proxmox가 자기 환경에 맞게 손댄 파일은 현재 버전(N)을 유지해야 하는 경우가 있습니다. 확신이 서지 않을 때는 D를 눌러 차이(diff)를 먼저 확인하는 습관이 실수를 막아줍니다. 제가 실제로 마주친 두 가지 사례를 그대로 옮기겠습니다.
첫 번째는 systemd-boot 훅 파일입니다.
Configuration file '/etc/initramfs/post-update.d/systemd-boot'
==> Modified (by you or by a script) since installation.
==> Package distributor has shipped an updated version.
What would you like to do about it ? Your options are:
Y or I : install the package maintainer's version
N or O : keep your currently-installed version
D : show the differences between the versions
Z : start a shell to examine the situation
The default action is to keep your current version.
*** systemd-boot (Y/I/N/O/D/Z) [default=N] ?
이건 N(현재 버전 유지)으로 두었습니다. 이 파일은 proxmox-boot-tool이 관리하는 부팅 구성과 얽힌 훅이고, 어차피 systemd-boot 메타패키지는 업그레이드 후 정리될 예정이었습니다. 제거될 패키지의 설정을 굳이 maintainer 버전으로 덮어, 그 사이의 재부팅에서 부팅 구성이 흔들릴 위험을 만들 이유가 없었습니다. 기본값이 N이므로 그냥 엔터를 눌러도 됩니다.
두 번째는 /etc/lvm/lvm.conf인데, 이 사례가 diff를 보는 습관의 중요성을 잘 보여줍니다.
Configuration file '/etc/lvm/lvm.conf'
==> Modified (by you or by a script) since installation.
==> Package distributor has shipped an updated version.
*** lvm.conf (Y/I/N/O/D/Z) [default=N] ?
"건드린 적 없는데 왜 Modified지?"라고 의아할 수 있지만, Proxmox 패키지 스크립트가 lvm.conf를 자기 환경에 맞게 손대기 때문에 사용자가 직접 만진 적 없어도 이 메시지는 거의 항상 뜹니다. 즉 "by you"가 아니라 "by a script"인 경우입니다. 여기서는 곧장 답하지 말고 D를 눌러 차이를 확인하는 것이 안전합니다. 제 경우 대부분의 차이는 주석 문구 수정이나 오타 교정 같은 무해한 것이었지만, diff 맨 끝에서 성격이 다른 블록을 발견했습니다.
-devices {
- # added by pve-manager to avoid scanning ZFS zvols and Ceph rbds
- global_filter=["r|/dev/zd.*|","r|/dev/rbd.*|"]
-}
-로 시작한다는 것은 이 줄들이 현재 제 버전에는 있지만 maintainer 새 버전에는 없다는 뜻입니다. 즉 Y를 누르면 이 블록이 사라집니다. 주석이 친절히 설명하듯, 이것은 pve-manager가 ZFS zvol(/dev/zd.*)과 Ceph rbd(/dev/rbd.*)를 LVM이 스캔하지 않도록 자동으로 넣은 PVE 전용 필터입니다. 이게 사라지면 LVM이 가상 디스크 장치들을 불필요하게 스캔하면서 경고를 내거나 동작이 꼬일 수 있습니다. 그래서 이 파일은 N(현재 버전 유지)을 택해 PVE 전용 필터를 보존했습니다. 놓치는 것은 무해한 주석 수정뿐이라 잃을 게 없는 선택이었습니다. 만약 diff를 보지 않고 "수정한 적 없으니 maintainer 버전"이라는 일반론만 따랐다면 놓쳤을 부분입니다.
두 사례의 교훈은 같습니다. "Modified by a script"는 대개 사용자가 아니라 Proxmox가 손댄 것이고, 확신이 서지 않으면 D로 diff를 먼저 보는 한 번의 수고가 메이저 업그레이드의 안전을 좌우합니다.
재부팅과 업그레이드 검증
dist-upgrade가 성공적으로 끝나면 재부팅합니다. 이미 6.x 커널을 쓰고 있었더라도 반드시 재부팅해야 합니다. 업그레이드된 커널이 PVE 9의 새 컴파일러와 ABI 버전으로 재빌드되었기 때문에, 새 커널로 부팅해야 나머지 시스템과의 호환성이 보장됩니다.
reboot
재부팅 후 다시 접속해보니 새 커널로 올라와 있었습니다.
Linux proxmox 7.0.12-1-pve #1 SMP PREEMPT_DYNAMIC PMX 7.0.12-1 (2026-06-09T21:07Z) x86_64
PVE 9가 처음 출시됐을 때는 6.14 커널이 기본이었지만, 이후 마이너 업데이트를 거치며 7.0 계열 커널로 올라갔습니다. 빌드 날짜가 최신인 것을 보면 최신 PVE 9.x 커널을 제대로 받았다는 뜻이라, 이것만으로도 업그레이드가 정상적으로 진행됐음을 가늠할 수 있었습니다.
이제 업그레이드가 실제로 완료됐는지 확정 짓는 검증입니다. 가장 확실한 방법은 pve8to9 --full을 다시 돌리는 것입니다.
pveversion -v | head -1 # pve-manager 버전 확인
uname -r # 커널 버전 확인
systemctl --failed # 실패한 서비스 확인
pve8to9 --full # 최종 점검
검증 결과는 깔끔했습니다. 버전과 커널이 모두 올바르게 올라왔고, 실패한 서비스도 없었습니다.
proxmox-ve: 9.2.0 (running kernel: 7.0.12-1-pve)
UNIT LOAD ACTIVE SUB DESCRIPTION
0 loaded units listed.
systemctl --failed에서 아무 유닛도 나오지 않는다는 것은 모든 서비스가 정상 기동했다는 뜻입니다. pve8to9 --full의 최종 요약은 다음과 같았습니다.
= SUMMARY =
TOTAL: 40
PASSED: 33
SKIPPED: 7
WARNINGS: 0
FAILURES: 0
WARNINGS: 0, FAILURES: 0. 업그레이드 전 1개였던 경고(실행 중인 게스트)도 사라졌습니다. 그리고 가장 신경 쓰였던 부트로더 항목이 이번에는 이렇게 통과했습니다.
INFO: Checking bootloader configuration...
PASS: bootloader packages installed correctly
업그레이드 전에 "still needed for bootctl"이라며 미뤄졌던 그 항목이 깔끔하게 정리된 것입니다. 결과적으로 부트로더 관련 패키지가 올바르게 설치되어, systemd-boot 메타패키지를 따로 손으로 제거할 필요조차 없었습니다. 사전에 부트로더 구성을 정확히 파악하고 "시점이 될 때까지 건드리지 않는다"는 원칙을 지킨 것이 그대로 보상으로 돌아온 셈입니다.
검증을 마쳤다면 웹 UI(:8006)에 접속해 강력 새로고침(Ctrl+Shift+R)으로 캐시를 비우고, VM들을 다시 켜서 정상 부팅과 디스크 접근을 눈으로 확인합니다. 브라우저 캐시를 비우지 않으면 구버전 UI 자원이 남아 화면이 깨져 보일 수 있으므로 이 단계를 빠뜨리지 않는 것이 좋습니다. 참고로 점검 스크립트가 옛 포맷의 그래프 데이터(RRD) 파일 6개가 있다는 INFO 메시지를 남겼는데, 과거 통계 표시용일 뿐이고 필요 없으면 지워도 되는 정보성 안내입니다. 경고도 실패도 아니므로 무시해도 무방합니다.
업그레이드 이후 게스트 디스크 확장하기
업그레이드를 마친 김에 게스트 VM의 디스크 용량도 늘렸습니다. CPU와 Memory는 콘솔에서 편집하면 재부팅 후에 바로 작업되지만, 디스크 용량은 게스트에서의 작업이 필수적이라서 별도로 정리해봤습니다. 이 작업은 업그레이드와 직접 관련은 없지만, "스토리지 정리"라는 같은 흐름에서 함께 처리하기 좋습니다.
게스트 파일시스템은 호스트 스토리지와 별개입니다. 호스트 스토리지가 어떤 종류이든 게스트 안의 파일시스템은 그 게스트에 설치된 종류를 따릅니다. 제 경우 게스트 내부 파일시스템은 ext4였습니다. 호스트 쪽 스토리지 종류만 보고 게스트도 같을 것이라 지레짐작하면 엉뚱한 확장 명령을 쓰게 되므로, 게스트 안에서 직접 확인하는 것이 안전합니다.
디스크 확장은 두 겹으로 이루어집니다. 먼저 Proxmox에서 디스크 "크기 자체"를 키우고, 그다음 게스트 OS 안에서 파티션과 파일시스템을 그 크기에 맞게 확장합니다. 첫 번째만 하고 두 번째를 빠뜨리면 디스크는 커졌는데 OS는 여전히 옛날 크기로 봅니다.

Proxmox에서는 웹 UI의 VM → Hardware → 디스크 선택 → Disk Action → Resize로 키웁니다. 입력값은 목표 크기가 아니라 추가할 증분이라는 점에 주의합니다. 예를 들어 500G를 1T로 만들려면 목표값 1000이 아니라 증분 524를 입력합니다. 늘리기만 가능하고 줄이는 것은 불가능하며, VM이 켜진 상태에서도 작업할 수 있습니다. CLI로는 qm resize <vmid> <disk> +<크기>G 형태입니다.
디스크를 키운 뒤 게스트(Debian)에 접속해 현재 상태를 봅니다.
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 1T 0 disk
|-sda1 8:1 0 3M 0 part
|-sda2 8:2 0 124M 0 part /boot/efi
`-sda3 8:3 0 499.9G 0 part /
/dev/sda3 ext4 492G 27G 446G 6% /
디스크 sda는 이미 1T로 잡혀 있는데(Proxmox에서 Resize는 끝난 상태), 파티션 sda3은 아직 499.9G에 머물러 있습니다. 즉 디스크 끝에 약 500G의 빈 공간이 생겼지만 파티션과 파일시스템이 아직 그걸 흡수하지 못한 상태입니다. 그리고 df -hT에서 파일시스템이 ext4임이 명확히 드러납니다. 확장 명령은 파일시스템 종류에 따라 다르므로, 이 확인이 선행되어야 합니다.
ext4는 다음 순서로 확장합니다. 모든 단계가 마운트된 채로(온라인) 가능하며, 루트 파티션이라도 언마운트할 필요가 없습니다.
sudo apt install cloud-guest-utils # growpart 제공
sudo growpart /dev/sda 3 # 파티션을 디스크 끝까지 확장
sudo resize2fs /dev/sda3 # ext4 파일시스템 확장
여기서 가장 흔한 실수는 growpart /dev/sda 3에서 디스크명과 파티션 번호 사이의 공백을 빠뜨리는 것입니다. /dev/sda3처럼 붙여 쓰면 안 되고 /dev/sda 3처럼 띄워야 합니다. growpart는 디스크 경로와 파티션 번호를 별개의 인자로 받기 때문입니다.
확장 후 df -hT /로 확인하면 루트 파일시스템이 약 1008G로 늘어나 있었습니다. "1T로 키웠는데 왜 1008G지?"라는 의문이 들 수 있는데, 이는 단위 차이와 오버헤드 때문입니다. Proxmox의 1T는 보통 1024 GiB를 의미하고, 거기서 EFI 파티션(124M)과 BIOS boot 파티션(3M), 그리고 ext4 메타데이터와 예약 공간이 조금씩 빠지면 루트 실사용 가능량이 1008G 안팎으로 찍힙니다. 즉 잘못된 것이 아니라 정상적으로 끝났다는 신호입니다. 500G가 안 되던 공간이 1008G로 늘었고, 기존 데이터(Used 27G)도 그대로 유지됐습니다.
마치며
단일 노드 + 외부 스토리지 분리 + Ceph/PBS 없는 구성에서, PVE 8.4에서 9.2.0으로의 인플레이스 업그레이드는 큰 사고 없이 마무리됐습니다. 돌이켜보면 이번 업그레이드에서 결과를 가른 것은 명령 자체가 아니라 몇 가지 판단이었습니다.
첫째, 부트로더를 섣불리 건드리지 않은 것입니다. bootctl status와 proxmox-boot-tool status로 실제 부팅 방식을 먼저 확인하고, pve8to9가 "아직 손대지 말라"고 알려준 시점을 존중했습니다. 그 결과 systemd-boot 메타패키지를 수동으로 제거할 필요조차 없이 부트로더가 깔끔하게 정리됐습니다. 둘째, 설정 파일 머지에서 diff를 먼저 본 것입니다. 특히 lvm.conf에서 PVE 전용 global_filter가 사라지는 것을 diff로 확인하고 현재 버전을 유지한 판단은, 그냥 기본값을 눌렀다면 놓쳤을 부분입니다. 셋째, pve8to9를 전 과정에 걸쳐 반복적으로 돌린 것입니다. 이 스크립트는 단순한 통과/실패 표시기가 아니라, 업그레이드의 어느 단계에서 무엇을 해야 하는지 시점에 맞춰 알려주는 안내자에 가까웠습니다.
같은 환경에서 업그레이드를 앞두고 있다면, 백업과 복원 테스트를 가장 먼저 챙기고, pve8to9 --full을 자주 돌리며, 부트로더와 LVM 설정처럼 환경에 따라 갈리는 지점에서는 명령을 베끼기보다 자기 시스템의 실제 구성을 먼저 확인하시길 권합니다. 메이저 업그레이드는 화려한 신기능보다 "사고 없이 끝났는가"로 평가되는 작업이고, 그 안전은 대담한 한 방이 아니라 명령을 치기 전 상태를 한 번 더 확인하는 작은 습관에서 나옵니다. 이 기록이 비슷한 규모로 자체 호스팅 인프라를 운영하시는 분들께 그 한 번의 확인을 떠올리게 하는 참고가 된다면 더할 나위 없겠습니다.