eBPF 프로그램은 Linux Kernel 내부에서 실행되지만 일반 프로그램처럼 전역 변수를 자유롭게 사용할 수 없습니다. 또한 커널에서 수집한 데이터를 사용자 공간(User Space)으로 전달하거나 여러 eBPF 프로그램 간에 데이터를 공유해야 하는 경우도 많습니다.
이때 사용하는 핵심 기능이 BPF Map입니다.
BPF Map은 eBPF 프로그램이 사용하는 데이터 저장소이며, Kernel과 User Space가 데이터를 안전하게 공유하는 통로 역할을 합니다.
이번 글에서는 BPF Map의 개념과 동작 원리, 다양한 Map 종류, 관리 방법, 그리고 실무 활용 사례를 자세히 알아보겠습니다.
BPF Map이란?
BPF Map은 eBPF 프로그램이 데이터를 저장하고 조회하기 위해 사용하는 Kernel 내부의 자료구조입니다.
기본 구조는 다음과 같습니다.
User Space
↓
BPF Syscall
↓
BPF Map
↑ ↓
eBPF Program
Kernel 내부에서 생성되지만 사용자 프로그램도 접근할 수 있습니다.
BPF Map이 필요한 이유
예를 들어 eBPF 프로그램이 초당 네트워크 패킷 수를 계산한다고 가정해 보겠습니다.
패킷이 들어올 때마다 값을 저장해야 합니다.
Packet
↓
eBPF Program
↓
Counter 증가
↓
BPF Map 저장
User Space 프로그램은 BPF Map에서 현재 값을 읽어 화면에 출력합니다.
BPF Map의 특징
BPF Map은 다음과 같은 특징을 가집니다.
- Kernel 내부 저장
- User Space 접근 가능
- 여러 eBPF 프로그램이 공유 가능
- 다양한 자료구조 제공
- 매우 높은 성능
일반적인 메모리 공유 방식보다 안전하게 설계되어 있습니다.
BPF Map 동작 과정
전체 흐름은 다음과 같습니다.
Packet
↓
eBPF Program
↓
Map Update
↓
Kernel Memory
↓
User Program Read
커널과 사용자 프로그램이 동일한 Map을 공유합니다.
BPF Map 종류
Linux는 다양한 Map 타입을 제공합니다.
| Map 종류 | 설명 |
|---|---|
| Hash | Key-Value 저장 |
| Array | 고정 크기 배열 |
| Per-CPU Hash | CPU별 독립 Hash |
| Per-CPU Array | CPU별 배열 |
| Queue | FIFO 구조 |
| Stack | LIFO 구조 |
| Ring Buffer | 이벤트 전달 |
| LRU Hash | 오래된 데이터 자동 제거 |
사용 목적에 따라 적절한 자료구조를 선택합니다.
Hash Map
가장 많이 사용하는 형태입니다.
Key
↓
Value
예시
PID
↓
Packet Count
프로세스별 네트워크 사용량을 저장할 때 많이 사용합니다.
Array Map
고정된 인덱스를 사용하는 구조입니다.
Index
↓
Value
예시
CPU0
CPU1
CPU2
CPU3
CPU별 통계를 저장하는 데 적합합니다.
Per-CPU Map
멀티코어 환경에서는 Lock 경쟁이 발생할 수 있습니다.
Per-CPU Map은
CPU0
↓
Local Data
CPU1
↓
Local Data
각 CPU마다 독립된 저장 공간을 사용하여 성능을 높입니다.
고성능 모니터링 도구에서 자주 사용됩니다.
Ring Buffer
Ring Buffer는 Kernel에서 User Space로 이벤트를 전달하는 구조입니다.
Kernel
↓
Ring Buffer
↓
User Space
Falco나 bpftrace 같은 도구에서 이벤트 전달에 사용됩니다.
Map 생성
eBPF 프로그램에서는 다음과 같이 Map을 생성합니다.
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 1024);
} my_map SEC(".maps");
Hash Map을 생성하는 예시입니다.
bpftool로 Map 확인
현재 생성된 Map은 다음 명령으로 확인할 수 있습니다.
sudo bpftool map show
예시
1:
type hash
name packet_count
현재 Kernel에 존재하는 Map 목록을 확인할 수 있습니다.
Map 내용 조회
특정 Map의 데이터를 확인하려면
sudo bpftool map dump id 1
예시
key:
value:
Map 내부의 Key와 Value를 확인할 수 있습니다.
Map 삭제
Map을 제거하려면 eBPF 프로그램을 언로드하거나 핀(Pin)된 Map을 삭제합니다.
핀된 Map 확인
ls /sys/fs/bpf
삭제
sudo rm /sys/fs/bpf/map_name
실무에서 자주 사용하는 명령어
Map 목록
sudo bpftool map show
Map 내용
sudo bpftool map dump id 1
Program 확인
sudo bpftool prog show
BPF 파일 시스템 확인
mount | grep bpf
Pin된 객체 확인
ls /sys/fs/bpf
Kernel 버전
uname -r
실무 사례
예를 들어 웹 서버의 초당 요청 수(RPS)를 실시간으로 분석한다고 가정해 보겠습니다.
다음 순서로 동작합니다.
- eBPF 프로그램이 HTTP 요청 감지
- PID를 Key로 사용
- 요청 수를 Value로 저장
- Hash Map 업데이트
- User Space 프로그램이 Map 읽기
- Grafana 대시보드에 실시간 표시
이처럼 BPF Map은 커널에서 수집한 데이터를 외부 모니터링 시스템과 연결하는 핵심 역할을 수행합니다.
자주 묻는 질문
BPF Map은 일반 Hash Table과 같은 것인가요?
개념은 비슷하지만 BPF Map은 Kernel 내부에서 동작하며, eBPF 프로그램과 User Space가 안전하게 데이터를 공유할 수 있도록 설계된 특수한 자료구조입니다.
Per-CPU Map은 왜 필요한가요?
여러 CPU가 하나의 Map을 동시에 수정하면 Lock 경쟁이 발생할 수 있습니다. Per-CPU Map은 CPU마다 별도의 저장 공간을 사용하여 성능 저하를 줄입니다.
BPF Map은 영구적으로 저장되나요?
기본적으로는 eBPF 프로그램이 종료되면 함께 제거됩니다. 하지만 Pin 기능을 사용하면 /sys/fs/bpf 아래에 유지하여 여러 프로그램이 계속 사용할 수 있습니다.
마무리
BPF Map은 eBPF 프로그램이 데이터를 저장하고 공유하기 위한 핵심 자료구조입니다. Hash, Array, Per-CPU Map, Ring Buffer 등 다양한 형태를 제공하며, 커널과 사용자 공간 간의 안전하고 효율적인 데이터 교환을 가능하게 합니다. bpftool을 활용하면 Map 생성 상태와 저장된 데이터를 확인할 수 있으며, eBPF 기반 모니터링과 네트워크 분석, 보안 시스템을 이해하는 데 반드시 알아야 하는 기술입니다.