최근 Linux eBPF 개발은 대부분 libbpf를 중심으로 이루어지고 있습니다. 과거에는 BCC(BPF Compiler Collection)가 많이 사용되었지만, 현재는 Linux Kernel 개발팀이 권장하는 방식이 libbpf + CO-RE 조합입니다.
libbpf는 eBPF 프로그램을 컴파일하고 커널에 로드하며, BPF Map과 Hook을 관리하는 기능을 제공하는 공식 라이브러리입니다. 특히 CO-RE(Compile Once – Run Everywhere)를 지원하여 하나의 eBPF 프로그램을 다양한 Linux Kernel에서 실행할 수 있도록 도와줍니다.
이번 글에서는 libbpf의 개념과 구조, 주요 기능, 동작 원리, CO-RE와의 관계, 실무 활용 방법을 자세히 알아보겠습니다.
Linux libbpf란?
libbpf는 Linux Kernel에서 공식적으로 지원하는 eBPF 사용자 공간(User Space) 라이브러리입니다.
기본 구조는 다음과 같습니다.
Application
↓
libbpf
↓
BPF System Call
↓
Linux Kernel
↓
eBPF Program
사용자는 libbpf를 통해 복잡한 시스템 호출을 직접 구현하지 않고도 eBPF 프로그램을 쉽게 관리할 수 있습니다.
libbpf가 필요한 이유
초기의 eBPF 개발 과정은 매우 복잡했습니다.
- eBPF 프로그램 컴파일
- Verifier 통과
- Kernel 로드
- Map 생성
- Hook 연결
- 데이터 전달
libbpf는 이러한 작업을 대부분 자동으로 처리합니다.
덕분에 개발자는 프로그램 로직 작성에 집중할 수 있습니다.
libbpf의 주요 기능
libbpf는 다음과 같은 기능을 제공합니다.
| 기능 | 설명 |
|---|---|
| Program Load | eBPF 프로그램 로드 |
| Program Attach | Hook 연결 |
| Map 생성 | BPF Map 관리 |
| Ring Buffer 지원 | 사용자 공간 통신 |
| Perf Buffer 지원 | 이벤트 전달 |
| CO-RE 지원 | 커널 호환성 |
| BTF 지원 | 구조체 자동 분석 |
최신 eBPF 기능 대부분이 libbpf를 통해 제공됩니다.
libbpf의 동작 구조
전체 흐름은 다음과 같습니다.
eBPF Source
↓
clang
↓
ELF Object
↓
libbpf
↓
Kernel Load
↓
Attach
↓
Running
컴파일된 ELF 파일을 libbpf가 읽어 커널에 자동으로 로드합니다.
libbpf와 CO-RE
CO-RE는 libbpf의 핵심 기능 중 하나입니다.
동작 과정은 다음과 같습니다.
ELF Object
↓
BTF 정보 확인
↓
Relocation 수행
↓
Kernel Load
↓
실행
커널 구조체가 달라도 실행 시 자동으로 구조를 보정합니다.
libbpf와 BTF
libbpf는 BTF(BPF Type Format)를 적극 활용합니다.
BTF에는 다음과 같은 정보가 저장됩니다.
- 구조체 이름
- 멤버 위치
- 자료형
- 크기
- Offset
libbpf는 이를 이용해 CO-RE Relocation을 수행합니다.
libbpf Bootstrap
공식 예제 프로젝트도 제공됩니다.
대표적으로
libbpf-bootstrap
프로젝트가 많이 사용됩니다.
기본 구조
Application
↓
Skeleton
↓
libbpf
↓
Kernel
Skeleton을 이용하면 프로그램 작성이 매우 간단해집니다.
Skeleton이란?
Skeleton은 libbpf가 자동 생성하는 C 코드입니다.
예를 들어
bpftool gen skeleton program.o
를 실행하면
program.skel.h
파일이 생성됩니다.
이를 통해
- Program Load
- Program Attach
- Map 접근
등을 간단하게 처리할 수 있습니다.
libbpf 설치
Ubuntu
sudo apt update
sudo apt install libbpf-dev
RHEL 계열
sudo dnf install libbpf-devel
설치 확인
pkg-config --modversion libbpf
컴파일 예시
대표적인 컴파일
clang \
-target bpf \
-g \
-O2 \
-c program.bpf.c \
-o program.bpf.o
User Program
gcc main.c \
-lbpf
libbpf와 링크하여 실행 파일을 생성합니다.
bpftool과 함께 사용
Skeleton 생성
bpftool gen skeleton program.bpf.o > program.skel.h
BTF 확인
bpftool btf show
Program 확인
bpftool prog show
libbpf API 예시
대표적인 API는 다음과 같습니다.
bpf_object__open_file()
eBPF Object 열기
bpf_object__load()
Kernel 로드
bpf_program__attach()
Hook 연결
bpf_map__fd()
Map 접근
이러한 API를 통해 대부분의 eBPF 작업을 수행할 수 있습니다.
BCC와 libbpf의 차이
| 항목 | libbpf | BCC |
|---|---|---|
| 개발 언어 | C | Python + C |
| CO-RE | 지원 | 제한적 |
| 공식 지원 | 매우 높음 | 낮아지는 추세 |
| 성능 | 매우 우수 | 우수 |
| 운영 환경 | 표준 | 기존 프로젝트 |
현재 신규 프로젝트는 대부분 libbpf 기반으로 개발됩니다.
실무에서 자주 사용하는 명령어
libbpf 설치 확인
pkg-config --modversion libbpf
BTF 확인
bpftool btf show
Skeleton 생성
bpftool gen skeleton program.bpf.o
Program 확인
bpftool prog show
Map 확인
bpftool map show
Kernel 확인
uname -r
실무 사례
예를 들어 SaaS 플랫폼을 운영하는 기업에서 Ubuntu, Debian, Rocky Linux 서버를 함께 운영한다고 가정해 보겠습니다.
과거에는 커널 버전마다 다른 eBPF 프로그램을 컴파일해야 했지만, 현재는 다음과 같이 개발합니다.
- libbpf 기반으로 eBPF 프로그램 작성
- CO-RE 방식으로 컴파일
- Skeleton 자동 생성
- 하나의 바이너리를 모든 서버에 배포
- 실행 시 BTF 정보를 이용해 자동으로 Relocation 수행
- 동일한 프로그램을 다양한 커널에서 실행
이 방식은 유지보수 비용을 크게 줄이고 자동화에도 적합합니다.
자주 묻는 질문
libbpf는 BCC를 대체하는 기술인가요?
완전히 대체하는 것은 아니지만, 신규 eBPF 프로젝트에서는 libbpf 사용이 권장됩니다. BCC는 빠른 프로토타이핑과 분석에 강점이 있고, libbpf는 운영 환경과 장기적인 프로젝트에 적합합니다.
libbpf는 반드시 CO-RE와 함께 사용해야 하나요?
필수는 아닙니다. 하지만 CO-RE를 함께 사용하면 다양한 커널 버전을 지원하기 쉬워지므로 최신 eBPF 개발에서는 일반적으로 함께 사용합니다.
libbpf를 사용하려면 BTF가 필요한가요?
기본적인 eBPF 프로그램은 BTF 없이도 동작할 수 있습니다. 그러나 CO-RE 기능을 사용하려면 커널이 BTF를 제공해야 합니다.
마무리
Linux libbpf는 최신 eBPF 개발의 사실상 표준으로 자리 잡은 공식 라이브러리입니다. eBPF 프로그램 로드, Hook 연결, BPF Map 관리, CO-RE 지원, BTF 활용 등 복잡한 작업을 간단하게 처리할 수 있으며, 최신 Linux 환경에서는 대부분의 eBPF 프로젝트가 libbpf를 기반으로 개발됩니다. CO-RE와 함께 이해하면 유지보수가 쉽고 이식성이 높은 eBPF 애플리케이션을 개발할 수 있습니다.