eBPF 프로그램을 개발할 때 가장 큰 문제 중 하나는 커널 버전마다 구조체의 레이아웃(Layout)이 달라진다는 점입니다.
예를 들어 task_struct, sock, sk_buff와 같은 커널 구조체는 새로운 커널 버전이 출시될 때마다 필드가 추가되거나 삭제되고, 순서가 변경될 수도 있습니다.
예전에는 이러한 차이 때문에 커널 버전이 바뀔 때마다 eBPF 프로그램을 다시 컴파일해야 했습니다.
이 문제를 해결하기 위해 등장한 기술이 CO-RE(Compile Once – Run Everywhere) 이며, 그 핵심이 바로 CO-RE Relocation입니다.
CO-RE Relocation은 실행 중인 커널의 BTF 정보를 이용하여 구조체의 실제 오프셋(Offset)을 자동으로 계산하고 수정하는 기술입니다.
이번 글에서는 CO-RE Relocation의 개념과 동작 원리, 내부 구조, BTF와의 관계, 실무 활용 방법을 자세히 알아보겠습니다.
Linux CO-RE Relocation이란?
CO-RE Relocation은 컴파일 시점이 아닌 실행 시점(Runtime)에 커널 구조체의 위치를 자동으로 보정하는 기술입니다.
기본 구조는 다음과 같습니다.
eBPF Program
↓
Compile
↓
Object File
↓
Kernel BTF
↓
CO-RE Relocation
↓
Correct Offset
↓
Program Run
즉, 실행되는 커널에 맞게 구조체의 레이아웃을 자동으로 조정합니다.
CO-RE Relocation이 필요한 이유
예를 들어 Kernel A에서는 다음과 같은 구조체가 있다고 가정합니다.
struct task_struct {
int pid;
char comm[16];
};
하지만 Kernel B에서는 다음과 같이 변경될 수 있습니다.
struct task_struct {
long flags;
int pid;
char comm[16];
};
pid의 위치가 달라졌기 때문에 이전 방식이라면 잘못된 데이터를 읽게 됩니다.
CO-RE Relocation은 이러한 차이를 자동으로 수정합니다.
기존 방식과 CO-RE 방식 비교
기존 방식
Compile
↓
Kernel A
↓
Kernel B
↓
재컴파일 필요
CO-RE 방식
Compile
↓
Object File
↓
Kernel A
↓
자동 보정
↓
Kernel B
↓
자동 보정
하나의 바이너리만으로 다양한 커널에서 실행할 수 있습니다.
CO-RE Relocation의 동작 과정
전체 과정은 다음과 같습니다.
eBPF Source
↓
Clang
↓
BTF 생성
↓
Object File
↓
Kernel BTF 비교
↓
Offset 계산
↓
Relocation 적용
↓
Program 실행
실행 시점에 필요한 정보만 자동으로 수정됩니다.
BTF와의 관계
CO-RE Relocation은 BTF를 기반으로 동작합니다.
Kernel BTF
↓
Struct Layout
↓
Field Offset
↓
CO-RE
↓
Access Field
BTF가 없다면 CO-RE Relocation도 수행할 수 없습니다.
어떤 정보를 수정할까?
CO-RE는 다양한 타입 정보를 자동으로 수정합니다.
대표적으로
- Structure Offset
- Member 위치
- Field Size
- Array 크기
- Type 변경
- Pointer 위치
등을 보정합니다.
Relocation 정보는 어디에 저장될까?
컴파일된 ELF Object에는 다음 Section이 존재합니다.
.text
.maps
.BTF
.BTF.ext
여기서
.BTF.ext
Section에 CO-RE Relocation 정보가 저장됩니다.
libbpf의 역할
Relocation 작업은 대부분 libbpf가 수행합니다.
동작 과정
Application
↓
libbpf
↓
Read BTF
↓
Compare Kernel
↓
Relocation
↓
Load Program
개발자가 직접 Offset을 계산할 필요가 없습니다.
CO-RE Helper 매크로
CO-RE에서는 다양한 Helper 매크로를 제공합니다.
대표적으로
BPF_CORE_READ(task, pid);
또는
BPF_CORE_READ(task, comm);
처럼 사용할 수 있습니다.
이 매크로는 현재 실행 중인 커널 구조체를 기준으로 자동으로 필드를 읽습니다.
CO-RE의 장점
CO-RE를 사용하면 다음과 같은 장점이 있습니다.
- 하나의 바이너리 사용
- 커널 버전 호환성 향상
- 재컴파일 불필요
- 유지보수 비용 감소
- 운영 환경 배포 단순화
- 최신 Kernel 자동 대응
특히 다양한 Linux 배포판을 운영하는 환경에서 매우 큰 장점을 제공합니다.
CO-RE 사용 시 주의사항
CO-RE를 사용하려면 다음 조건이 필요합니다.
- Kernel BTF 지원
- Clang 지원
- libbpf 사용
- 최신 bpftool 권장
- BTF 정보 포함하여 컴파일
구형 커널에서는 CO-RE를 사용할 수 없는 경우가 있습니다.
실무에서 자주 사용하는 명령어
Kernel BTF 확인
ls /sys/kernel/btf
BTF 정보 확인
sudo bpftool btf show
BTF Dump
sudo bpftool btf dump file /sys/kernel/btf/vmlinux format c
Kernel 기능 확인
sudo bpftool feature
Program 확인
sudo bpftool prog show
libbpf 버전 확인
pkg-config --modversion libbpf
실무 사례
예를 들어 하나의 XDP 기반 방화벽 프로그램을 Ubuntu 22.04에서 컴파일했다고 가정해 보겠습니다.
과거에는 Debian, Fedora, Rocky Linux 등 다른 배포판에서 실행하려면 각 커널 버전에 맞게 다시 컴파일해야 했습니다.
하지만 CO-RE Relocation을 사용하면 다음과 같은 방식으로 동작합니다.
- 프로그램 컴파일 시 BTF와 Relocation 정보 포함
- 대상 서버에서 Kernel BTF 확인
- libbpf가 현재 커널 구조체와 비교
- 구조체 오프셋 자동 계산
- 동일한 eBPF 프로그램 실행
이처럼 하나의 바이너리로 여러 Linux 배포판에서 안정적으로 실행할 수 있습니다.
자주 묻는 질문
CO-RE Relocation은 언제 수행되나요?
컴파일 시가 아니라 프로그램을 커널에 로드하는 시점에 수행됩니다. libbpf가 현재 커널의 BTF 정보를 읽어 필요한 Relocation을 적용합니다.
CO-RE와 BTF는 반드시 함께 사용해야 하나요?
네. CO-RE는 BTF를 기반으로 구조체와 타입 정보를 비교하여 오프셋을 계산합니다. 따라서 BTF가 없는 환경에서는 CO-RE를 사용할 수 없습니다.
CO-RE를 사용하면 모든 커널에서 실행 가능한가요?
모든 커널을 지원하는 것은 아닙니다. 대상 커널이 BTF를 제공하고 CO-RE를 지원해야 합니다. 최신 Linux 배포판에서는 대부분 지원하지만, 오래된 커널에서는 지원되지 않을 수 있습니다.
마무리
Linux CO-RE Relocation은 커널 구조체의 오프셋과 타입 정보를 실행 시점에 자동으로 보정하는 기술입니다. BTF와 libbpf를 기반으로 동작하며, 하나의 eBPF 바이너리를 다양한 커널에서 재컴파일 없이 실행할 수 있도록 지원합니다. 현대적인 eBPF 개발에서는 CO-RE와 BTF를 함께 사용하는 것이 사실상의 표준이며, 이식성과 유지보수성을 크게 향상시키는 핵심 기술입니다.