- Authors
- Name
eBPFとは?
eBPF(extended Berkeley Packet Filter)は、Linuxカーネル内部でサンドボックス化されたプログラムを実行できるようにする技術です。カーネルモジュールを修正せずにネットワーキング、セキュリティ、観測性の機能を追加できます。
従来の観測方式 vs eBPF
| 方式 | オーバーヘッド | カーネル修正 | 可視性 |
|---|---|---|---|
| ログ(stdout) | 中程度 | 不要 | アプリレベルのみ |
| Prometheusメトリクス | 低い | 不要 | アプリが公開するもののみ |
| サイドカープロキシ(Envoy) | 高い | 不要 | L7まで |
| eBPF | 非常に低い | 不要 | カーネルからL7まで |
eBPFの核心的な利点は、エージェントなしでカーネルレベルで観測できることです。
Cilium + Hubble:ネットワーク観測性
Ciliumインストール
# Cilium CLIインストール
CILIUM_CLI_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/cilium-cli/main/stable.txt)
curl -L --fail --remote-name-all \
https://github.com/cilium/cilium-cli/releases/download/${CILIUM_CLI_VERSION}/cilium-linux-amd64.tar.gz
sudo tar xzvfC cilium-linux-amd64.tar.gz /usr/local/bin
rm cilium-linux-amd64.tar.gz
# Ciliumインストール(Hubble含む)
cilium install --version 1.16.5 \
--set hubble.relay.enabled=true \
--set hubble.ui.enabled=true \
--set hubble.metrics.enableOpenMetrics=true \
--set hubble.metrics.enabled="{dns,drop,tcp,flow,port-distribution,icmp,httpV2:exemplars=true;labelsContext=source_ip\,source_namespace\,source_workload\,destination_ip\,destination_namespace\,destination_workload\,traffic_direction}"
# ステータス確認
cilium status
cilium hubble port-forward &
Hubble CLIでネットワークフローを観察
# すべてのネットワークフローを観察
hubble observe
# 特定のNamespaceのフローのみ
hubble observe --namespace production
# DNSクエリ観察
hubble observe --protocol dns
# HTTPリクエスト観察(L7)
hubble observe --protocol http
# ドロップされたパケット観察(ネットワークポリシー違反など)
hubble observe --verdict DROPPED
# 特定のPod間通信
hubble observe --from-pod production/frontend --to-pod production/api-server
# JSON出力でパイプライン連携
hubble observe --namespace production -o json | jq '.flow.source.identity'
Hubble UI
# Hubble UIポートフォワーディング
kubectl port-forward -n kube-system svc/hubble-ui 12000:80
# ブラウザで http://localhost:12000 にアクセス
# サービスマップ + リアルタイムトラフィックフローを確認可能
HubbleメトリクスをPrometheusで収集
# Prometheus ServiceMonitor
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: hubble-metrics
namespace: kube-system
spec:
selector:
matchLabels:
k8s-app: hubble
endpoints:
- port: hubble-metrics
interval: 15s
# Grafanaダッシュボード用PromQLクエリ
# HTTPリクエスト率(サービス別)
sum(rate(hubble_http_requests_total[5m])) by (destination_workload, method, status)
# DNSエラー率
sum(rate(hubble_dns_responses_total{rcode!="No Error"}[5m])) by (source_workload, qtypes)
# ドロップされたパケット(ネットワークポリシー)
sum(rate(hubble_drop_total[5m])) by (reason, source_workload)
# TCP接続時間
histogram_quantile(0.99, sum(rate(hubble_tcp_connect_duration_seconds_bucket[5m])) by (le, destination_workload))
Tetragon:セキュリティ観測性
TetragonはeBPFベースのセキュリティ観測性+ランタイムセキュリティツールです。プロセス実行、ファイルアクセス、ネットワーク接続などをカーネルレベルで検知します。
Tetragonインストール
# Helmでインストール
helm repo add cilium https://helm.cilium.io
helm install tetragon cilium/tetragon -n kube-system
# Tetragon CLIインストール
GOOS=$(go env GOOS)
GOARCH=$(go env GOARCH)
curl -L --remote-name-all \
https://github.com/cilium/tetragon/releases/latest/download/tetra-${GOOS}-${GOARCH}.tar.gz
sudo tar -C /usr/local/bin -xzvf tetra-${GOOS}-${GOARCH}.tar.gz
プロセスイベントの観察
# すべてのプロセス実行イベント
kubectl exec -n kube-system ds/tetragon -c tetragon -- \
tetra getevents -o compact
# 出力例:
# 🚀 process default/nginx-7b4f... /bin/sh -c nginx -g 'daemon off;'
# 🚀 process default/nginx-7b4f... /usr/sbin/nginx -g daemon off;
# 💥 exit default/nginx-7b4f... /bin/sh -c nginx -g 'daemon off;' 0
TracingPolicy:カスタムセキュリティルール
# 機密ファイルアクセスの検知
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
name: sensitive-file-access
spec:
kprobes:
- call: 'fd_install'
syscall: false
args:
- index: 0
type: int
- index: 1
type: 'file'
selectors:
- matchArgs:
- index: 1
operator: 'Prefix'
values:
- '/etc/shadow'
- '/etc/passwd'
- '/root/.ssh'
- '/var/run/secrets/kubernetes.io'
# 外部ネットワーク接続の検知
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
name: external-connections
spec:
kprobes:
- call: 'tcp_connect'
syscall: false
args:
- index: 0
type: 'sock'
selectors:
- matchArgs:
- index: 0
operator: 'NotDAddr'
values:
- '10.0.0.0/8'
- '172.16.0.0/12'
- '192.168.0.0/16'
# TracingPolicyを適用
kubectl apply -f sensitive-file-access.yaml
# イベント観察
kubectl exec -n kube-system ds/tetragon -c tetragon -- \
tetra getevents -o compact --pods nginx
# テスト:nginx Podから/etc/shadowへのアクセスを試行
kubectl exec -it nginx -- cat /etc/shadow
# Tetragonイベント出力:
# 📬 open default/nginx /etc/shadow
カスタムeBPF観測ツール
bpftraceによる高速分析
# システムコール頻度(上位10件)
bpftrace -e 'tracepoint:raw_syscalls:sys_enter { @[comm] = count(); }
interval:s:5 { print(@, 10); clear(@); }'
# TCP再送追跡
bpftrace -e 'kprobe:tcp_retransmit_skb {
@retrans[comm, pid] = count();
}'
# ファイルオープン追跡
bpftrace -e 'tracepoint:syscalls:sys_enter_openat {
printf("%s PID:%d -> %s\n", comm, pid, str(args->filename));
}'
# 遅延が大きいディスクI/O(10ms以上)
bpftrace -e 'kprobe:blk_account_io_done {
$duration = nsecs - @start[arg0];
if ($duration > 10000000) {
printf("slow IO: %d ms, comm=%s\n", $duration/1000000, comm);
}
}'
Python + bccによるカスタムツール
#!/usr/bin/env python3
# tcp_latency.py - TCP接続レイテンシ追跡
from bcc import BPF
bpf_text = """
#include <net/sock.h>
#include <bcc/proto.h>
struct event_t {
u32 pid;
u32 daddr;
u16 dport;
u64 delta_us;
char comm[16];
};
BPF_HASH(start, struct sock *);
BPF_PERF_OUTPUT(events);
int trace_connect(struct pt_regs *ctx, struct sock *sk) {
u64 ts = bpf_ktime_get_ns();
start.update(&sk, &ts);
return 0;
}
int trace_tcp_rcv_state_process(struct pt_regs *ctx, struct sock *sk) {
if (sk->__sk_common.skc_state != TCP_SYN_SENT)
return 0;
u64 *tsp = start.lookup(&sk);
if (!tsp) return 0;
struct event_t event = {};
event.pid = bpf_get_current_pid_tgid() >> 32;
event.delta_us = (bpf_ktime_get_ns() - *tsp) / 1000;
event.daddr = sk->__sk_common.skc_daddr;
event.dport = sk->__sk_common.skc_dport;
bpf_get_current_comm(&event.comm, sizeof(event.comm));
events.perf_submit(ctx, &event, sizeof(event));
start.delete(&sk);
return 0;
}
"""
b = BPF(text=bpf_text)
b.attach_kprobe(event="tcp_v4_connect", fn_name="trace_connect")
b.attach_kprobe(event="tcp_rcv_state_process", fn_name="trace_tcp_rcv_state_process")
def print_event(cpu, data, size):
event = b["events"].event(data)
print(f"PID={event.pid} COMM={event.comm.decode()} "
f"DEST={socket.inet_ntoa(struct.pack('I', event.daddr))}:{socket.ntohs(event.dport)} "
f"LATENCY={event.delta_us}us")
b["events"].open_perf_buffer(print_event)
while True:
b.perf_buffer_poll()
eBPFツール比較
| ツール | 用途 | 長所 | 短所 |
|---|---|---|---|
| Hubble | ネットワーク観測 | Cilium統合、UI | Cilium必須 |
| Tetragon | セキュリティ観測 | ランタイムセキュリティ | 学習コスト |
| Pixie | 全体観測 | 自動計装、SQLクエリ | リソース使用量 |
| bpftrace | デバッグ | 高速なアドホック分析 | プロダクション不向き |
| Grafana Beyla | APM | 自動HTTP/gRPC計装 | L7のみ |
プロダクション導入ガイド
段階的導入戦略
Phase 1: Cilium + Hubble(ネットワーク可視性)
├── サービスマップ自動生成
├── DNSエラー検知
└── ネットワークポリシー違反モニタリング
Phase 2: Tetragon(セキュリティ観測)
├── プロセス実行監査
├── 機密ファイルアクセス検知
└── 外部接続モニタリング
Phase 3: カスタムeBPF(深層分析)
├── パフォーマンスプロファイリング
├── レイテンシ分析
└── カスタムメトリクス
リソースオーバーヘッド
Cilium Agent: ~200MB RAM, ~0.1 CPU per node
Hubble Relay: ~128MB RAM, ~0.05 CPU
Tetragon: ~256MB RAM, ~0.15 CPU per node
合計オーバーヘッド:ノードあたり ~1% CPU、~600MB RAM
→ サイドカープロキシ(Envoy)比で50〜70%削減
確認クイズ(6問)
Q1. eBPFが従来の観測方式より優れている点は?
カーネルレベルで動作するため、アプリケーション修正なしでネットワーク、プロセス、ファイルアクセスなどを観測でき、サイドカープロキシと比較してオーバーヘッドが非常に低いです。
Q2. HubbleでDNSエラーを観察するコマンドは?
hubble observe --protocol dns または DNSメトリクスの hubble_dns_responses_total{rcode!="No Error"} を確認
Q3. TetragonのTracingPolicyで検知できるイベントの種類は?
プロセス実行、ファイルアクセス(open)、ネットワーク接続(tcp_connect)、システムコールなどのカーネルレベルイベント
Q4. bpftraceとbccの違いは?
bpftraceはAWKスタイルの簡潔な構文で高速なアドホック分析に適しており、bccはPython/Cで複雑なカスタムツールを開発できます。
Q5. Cilium + Hubbleのノードあたりのリソースオーバーヘッドは概ね?
CPU約0.1コア、RAM約200MB(Hubble Relayは別途)
Q6. eBPFベースの観測導入で最初に推奨されるステップは?
Cilium + Hubbleでネットワーク可視性を確保すること。サービスマップ、DNSエラー、ネットワークポリシー違反を先にモニタリングします。