Profile picture

[Linux] Diskless 기반 PXE 시스템 구축하기

JaehyoJJAng2025년 09월 12일

개요

이전 게시글에서 Kickstart 기반의 PXE 시스템을 구축하는 실습을 진행했었습니다 ..!


이번 게시글에서는 디스크리스(diskless) 시스템을 PXE로 어떻게 구축하는지 실습을 진행해보겠습니다.


디스크리스 시스템을 구축하면 다음과 같은 이점이 있습니다.

  • 하드디스크 없이 운영 가능한 씬 클라이언트 시스템 구축 가능
  • 중앙 집중식 관리로 보안 강화 (?)
    • 메인 PXE 서버 --- PXE Client 1, PXE Client 2...

보통 PXE를 도입하는 가장 큰 이유는 여러 대의 서버들에 대해서 OS를 자동으로 설치할 수 있다는 이점 때문이겠죠?


  • PXE로 커널 + initrd (램 디스크)를 받아오고
  • 이후에 Kickstart 등으로 자동 설치 진행

보통 이 순서대로 진행하여 클라이언트의 로컬 디스크에 OS가 설치됩니다.


그런데 위와 같은 목적이 아닌 다른 목적으로 PXE를 도입하는 경우도 있습니다.


  • 디스크리스(Diskless) 형 (thin client / nfs root)

PXE로 커널 + initrd를 불러온 뒤, root 파일 시스템을 NFS, HTTP, iSCSI같은 네트워크 스토리지에서 마운트해서 실행하는 방법입니다.


로컬 디스크에는 아무것도 설치되지 않고, OS 자체가 네트워크를 통해 실행됩니다.

당연히 클라이언트에는 디스크가 따로 장착될 필요도 없겠죠?


그렇다면 왜 Diskless 기반의 Thin Client를 쓰는가?

일반적인 PXE 시스템 구축과는 운영 목적이 아예 다릅니다 ..!


1. 운영 관리 단순화

  • 모든 클라이언트는 네트워크 부팅 -> OS와 애플리케이션은 서버(NFS, iSCSI 등)에 있음.
  • 업데이트, 보안 패치, 프로그램 설치는 클라이언트 개별이 아닌 서버 한 군데 만 하면 됨.
  • 수백 ~ 수천 대 관리가 훨씬 쉬워짐

2. 저비용 Thin Client 환경

  • 클라이언트 PC에 디스크나 고성능 스펙이 필요 없음.
  • 부팅만 가능하면 되고, 실제 데이터/스토리지는 서버에 있음.

3. 보안 및 데이터 중앙 집중

  • 로컬 디스크가 클라이언트에 장착되지 않으니 데이터 유출 위험 감소
  • 모든 데이터는 중앙 서버에 저장됨 -> 백업이나 보안면에 있어서 관리가 용이하겠죠?


제가 근무하는 환경에서도 이러한 Thin Client 기반의 PXE 시스템을 구축하고 운영하고 있기 때문에,

위와 같은 이점이 더 크게 와닿습니다.


PXE 부팅 과정?

결론부터 말하면, PXE 부팅은 2단계로 진행됩니다.

그리고 initrd.img는 NFS라는 "진짜 집"에 들어가기 위한 '임시 열쇠' 입니다.


1. 1차 부팅 (메모리 부팅)

"일단 부팅에 필요한 도구부터 챙기자."

  • 1. 커널 + 램디스크 로드: 클라이언트는 TFTP 서버에서 vmlinuz(커널)와 initrd.img(램디스크)를 다운로드해 자신의 RAM에 올립니다.
  • 2. 미니 OS 부팅: 커널이 initrd.img의 압축을 풀어 메모리상에 펼칩니다. 이 initrd.img는 사실 미니 OS인거죠. 지금 클라이언트는 100% RAM에서만 동작하는 이 "미니 OS"로 부팅된 상태입니다.
  • 3. 임무 확인: 이 미니 OS(Dracut 환경)는 pxelinux.cfg/defaultappend 라인을 읽고 자신의 임무(NFS 경로, IP 설정 등)를 확인합니다!

2. '진짜 OS'로 전환 (NFS 부팅)

NFS 마운트

램디스크의 미니 OS는 1단계에서 챙긴 도구(NFS 모듈)를 사용해, append 라인에 적힌 NFS 경로(...:/nfs/rocky8_data)를 임시 폴더(예: /sysroot)에 연결(마운트)합니다.


switch_root (핵심!)

NFS 연결이 성공하면, 미니 OS는 자신의 임무를 완수했습니다. 이제 커널에게 외칩니다. "이제부터 진짜 루트(/)는 램디스크가 아니라, 저기 연결된 NFS 폴더입니다!"


제어권 이양

커널은 OS의 중심(루트)을 램디스크에서 NFS 폴더로 전환합니다. 이 순간, 램디스크(initrd.img)는 메모리에서 사라집니다.


2차 부팅 시작

이제 클라이언트의 루트(/)는 NFS 서버의 OS 데이터입니다. 커널은 이 디렉터리 안에 있는 **"진짜 OS"**의 첫 번째 프로세스(/sbin/init 또는 systemd)를 실행시킵니다.


'열쇠'는 아무거나 써도 되나요?

여기서 한 가지 의문이 생깁니다.

"그럼 initrd.img(미니 OS)는 CentOS 6이든 7이든 아무거나 써도, 결국 NFS에 있는 Rocky 8로 부팅되는 거 아닌가요?"


정답은 '절대 아닙니다!'입니다.

vmlinuzinitrd.img절대 분리해서 생각할 수 없는 '하나의 세트' 입니다.


이해하기 쉬운 비유를 들어보죠.

  • vmlinuz (커널): 2025년형 최신 '자동차 엔진' (예: Rocky 8 커널 4.18)
  • initrd.img (램디스크): 그 엔진 전용 '시동 모터와 연료펌프' (커널 4.18용 드라이버와 유틸리티가 담김)
  • nfsroot=... (NFS OS): 시동이 걸린 후 차가 달려야 할 '고속도로와 도시' (Rocky 8 시스템)

만약 1990년형 '시동 모터'(CentOS 6 initrd.img)를 가져와서 2025년형 '엔진'(Rocky 8 vmlinuz)에 연결하면 어떻게 될까요? 규격이 맞지 않아 시동조차 걸리지 않을 겁니다. (커널 패닉!)


왜 호환이 불가능한가?

  1. 커널 모듈 불일치: initrd.img 안에는 vmlinuz가 필요로 하는 핵심 드라이버(.ko 파일)가 들어있습니다. 이 모듈은 커널 버전과 100% 일치해야만 로드될 수 있습니다. CentOS 6의 커널(2.6.x) 모듈은 Rocky 8 커널(4.18.x)에서 인식조차 되지 않습니다.
  2. 드라이버 부재: CentOS 6의 램디스크에는 최신 하드웨어(네트워크 카드 등) 드라이버가 없습니다. 1단계 부팅에서 네트워크조차 잡지 못하고 실패합니다.
  3. 유틸리티 비호환: switch_root 과정이나 systemd로 제어권을 넘기는 방식 등, OS 부팅을 처리하는 내부 유틸리티가 구형 OS와 최신 OS는 완전히 다릅니다.

결론 및 핵심 요약

PXE Diskless 환경을 구축할 때 다음 규칙은 반드시 지켜야 합니다.

  1. vmlinuzinitrd.img는 부팅하려는 NFS OS와 동일한 버전에서 가져온 '한 세트'여야 합니다.
    • Rocky 8.5를 NFS로 부팅하고 싶다면?
    • vmlinuzinitrd.imgRocky 8.5의 해당 커널 버전에서 추출해야 합니다.
  2. initrd.img의 역할은 '열쇠'입니다.
    • 네트워크를 연결하고 NFS를 마운트하여 '진짜 OS'로 제어권을 넘겨주는 '도우미' 역할만 하고 사라집니다.
  3. -no-hostonly 옵션을 잊지 마세요.
    • dracut으로 initrd.img를 생성할 때 이 옵션을 사용해야, 특정 서버에 종속되지 않고 다양한 클라이언트에서 부팅되는 '범용 열쇠'가 만들어집니다.


Diskless 기반 PXE 서버 구축하기

이제 본격적으로 PXE 서버를 구축해보겠습니다.

실습은 VMWare Workstation에서 진행을 하겠습니다.


1. 환경 설정

필수 구성 요소

  • PXE 서버용 VM (CentOS 7 또는 Rocky 8)
  • 데이터 복제용 깡통 OS VM
  • 클라이언트 테스트용 VM (No disk)
  • 격리된 네트워크 (VMWare의 Host-Only 네트워크 사용)

VMWare의 Host-Only 네트워크 대역은 다음과 같이 설정됩니다.
image

PXE 서버: 192.168.221.1/24
DHCP 범위: 192.168.221.128 ~ 192.168.221.200

또한, PXE 서버에는 NIC가 두 개 장착이 되어야겠죠?

  • NIC 1: 외부 통신용
  • NIC 2: 내부 통신용 (Host-Only: Gateway 역할)

image


2. 필수 패키지 설치

# EPEL 저장소 추가
sudo yum install -y epel-release

# 필수 패키지 설치
sudo yum install -y dhcp tftp tftp-server syslinux xinetd nfs-utils

3. DHCP 서버 설정

DHCP 서버 측에서 PXE 부팅에 필요한 부팅 정보를 제공해야 합니다.

# /etc/dhcp/dhcpd.conf
default-lease-time 600;           # 기본 IP 임대 시간 (10분)
max-lease-time 7200;             # 최대 IP 임대 시간 (2시간)
authoritative;                   # 이 서버가 해당 네트워크의 공식 DHCP 서버임을 선언

subnet 192.168.221.0 netmask 255.255.255.0 {
   range dynamic-bootp 192.168.221.128 192.168.221.200;  # IP 할당 범위
   option broadcast-address 192.168.221.255;          # 브로드캐스트 주소
   option routers 192.168.221.1;                      # 게이트웨이 (PXE 서버)
   option domain-name-servers 168.126.63.1;           # DNS 서버
   next-server 192.168.221.1;                         # TFTP 서버 주소 (추가 필요)
   filename "pxelinux.0";                             # 부트로더 파일명
}

4. TFTP 서버 설정

# /etc/xinetd.d/tftp 편집
service tftp
{
    socket_type     = dgram
    protocol        = udp
    wait            = yes
    user            = root
    server          = /usr/sbin/in.tftpd
    server_args     = -s /var/lib/tftpboot
    disable         = no                    # yes를 no로 변경
    per_source      = 11
    cps             = 100 2
    flags           = IPv4
}

5. PXE 부트 환경 구성

PXE 부트에 필요한 파일들을 tftp root 디렉토리에 복사해주도록 합시다!

# 필요한 파일 복사
cp /usr/share/syslinux/pxelinux.0 /var/lib/tftpboot/
cp /usr/share/syslinux/ldlinux.c32 /var/lib/tftpboot

# PXE 설정 디렉토리 생성
mkdir -p /var/lib/tftpboot/pxelinux.cfg

6. PXE 부트 메뉴 설정

default rocky8                          # 기본 선택 메뉴
label rocky8
        kernel rocky8/vmlinuz           # 커널 이미지 경로
        append initrd=rocky8/initrd.img root=nfs:192.168.221.1:/disk/tftpboot/rocky8/root -o rw selinux=0

    # initrd: 초기 램디스크 이미지
    # root=nfs: NFS를 통해 루트 파일시스템 마운트
    # rw: 읽기/쓰기 모드
    # selinux=0: SELinux 비활성화

위 설정이 바로 디스크리스 부팅 방식을 사용하고 있는겁니다! OS를 설치하는 것이 아니라 NFS를 통해 직접 부팅하는 방식이죠.


7. NFS 서버 설정 (디스크리스 부팅용)

# /etc/exports 파일 편집
/disk/tftpboot/rocky8/root 192.168.221.0/24(rw,sync,no_root_squash,no_subtree_check)

# NFS 서비스 시작
sudo systemctl enable --now nfs-server
sudo exportfs -a

8. Rocky 루트 파일시스템 준비

NFS 네트워크 부팅을 클라이언트에서 시도하려면 nfs 마운트 포인트(/disk/tftpboot/rocky8/root)에 당연히 부팅 가능한 OS 데이터가 있어야겠죠?


그렇다면 부팅 가능한 OS 데이터는 어디서 만들어야 할까요?


하기에 작성된 것과 같이 여러 방법이 있지만,

저는 Rocky 8 깡통 OS를 VM으로 생성하여 해당 VM의 데이터를 rsync로 복제해 PXE 서버로 넘겨주도록 하겠습니다!



8-1. Rocky OS 복제하기 (rsync)

먼저 VMWare에서 VM 1개를 추가로 생성해주고 Rocky OS 8.3을 설치해주겠습니다.
image
이미 설치를 진행하였기 때문에 설치 과정은 넘어가겠습니다.


PXE 서버의 경우 다음과 같이 nfs 마운트 포인트가 잡혀있습니다.

showmount -e localhost

Export list for localhost:
/disk/tftpboot/rocky8/root 192.168.221.0/24

Rocky VM에서 PXE 서버의 nfs 경로로 마운트를 잡아주고,

해당 경로에 OS 데이터를 복제하도록 하겠습니다.

# Rocky 깡통 VM에서 진행함.
# mount -t nfs <PXE 서버 IP>:<마운트포인트> <매핑할_로컬경로>
mount -t nfs 192.168.221.1:/disk/tftpboot/rocky8/root /data

rsync로 데이터 복제 시작

rsync -av --exclude={"/proc", "/dev", "/run", "/sys", "/data", "/tmp"} / /data

image nfs 마운트 포인트를 확인해보면 다음과 같이 OS 데이터가 넘어간 것을 볼 수 있습니다.



8-2. OS 데이터만 복제하면 끝?

diskless 클라이언트의 /etc/fstab 파일에는 물리적인 디스크 장치(/dev/sda 등)에 대한 설정이 없고, 대신 시스템 운영에 필수적인 가상 파일 시스템과 NFS 루트 마운트 정보만 포함됩니다.


fstabFile System Table의 약자로,

리눅스 시스템이 부팅될 때 어떤 파일 시스템(파티션, 저장 장치 등)을 어디에, 그리고 어떤 옵션으로 연결(마운트)할지를 미리 기록해둔 설정 파일입니다.


계속해서 언급했듯이 diskless 클라이언트는 하드디스크 없이 네트워크를 통해 부팅합니다.


pxelinux.cfg/default 파일에 작성했던 내용 있죠?

append initrd=rocky8/initrd.img root=nfs:192.168.221.1:/disk/tftpboot/rocky8/root -o rw selinux=0

이 내용은 클라이언트가 부팅할 때 수행할 작업을 지시하는 내용입니다.


여기서 중요한 부분은 root=nfs:... 입니다.

  1. 클라이언트 PC는 PXE를 통해 커널(vmlinuz)과 초기 램디스크(initrd.img)를 다운로드하여 메모리에 올립니다.
  2. 커널이 실행되면서 append에 적힌 파라미터를 읽습니다.
  3. root=nfs:... 설정을 보고, "아, 내 루트 파일 시스템(/)은 물리 디스크가 아니라 192.168.221.1 서버의 /disk/tftpboot/rocky8/root라는 NFS 공유 폴더구나!" 라고 인지합니다.
  4. 클라이언트는 즉시 네트워크를 통해서 해당 NFS 경로를 자신의 루트 파일 시스템(/)으로 마운트합니다.

이 과정은 fstab 파일을 읽기 전에 커널 레벨에서 먼저 일어나게 됩니다.

즉, 루트 파일 시스템을 어디서 가져올지는 fstab이 아니라 커널 부팅 옵션이 결정하는 거죠.


이제 본론입니다.

NFS 서버의 /disk/tftpboot/rocky8/root 디렉터리 안에 있는 etc/fstab 파일은 어떻게 작성해야 할까요?


클라이언트에는 물리 디스크가 없으므로 /dev/sda 같은 장치 설정은 당연히 필요 없습니다.

하지만 시스템이 정상적으로 동작하기 위해서는 꼭 필요한 가상 파일 시스템 들은 마운트해줘야 하죠.


따라서 디스크리스 클라이언트의 fstab 파일은 다음과 같은 모습이 됩니다.

$ vim /disk/tftpboot/rocky8/root/etc/fstab

# 1. NFS 루트 파일 시스템 정보 (선택적이지만 명시적으로 작성하는 것을 권장)
192.168.221.1:/disk/tftpboot/rocky8/root   /   nfs    defaults,vers=4.2,_netdev    0 0

# 2. 시스템 운영에 필수적인 가상 파일 시스템들
proc                    /proc        proc    defaults              0 0
sysfs                   /sys         sysfs   defaults              0 0
devpts                  /dev/pts     devpts  gid=5,mode=620        0 0
tmpfs                   /dev/shm     tmpfs   defaults              0 0
tmpfs                   /run         tmpfs   defaults              0 0

# 만약 swap 공간을 네트워크를 통해 사용하고 싶다면 추가 (예: NFS 파일 스왑)
# /path/on/nfs/swapfile    none         swap    sw,_netdev            0 0
  • 가상 파일 시스템
    • proc, sysfs, devpts, tmpfs 등은 디스크에 존재하는 파일 시스템이 아니라, 커널이 관리하는 메모리 상의 데이터나 프로세스 정보를 파일처럼 보이게 만들어주는 가상 파일 시스템입니다.
    • 이들은 시스템 운영에 반드시 필요하므로 꼭 작성해주어야 합니다. Rocky Linux나 CentOS를 설치하면 이 부분은 기본적으로 fstab에 생성되어 있으니, 기존 내용을 유지하면 됩니다.

8-3. TFTP 커널 / initrd 배포

PXE 클라이언트에 건네줄 vmlinuz(kernel), initrd.img(Ramdisk)는 해당 VM의 /boot 디렉토리에서 가져오면 됩니다.


이 작업은 PXE 서버에서 진행해주세요.


8-1. Rocky OS 복제하기 작업으로 인해 PXE 서버의 nfs 마운트 포인트(/disk/tftpboot/rocky8/root)에 OS 데이터가 넘어왔을겁니다.


/disk/tftpboot/rocky8/root/boot에 있는 커널 및 램디스크 파일을 tftp 루트 디렉토리로 복사해줍시다.

cp /disk/tftpboot/rocky8/root/boot/vmlinuz-* /var/lib/tftpboot/vmlinuz
cp /disk/tftpboot/rocky8/root/boot/initramfs-* /var/lib/tftpboot/initrd.img

반드시 설치 완료된 VM의 /boot 안 커널/ramdisk를 사용해야 합니다.


8-4. initramfs nfs 지원 확인

initrd.img 안에 NFS 모듈이 포함되어 있는지 확인해봅시다.

만약 없는 경우 PXE 부팅 시 root nfs mount가 실패할 수 있습니다.


확인 방법

lsinitrd /disk/tftpboot/rocky8/root/boot/initramfs-*.img | grep nfs

출력되지 않는 경우 rebuild 실행

깡통 VM에서 dracut 명령을 통해 rebuild를 진행한 후, 다시 PXE 서버로 전송해도 됩니다.


하지만 저는 /disk/tftpboot/rocky8/root 디렉토리에 chroot로 루트 파일 시스템을 변경한 후, rebuild 작업을 진행해주도록 하겠습니다.

mkdir -p /disk/tftpboot/rocky8/root/{proc,dev,sys,run}

mount --bind /proc /disk/tftpboot/rocky8/root/proc
mount --bind /dev/disk/tftpboot/rocky8/root/dev
mount --bind /sys/disk/tftpboot/rocky8/root/sys
mount --bind /run/disk/tftpboot/rocky8/root/run

chroot /disk/tftpboot/rocky8/root

# rebuild 진행
dracut -f --add "nfs network base fips" /boot/initramfs-$(uname -r).img $(uname -r)

9. 방화벽 설정

# 필요한 포트 오픈
firewall-cmd --permanent --add-service=dhcp
firewall-cmd --permanent --add-service=tftp
firewall-cmd --permanent --add-service=nfs
firewall-cmd --permanent --add-port=111/tcp
firewall-cmd --permanent --add-port=111/udp
firewall-cmd --permanent --add-port=2049/tcp
firewall-cmd --permanent --add-port=2049/udp
firewall-cmd --reload

VMWare에서 테스트 진행하기

깡통 VM을 다음과 같이 생성해줍시다.

  • Edit → Virtual Network Editor
  • Add Network → VMnet2 (Host-only)
  • Subnet: 192.168.221.0/24
  • DHCP 비활성화

위처럼 생성해주고 부팅해주면 다음과 같이 PXE 부팅이 시작됩니다.
image


의도한대로 Rocky OS 부팅이 진행된 것을 볼 수 있습니다!
image


트러블슈팅

1. TFTP open timeout

방화벽 차단 or 서비스 비활성화 이슈

# TFTP 서비스 확인
systemctl status tftp

# 방화벽 확인
firewall-cmd --list-all

# SELinux 확인
getenforce

2. Permission denied while mounting NFS

# NFS exports 확인
exportfs -v

# 권한 설정 확인
chmod 755 /var/lib/tftpboot/centos7/root

3. DHCP 미응답 이슈

# DHCP 설정 검증
dhcpd -t -cf /etc/dhcp/dhcpd.conf
# 네트워크 인터페이스 확인
ip addr show

4. /var/lib/tftpboot/pxelinux.cfg/default 파일에서 initrd.img 권한 오류 문제 발생

# 오류 내용
Loading rocky8/initrd.img ...failed: No such file or directory 

# 해결 방법
# initrd.img 파일의 권한을 644로 올려주면 됨.
chmod 644 initrd.img

5. kernel, ramdisk, root file system 불일치 시 커널 패닉 문제 발생함.

  • vmlinuz-4.18.0-553.el8_10.x86_64
  • initramfs-4.18.0-553.el8_10.x86_64.img

위 두 파일은 동일한 버전임.

하지만 커널 및 램 디스크 버전 불일치 시 PXE 부팅 도중 커널 패닉 문제가 발생함

    Tag -

Loading script...