Post

[eBPF 관측성] Day 5: 프로덕션 운영 - 보안 모니터링부터 메트릭 파이프라인까지

[eBPF 관측성] Day 5: 프로덕션 운영 - 보안 모니터링부터 메트릭 파이프라인까지

이 글은 AI(Claude)의 도움을 받아 작성하고, 작성자가 검토·편집했습니다.

서론: 도구에서 시스템으로

Day 1~4에서 관측·네트워크·프로파일링 도구를 만들었다. 마지막 편은 이것을 프로덕션에서 24시간 안전하게 굴리는 법이다. 보안 이벤트 감시, 컨테이너 환경 적용, 메트릭 파이프라인 연동, 그리고 운영 원칙을 정리한다.

1. 보안 모니터링: 의심스러운 행위 탐지

eBPF는 실행 중인 시스템에서 “정상에서 벗어난 행위”를 실시간 감지하는 데 강하다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/* 권한 상승 시도 감지: setuid(0) 호출 추적 */
SEC("tracepoint/syscalls/sys_enter_setuid")
int detect_setuid_root(struct trace_event_raw_sys_enter *ctx)
{
    __u32 uid = bpf_get_current_uid_gid() & 0xffffffff;
    __u64 target_uid = ctx->args[0];

    /* 비-root가 root로의 전환을 시도 */
    if (uid != 0 && target_uid == 0) {
        struct event *e = bpf_ringbuf_reserve(&alerts, sizeof(*e), 0);
        if (!e) return 0;
        e->pid = bpf_get_current_pid_tgid() >> 32;
        e->uid = uid;
        bpf_get_current_comm(&e->comm, sizeof(e->comm));
        bpf_ringbuf_submit(e, 0);
    }
    return 0;
}

흔한 탐지 패턴:

  • execve/tmp·/dev/shm에서 실행되는 바이너리
  • 컨테이너 내부에서의 mount·ptrace 호출
  • 예상치 못한 아웃바운드 연결(tcp_connect)
  • unlink로 로그·바이너리 삭제

참고: 직접 만들기보다 Falco, Tetragon 같은 검증된 런타임 보안 도구가 이 패턴들을 룰 기반으로 제공한다. 프로덕션 보안은 직접 구현보다 검증된 도구를 우선한다.

2. 컨테이너·쿠버네티스 환경

컨테이너는 결국 같은 호스트 커널을 공유한다. eBPF는 호스트 커널에 attach하므로 노드 하나에 한 번 붙으면 그 위 모든 컨테이너를 관측한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# DaemonSet으로 노드마다 eBPF 에이전트 배포
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: ebpf-agent
spec:
  template:
    spec:
      hostPID: true            # 호스트 PID 네임스페이스 접근
      containers:
      - name: agent
        image: myorg/ebpf-agent:1.0
        securityContext:
          capabilities:
            add: ["BPF", "PERFMON", "NET_ADMIN"]  # root 대신 최소 권한
        volumeMounts:
        - { name: bpffs,   mountPath: /sys/fs/bpf }
        - { name: btf,     mountPath: /sys/kernel/btf, readOnly: true }
      volumes:
      - name: bpffs
        hostPath: { path: /sys/fs/bpf, type: Directory }
      - name: btf
        hostPath: { path: /sys/kernel/btf }

이벤트의 PID를 cgroup 경로로 매핑하면 어느 파드·컨테이너에서 발생했는지 식별할 수 있다. Cilium은 이 방식으로 쿠버네티스 네트워크 정책·관측을 eBPF로 구현한다.

3. 메트릭 파이프라인: eBPF → Prometheus

관측 데이터를 일회성으로 보는 데 그치지 않고, 시계열로 쌓아 알림·대시보드로 연결한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# eBPF 맵을 주기적으로 읽어 Prometheus로 노출
from prometheus_client import Counter, Histogram, start_http_server
from bcc import BPF
import time

b = BPF(src_file="syscall_latency.bpf.c")
b.attach_kprobe(event="...", fn_name="...")

syscall_latency = Histogram(
    'syscall_latency_seconds', '시스템콜 지연',
    ['syscall'], buckets=[.0001, .001, .01, .1, 1])
drop_total = Counter(
    'xdp_dropped_packets_total', 'XDP 드롭 패킷', ['reason'])

start_http_server(9100)   # Prometheus scrape 엔드포인트

while True:
    # 커널 맵의 누적 히스토그램을 읽어 메트릭으로 변환
    for k, v in b["latency_hist"].items():
        syscall_latency.labels(syscall=k.name).observe(v.value)
    b["latency_hist"].clear()
    time.sleep(5)

이렇게 하면 Day 1의 일회성 히스토그램이 Grafana 대시보드의 상시 지표가 된다.

4. 오버헤드 관리: 프로덕션의 철칙

프로덕션 eBPF의 가장 큰 위험은 관측 자체가 시스템을 느리게 하는 것이다.

1
2
3
4
5
6
7
8
9
10
핫패스에 붙일 때:
  나쁨:  초당 1천만 회 호출되는 함수에 kprobe + 이벤트 전송
  좋음:  커널에서 집계(맵 누적) 후 사용자 공간은 5초마다 읽기

원칙:
  1. 가능하면 kprobe보다 tracepoint (안정적 + 약간 빠름)
  2. 이벤트를 개별 전송하지 말고 커널에서 집계
  3. PERCPU 맵으로 CPU 간 락 경합 제거
  4. 샘플링(예: 99Hz)으로 빈도 높은 이벤트 부하 제한
  5. 배포 전 부하 환경에서 오버헤드 측정

5. 안전한 배포와 롤백

1
2
3
4
5
6
7
8
9
10
11
12
13
# 1) attach된 모든 BPF 프로그램 확인
sudo bpftool prog list

# 2) 핀(pin)으로 프로그램을 BPF 파일시스템에 고정 → 로더 죽어도 유지
sudo bpftool prog pin id <ID> /sys/fs/bpf/myprog

# 3) 문제 시 즉시 detach (롤백)
sudo bpftool net detach xdp dev eth0
sudo rm /sys/fs/bpf/myprog

# 4) 커널 버전 호환성 사전 점검
bpftool btf list            # BTF 존재 확인 (CO-RE 전제)
uname -r                    # 대상 커널 버전 기록

XDP를 native 모드로 잘못 붙여 트래픽이 끊기는 사고가 흔하다. 신규 프로그램은 generic 모드·트래픽 미러 환경에서 먼저 검증한 뒤 본 인터페이스에 올린다.

6. 도구 생태계 정리

영역권장 도구
빠른 한 줄 관측bpftrace, bcc tools
재사용 트레이서 개발libbpf + CO-RE
네트워크/쿠버네티스Cilium
런타임 보안Falco, Tetragon
지속 프로파일링Parca, Pyroscope
범용 관측 플랫폼Pixie

직접 작성은 학습과 특수 요구에, 프로덕션 상시 운영은 검증된 도구에 맡기는 것이 현명하다.

7. 시리즈 종합 체크리스트

  1. Verifier·JIT·BTF로 eBPF가 안전하게 커널을 확장하는 원리를 이해했다. (Day 1~2)
  2. CO-RE로 커널 버전 무관한 단일 바이너리 트레이서를 빌드했다. (Day 2)
  3. XDP/tc로 패킷을 최하단에서 관측·차단했다. (Day 3)
  4. On/Off-CPU 플레임그래프로 병목을 시각화했다. (Day 4)
  5. 보안 감시·컨테이너 배포·Prometheus 연동·오버헤드 관리로 프로덕션 운영 체계를 갖췄다. (Day 5)

시리즈 마무리

eBPF는 “커널을 건드리지 않고 커널을 본다”는 모순을 안전하게 실현한 기술이다. 핵심은 두 가지다. 첫째, 관측은 공짜가 아니므로 무엇을 얼마나 자주 볼지 설계해야 한다. 둘째, 직접 만드는 역량은 검증된 도구를 깊이 이해하고 디버깅하기 위한 토대다.

입문(개념·bpftrace)→개발(libbpf·CO-RE)→네트워크(XDP·tc)→프로파일링(플레임그래프)→운영(보안·배포) 다섯 단계를 거치면, 블랙박스였던 리눅스 시스템을 필요한 만큼 투명하게 들여다보는 관측 역량을 갖추게 된다.

This post is licensed under CC BY 4.0 by the author.