eBPFとは何か
eBPF(extended Berkeley Packet Filter)は、Linuxカーネル内でサンドボックス化されたプログラムを実行できる革新的な技術です。カーネルのソースコードを変更したり、カーネルモジュールをロードしたりすることなく、カーネルの機能を安全に拡張できます。
2025年現在、eBPFはクラウドネイティブインフラの中核技術として確立され、ネットワーキング、セキュリティ、オブザーバビリティの3分野で革命を起こしています。
eBPFの仕組み
アーキテクチャ概要
┌─────────────────────────────────────────────────────────┐
│ ユーザー空間 │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Cilium │ │ Falco │ │ Pixie │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ BPF システムコール │ │
│ └─────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────┤
│ カーネル空間 │
│ ┌─────────────────────────────────────────────────┐ │
│ │ BPF Verifier │ │
│ │ (安全性検証・無限ループ禁止) │ │
│ └─────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ JIT Compiler │ │
│ │ (ネイティブコードにコンパイル) │ │
│ └─────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ BPF Maps │ │
│ │ (カーネル/ユーザー間データ共有) │ │
│ └─────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────┬───────────┬───────────┬───────────┐ │
│ │ kprobes │ tracepoints│ XDP │ TC │ │
│ │(関数フック)│(イベント) │(パケット) │(トラフィック)│ │
│ └───────────┴───────────┴───────────┴───────────┘ │
└─────────────────────────────────────────────────────────┘
BPF Verifier - 安全性の要
eBPFプログラムがカーネルにロードされる前に、Verifierが以下を検証します:
// BPF Verifierが検証する項目
// 1. メモリアクセスの境界チェック
// 2. 無限ループの禁止(最大命令数制限)
// 3. 特権操作の制限
// 4. ポインタの安全性
SEC("xdp")
int xdp_drop_icmp(struct xdp_md *ctx) {
void *data_end = (void *)(long)ctx->data_end;
void *data = (void *)(long)ctx->data;
// 境界チェック必須(Verifierが強制)
struct ethhdr *eth = data;
if ((void *)(eth + 1) > data_end)
return XDP_PASS;
if (eth->h_proto != __constant_htons(ETH_P_IP))
return XDP_PASS;
struct iphdr *ip = (void *)(eth + 1);
if ((void *)(ip + 1) > data_end)
return XDP_PASS;
// ICMPパケットをドロップ
if (ip->protocol == IPPROTO_ICMP)
return XDP_DROP;
return XDP_PASS;
}
BPF Maps - データ構造
// Hash Map: キーバリュー形式
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 10000);
__type(key, __u32); // IPアドレス
__type(value, __u64); // パケットカウント
} packet_count SEC(".maps");
// Ring Buffer: イベントストリーミング
struct {
__uint(type, BPF_MAP_TYPE_RINGBUF);
__uint(max_entries, 256 * 1024);
} events SEC(".maps");
// Per-CPU Array: 高速カウンター
struct {
__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
__uint(max_entries, 256);
__type(key, __u32);
__type(value, __u64);
} cpu_stats SEC(".maps");
Cilium - eBPFネットワーキングの標準
Ciliumは、eBPFを活用したKubernetesネットワーキングソリューションです。2025年、CNCFのGraduatedプロジェクトとして、多くの本番環境で採用されています。
Ciliumの主要機能
| 機能 | 説明 | 利点 |
|---|---|---|
| CNI | Kubernetesネットワーキング | kube-proxyの置き換え |
| Service Mesh | L7ロードバランシング | サイドカー不要 |
| Network Policy | L3-L7ポリシー | きめ細かいアクセス制御 |
| Encryption | WireGuard/IPsec | 透過的暗号化 |
| Observability | Hubble | ネットワーク可視化 |
Cilium CNI設定
# Helm values.yaml
apiVersion: cilium.io/v2
kind: CiliumConfig
metadata:
name: cilium-config
namespace: kube-system
spec:
# eBPFベースのkube-proxy代替
kubeProxyReplacement: "true"
# XDPによる高速パケット処理
loadBalancer:
mode: "dsr" # Direct Server Return
acceleration: native
# WireGuardによる透過的暗号化
encryption:
enabled: true
type: wireguard
# Hubble(可視化)の有効化
hubble:
enabled: true
relay:
enabled: true
ui:
enabled: true
# eBPF Host Routing
bpf:
masquerade: true
hostLegacyRouting: false
Cilium Network Policy
# L7レベルのきめ細かいポリシー
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: api-access-policy
namespace: production
spec:
endpointSelector:
matchLabels:
app: api-server
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: "8080"
protocol: TCP
rules:
http:
- method: "GET"
path: "/api/v1/users"
- method: "POST"
path: "/api/v1/orders"
headers:
- "Content-Type: application/json"
- fromEndpoints:
- matchLabels:
app: admin-dashboard
toPorts:
- ports:
- port: "8080"
protocol: TCP
rules:
http:
- method: ".*"
path: "/api/v1/.*"
Hubbleによるネットワーク可視化
# Hubble CLIでリアルタイムフロー監視
$ hubble observe --namespace production
TIMESTAMP SOURCE DESTINATION TYPE
Jan 12 10:15:32.123 production/frontend-xxx production/api-server L7/HTTP GET /api/v1/users -> 200
Jan 12 10:15:32.456 production/api-server production/database L4/TCP -> FORWARDED
Jan 12 10:15:33.789 external/203.0.113.1 production/nginx-ingress L7/HTTP GET /login -> 200
# サービスマップの生成
$ hubble observe --namespace production -o json | hubble-ui
Falco - eBPFランタイムセキュリティ
Falcoは、eBPFを使用したランタイム脅威検出エンジンです。システムコールをリアルタイムで監視し、異常な振る舞いを検出します。
Falcoアーキテクチャ
┌─────────────────────────────────────────────────────────┐
│ Falco Engine │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Rule Engine │ │ Filtering │ │ Output │ │
│ │ (YAML) │──▶│ Engine │──▶│ Channels │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ ▲ │ │
│ │ ▼ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Syscalls │ │ Slack/PD/ │ │
│ │ Events │ │ SIEM/K8s │ │
│ └─────────────┘ └─────────────┘ │
├─────────────────────────────────────────────────────────┤
│ Kernel Space │
│ ┌─────────────────────────────────────────────────┐ │
│ │ eBPF Probe (Modern Driver) │ │
│ │ - sys_enter/sys_exit tracepoints │ │
│ │ - 低オーバーヘッド・高精度 │ │
│ └─────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
Falcoルール例
# /etc/falco/rules.d/custom_rules.yaml
# コンテナ内でのシェル実行を検出
- rule: Shell Spawned in Container
desc: Detect shell spawned in a container
condition: >
spawned_process and
container and
shell_procs and
not shell_spawned_by_known_process
output: >
Shell spawned in container
(user=%user.name container=%container.name
shell=%proc.name parent=%proc.pname
cmdline=%proc.cmdline image=%container.image.repository)
priority: WARNING
tags: [container, shell, mitre_execution]
# 機密ファイルへのアクセスを検出
- rule: Read Sensitive File
desc: Detect read of sensitive files
condition: >
open_read and
container and
sensitive_files and
not proc.name in (allowed_sensitive_file_readers)
output: >
Sensitive file opened for reading
(user=%user.name file=%fd.name
container=%container.name image=%container.image.repository)
priority: WARNING
tags: [filesystem, mitre_credential_access]
# 異常なネットワーク接続を検出
- rule: Unexpected Outbound Connection
desc: Detect unexpected outbound network connection
condition: >
outbound and
container and
not expected_outbound_connection and
not fd.sip in (allowed_outbound_ips)
output: >
Unexpected outbound connection
(user=%user.name command=%proc.cmdline
connection=%fd.name container=%container.name
image=%container.image.repository)
priority: NOTICE
tags: [network, mitre_exfiltration]
# 特権コンテナの実行を検出
- rule: Privileged Container Started
desc: Detect privileged container
condition: >
container_started and
container.privileged=true
output: >
Privileged container started
(user=%user.name container=%container.name
image=%container.image.repository)
priority: WARNING
tags: [container, cis, mitre_privilege_escalation]
# クリプトマイニングの兆候を検出
- rule: Detect Crypto Mining
desc: Detect crypto mining processes
condition: >
spawned_process and
(proc.name in (crypto_miners) or
proc.cmdline contains "stratum+tcp" or
proc.cmdline contains "xmrig" or
proc.cmdline contains "minerd")
output: >
Crypto mining detected
(user=%user.name command=%proc.cmdline
container=%container.name image=%container.image.repository)
priority: CRITICAL
tags: [cryptomining, mitre_resource_hijacking]
FalcoのKubernetesデプロイ
# Helm values.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: falco-config
namespace: falco
data:
falco.yaml: |
# eBPFドライバーを使用
driver:
kind: modern_ebpf
# JSON出力形式
json_output: true
json_include_output_property: true
# 出力先設定
stdout_output:
enabled: true
# Webhook出力
http_output:
enabled: true
url: "http://falcosidekick:2801/"
# gRPC出力
grpc:
enabled: true
bind_address: "0.0.0.0:5060"
# Kubernetes監査ログ統合
webserver:
enabled: true
listen_port: 8765
k8s_audit_endpoint: /k8s-audit
---
# Falcosidekickで各種サービスに連携
apiVersion: apps/v1
kind: Deployment
metadata:
name: falcosidekick
namespace: falco
spec:
replicas: 2
template:
spec:
containers:
- name: falcosidekick
image: falcosecurity/falcosidekick:latest
env:
# Slack通知
- name: SLACK_WEBHOOKURL
valueFrom:
secretKeyRef:
name: falco-secrets
key: slack-webhook
# PagerDuty連携
- name: PAGERDUTY_ROUTINGKEY
valueFrom:
secretKeyRef:
name: falco-secrets
key: pagerduty-key
# Elasticsearch送信
- name: ELASTICSEARCH_HOSTPORT
value: "elasticsearch.logging:9200"
- name: ELASTICSEARCH_INDEX
value: "falco-alerts"
Pixie - eBPFオブザーバビリティ
Pixieは、eBPFによる自動計装オブザーバビリティプラットフォームです。コード変更なしで、Kubernetes上のアプリケーションを深く可視化します。
Pixieの特徴
┌─────────────────────────────────────────────────────────┐
│ Pixie Platform │
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ PxL (Pixie Language) │ │
│ │ - Pythonライクなクエリ言語 │ │
│ │ - リアルタイムデータ分析 │ │
│ └──────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Data Collection │ │
│ │ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │ │
│ │ │ HTTP │ │ MySQL │ │ Redis │ │ gRPC │ │ │
│ │ │ │ │ │ │ │ │ │ │ │
│ │ └────────┘ └────────┘ └────────┘ └────────┘ │ │
│ │ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │ │
│ │ │Postgres│ │ Kafka │ │ DNS │ │ ... │ │ │
│ │ └────────┘ └────────┘ └────────┘ └────────┘ │ │
│ └──────────────────────────────────────────────────┘ │
│ ▲ │
│ │ eBPF │
├─────────────────────────┼───────────────────────────────┤
│ Linux Kernel │ │
│ ┌──────────────────────┴───────────────────────────┐ │
│ │ Syscall Tracing | Network Tracing | CPU Profiling│ │
│ └──────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
PxLクエリ例
# HTTP リクエストレイテンシ分析
import px
# 過去5分間のHTTPリクエストを取得
df = px.DataFrame(table='http_events', start_time='-5m')
# サービスごとのレイテンシ統計
df = df.groupby(['service', 'req_path']).agg(
count=('latency', px.count),
avg_latency=('latency', px.mean),
p50_latency=('latency', px.quantile, 0.5),
p99_latency=('latency', px.quantile, 0.99),
error_rate=('resp_status', lambda x: px.mean(x >= 400))
)
# 結果をソート
df = df.sort('p99_latency', ascending=False)
px.display(df, 'HTTP Latency by Service')
# データベースクエリ分析
import px
# MySQLクエリを取得
df = px.DataFrame(table='mysql_events', start_time='-10m')
# スロークエリを抽出
slow_queries = df[df['latency'] > 100000000] # 100ms以上
# クエリパターンごとに集計
slow_queries = slow_queries.groupby(['req_body']).agg(
count=('latency', px.count),
avg_latency_ms=('latency', lambda x: px.mean(x) / 1000000),
max_latency_ms=('latency', lambda x: px.max(x) / 1000000)
)
px.display(slow_queries.head(20), 'Top 20 Slow Queries')
# CPU プロファイリング
import px
# CPU使用率の高いプロセスを特定
df = px.DataFrame(table='process_stats', start_time='-5m')
# コンテナごとのCPU使用率
df = df.groupby(['container_name', 'cmdline']).agg(
avg_cpu=('cpu_usage', px.mean),
max_cpu=('cpu_usage', px.max),
memory_mb=('memory_usage', lambda x: px.mean(x) / 1024 / 1024)
)
df = df[df['avg_cpu'] > 0.1] # 10%以上
df = df.sort('avg_cpu', ascending=False)
px.display(df.head(20), 'High CPU Processes')
PixieのKubernetesデプロイ
# Pixie CLIでのデプロイ
# $ px deploy
apiVersion: v1
kind: Namespace
metadata:
name: pl
---
# Vizierエージェント設定
apiVersion: px.dev/v1alpha1
kind: Vizier
metadata:
name: pixie
namespace: pl
spec:
version: "0.15.0"
deployKey: <deploy-key>
cloudAddr: "withpixie.ai:443"
# PEM(Pixie Edge Module)設定
pemMemoryLimit: "2Gi"
pemMemoryRequest: "1Gi"
# データ保持期間
dataRetention: "24h"
# 監視対象の名前空間
customPEMFlags:
PL_STIRLING_SOURCES_NAMESPACES: "default,production,staging"
# リソース制限
resources:
limits:
memory: "2Gi"
requests:
memory: "1Gi"
cpu: "500m"
実装例:eBPFによるセキュリティモニタリング
カスタムeBPFプログラム
// security_monitor.bpf.c
#include <linux/bpf.h>
#include <linux/ptrace.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
// イベント構造体
struct event {
__u32 pid;
__u32 uid;
__u32 gid;
char comm[16];
char filename[256];
__u64 timestamp;
};
// Ring Buffer
struct {
__uint(type, BPF_MAP_TYPE_RINGBUF);
__uint(max_entries, 256 * 1024);
} events SEC(".maps");
// 疑わしいファイルパス
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 1024);
__type(key, char[256]);
__type(value, __u32);
} suspicious_paths SEC(".maps");
// openatシステムコールをフック
SEC("tracepoint/syscalls/sys_enter_openat")
int trace_openat(struct trace_event_raw_sys_enter *ctx) {
struct event *e;
const char *filename;
__u32 *is_suspicious;
char path[256] = {};
// ファイル名を取得
filename = (const char *)ctx->args[1];
bpf_probe_read_user_str(path, sizeof(path), filename);
// 疑わしいパスかチェック
is_suspicious = bpf_map_lookup_elem(&suspicious_paths, path);
if (!is_suspicious)
return 0;
// イベントを送信
e = bpf_ringbuf_reserve(&events, sizeof(*e), 0);
if (!e)
return 0;
e->pid = bpf_get_current_pid_tgid() >> 32;
e->uid = bpf_get_current_uid_gid() & 0xFFFFFFFF;
e->gid = bpf_get_current_uid_gid() >> 32;
e->timestamp = bpf_ktime_get_ns();
bpf_get_current_comm(&e->comm, sizeof(e->comm));
__builtin_memcpy(e->filename, path, sizeof(e->filename));
bpf_ringbuf_submit(e, 0);
return 0;
}
// execveシステムコールをフック
SEC("tracepoint/syscalls/sys_enter_execve")
int trace_execve(struct trace_event_raw_sys_enter *ctx) {
struct event *e;
const char *filename;
e = bpf_ringbuf_reserve(&events, sizeof(*e), 0);
if (!e)
return 0;
filename = (const char *)ctx->args[0];
e->pid = bpf_get_current_pid_tgid() >> 32;
e->uid = bpf_get_current_uid_gid() & 0xFFFFFFFF;
e->gid = bpf_get_current_uid_gid() >> 32;
e->timestamp = bpf_ktime_get_ns();
bpf_get_current_comm(&e->comm, sizeof(e->comm));
bpf_probe_read_user_str(e->filename, sizeof(e->filename), filename);
bpf_ringbuf_submit(e, 0);
return 0;
}
char LICENSE[] SEC("license") = "GPL";
ユーザー空間プログラム(Go)
// main.go
package main
import (
"bytes"
"encoding/binary"
"fmt"
"log"
"os"
"os/signal"
"syscall"
"github.com/cilium/ebpf"
"github.com/cilium/ebpf/link"
"github.com/cilium/ebpf/ringbuf"
"github.com/cilium/ebpf/rlimit"
)
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -cc clang security_monitor security_monitor.bpf.c
type Event struct {
Pid uint32
Uid uint32
Gid uint32
Comm [16]byte
Filename [256]byte
Timestamp uint64
}
func main() {
// メモリ制限を解除
if err := rlimit.RemoveMemlock(); err != nil {
log.Fatalf("Failed to remove memlock: %v", err)
}
// eBPFプログラムをロード
objs := security_monitorObjects{}
if err := loadSecurity_monitorObjects(&objs, nil); err != nil {
log.Fatalf("Failed to load eBPF objects: %v", err)
}
defer objs.Close()
// 疑わしいパスを登録
suspiciousPaths := []string{
"/etc/passwd",
"/etc/shadow",
"/root/.ssh/authorized_keys",
"/proc/self/environ",
}
for _, path := range suspiciousPaths {
key := make([]byte, 256)
copy(key, path)
value := uint32(1)
if err := objs.SuspiciousPaths.Put(key, value); err != nil {
log.Printf("Failed to add path %s: %v", path, err)
}
}
// トレースポイントにアタッチ
tpOpenat, err := link.Tracepoint("syscalls", "sys_enter_openat", objs.TraceOpenat, nil)
if err != nil {
log.Fatalf("Failed to attach openat tracepoint: %v", err)
}
defer tpOpenat.Close()
tpExecve, err := link.Tracepoint("syscalls", "sys_enter_execve", objs.TraceExecve, nil)
if err != nil {
log.Fatalf("Failed to attach execve tracepoint: %v", err)
}
defer tpExecve.Close()
// Ring Bufferからイベントを読み取り
rd, err := ringbuf.NewReader(objs.Events)
if err != nil {
log.Fatalf("Failed to create ring buffer reader: %v", err)
}
defer rd.Close()
// シグナルハンドラ
sig := make(chan os.Signal, 1)
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
fmt.Println("Security Monitor started. Press Ctrl+C to exit.")
fmt.Println("Monitoring suspicious file access and process execution...")
go func() {
<-sig
rd.Close()
}()
// イベントループ
for {
record, err := rd.Read()
if err != nil {
if err == ringbuf.ErrClosed {
break
}
log.Printf("Error reading from ring buffer: %v", err)
continue
}
var event Event
if err := binary.Read(bytes.NewReader(record.RawSample), binary.LittleEndian, &event); err != nil {
log.Printf("Error parsing event: %v", err)
continue
}
comm := string(bytes.TrimRight(event.Comm[:], "\x00"))
filename := string(bytes.TrimRight(event.Filename[:], "\x00"))
fmt.Printf("[ALERT] PID=%d UID=%d COMM=%s FILE=%s\n",
event.Pid, event.Uid, comm, filename)
}
}
2025年のeBPF動向
Linux Kernel 6.12以降の新機能
| 機能 | 説明 | ユースケース |
|---|---|---|
| BPF Token | 細粒度権限管理 | コンテナ内でのeBPF |
| Arena Maps | 大容量メモリマップ | MLモデル処理 |
| BPF LSM | セキュリティモジュール統合 | カスタムセキュリティポリシー |
| Typed Pointers | 型安全なポインタ | Verifier精度向上 |
主要プロジェクトの成熟度
┌────────────────────────────────────────────────────────┐
│ eBPF エコシステム成熟度 (2025) │
├────────────────┬─────────────┬─────────────────────────┤
│ プロジェクト │ 成熟度 │ 採用状況 │
├────────────────┼─────────────┼─────────────────────────┤
│ Cilium │ Graduated │ 大規模本番環境で標準 │
│ Falco │ Graduated │ セキュリティ基盤として確立 │
│ Pixie │ Sandbox │ オブザーバビリティで急成長 │
│ Tetragon │ Incubating │ ランタイム強制で注目 │
│ Katran │ Production │ Meta社で大規模運用 │
│ bpftrace │ Stable │ デバッグの標準ツール │
└────────────────┴─────────────┴─────────────────────────┘
パフォーマンス比較
# iptables vs eBPF (Cilium) パフォーマンス比較
benchmark_results:
throughput:
iptables: "100,000 pps"
cilium_ebpf: "1,000,000 pps"
improvement: "10x"
latency:
iptables_p99: "150 microseconds"
cilium_ebpf_p99: "15 microseconds"
improvement: "10x"
cpu_overhead:
iptables: "15%"
cilium_ebpf: "3%"
improvement: "5x"
memory_footprint:
iptables: "500MB (100k rules)"
cilium_ebpf: "50MB (100k rules)"
improvement: "10x"
Windows eBPFサポート
2025年、MicrosoftはWindows上でのeBPFサポートを強化しています:
# Windows eBPF for Windows (ebpf-for-windows)
# インストール
winget install Microsoft.eBPF
# 動作確認
bpftool prog list
# Ciliumとの互換性
# Windows Nodeでも同じCilium Network Policyが適用可能
まとめ
2025年、eBPFはクラウドネイティブインフラの中核技術として確立されました:
- Cilium: Kubernetesネットワーキングの標準として、kube-proxyの置き換えやサイドカーレスService Meshを実現
- Falco: ランタイムセキュリティのデファクトスタンダードとして、コンテナの脅威検出を自動化
- Pixie: コード変更不要のオブザーバビリティで、アプリケーションの深い可視化を提供
eBPFの強みは、カーネルレベルの高速処理と安全なサンドボックス実行を両立している点です。従来のカーネルモジュールと異なり、Verifierによる安全性保証があるため、本番環境での採用リスクが低減されています。
今後も、AIワークロードの最適化、セキュリティポリシーの自動化、マルチクラウド環境での統一監視など、eBPFの活用領域は拡大していくでしょう。クラウドネイティブ開発者にとって、eBPFの理解は必須スキルとなっています。
← 一覧に戻る参考リソース:
- eBPF.io - eBPF公式サイト
- Cilium Documentation - Cilium公式ドキュメント
- Falco Documentation - Falco公式ドキュメント
- Pixie Documentation - Pixie公式ドキュメント