여러 대에 같은 OS 를 반복 설치할 때 매체를 들고 다니는 대신 네트워크 부팅으로 설치한다. 구성은 세 가지가 맞물린다.
| 요소 | 역할 |
|---|---|
| DHCP | IP 를 주면서 "어느 서버에서 무슨 파일을 받아라" 를 알려 준다 |
| TFTP | 부트로더와 커널·initrd 를 준다. 느리므로 최소한만 올린다 |
| HTTP | 설치 이미지 전체를 준다 |
동작 순서는 다음과 같다.
클라이언트 PXE 부팅
→ DHCP 요청, 부트 파일 위치 수신
→ TFTP 로 부트로더 내려받기
→ 커널 + initrd 로딩
→ HTTP 로 설치 이미지 내려받기
sudo dnf install -y dnsmasq syslinux tftp-server httpd
dnsmasq 하나가 DHCP 와 TFTP 를 모두 맡으므로 구성이 단순하다.
sudo mkdir -p /var/lib/tftpboot/pxelinux.cfg
sudo cp /usr/share/syslinux/pxelinux.0 /var/lib/tftpboot/
sudo cp /usr/share/syslinux/{menu.c32,ldlinux.c32,libutil.c32,libcom32.c32} /var/lib/tftpboot/
menu.c32 는 libutil.c32 와 libcom32.c32 를 필요로 한다. 이 둘을 빠뜨리면 메뉴가 뜨지 않고 멈춘다.
sudo mkdir -p /mnt/iso /var/www/html/rocky
sudo mount -o loop,ro /srv/iso/Rocky-10.1-x86_64-dvd.iso /mnt/iso
sudo cp /mnt/iso/images/pxeboot/vmlinuz /var/lib/tftpboot/
sudo cp /mnt/iso/images/pxeboot/initrd.img /var/lib/tftpboot/
sudo cp -a /mnt/iso/. /var/www/html/rocky/
sudo systemctl enable --now httpd
sudo restorecon -Rv /var/www/html/rocky
restorecon 을 빼면 SELinux 가 enforcing 인 환경에서 httpd 가 파일을 읽지 못해 403 이 난다.
sudo vi /var/lib/tftpboot/pxelinux.cfg/default
DEFAULT menu.c32
PROMPT 0
TIMEOUT 100
MENU TITLE PXE Boot Menu
LABEL rocky
MENU LABEL Install Rocky Linux 10
KERNEL vmlinuz
APPEND initrd=initrd.img inst.repo=http://192.168.0.10/rocky inst.ks=http://192.168.0.10/ks/rocky.cfg
LABEL local
MENU LABEL Boot from local disk
LOCALBOOT 0
inst.ks 를 빼면 대화형 설치 화면이 뜬다. 여러 대에 같은 구성을 넣을 때 kickstart 파일을 만들어 두면 전 과정이 무인으로 진행된다.
local 항목을 반드시 둔다. 설치가 끝난 장비가 다시 PXE 로 부팅해 설치를 되풀이하는 사고를 막는다. 기본 항목도 local 로 두는 편이 안전하다.
sudo vi /etc/dnsmasq.conf
interface=eno1
bind-interfaces
# 기존 DHCP 가 없을 때
dhcp-range=192.168.0.100,192.168.0.200,12h
dhcp-boot=pxelinux.0
enable-tftp
tftp-root=/var/lib/tftpboot
sudo systemctl enable --now dnsmasq
sudo firewall-cmd --permanent --add-service={dhcp,tftp,http}
sudo firewall-cmd --reload
기존 DHCP 서버가 있는 망이라면 IP 배분은 건드리지 않고 부트 정보만 얹는다.
# 주소는 기존 DHCP 가 주고, PXE 정보만 이쪽에서 준다
dhcp-range=192.168.0.0,proxy
dhcp-boot=pxelinux.0
DHCP 두 대가 같은 대역에서 주소를 배분하면 기존 망이 망가진다. proxyDHCP 모드를 쓰거나, 아예 별도 격리망에서 설치 작업을 한다.
pxelinux.0 는 레거시 BIOS 전용이다. UEFI 장비는 GRUB 의 EFI 바이너리를 받아야 한다.
sudo dnf install -y grub2-efi-x64 shim-x64
sudo cp /boot/efi/EFI/rocky/grubx64.efi /var/lib/tftpboot/
sudo cp /boot/efi/EFI/BOOT/BOOTX64.EFI /var/lib/tftpboot/
클라이언트 아키텍처에 따라 다른 파일을 주도록 한다.
dhcp-match=set:efi-x86_64,option:client-arch,7
dhcp-match=set:efi-x86_64,option:client-arch,9
dhcp-boot=tag:efi-x86_64,grubx64.efi
dhcp-boot=tag:!efi-x86_64,pxelinux.0
UEFI 부팅은 별도의 grub.cfg 를 TFTP 루트에 둬야 한다. 메뉴 문법이 syslinux 와 다르다.
Secure Boot 가 켜져 있으면 서명되지 않은 부트로더는 거부된다. 배포판이 제공하는 shim 을 쓰거나 대상 장비에서 Secure Boot 를 끈다.
단계별로 어디서 멈추는지 확인한다.
# DHCP 응답이 나가는가
sudo tcpdump -nn -i eno1 'port 67 or port 68'
# TFTP 요청이 오는가
sudo tcpdump -nn -i eno1 'port 69'
sudo journalctl -u dnsmasq -f
# 파일이 실제로 있는가
ls -l /var/lib/tftpboot/
curl -I http://192.168.0.10/rocky/.treeinfo
| 증상 | 확인할 것 |
|---|---|
PXE-E51: No DHCP or proxyDHCP offers |
DHCP 미동작, 다른 VLAN, relay 미설정 |
PXE-E53: No boot filename received |
dhcp-boot 누락 |
PXE-T01: File not found |
TFTP 루트의 파일명 불일치, SELinux |
| 메뉴가 뜨지 않고 멈춤 | libutil.c32·libcom32.c32 누락 |
| 커널은 뜨는데 설치 화면에서 저장소 오류 | inst.repo URL, httpd 권한, 방화벽 |
수십 대 이상을 반복 설치하고 이미지를 여러 개 관리해야 한다면 직접 구성하는 대신 전용 도구를 검토한다.
| 도구 | 성격 |
|---|---|
| Cobbler | PXE·kickstart 관리 자동화 |
| Foreman | 프로비저닝과 구성 관리 통합 |
| iPXE | HTTP 부팅으로 TFTP 구간을 줄인다 |
| MAAS | Ubuntu 계열 베어메탈 프로비저닝 |