eBPF를 위한 라즈베리파이 커널 빌드 가이드

라즈베리파이 OS에는 이미 최신 커널이 올라가 있고, CONFIG_BPF_SYSCALLCONFIG_BPF_JIT도 기본으로 켜져 있어서 단순한 eBPF 프로그램은 커널을 새로 빌드하지 않아도 로드된다. 문제는 그다음부터다. bpftrace나 최신 BCC 도구 상당수는 BTF(BPF Type Format) 기반 CO-RE로 동작하는데, 라즈베리파이 공식 커널의 기본 설정(bcm2711_defconfig/bcm2712_defconfig)에는 CONFIG_DEBUG_INFO_BTF가 아예 빠져 있고, 유저스페이스 함수를 추적하는 CONFIG_UPROBE_EVENTSrpi-6.6.y 기준으로 명시적으로 꺼져 있다(# CONFIG_UPROBE_EVENTS is not set). 그래서 라즈베리파이에서 본격적인 eBPF 트레이싱 도구를 쓰려면 결국 커널을 직접 빌드해야 하는 상황이 생긴다. 이 글에서는 스톡 커널에 정확히 무엇이 빠져 있는지 확인하고, 그 설정을 켠 라즈베리파이 전용 커널을 빌드·배포하는 과정을 정리한다.

스톡 커널에서 무엇이 빠져 있는가

직접 빌드에 들어가기 전에, 실제로 무엇이 부족한지 라즈베리파이 공식 저장소의 defconfig로 확인할 수 있다.

git clone --depth=1 -b rpi-6.6.y https://github.com/raspberrypi/linux.git
cd linux
grep -E "CONFIG_BPF_SYSCALL|CONFIG_BPF_JIT|CONFIG_DEBUG_INFO_BTF|CONFIG_UPROBE_EVENTS" \
  arch/arm64/configs/bcm2711_defconfig
설정 항목기본 상태의미
CONFIG_BPF_SYSCALL활성화(y)기본 BPF 시스템 콜. 이미 켜져 있어 단순 eBPF 프로그램 로드는 커널 빌드 없이도 된다.
CONFIG_BPF_JIT활성화(y)바이트코드를 네이티브 코드로 JIT 컴파일. 이것도 기본으로 켜져 있다.
CONFIG_DEBUG_INFO_BTFdefconfig에 없음(비활성)BTF 디버그 정보. bpftrace, libbpf 기반 CO-RE 도구가 커널 타입 정보를 읽으려면 필수다.
CONFIG_UPROBE_EVENTS명시적으로 비활성유저스페이스 함수 uprobe 추적에 필요. 이게 꺼져 있으면 애플리케이션 레벨 추적 도구가 동작하지 않는다.

보드에 따라 defconfig 파일이 다르다는 점은 주의해야 한다. Pi 4/400/CM4는 bcm2711_defconfig, Pi 5는 bcm2712_defconfig를 쓴다. 아래 과정은 Pi 4 계열(arm64) 기준으로 정리했고, Pi 5라면 defconfig 이름만 바꿔주면 된다.

빌드 환경 준비

크로스 컴파일 머신(x86_64 데스크톱 등)에서 빌드하는 걸 기준으로 한다. BTF를 생성하려면 dwarves 패키지(pahole 포함)가 반드시 있어야 하는데, 빠뜨리기 쉬운 부분이라 미리 챙겨둔다.

sudo apt update
sudo apt install -y git bc bison flex libssl-dev make gcc \
  gcc-aarch64-linux-gnu dwarves

커널 소스 받기

git clone --depth=1 -b rpi-6.6.y https://github.com/raspberrypi/linux.git
cd linux

커널 설정 — eBPF 관련 옵션 활성화

기본 설정을 불러온 뒤, 빠져 있는 항목을 scripts/config로 켠다. menuconfig UI를 켜서 메뉴를 뒤지는 것보다 훨씬 재현 가능하고 스크립트화하기 쉽다.

make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcm2711_defconfig

./scripts/config --enable DEBUG_INFO_BTF
./scripts/config --enable UPROBE_EVENTS
./scripts/config --enable KPROBE_EVENTS
./scripts/config --enable FTRACE_SYSCALLS

# 방금 켠 옵션들이 의존하는 다른 옵션까지 함께 반영
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- olddefconfig

# 실제로 켜졌는지 확인
grep -E "DEBUG_INFO_BTF|UPROBE_EVENTS|KPROBE_EVENTS|FTRACE_SYSCALLS" .config

메뉴에서 직접 확인하고 싶다면 make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- menuconfig로 열어서 Kernel hacking → Compile-time checks and compiler options → Generate BTF typeinfo for vmlinux(DEBUG_INFO_BTF), Kernel hacking → Tracers → uprobes-based dynamic events(UPROBE_EVENTS) 위치에서 각각 확인할 수 있다.

커널 빌드

make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j$(nproc)
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- modules -j$(nproc)
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- modules_install INSTALL_MOD_PATH=./modules

빌드된 커널 배포

SD 카드의 부팅 파티션(boot)과 루트 파일시스템(root) 파티션을 각각 마운트한 뒤 복사한다. 기존 커널을 덮어쓰기 전에 kernel8.img를 백업해두면 부팅 실패 시 되돌리기 쉽다.

sudo mount /dev/sdX1 /mnt/boot
sudo mount /dev/sdX2 /mnt/root

# 기존 커널 백업
sudo cp /mnt/boot/kernel8.img /mnt/boot/kernel8.img.bak

# 새 커널·DTB 복사
sudo cp arch/arm64/boot/Image /mnt/boot/kernel8.img
sudo cp arch/arm64/boot/dts/broadcom/*.dtb /mnt/boot/
sudo mkdir -p /mnt/boot/overlays
sudo cp arch/arm64/boot/dts/overlays/*.dtb* /mnt/boot/overlays/
sudo cp arch/arm64/boot/dts/overlays/README /mnt/boot/overlays/

# 모듈 복사
sudo cp -r modules/lib/modules/* /mnt/root/lib/modules/

/mnt/boot/config.txt에 다음 항목이 있는지 확인한다.

arm_64bit=1
kernel=kernel8.img

SD 카드를 라즈베리파이에 넣고 재부팅한 뒤 커널 버전을 확인한다.

sudo reboot
# 재부팅 후
uname -r

eBPF 동작 확인

bpftool로 BTF와 프로그램 로드 상태를 확인하고, bpftrace로 실제 트레이싱까지 되는지 테스트한다.

sudo apt install -y linux-tools-common bpftrace
ls /sys/kernel/btf/vmlinux            # BTF가 실제로 실려 있는지 확인
sudo bpftool prog

# tracepoint:syscalls 계열이 뜨는지 확인 (FTRACE_SYSCALLS 검증)
sudo bpftrace -l 'tracepoint:syscalls:sys_enter_openat'

# 실제 추적 테스트
sudo bpftrace -e 'tracepoint:syscalls:sys_enter_openat { printf("%s %s\n", comm, str(args.filename)); }'

이 명령들이 오류 없이 출력을 내면 BTF와 syscalls tracepoint, uprobe 이벤트가 정상적으로 켜진 것이다. tracepoint:syscalls:* 목록이 비어 있다면 FTRACE_SYSCALLS가 실제로 반영됐는지 .config를 다시 확인해야 한다.

주의사항

  • Pi 4/400/CM4와 Pi 5는 SoC가 다르므로(BCM2711 vs BCM2712) defconfig와 DTB 파일이 서로 호환되지 않는다. 보드에 맞는 defconfig를 반드시 확인한다.
  • overlays 디렉터리가 SD 카드에 없는 상태로 복사를 시도하면 실패하니, mkdir -p로 미리 만들어둔다.
  • 새 커널로 부팅에 실패하면 복구가 번거로우므로, 기존 kernel8.img를 백업해두거나 별도 SD 카드에서 먼저 테스트하는 걸 권장한다.
  • dwarves(pahole)가 빌드 머신에 없으면 DEBUG_INFO_BTF를 켜도 경고만 나오고 BTF 없이 빌드가 끝나버릴 수 있다. 빌드 로그에서 pahole 관련 경고가 있는지 확인한다.
  • 라즈베리파이 공식 저장소는 브랜치(rpi-6.6.y 등)별로 defconfig 내용이 바뀌므로, 이 글의 grep 결과도 시간이 지나면 달라질 수 있다. 새로 시작한다면 먼저 자신의 브랜치에서 직접 확인하는 걸 권장한다.

마무리

라즈베리파이 스톡 커널은 기본적인 eBPF 프로그램 실행 자체는 이미 지원하지만, BTF 기반 CO-RE 도구와 uprobe 추적까지 쓰려면 커널을 직접 빌드해서 DEBUG_INFO_BTF, UPROBE_EVENTS, FTRACE_SYSCALLS 같은 옵션을 켜야 한다. 빌드 자체는 크로스 컴파일 환경만 갖추면 오래 걸리지 않고, scripts/config로 필요한 옵션만 콕 집어 켜는 방식이 menuconfig보다 재현하기 쉽다. 빌드가 끝나면 bpftoolbpftrace로 BTF와 tracepoint가 실제로 동작하는지 반드시 확인한 뒤 다음 단계(eBPF 프로그램 개발, 트레이싱 스크립트 작성)로 넘어가는 게 안전하다.

참고

답글 남기기