RHEL 고급 #1 부팅 프로세스 — GRUB2, dracut, 복구 모드

10 분 소요

RHEL 고급 시리즈를 부팅 프로세스로 시작하겠습니다. 평소에는 전원만 누르면 알아서 로그인 프롬프트가 뜨니 부팅 단계는 거의 의식하지 않습니다. 그러다 한 번 부팅이 멈추거나, 커널 옵션을 바꿔야 하거나, root 비밀번호를 잊어버린 머신을 살려야 할 때, “전원 → 로그인” 사이에 무엇이 일어나는지 모르면 손을 못 댑니다. 이번 글은 그 사이를 단계별로 분해하고, 각 단계에서 잘못됐을 때 어떻게 들어가서 고치는지까지 정리하겠습니다.

RHEL 고급 시리즈에서 이번 글의 위치:

  • #1 부팅 프로세스 — GRUB2, dracut, 복구 모드 ← 이번 글
  • #2 커널 튜닝 — sysctl, tuned, kdump
  • #3 성능 분석 — sar, top/htop, iostat, vmstat, perf
  • #4 SELinux 고급 — 정책 작성, audit2allow
  • #5 보안 강화 — auditd, OpenSCAP, FIPS
  • #6 Subscription / Satellite / Insights
  • #7 Cockpit으로 GUI 관리와 web console

RHEL 9 부팅의 전체 흐름 #

전원이 들어오면 다음 다섯 단계가 순서대로 진행됩니다.

부팅 5단계
1. 펌웨어 (UEFI 또는 BIOS)
       │  ESP (EFI System Partition)에서 부트로더 실행
2. GRUB2 (부트로더)
       │  /boot의 커널 + initramfs를 메모리에 적재
3. 커널 (vmlinuz) + initramfs
       │  필수 드라이버로 진짜 root 파일시스템 mount
4. systemd (PID 1)
       │  default.target까지 unit 의존성 트리 따라 시작
5. 로그인 프롬프트 (multi-user.target / graphical.target)

각 단계는 다음 단계에 딱 한 가지만 넘겨주는 구조입니다. 펌웨어는 부트로더 위치만 알면 되고, GRUB2는 커널과 initramfs만 메모리에 올리면 끝입니다. 커널은 systemd를 PID 1로 띄우면 자기 일이 끝나고, 그 뒤로는 systemd의 영역입니다. 단계를 분리해서 보면 어디서 멈췄는지 진단하기 훨씬 쉬워집니다.

1단계 — UEFI/BIOS #

요즘 RHEL 9 머신은 거의 다 UEFI 부팅입니다. UEFI 펌웨어는 시스템 디스크의 EFI System Partition (ESP) 을 찾아서 그 안의 부트로더 실행 파일을 직접 호출합니다.

UEFI 부팅인지 확인
$ ls /sys/firmware/efi
config_table  efivars  fw_platform_size  fw_vendor  ...

# 디렉터리가 존재하면 UEFI, 없으면 레거시 BIOS

ESP는 보통 /boot/efi에 mount 됩니다.

ESP 마운트와 GRUB2 EFI 바이너리
$ mount | grep efi
/dev/nvme0n1p1 on /boot/efi type vfat (...)

$ ls /boot/efi/EFI/redhat/
BOOTX64.CSV  fonts  grub.cfg  grubx64.efi  shimx64.efi

shimx64.efi가 펌웨어가 처음 호출하는 파일입니다. Secure Boot 환경에서는 shim이 Microsoft가 서명한 신뢰 체인 안에서 GRUB2 (grubx64.efi)의 서명을 검증한 뒤 GRUB2를 띄우는 역할을 합니다. RHEL의 Secure Boot 흐름이 깔끔하게 동작하는 이유가 여기에 있습니다.

UEFI 펌웨어가 어느 부트로더를 띄울지는 NVRAM의 boot entry에 적혀 있습니다. efibootmgr로 확인합니다.

UEFI boot entry 확인
$ sudo efibootmgr -v
BootCurrent: 0001
Timeout: 0 seconds
BootOrder: 0001,0002,0000
Boot0001* Red Hat Enterprise Linux  HD(1,GPT,...)/File(\EFI\redhat\shimx64.efi)
Boot0002* UEFI: USB ...

순서를 바꾸거나 항목을 추가/삭제할 때도 같은 명령을 씁니다. Live USB로 들어가서 efibootmgr -c로 부트 항목을 직접 만드는 일이 GRUB2가 망가졌을 때의 마지막 수단이 됩니다.

2단계 — GRUB2 #

GRUB2 (GRand Unified Bootloader 2)가 하는 일은 한 줄로 요약됩니다. /boot에서 커널 이미지(vmlinuz)와 initramfs를 메모리에 올리고 커널에 인자를 넘긴 뒤 제어를 넘긴다.

/boot 안의 부트 자산
$ ls /boot
config-5.14.0-...el9.x86_64
initramfs-5.14.0-...el9.x86_64.img
vmlinuz-5.14.0-...el9.x86_64
loader/
grub2/

grub.cfg는 직접 편집하지 않는다 #

GRUB2의 메뉴와 부팅 옵션이 들어 있는 파일은 두 가지가 있습니다. UEFI 환경이면 /boot/efi/EFI/redhat/grub.cfg, 레거시 BIOS 면 /boot/grub2/grub.cfg. 둘 다 자동 생성 파일 이라 직접 손대지 않습니다.

grub.cfg 생성
# UEFI
$ sudo grub2-mkconfig -o /boot/efi/EFI/redhat/grub.cfg

# 레거시 BIOS
$ sudo grub2-mkconfig -o /boot/grub2/grub.cfg

grub2-mkconfig가 보고 만드는 입력은 다음 두 곳입니다.

  • /etc/default/grub — 전역 기본값 (timeout, 기본 커널 인자 등)
  • /etc/grub.d/ — 메뉴 항목을 만드는 셸 스크립트들 (보통 손대지 않음)

/etc/default/grub의 핵심 키 #

/etc/default/grub 예시
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="resume=/dev/mapper/rhel-swap rd.lvm.lv=rhel/root rd.lvm.lv=rhel/swap rhgb quiet"
GRUB_DISABLE_RECOVERY="true"
GRUB_ENABLE_BLSCFG=true
의미
GRUB_TIMEOUT메뉴 대기 시간 (초). 0이면 메뉴를 보여주지 않음
GRUB_DEFAULTsaved 면 마지막 부팅 항목이 기본. 숫자면 해당 인덱스
GRUB_CMDLINE_LINUX커널이 받을 인자 — 모든 부팅 항목에 공통 적용
GRUB_ENABLE_BLSCFGBLS (Boot Loader Spec) 사용 여부. RHEL 9 기본 true

GRUB_CMDLINE_LINUXquiet를 빼고 console=tty0 같은 옵션을 넣으면 부팅 메시지가 화면에 그대로 흐릅니다. 부팅이 어디서 멈추는지 추적할 때 쓰는 첫 번째 카드입니다.

수정한 뒤 반드시 grub2-mkconfig로 다시 생성해야 반영됩니다.

grubby — 한 줄로 커널 인자 추가 #

GRUB_CMDLINE_LINUX를 직접 편집하고 grub2-mkconfig를 도는 흐름이 번거로우면 grubby 한 줄로 끝낼 수 있습니다. 모든 BLS 항목에 동일하게 적용 됩니다.

grubby 사용
# 모든 커널에 인자 추가
$ sudo grubby --update-kernel=ALL --args="audit=1"

# 인자 제거
$ sudo grubby --update-kernel=ALL --remove-args="quiet"

# 현재 부팅된 커널의 인자 확인
$ sudo grubby --info=$(grubby --default-kernel)

운영에서 권장하는 흐름입니다. /etc/default/grub 직접 편집은 정말 전역 옵션을 바꿀 때만 쓰고, 평소 커널 파라미터 조정은 grubby로.

BLS — Boot Loader Specification #

RHEL 9가 기본으로 쓰는 메뉴 관리 방식입니다. 부팅 항목 하나당 /boot/loader/entries/ 안에 한 파일씩 둡니다.

BLS 항목
$ ls /boot/loader/entries/
6a5f...77a-5.14.0-...el9.x86_64.conf
6a5f...77a-0-rescue.conf

$ cat /boot/loader/entries/6a5f...77a-5.14.0-...el9.x86_64.conf
title Red Hat Enterprise Linux (5.14.0-...el9.x86_64) 9.4 (Plow)
version 5.14.0-...el9.x86_64
linux /vmlinuz-5.14.0-...el9.x86_64
initrd /initramfs-5.14.0-...el9.x86_64.img
options root=/dev/mapper/rhel-root ro resume=... rhgb quiet
grub_users $grub_users
grub_arg --unrestricted
grub_class rhel

커널을 새로 설치하면 kernel-install 훅이 자동으로 BLS 항목을 추가합니다. grubby가 수정하는 대상도 결국 이 파일들입니다.

3단계 — 커널과 initramfs (dracut) #

GRUB2가 메모리에 올린 다음 두 가지가 짝을 이뤄 동작합니다.

  • vmlinuz — 실제 커널 이미지
  • initramfs — 커널이 진짜 root 파일시스템을 mount 할 때까지 임시로 쓰는 RAM 디스크

initramfs가 왜 필요한가 #

진짜 root 파일시스템이 LVM 위에 올라가 있거나, RAID 위에 있거나, NFS에 있거나, LUKS로 암호화돼 있다고 합시다. 커널 자체가 그런 모든 케이스에 대응하는 드라이버를 내장하면 거대해지고 보안 패치 주기도 무거워집니다. 그래서 RHEL은 현재 머신이 root를 mount 하는 데 필요한 드라이버만 추려서 임시 RAM 디스크로 묶어둡니다. 그게 initramfs입니다.

부팅 흐름:

  1. 커널이 메모리에서 깨어남
  2. initramfs를 RAM에 풀어서 임시 root (/)로 사용
  3. 그 안의 도구로 LVM 활성화 → 실제 root 파일시스템을 임시로 mount
  4. pivot_root로 진짜 root로 전환
  5. systemd (/sbin/init) 실행

initramfs가 망가지거나 필요한 드라이버가 빠지면 부팅이 3단계에서 멈춥니다. “Cannot find root device” 같은 에러가 그 증상입니다.

dracut — initramfs를 만드는 도구 #

dracut이 모듈식으로 initramfs를 생성합니다.

dracut 기본
# 현재 커널용 initramfs 재생성 (덮어쓰기)
$ sudo dracut --force

# 특정 커널 버전용
$ sudo dracut --force /boot/initramfs-$(uname -r).img $(uname -r)

# 모든 설치된 커널용
$ sudo dracut --force --regenerate-all

언제 다시 만들어야 할까요.

  • root가 올라간 디스크/스토리지 구성을 바꿨을 때 (예: LVM → 일반 파티션)
  • 커널 모듈을 추가했고 부팅 단계부터 필요할 때
  • LUKS 암호화를 새로 활성화/해제했을 때
  • /etc/dracut.conf.d/의 설정을 바꿨을 때

initramfs 안 들여다보기 #

안 들어가서 확인
$ lsinitrd /boot/initramfs-$(uname -r).img | less

어떤 모듈이 들어 있는지, 어떤 hook 스크립트가 어떤 순서로 도는지 다 보입니다. 부팅이 initramfs 단계에서 멈출 때 첫 진단 도구입니다.

dracut 모듈 설정 #

/etc/dracut.conf.d/*.conf에 단편적인 설정을 적습니다.

/etc/dracut.conf.d/network.conf 예시
add_dracutmodules+=" network "
omit_dracutmodules+=" plymouth "

add_dracutmodules는 강제 포함, omit_dracutmodules는 강제 제외입니다. 양쪽 다 양옆에 공백 이 있는 점에 주의 — 빠뜨리면 다른 모듈 이름과 붙어서 의도와 다른 결과가 나옵니다.

4단계 — systemd가 PID 1로 #

initramfs가 진짜 root로 pivot_root 한 뒤 /sbin/init (실은 /usr/lib/systemd/systemd로의 심볼릭 링크)가 PID 1로 깨어납니다. 그 뒤로는 기초 #4에서 다룬 systemd 영역입니다.

default.target #

systemd는 default.target까지 unit 의존성을 따라 시작합니다. RHEL 서버에서는 보통 multi-user.target이 default입니다.

default target 확인/변경
$ systemctl get-default
multi-user.target

$ sudo systemctl set-default graphical.target
$ sudo systemctl set-default multi-user.target

부팅 시간 분석 #

systemd 단계에서 시간이 어디서 새는지 확인하는 도구가 있습니다.

systemd-analyze
$ systemd-analyze
Startup finished in 2.5s (firmware) + 4.1s (loader) + 3.2s (kernel) + 8.7s (initrd) + 12.4s (userspace) = 30.9s
multi-user.target reached after 12.4s in userspace.

$ systemd-analyze blame
4.512s NetworkManager-wait-online.service
2.103s plymouth-quit-wait.service
1.876s dnf-makecache.service
...

$ systemd-analyze critical-chain
multi-user.target @12.4s
└─sshd.service @11.8s +0.6s
  └─network-online.target @11.7s
    └─NetworkManager-wait-online.service @7.2s +4.5s

blame은 단순히 각 서비스의 시작 시간을 큰 순서로 보여주고, critical-chaindefault target 도달까지의 직렬 의존 경로를 보여줍니다. 부팅이 느릴 때 손을 댈 곳은 critical-chain의 후보 중에 있습니다.

5단계 — 복구 모드와 트러블슈팅 #

부팅이 어딘가에서 멈췄다면 어떻게 들어갈지가 다음 질문입니다. 멈춘 단계에 따라 들어가는 카드가 다릅니다.

rescue.target과 emergency.target #

구조 차이
multi-user.target  ← 평소
rescue.target      ← root 셸. 로컬 파일시스템 mount 됨, 네트워크 안 뜸
emergency.target   ← root 셸. root만 read-only mount, 그 외 거의 아무것도 안 뜸

GRUB 메뉴에서 e를 눌러 부팅 항목을 편집한 뒤, linux ... 줄 끝에 systemd.unit 인자를 추가합니다.

GRUB 편집 — rescue로 들어가기
linux ($root)/vmlinuz-... root=/dev/mapper/rhel-root ro ... systemd.unit=rescue.target

Ctrl+X로 부팅하면 root 셸이 뜹니다. 이 모드에서는 비밀번호를 묻습니다. root 비밀번호를 모르는 상황에는 다음 절차로 넘어갑니다.

root 비밀번호 복구 — rd.break #

GRUB 부팅 항목 편집 화면에서 linux 줄에 다음을 추가합니다.

GRUB 편집 — rd.break
linux ($root)/vmlinuz-... ... rd.break enforcing=0
인자의미
rd.breakinitramfs 단계에서 멈춰서 셸을 띄움. root 비밀번호를 묻지 않음
enforcing=0SELinux Permissive로 부팅. 비밀번호 변경 후 라벨이 깨지는 문제 회피

Ctrl+X로 부팅하면 switch_root:/# 프롬프트가 뜹니다. 진짜 root가 아직 mount만 됐고 pivot_root 직전 상태입니다.

root 비밀번호 변경 절차
switch_root:/# mount -o remount,rw /sysroot
switch_root:/# chroot /sysroot
sh-5.1# passwd
New password: ...
sh-5.1# touch /.autorelabel       # 다음 부팅 때 SELinux 라벨 재설정
sh-5.1# exit
switch_root:/# exit               # 정상 부팅 재개

/.autorelabel을 만들어두면 다음 부팅 때 systemd가 모든 파일의 SELinux 라벨을 다시 부여합니다. 시간이 좀 걸리지만 (몇 분 ~ 십수 분) enforcing=0으로 변경한 /etc/shadow의 라벨이 어긋나는 사고를 막아줍니다. 안 만들면 다음 부팅에서 SSH 로그인 등이 막힐 수 있습니다.

initramfs 단계에서 멈췄을 때 #

“Warning: dracut-initqueue timeout” 같은 메시지에서 멈추면 root 파일시스템을 못 찾는 상황입니다.

체크 순서:

dracut 셸에서
# emergency 셸이 떴다면
dracut:/# cat /proc/cmdline       # 커널 인자 확인 — root=... 가 맞는지
dracut:/# ls /dev/mapper/         # LVM 장치가 보이는지
dracut:/# vgchange -ay            # VG 수동 활성화
dracut:/# blkid                   # 디스크 시그니처 확인

/etc/fstab에 잘못된 UUID 나 디바이스를 적어둔 직후 재부팅하면 가장 흔히 겪는 상황입니다. rescue ISO로 들어가 chroot 한 뒤 /etc/fstab을 고치는 게 표준 복구 절차입니다.

systemd 단계에서 멈췄을 때 #

multi-user.target 직전에서 어떤 서비스가 못 떠서 부팅이 안 끝나는 경우입니다.

다음 부팅에서
# emergency 모드로 부팅 (GRUB 편집 → systemd.unit=emergency.target)
# 또는 정상 부팅 후 분석
$ systemctl list-jobs           # 진행 중/멈춰 있는 job
$ systemctl status              # 전체 상태 트리
$ journalctl -b -1              # 직전 부팅 로그
$ journalctl -b -1 -p err       # 직전 부팅의 에러만

journalctl -b -1-1은 “한 번 전 부팅” 입니다. 이번에 부팅한 로그는 -b 0 또는 그냥 -b. 부팅이 멈춰서 강제로 재부팅한 직후의 진단에서 가장 자주 쓰는 옵션입니다.

흔한 함정 #

  • grub.cfg 직접 편집grub2-mkconfig가 다시 돌면 변경분이 통째로 날아갑니다. 항상 /etc/default/grub 또는 grubby로 수정합니다.
  • 커널 인자 변경 후 grub2-mkconfig 누락/etc/default/grub만 고치고 끝내면 다음 부팅에 반영 안 됩니다. UEFI와 BIOS의 출력 경로가 다른 점도 자주 잊습니다.
  • dracut 재생성 안 함 — root 디스크 구성을 바꿨는데 initramfs를 그대로 두면 부팅이 멈춥니다. 디스크 작업 직후 dracut --force를 습관화합니다.
  • rd.break/.autorelabel 누락 — root 비밀번호를 바꾸고 그냥 부팅하면 SELinux 라벨이 어긋나서 SSH 로그인 등이 막힐 수 있습니다.
  • enforcing=0 잊기rd.break만 쓰고 enforcing=0을 빼면 SELinux가 비밀번호 파일 변경을 거부할 수 있습니다.
  • GRUB timeout 0GRUB_TIMEOUT=0으로 두면 메뉴 자체가 안 떠서 GRUB 편집으로 들어갈 기회가 없어집니다. 운영 머신은 최소 3 ~ 5초 권장.
  • multi-user가 아닌 graphical 기본 — 서버에 X가 설치돼 들어가면 부팅이 GUI까지 기다립니다. 서버는 multi-user.target으로 명시합니다.

기억해 둘 명령 #

작업명령
UEFI 부팅 항목 확인sudo efibootmgr -v
GRUB 메뉴 재생성 (UEFI)sudo grub2-mkconfig -o /boot/efi/EFI/redhat/grub.cfg
커널 인자 추가/제거sudo grubby --update-kernel=ALL --args="..."
현재 커널 인자 확인sudo grubby --info=$(grubby --default-kernel)
initramfs 재생성sudo dracut --force --regenerate-all
initramfs 안 보기lsinitrd /boot/initramfs-$(uname -r).img
default target 확인/변경systemctl get-default / set-default
부팅 시간 분석systemd-analyze blame / critical-chain
직전 부팅 로그journalctl -b -1 -p err

정리 #

  • 부팅은 5단계 — UEFI/BIOS → GRUB2 → 커널+initramfs → systemd → default target. 어디서 멈췄는지를 단계별로 잡으면 진단이 쉬워집니다.
  • GRUB2 설정/etc/default/grub + grubby로 관리. grub.cfg는 자동 생성이라 직접 편집 금지.
  • initramfs — 진짜 root를 mount 하기 전 임시 RAM 디스크. 디스크 구성을 바꿨다면 dracut --force.
  • 복구 모드rescue.target (네트워크 없이 로컬 셸), emergency.target (read-only root 셸). GRUB 편집으로 진입.
  • root 비밀번호 복구rd.break enforcing=0으로 initramfs 셸 → chroot /sysrootpasswd/.autorelabel.

다음 글은 부팅 직후 커널이 어떻게 동작할지를 결정하는 커널 튜닝 입니다. sysctl로 런타임 파라미터를 잡고, tuned 프로파일로 워크로드 별 최적화를 적용하고, kdump로 커널 패닉 시점의 덤프를 받는 흐름까지 한 사이클로 다루겠습니다.

X