개요
Rocky Linux 9 기반 서버에서 dnf update를 돌리던 중 특정 RPM 패키지의 압축 해제가 반복적으로 실패했다.
처음에는 단순한 RPM 패키지나 DNF 캐시 문제로 보였지만, 점검 과정에서 XFS 파일시스템의 메타데이터 손상이 드러났다.
결국 initramfs 환경에서 xfs_repair로 파일시스템을 복구하고, 불완전하게 업데이트된 RPM 패키지의 버전을 다시 맞춰서 해결했다.
1. 최초 증상
오랫동안 사용하지 않던 VM서버를 구동하고 서버에서 일반적인 시스템 업데이트를 수행했다.
sudo dnf -y update
업데이트 대상 중 openssl-devel 패키지를 설치하는 과정에서 다음과 같이 RPM 압축 해제에 실패했다.
Upgrading:
openssl-devel x86_64 1:3.5.5-6.el9_8
Transaction check succeeded
Transaction test succeeded
Running transaction
Upgrading: openssl-devel-1:3.5.5-6.el9_8.x86_64
Error unpacking rpm package openssl-devel-1:3.5.5-6.el9_8.x86_64
Failed:
openssl-devel-1:3.5.1-7.el9_7.x86_64
openssl-devel-1:3.5.5-6.el9_8.x86_64
Error: Transaction failed
Transaction check와 Transaction test까지는 통과하지만, 실제 파일을 기록하는 단계에서 실패하고 있었다.
처음에는 디스크 공간 부족이나 inode 고갈 가능성을 의심하여 확인했다.
df -h
df -i
mount | grep ' / '
하지만 루트 파일시스템의 디스크 사용량은 약 37% 수준이었고, inode 역시 충분했다.
루트 파일시스템은 XFS로 구성되어 있었다.
/dev/mapper/rlm-root on / type xfs (rw,...)
단순한 저장공간 부족 문제는 아니었다.
2. RPM 패키지 무결성 검사
문제가 발생한 openssl-devel 패키지를 확인했다.
rpm -q openssl-devel
rpm -V openssl-devel
당시 설치된 패키지는 다음 버전이었다.
openssl-devel-3.5.1-7.el9_7.x86_64
그런데 rpm -V를 돌리자 많은 파일에서 변경 사항이 발견됐고, 특히 일부 파일에서는 다음 메시지가 나타났다.
missing ... (Structure needs cleaning)
Structure needs cleaning은 단순한 RPM 패키지 손상과는 성격이 다르다.
Linux에서 EUCLEAN에 해당하는 오류이며, 사용 중인 XFS 파일시스템 자체의 메타데이터 이상을 의심할 수 있는 상황이었다.
처음보는 오류라서 섣부르게 진행하기 전에 ChatGPT와 Claude의 도움을 받아 원인 분석을 하고 해결 방안을 모색했다.
이 시점부터 DNF/RPM 문제를 계속 붙잡기보다는 파일시스템 상태를 먼저 확인하는 방향으로 전환했다.
3. 커널 로그에서 XFS 메타데이터 손상 확인
커널 로그를 확인했다.
sudo dmesg -T | grep -Ei 'XFS.*(corrupt|error|repair)|Structure needs cleaning'
다음 오류가 반복적으로 발견됐다.
XFS (dm-0): Metadata corruption detected at xfs_dinode_verify...
XFS (dm-0): Unmount and run xfs_repair
XFS (dm-0): First 128 bytes of corrupted metadata buffer:
커널이 직접 Metadata corruption detected와 Unmount and run xfs_repair를 출력하고 있었기 때문에 XFS 메타데이터 손상으로 판단할 수 있었다. dm-0에 대한 XFS metadata corruption과 xfs_repair 실행 요구가 진단 로그에 반복적으로 기록되어 있었다.
이 상태에서 dnf update를 계속 시도하면 추가 파일 손상이 발생하거나 패키지 상태가 더 꼬일 가능성이 있어서 패키지 작업을 중단했다.
4. ISO 없이 XFS 복구 환경 진입
루트 파일시스템 자체가 손상된 상태이기 때문에, 정상 부팅 상태에서 다음과 같이 실행해서는 안 된다.
xfs_repair /dev/mapper/rlm-root
xfs_repair는 기본적으로 대상 XFS 파일시스템을 마운트 해제한 상태에서 실행해야 한다.
해당 서버는 Proxmox VE에서 동작하는 VM이었고, 별도의 Rocky Linux 설치 ISO를 쓸 수 없는 상태였다.
기존에 사용하던 ISO 파일을 용량을 정리하느라 지워버린 상태였고 대체 방안을 찾아야 했다.
그래서 GRUB의 rd.break를 이용해 initramfs 환경으로 진입했다.
VM을 재부팅하고 GRUB 메뉴에서 현재 Rocky Linux 커널을 선택한 뒤 e 키를 눌러 부팅 옵션을 수정했다.
커널 옵션이 들어있는 linux 행 마지막에 다음 옵션을 추가했다.
rd.break
이후 Ctrl + X로 부팅을 계속하여 다음과 같은 initramfs shell로 진입했다.
switch_root:/#
5. 루트 XFS 마운트 상태 확인
initramfs 환경에서 먼저 LVM 장치를 확인했다.
ls /dev/mapper
결과:
control
rlm-root
rlm-swap
xfs_repair가 사용 가능한지도 확인했다.
xfs_repair -V
당시 환경에서는 다음 버전이 확인됐다.
xfs_repair version 6.4.0
하지만 바로 xfs_repair를 실행하지 않고, 루트 파일시스템의 마운트 여부를 먼저 확인했다.
cat /proc/mounts | grep -E 'rlm-root|dm-0|sysroot'
결과:
/dev/mapper/rlm-root /sysroot xfs ro,relatime,... 0 0
읽기 전용(ro) 상태이기는 했지만 /sysroot에 여전히 마운트되어 있었다.
먼저 마운트를 해제했다.
umount /sysroot
이후 다시 확인했다.
cat /proc/mounts | grep -E 'rlm-root|dm-0|sysroot'
아무 결과도 출력되지 않아 /dev/mapper/rlm-root가 완전히 마운트 해제된 것을 확인했다.
6. xfs_repair -n으로 사전 검사
바로 파일시스템을 수정하기보다는 -n 옵션으로 검사만 먼저 수행했다.
xfs_repair -n /dev/mapper/rlm-root
-n은 실제 파일시스템을 수정하지 않고, xfs_repair가 어떤 작업을 수행할지 확인하는 용도로 쓸 수 있다.
검사 결과 다수의 디렉터리 엔트리와 inode 문제가 발견됐다.
inode ..., would junk entry
entry "EVP_des_cfb.3ossl.gz"
in directory inode ...
points to non-existent inode ...
would rebuild directory inode ...
moving disconnected inodes to lost+found ...
Phase 7 - verify link counts...
No modify flag set, skipping filesystem flush and exiting.
특히 OpenSSL 관련 파일이 존재하지 않는 inode를 참조하고 있었고, 디렉터리 재구성이 필요하다는 결과가 나왔다.
이것으로 DNF에서 openssl-devel 업데이트가 실패했던 현상과 실제 XFS 파일시스템 손상이 연결되어 있음을 확인할 수 있었다.
7. XFS 실제 복구
사전 검사 결과를 확인한 후 실제 복구를 수행했다.
xfs_repair /dev/mapper/rlm-root
복구 과정에서는 다음과 같은 작업이 수행됐다.
clearing inode number in entry at offset ...
entry "EVP_des_ede.3ossl.gz"
references non-existent inode ...
clearing inode number ...
Phase 5 - rebuild AG headers and trees...
Phase 6 - check inode connectivity...
rebuilding directory inode ...
moving disconnected inodes to lost+found ...
Phase 7 - verify and correct link counts...
done
최종적으로:
done
까지 정상적으로 진행됐으며 별도의 fatal error는 발생하지 않았다.
중요한 점은 이번 복구에서 다음 옵션을 사용하지 않았다는 것이다.
xfs_repair -L
-L은 XFS 로그를 강제로 초기화하는 옵션으로, 데이터 손실 가능성이 있으므로 일반적인 첫 번째 복구 방법으로 써서는 안 된다.
이번 경우에는 일반 xfs_repair만으로 정상적으로 복구가 완료됐다.
8. 재부팅 후 XFS 상태 검증
복구 완료 후 시스템을 재부팅했다.
reboot -f
Rocky Linux가 정상적으로 부팅된 후 다시 XFS 오류를 확인했다.
sudo dmesg -T | grep -Ei 'XFS.*(corrupt|error|repair)|Structure needs cleaning'
결과는 아무것도 출력되지 않았다.
추가로 I/O 오류도 확인했다.
sudo dmesg -T | grep -Ei 'I/O error|Buffer I/O|blk_update|critical medium|reset'
출력된 것은 VM 부팅 시 가상 SCSI 장치 초기화에 해당하는 다음 메시지뿐이었다.
sd 0:0:0:0: Power-on or device reset occurred
I/O error, Buffer I/O error 등 실제 블록 장치 오류는 발견되지 않았고, 기존에 발생하던 XFS metadata corruption 메시지도 사라졌다.
파일시스템 복구가 정상적으로 이루어진 것으로 판단했다.
9. 불완전하게 업데이트된 RPM 패키지 복구
파일시스템은 정상화됐지만, 앞서 실패했던 DNF 트랜잭션 때문에 OpenSSL 패키지 버전이 서로 맞지 않는 상태였다.
rpm -qa | grep '^openssl' | sort
당시 상태는 다음과 같았다.
openssl-3.5.5-6.el9_8.x86_64
openssl-devel-3.5.1-7.el9_7.x86_64
openssl-libs-3.5.5-6.el9_8.x86_64
openssl과 openssl-libs는 이미 EL9_8 버전으로 업데이트됐지만, openssl-devel만 기존 EL9_7 버전에 남아 있었다.
때문에 rpm -V openssl-devel에서도 다음 의존성 문제가 나타났다.
Unsatisfied dependencies for openssl-devel-1:3.5.1-7.el9_7.x86_64:
openssl-libs(x86-64) = 1:3.5.1-7.el9_7 is needed
또한 다수의 OpenSSL 헤더 파일에서:
S.5....T. /usr/include/openssl/aes.h
S.5....T. /usr/include/openssl/asn1.h
...
와 같은 무결성 차이가 발견됐다.
파일시스템 손상과 업데이트 실패로 인해 OpenSSL 패키지 그룹이 부분적으로만 업데이트된 상태였던 것이다.
10. DNF로 패키지 버전 동기화
먼저 DNF 캐시를 정리했다.
sudo dnf clean all
sudo dnf makecache
그 후 관련 OpenSSL 패키지를 저장소 기준으로 동기화했다.
sudo dnf distro-sync openssl openssl-libs openssl-devel
동기화 후:
rpm -qa | grep '^openssl' | sort
결과:
openssl-3.5.5-6.el9_8.x86_64
openssl-devel-3.5.5-6.el9_8.x86_64
openssl-libs-3.5.5-6.el9_8.x86_64
세 패키지가 모두 동일한 EL9_8 버전으로 정상화됐다.
마지막으로 패키지 무결성을 확인했다.
rpm -V openssl-devel
아무 결과도 출력되지 않았다.
rpm -V는 검증 과정에서 차이가 발견된 항목을 출력하기 때문에, 아무것도 출력되지 않는 것은 현재 설치된 openssl-devel 파일들이 RPM 데이터베이스가 기대하는 상태와 일치한다는 의미다.
11. 최종 결과
이번 장애는 처음에는 단순한 dnf update 실패로 나타났다.
그러나 실제 조사 결과 다음과 같은 흐름으로 문제가 이어져 있었다.
DNF 업데이트 수행
│
▼
openssl-devel RPM unpack 실패
│
▼
rpm -V 검사
│
├── 다수의 파일 무결성 이상
└── Structure needs cleaning
│
▼
커널 로그 확인
│
▼
XFS Metadata corruption 확인
│
▼
GRUB rd.break
│
▼
initramfs 진입
│
▼
/sysroot 마운트 해제
│
▼
xfs_repair -n
│
▼
inode / directory corruption 확인
│
▼
xfs_repair
│
▼
XFS 메타데이터 복구
│
▼
정상 부팅
│
▼
커널 로그 재검사
│
▼
XFS 오류 없음
│
▼
dnf distro-sync
│
▼
OpenSSL 패키지 버전 정상화
│
▼
rpm -V 정상
핵심 요약
| 문제 | 원인 | 해결 |
|---|---|---|
| RPM unpack 실패 | XFS 메타데이터 손상 | initramfs에서 xfs_repair |
| Structure needs cleaning | 파일시스템 EUCLEAN 오류 | 커널 로그로 XFS 손상 확인 |
| 루트 XFS 복구 불가 | /sysroot 마운트 상태 | rd.break 진입 후 umount |
| OpenSSL 버전 불일치 | 중단된 RPM 트랜잭션 | dnf distro-sync |
| 패키지 무결성 확인 | 부분 업데이트 잔재 | rpm -V 최종 검증 |
정리하며
이번 사례에서 가장 중요한 부분은 DNF 오류 자체만 보고 패키지 관리자를 반복해서 조치하지 않은 것이었다.
특히 다음과 같은 메시지가 나타난다면:
Structure needs cleaning
단순히 파일이 없거나 RPM 데이터베이스가 꼬인 것으로 생각하기보다, 파일시스템 문제 가능성도 확인할 필요가 있다.
이번 경우에는 커널 로그에서:
XFS (dm-0): Metadata corruption detected
XFS (dm-0): Unmount and run xfs_repair
가 확인되면서 XFS 문제임을 확정할 수 있었다.
또한 루트 XFS를 복구할 때는 읽기 전용 여부와 관계없이 마운트 상태에서 바로 xfs_repair를 실행하지 않고, initramfs에서 /sysroot를 완전히 마운트 해제한 다음 xfs_repair -n으로 먼저 상태를 확인하고 실제 복구를 진행했다.
복구 이후에는 파일시스템만 확인하고 끝내지 않고, 손상 당시 중단된 RPM 트랜잭션 때문에 발생한 패키지 버전 불일치까지 dnf distro-sync로 정상화하고 rpm -V로 최종 검증했다.
다만 XFS가 최초에 손상된 근본 원인은 이번 조사만으로 특정하지 못했다. VM의 비정상 종료, PVE 호스트나 스토리지 문제 등 여러 가능성이 있으므로, 동일 증상이 재발한다면 게스트 OS 복구만 반복하기보다 PVE 호스트의 스토리지와 물리 디스크 상태까지 봐야 한다.
멀쩡하던 서버라고 생각했지만, 실은 오래전부터 XFS 손상이 잠재해 있다가 업데이트를 계기로 겉으로 드러난 셈이다.