はじめに
2025年7月29日、Cilium 1.18がリリースされました。
3298コミット、955人以上のコントリビューター、GitHub Stars 22,000超え。CNCFのGraduatedプロジェクトとして、Kubernetesネットワークの世界で存在感を増しています。
「eBPFがアツい」「Ciliumがkube-proxyを置き換える」そんな話を聞きつつも、なかなか手を動かせていなかったので、この機会にローカル環境で試してみました。
この記事では、kindを使ってCilium + Hubbleを構築し、eBPFベースのネットワーク可視化を体験するまでの手順を紹介します。
Ciliumってなに?
Ciliumは、eBPF(extended Berkeley Packet Filter)を基盤としたCNI(Container Network Interface)プラグインです。
従来のCNI(Flannel、Calico等)との違い
従来のKubernetesネットワークはiptablesでパケット処理を行っていました。
◼︎従来のフロー
パケット → iptables → ユーザー空間 → 判定 → カーネル → 転送
iptablesはルール数が増えると線形に遅くなり、大規模クラスタではボトルネックになりがちです。一方、CiliumはeBPFを使ってカーネル内で直接パケット処理を行います。
◼︎Ciliumのフロー
パケット → カーネル内のeBPFプログラム → 転送
| 項目 | 従来(iptables) | Cilium(eBPF) |
|---|---|---|
| パケット処理 | ユーザー空間 ↔ カーネル空間を行き来 | カーネル内で完結 |
| ルール数増加時 | 線形に遅くなる | 影響が少ない |
| 可視化 | 別ツールが必要 | Hubble統合 |
| L7ポリシー | 実装が難しい | ネイティブ対応 |
| kube-proxy | 必要 | 置き換え可能 |
eBPFとは
eBPFは、カーネルを再コンパイルせずに、カーネル内でカスタムプログラムを実行できる技術です。

従来のカーネル拡張との違い
| 方法 | 特徴 | リスク |
|---|---|---|
| カーネル再コンパイル | 機能追加のたびにカーネルをビルド | 運用負荷大、互換性問題 |
| カーネルモジュール | 動的にロード可能 | バグでカーネルパニックの可能性 |
| eBPF | 検証器でチェック後にカーネル内で実行 | 安全性が担保される |
eBPFの仕組み
eBPFプログラムは 検証器(Verifier) によって安全性がチェックされるため、カーネルをクラッシュさせるようなコードは実行前にリジェクトされます。

https://ebpf.io/ja/what-is-ebpf/#%E6%A4%9C%E8%A8%BC から抜粋
もともとはパケットフィルタリング用途のようでしたが、現在ではネットワーク、セキュリティ、オブザーバビリティなど幅広い用途で使われており、Netflix、Google、Metaなど大規模なトラフィックを捌く企業で採用が進んでいます。
Hubbleとは
Hubbleは、Ciliumに統合されたネットワーク可視化・オブザーバビリティツールです。
従来のKubernetesネットワーク可視化の課題
Kubernetesのネットワークトラブルシューティングは大変でした。「このPodはどこと通信してる?」「なぜ通信が失敗してる?」を調べるには、以下のような方法が必要でした。
| 方法 | 概要 | 課題 |
|---|---|---|
| tcpdump / Wireshark | 手動でパケットキャプチャ | 大規模クラスタでは非現実的、Pod特定が困難 |
| Envoy Sidecar(Istio等) | 各Podにプロキシを注入して通信を観測 | 全Podにサイドカー必要、リソースオーバーヘッド大 |
| Datadog / New Relic等 | SaaS型のAPM/オブザーバビリティ | エージェント導入が必要、コストがかかる |
| アプリへのログ埋め込み | 自前で通信ログを実装 | コード変更が必要、開発工数がかかる |
Hubbleのアプローチ
HubbleはeBPFを活用してカーネルレベルで通信を観測します。
| 特徴 | 説明 |
|---|---|
| サイドカー不要 | Podへの変更なしで全トラフィックを観測 |
| 低オーバーヘッド | カーネル内で処理するためCPU/メモリ消費が少ない |
| コード変更不要 | アプリケーションに手を加えずに可視化 |
| L3/L4/L7対応 | TCP接続からHTTPリクエストまで可視化可能 |
Hubbleを使えば、以下のことがUIやCLIで簡単に確認できます。
- リアルタイムのトラフィック監視:どのPodがどこと通信しているか
- サービスマップ:依存関係の可視化
- NetworkPolicyの動作確認:許可/拒否がひと目でわかる
-
L7レベルの観測:HTTPリクエスト、gRPCコールなど

https://github.com/cilium/hubble から引用
Cilium 1.18の主な新機能
今回のリリースでは、以下のような機能が追加されています。
ネットワーク
- ロードバランシングの再設計:メモリ使用量の削減と拡張性の向上
- Ingress帯域制限:bandwidth managerでIngress方向のレート制限が可能に
- 複数Egress Gateway:1つのポリシーで複数のゲートウェイノードを指定可能
IPv6
- トンネルモードでIPv6アンダーレイ対応:IPsec暗号化と組み合わせ可能
- IPv6フラグメント対応:順序付きIPv6フラグメントの処理に対応
オブザーバビリティ
- Hubble CLIでポリシー名表示:どの(C)CNPが通信を許可/拒否したかが見える
- カプセル化トラフィックのデコード:より深い可視化
パフォーマンス
- ポリシー・サービス実装が最大45%高速化
- Dockerイメージサイズ32%削減(arm64)
詳細はリリースノートをご参照ください。
環境構築
それでは実際に動かしてみます。kindを使えば30分程度で環境構築からHubbleでの可視化まで試せます。
前提条件
- Docker Desktop(またはDocker Engine)
- kind
- Homebrew(Macの場合)
1. Cilium CLIのインストール
brew install cilium-cli
インストール確認
cilium version --client
cilium-cli: v0.18.9 compiled with go1.25.5 on darwin/arm64
cilium image (default): v1.18.3
cilium image (stable): v1.18.4
2. kindクラスタの作成(CNIなし)
CiliumをCNIとして使うため、kindのデフォルトCNIを無効化してクラスタを作成します。
(事前にDocker Engineを起動します)
cat <<EOF | kind create cluster --name cilium-demo --config=-
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
networking:
disableDefaultCNI: true
kubeProxyMode: none
nodes:
- role: control-plane
- role: worker
- role: worker
EOF
設定のポイント
-
disableDefaultCNI: true:kindのデフォルトCNI(kindnet)を無効化 -
kubeProxyMode: none:kube-proxyも無効化(CiliumがeBPFで代替) - workerノード2台:Pod間通信を試すため
クラスタ作成後、PodはPending状態になります。
CNIがまだインストールされていないためで、これは正常な状態です。次のステップでCiliumをインストールするとRunningになります。
kubectl get pods -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-5d78c9869d-llfq5 0/1 Pending 0 46s
kube-system coredns-5d78c9869d-prnqh 0/1 Pending 0 46s
kube-system etcd-cilium-demo-control-plane 1/1 Running 0 62s
kube-system kube-apiserver-cilium-demo-control-plane 1/1 Running 0 62s
...
3. Ciliumのインストール
Hubble UIも一緒に有効化してインストールします。
cilium install --set hubble.relay.enabled=true --set hubble.ui.enabled=true
# 出力結果
🔮 Auto-detected Kubernetes kind: kind
ℹ️ Using Cilium version 1.18.3
🔮 Auto-detected cluster name: kind-cilium-demo
ℹ️ Detecting real Kubernetes API server addr and port on Kind
🔮 Auto-detected kube-proxy has not been installed
ℹ️ Cilium will fully replace all functionalities of kube-proxy
...魔法みたいな絵文字が出てきてワクワクします。
インストール完了まで待機します。
cilium status --wait
/¯¯\
/¯¯\__/¯¯\ Cilium: OK
\__/¯¯\__/ Operator: OK
/¯¯\__/¯¯\ Envoy DaemonSet: OK
\__/¯¯\__/ Hubble Relay: OK
\__/ ClusterMesh: disabled
DaemonSet cilium Desired: 3, Ready: 3/3, Available: 3/3
DaemonSet cilium-envoy Desired: 3, Ready: 3/3, Available: 3/3
Deployment cilium-operator Desired: 1, Ready: 1/1, Available: 1/1
Deployment hubble-relay Desired: 1, Ready: 1/1, Available: 1/1
Deployment hubble-ui Desired: 1, Ready: 1/1, Available: 1/1
Containers: cilium Running: 3
cilium-envoy Running: 3
cilium-operator Running: 1
clustermesh-apiserver
hubble-relay Running: 1
hubble-ui Running: 1
Cluster Pods: 5/5 managed by Cilium
Helm chart version: 1.18.3
Image versions cilium quay.io/cilium/cilium:v1.18.3@sha256:5649db451c88d928ea585514746d50d91e6210801b300c897283ea319d68de15: 3
cilium-envoy quay.io/cilium/cilium-envoy:v1.34.10-1761014632-c360e8557eb41011dfb5210f8fb53fed6c0b3222@sha256:ca76eb4e9812d114c7f43215a742c00b8bf41200992af0d21b5561d46156fd15: 3
cilium-operator quay.io/cilium/operator-generic:v1.18.3@sha256:b5a0138e1a38e4437c5215257ff4e35373619501f4877dbaf92c89ecfad81797: 1
hubble-relay quay.io/cilium/hubble-relay:v1.18.3@sha256:e53e00c47fe4ffb9c086bad0c1c77f23cb968be4385881160683d9e15aa34dc3: 1
hubble-ui quay.io/cilium/hubble-ui-backend:v0.13.3@sha256:db1454e45dc39ca41fbf7cad31eec95d99e5b9949c39daaad0fa81ef29d56953: 1
hubble-ui quay.io/cilium/hubble-ui:v0.13.3@sha256:661d5de7050182d495c6497ff0b007a7a1e379648e60830dd68c4d78ae21761d: 1
全てOKになっていれば成功です!
(筆者はDockerのディスク容量が足りずエラーとなったので、不要リソースを削除して待機したところ、Ciliumのイメージが正常に起動されました)
4. Hubble CLIのインストール
brew install hubble
Hubble Relayに接続できるようポートフォワードを設定します。
cilium hubble port-forward &
接続確認
hubble status
# 出力結果
Healthcheck (via localhost:4245): Ok
Current/Max Flows: 5,612/12,285 (45.68%)
Flows/s: 16.07
Connected Nodes: 3/3
実践:トラフィックを可視化してみる
サンプルアプリのデプロイ
通信を可視化するためのシンプルなアプリをデプロイします。
# curlが使えるクライアントPod
kubectl create deployment client --image=curlimages/curl -- sleep infinity
# レスポンスを返すサーバーPod
kubectl create deployment server --image=traefik/whoami
kubectl expose deployment server --port=80
Podが起動したことを確認します。
kubectl get pods -w
トラフィックを生成
継続的にリクエストを送信します。
kubectl exec deployment/client -- sh -c 'while true; do curl -s server; sleep 1; done'
# 出力結果
Hostname: server-74575447bc-l9zt5
IP: 127.0.0.1
IP: ::1
IP: xx.xx.xx.xx
IP: xx.xx.xx.xx
RemoteAddr: xx.xx.xx.xx:34568
GET / HTTP/1.1
Host: server
User-Agent: curl/8.17.0
Accept: */*
...
Hubble CLIでトラフィック観測
別ターミナルでHubbleを起動します。
hubble observe --namespace default -f
# 出力結果
Dec 14 10:45:47.483: default/client-cb975b8bc-nb4kx:51944 (ID:4605) -> default/server-74575447bc-l9zt5:80 (ID:22656) to-endpoint FORWARDED (TCP Flags: SYN)
Dec 14 10:45:47.483: default/client-cb975b8bc-nb4kx:51944 (ID:4605) <- default/server-74575447bc-l9zt5:80 (ID:22656) to-endpoint FORWARDED (TCP Flags: SYN, ACK)
Dec 14 10:45:47.483: default/client-cb975b8bc-nb4kx:51944 (ID:4605) -> default/server-74575447bc-l9zt5:80 (ID:22656) to-endpoint FORWARDED (TCP Flags: ACK)
Dec 14 10:45:47.483: default/client-cb975b8bc-nb4kx:51944 (ID:4605) <> default/server-74575447bc-l9zt5 (ID:22656) pre-xlate-rev TRACED (TCP)
client → server への通信がリアルタイムで見えます!
便利なフィルタオプション
HTTP通信のみ表示
hubble observe --namespace default --protocol http -f
L7可視化を有効にする必要があります。
CiliumNetworkPolicyでL7ルールを適用すると、HTTP通信の詳細が見えるようになります。
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: l7-visibility
namespace: default
spec:
endpointSelector:
matchLabels:
app: server
ingress:
- fromEndpoints:
- {}
toPorts:
- ports:
- port: "80"
protocol: TCP
rules:
http:
- method: "GET"
# 出力結果
Dec 14 10:51:53.966: default/client-cb975b8bc-nb4kx:54232 (ID:4605) <- default/server-74575447bc-l9zt5:80 (ID:22656) http-response FORWARDED (HTTP/1.1 200 3ms (GET http://server/))
Dec 14 10:51:54.280: default/client-cb975b8bc-nb4kx:54234 (ID:4605) -> default/server-74575447bc-l9zt5:80 (ID:22656) http-request FORWARDED (HTTP/1.1 GET http://server/)
Dec 14 10:51:54.282: default/client-cb975b8bc-nb4kx:54234 (ID:4605) <- default/server-74575447bc-l9zt5:80 (ID:22656) http-response FORWARDED (HTTP/1.1 200 3ms (GET http://server/))
DROPされた通信のみ(後続のNetworkPolicy検証で使います)
hubble observe --verdict DROPPED -f
Hubble UIで可視化
cilium hubble ui
ブラウザで http://localhost:12000 が開きます。

Hubble UIで以下のことが可能です。
特にService Mapは、マイクロサービス構成の可視化に便利です。
実践:NetworkPolicyを試す
Ciliumの真価はNetworkPolicyで発揮されます。eBPFベースなので、iptablesより効率的にポリシーを適用できます。
serverへのアクセスを制限
まず、serverへの全てのIngressトラフィックを拒否するポリシーを適用します。
# deny-server-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-server-ingress
namespace: default
spec:
podSelector:
matchLabels:
app: server
policyTypes:
- Ingress
kubectl apply -f deny-server-ingress.yaml
clientからアクセスしてみると、タイムアウトします。
kubectl exec deployment/client -- curl -s --max-time 5 server
# タイムアウト
CiliumNetworkPolicyとKubernetes NetworkPolicyが両方あると、CiliumNetworkPolicyが優先されます。
そのため、先ほど作成したl7-visibilityのCiliumNetworkPolicyは削除しています。
Hubbleでポリシー適用を確認
hubble observe --verdict DROPPED -f
Dec 14 11:01:38.772: default/client-cb975b8bc-nb4kx:35044 (ID:4605) <> default/server-74575447bc-l9zt5:80 (ID:22656) Policy denied DROPPED (TCP Flags: SYN)
Dec 14 11:01:40.819: default/client-cb975b8bc-nb4kx:35044 (ID:4605) <> default/server-74575447bc-l9zt5:80 (ID:22656) policy-verdict:none INGRESS DENIED (TCP Flags: SYN)
DROPPEDとして表示され、どの通信がポリシーによって拒否されたかが明確にわかります。
Hubble UIでもイベント表示を確認できます。

まとめ
今回はCilium + Hubbleをkindで試してみましたが、eBPFを意識せずともネットワーク可視化やNetworkPolicyのデバッグがここまで簡単にできるのは驚きでした。
良かった点
- 可視化が圧倒的に楽:Hubble UIでPod間通信がひと目でわかる
- NetworkPolicyのデバッグが簡単:どの通信を許可/拒否したか明確
-
導入のハードルが低い:
cilium install一発で完了 - kube-proxy不要:eBPFでサービスロードバランシングも実現
特にHubbleの--verdict DROPPEDは、本番環境でのトラブルシューティングでも重宝しそうです。まずはkindで感覚を掴めたので、次は検証環境での導入を検討してみたいと思います。
本番導入を考えた場合
今回はkindで試しましたが、本番環境では以下の検討が必要です。
- カーネルバージョン:Linux 5.10以上推奨(RHEL 8.10相当)
- 既存CNIからの移行:Cilium Migration Guideを参照
- モニタリング統合:PrometheusやGrafanaとの連携 etc
次に試してみたいこと
- Tetragon:eBPFベースのランタイムセキュリティ
- ClusterMesh:マルチクラスタ接続
- Gateway API:Ciliumの次世代Ingress
この記事が少しでも誰かの参考になれば幸いです。
参考資料
