콘텐츠로 이동

eBPF 정리

eBPF란

eBPF(extended Berkeley Packet Filter)란 커널 소스 수정이나 모듈 적재 없이, 검증(Verification)을 통과한 프로그램을 커널 이벤트 지점에 안전하게 로드해 실행하는 기술

  • 성격: 커널 재컴파일·재부팅 없이 관측·네트워킹·보안 로직을 실행 중에 주입하는 커널 확장 계층
  • 안전성: verifier가 로드 전 정적 검증 → 무한 루프·메모리 위반 프로그램은 로드 거부
  • 실행: 검증 통과 후 JIT로 네이티브 기계어 변환 → 네이티브에 근접한 속도
  • 데이터 교환: 커널 상주 key-value 저장소인 maps로 유저스페이스와 상태 공유
  • 위치: 프로그램 타입(program type)이 attach 가능한 훅·헬퍼(helper)·맵 접근 범위를 결정

로드 파이프라인

graph LR
    Src["프로그램 작성<br>(C/Rust)"] --> BC["eBPF 바이트코드"]
    BC --> Ver["Verifier<br>정적 검증"]
    Ver --> JIT["JIT 컴파일<br>(네이티브 기계어)"]
    JIT --> Hook["훅 attach<br>(kprobe/XDP/tc/LSM)"]
    Hook --> Map["Maps<br>유저스페이스 데이터 교환"]
  • 작성: C나 Rust로 작성한 소스를 clang/LLVM이 eBPF 바이트코드로 컴파일
  • 검증: verifier가 제어 흐름·메모리·헬퍼 호출·종료 보장을 정적 분석 → 안전하지 않으면 거부
  • 컴파일: 검증 통과분만 JIT가 호스트 ISA 기계어로 변환(미지원 아키텍처는 인터프리터 실행)
  • attach: kprobe·XDP·tc·LSM 등 program type이 지정한 훅에 프로그램 연결
  • 교환: 실행 결과를 maps에 적재 → 유저스페이스 로더가 읽어 집계·표시

핵심 구성요소

구성요소 역할
Verifier 로드 전 안전성 정적 검증, 위반 시 거부
JIT 컴파일러 검증된 바이트코드를 네이티브 기계어로 변환
Maps 커널·유저스페이스·프로그램 간 상태 공유 저장소
Helper 함수 커널이 노출한 제한된 API(맵 접근·시각·리다이렉트 등)
program type attach 가능한 훅과 접근 가능한 헬퍼·컨텍스트 결정

커널 모듈과의 차이

커널 모듈은 커널에 임의 코드를 직접 삽입하는 반면, eBPF는 verifier 검증을 거친 제한된 코드만 주입하는 것이 핵심 차이

비교 항목 커널 모듈(Kernel Module) eBPF
크래시 영향 버그 시 커널 패닉·전체 다운 verifier가 사전 차단, 실패해도 로드 거부에 그침
안전 검증 없음, 개발자 책임 로드 전 정적 verifier 통과 필수
적재 방식 insmod로 커널에 직접 삽입 sys_bpf()로 검증 후 주입, 재부팅 불필요
이식성 커널 버전·빌드마다 재컴파일 CO-RE로 단일 바이너리가 여러 커널 대응
실행 범위 커널 전역의 임의 코드 실행 허용된 헬퍼·훅·맵으로 범위 제한
권한 CAP_SYS_MODULE, 사실상 전권 CAP_BPF + 용도별 최소 권한

훅 위치 정리

program type별로 attach 지점이 정해지며, 크게 관측·네트워킹·보안 계층으로 갈림

훅 계층 용도
kprobe/kretprobe 커널 함수 진입·반환 임의 커널 함수 동적 추적(관측)
fentry/fexit 커널 함수(BTF 기반) kprobe보다 낮은 오버헤드의 진입·반환 추적(관측)
uprobe/uretprobe 유저 함수 유저스페이스 애플리케이션 함수 추적(관측)
tracepoint 커널 정적 지점 커널이 노출한 안정적 이벤트 추적(관측)
perf event PMU·샘플링 CPU 프로파일링·주기적 샘플링(관측)
XDP NIC 드라이버 RX 경로 스택 진입 전 패킷 처리(네트워킹)
tc(clsact) 커널 네트워크 스택 ingress·egress 패킷 분류·정형(네트워킹)
BPF LSM LSM 보안 훅 커널 보안 지점에 정책 부착·차단(보안)
  • seccomp는 eBPF가 아닌 classic BPF(cBPF) 필터를 사용 → eBPF의 보안 경로는 BPF LSM이 중심

XDP가 빠른 이유

  • 위치: NIC 드라이버 RX 경로에서 sk_buff 할당 이전에 실행 → 커널 스택 진입 전에 처리
  • 생략: netfilter·conntrack·소켓 계층 등 스택 처리를 건너뜀
  • 액션: XDP_PASS/DROP/TX/REDIRECT로 즉시 판정 → DDoS 드롭·L4 포워딩에 유리
  • 모드: Native(드라이버 지원 필요, 최속)와 Generic(skb 기반, 범용이나 느림)으로 갈림

verifier 동작

verifier는 로드 시점에 프로그램을 심볼릭 실행하며 안전성을 정적으로 증명하는 커널 검사기

  • 종료 보장: 제어 흐름 그래프에 순환이 없어야 함, 유계 루프만 허용 → 무한 루프 거부
  • 메모리 안전: 레지스터·스택·맵 접근 범위를 추적해 경계 밖 접근 차단
  • 타입 안전: 포인터와 스칼라 타입을 구분해 잘못된 역참조 거부
  • 헬퍼 검사: program type이 허용한 헬퍼만 호출 가능, 인자 타입도 검증
  • 상태 가지치기: 이미 지난 동일 상태에 도달하면 탐색을 잘라 검증 비용 관리
  • 실패 시: 로드 자체가 거부되어 실행 중 커널에는 아무 영향 없음

maps 정리

maps는 eBPF 프로그램이 상태를 저장하고 유저스페이스와 데이터를 주고받는 커널 상주 저장소

맵 종류 설명
Array 정수 인덱스 기반 고정 크기 배열
Hash 임의 key-value 해시 테이블
LRU Hash 용량 초과 시 오래된 항목부터 제거
Per-CPU CPU별 사본 유지로 락 경합 회피
Ring Buffer 커널에서 유저스페이스로 이벤트 스트리밍
Prog Array tail call 대상 프로그램 참조 배열
  • 공유 범위: 프로그램 간·호출 간·유저스페이스와 상태 공유
  • 접근: 유저스페이스는 파일 디스크립터(fd)로, 커널 프로그램은 헬퍼로 read/write

개발 스택 비교

관측 원라이너부터 이식성 있는 프로덕션 바이너리까지 도구별 적합 영역이 다름

도구 형태 언어 적합
bcc 트레이싱 툴킷 + 바인딩 Python·Lua, 커널부 C 런타임 컴파일 기반 커널 관측 도구 다수, 대상 노드에 커널 헤더·LLVM 필요
bpftrace 고수준 트레이싱 DSL awk 유사 스크립트 일회성 커널·유저 관측을 짧은 스크립트로 수행
libbpf C 라이브러리(업스트림 커널) C/C++ CO-RE·BPF skeleton 지원, 단일 바이너리 배포
cilium/ebpf 순수 Go 라이브러리 Go libbpf 비의존, Go 앱에 eBPF 내장. Cilium·Tetragon 등이 사용
aya Rust 라이브러리 Rust(유저·커널 모두) libbpf 비의존, CO-RE 지원. 유저·커널 코드를 한 언어로 작성
  • bcc는 대상 노드에서 커널 헤더로 런타임 컴파일 → libbpf CO-RE는 한 번 컴파일해 여러 커널에서 재사용
  • 프로덕션 배포는 libbpf(C)·cilium/ebpf(Go)·aya(Rust) 중 앱 언어에 맞춰 선택

선택 가이드

상황 추천 사유
즉석 커널 관측 bpftrace 짧은 스크립트로 원라이너 추적
이식성 있는 C 배포 libbpf CO-RE·skeleton으로 단일 바이너리
Go 앱에 내장 cilium/ebpf 순수 Go, 외부 의존 최소
Rust 단일 언어 aya 유저·커널 코드를 Rust로 통일

eBPF 기반 제품

관측·네트워킹·보안 각 영역에서 eBPF를 코어로 쓰는 대표 제품과 라이선스 정리

제품 영역 설명
Cilium 네트워킹·CNI eBPF 기반 CNI, kube-proxy 대체 라우팅. Apache 2.0(CNCF)
Hubble 관측 Cilium 위에 얹는 네트워크 흐름·서비스 의존성 관측. Apache 2.0
Falco 런타임 보안 커널 이벤트 기반 이상 행위 탐지·알림. Apache 2.0(CNCF)
Tetragon 보안 정책 프로세스·시스템콜 관측 + 실시간 런타임 시행(enforcement). Apache 2.0
Pixie 관측(APM) 코드 수정 없이 자동 계측으로 애플리케이션 텔레메트리 수집. Apache 2.0(CNCF)
Katran L4 로드밸런서 XDP 기반 고성능 L4 LB 포워딩 플레인(C++ + eBPF). GPL-2.0(Meta)

사용 사례

동일한 로드·검증·attach 구조가 관측·네트워킹·보안 세 영역에 그대로 재사용됨

관측(Observability)

  • 시스템콜·커널 함수·네트워크 이벤트를 애플리케이션 코드 수정 없이 추적
  • 커널·유저 양쪽 함수에 훅 가능 → 재배포 없이 관측 지점 추가
  • 커널 안에서 집계 후 요약만 유저스페이스로 전달 → 데이터 복사·오버헤드 절감
  • 사례: bpftrace 원라이너, Pixie 자동 계측, Hubble 서비스 흐름 관측

네트워킹(Networking)

  • XDP·tc로 패킷을 스택 앞단에서 파싱·필터·리다이렉트
  • kube-proxy의 iptables 규칙 대신 eBPF 맵 기반 로드밸런싱으로 대체
  • 서비스 수 증가에도 룩업이 선형 규칙 스캔이 아닌 맵 조회라 확장에 유리
  • 사례: Cilium CNI, Katran L4 로드밸런서, XDP 기반 DDoS 드롭

보안(Security)

  • BPF LSM으로 커널 보안 훅에 정책을 부착하고 위반 시 차단
  • 프로세스 실행·파일 접근·네트워크 연결을 실시간 관측·시행
  • 커널 이벤트를 직접 보므로 유저스페이스 우회·후킹 회피에 강함
  • 사례: Falco 이상 탐지, Tetragon 런타임 정책 시행

한계와 운영 주의

  • verifier 제약: 무한 루프 금지, 유계 루프(bounded loop)만 허용. 명령어·분기 탐색량 상한 → 복잡 로직은 함수 분할·tail call로 우회
  • 커널 버전 의존: program type·헬퍼·훅이 커널 버전별로 다름. BPF LSM은 5.7+, CAP_BPF는 5.8+ 등 최소 버전 존재
  • CO-RE 전제: 이식성은 대상 커널의 BTF(BPF Type Format) 정보에 의존 → BTF 미제공 커널은 bcc식 헤더 기반 재빌드 필요
  • 권한: 로드에 CAP_BPF, 네트워킹은 +CAP_NET_ADMIN, 트레이싱은 +CAP_PERFMON 필요. 과거엔 CAP_SYS_ADMIN 단일 요구, 6.9의 BPF token으로 위임 가능
  • 오버헤드: 훅이 패킷·시스템콜 같은 핫패스에 직렬로 붙으면 지연 가산 → 관측 대상 빈도에 비례
  • 디버깅: verifier 실패 메시지 해석 난이도↑, 커널 컨텍스트라 일반 디버거 사용 제약 → bpftool·verifier 로그에 의존

결론

  • eBPF는 커널을 재컴파일·재부팅하지 않고 검증된 프로그램을 이벤트 지점에 안전하게 주입하는 실행 계층
  • verifier(안전)·JIT(속도)·maps(데이터 교환)·CO-RE(이식성)가 커널 모듈 대비 우위의 네 축
  • 관측은 bcc·bpftrace·Pixie, 네트워킹은 Cilium·Katran, 보안은 Falco·Tetragon으로 영역이 갈림
  • 커널 모듈은 "커널에 직접 심는 코드", eBPF는 "커널이 검증하고 돌려주는 코드"로 이해하면 됌