この記事のポイント
- Cilium は Linux
eBPFを使い、iptables ではなくカーネルレベルでパケットを制御する CNI プラグインです - Ubuntu 24.04 + kind(Kubernetes in Docker)で Cilium v1.17.4 を Helm でインストールし、実際に動作を確認しました
CiliumNetworkPolicyを適用すると、eBPF マップにポリシーが書き込まれ、cilium bpf policy listでパケット数まで確認できます- Hubble UI(可視化ダッシュボード)を port-forward で起動し、フロー観測ができます
- 本記事のすべてのコマンド出力は Ubuntu 24.04.4 LTS 上で 2026-06-20 に実測しています
Kubernetes のネットワーク周りで「CNI って何?」「Cilium を試してみたいけど難しそう」と感じている方に向けて書きました。
Cilium の大きな特徴は eBPF(extended Berkeley Packet Filter) を使っている点で、従来の iptables ベースの CNI と仕組みが根本的に違います。実際にインストールして動かしてみないと感覚がつかみにくいので、この記事では Ubuntu 24.04 + kind(Kubernetes in Docker)を使って一から手を動かします。
eBPF ポリシーの適用確認(cilium bpf policy list でパケットカウントまで見える)と、Hubble UI のスクリーンショットも載せています。
動作確認済み環境
- OS:Ubuntu 24.04.4 LTS(Noble Numbat)
- カーネル:6.8.0-83-generic
- Docker:29.5.3
- kind:v0.24.0 / Kubernetes v1.31.0
- Cilium:v1.17.4(Helm chart 1.17.4)
- cilium-cli:v0.19.4
- 検証日:2026-06-20

CNI と Cilium の基本を5分でおさらい
Kubernetes では Pod 間の通信を担う「CNI(Container Network Interface)プラグイン」が必須です。代表的なものに Flannel・Calico・kindnet などがあり、どれも iptables ルールを積み上げて通信を制御していました。ノードが増え Pod 数が増えると iptables テーブルが肥大化し、ルール追加のたびにカーネルへのロックが走る——これが大規模クラスタで問題になってきました。
Cilium はこの問題を eBPF で解決するアプローチです。eBPF は Linux 5.x 以降(Ubuntu 22.04 以上)でまともに使えるようになったカーネル技術で、カーネルコードを書き換えずにネットワーク処理をカーネル内に「注入」できます。iptables を介さずパケットを処理するため、ルール追加のコストが桁違いに小さくなります。
加えて Cilium には Hubble(可視化・監視レイヤー)が付属しており、Pod 間のネットワークフローをリアルタイムで見られる UI も使えます。
前提:ツールのインストール
Ubuntu 24.04 の環境で以下の3つをインストールします。手元にすでに動いている Kubernetes クラスタがあれば kind は不要です。
手順1:kubectl をインストールする
$ chmod +x kubectl && sudo mv kubectl /usr/local/bin/
$ kubectl version –client
Client Version: v1.36.2
手順2:kind をインストールする
$ chmod +x kind && sudo mv kind /usr/local/bin/
$ kind version
kind v0.24.0 go1.22.6 linux/amd64
手順3:cilium-cli と Helm をインストールする
$ curl -L “https://github.com/cilium/cilium-cli/releases/download/${CILIUM_CLI_VERSION}/cilium-linux-amd64.tar.gz” | tar xz
$ sudo mv cilium /usr/local/bin/
$ cilium version –client
cilium-cli: v0.19.4 compiled with go1.26.3 on linux/amd64
$ curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
kind クラスタを作成する
kind でシングルノードのクラスタを作ります。ここでは kindnet(kind のデフォルト CNI)を有効にしたまま Cilium を追加インストールします。CNI を完全に置き換える構成(disableDefaultCNI: true)も可能ですが、このホスト環境では kube-proxy が起動しきらない問題があったため、Helm の k8sServiceHost/k8sServicePort オプションで API サーバーを直指定する方法を採りました。
✓ Ensuring node image (kindest/node:v1.31.0)
✓ Preparing nodes
✓ Starting control-plane
✓ Installing CNI
Set kubectl context to “kind-cilium-demo”
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
cilium-demo-control-plane Ready control-plane 24s v1.31.0
Cilium を Helm でインストールする
Cilium の公式 Helm リポジトリを追加して v1.17.4 をインストールします。hubble.relay.enabled=true と hubble.ui.enabled=true を付けることで、Hubble UI もまとめてデプロイされます。

$ CONTROL_PLANE_IP=$(docker inspect cilium-demo-control-plane –format ‘{{.NetworkSettings.Networks.kind.IPAddress}}’)
$ helm install cilium cilium/cilium \
–version 1.17.4 \
–namespace kube-system \
–set ipam.mode=kubernetes \
–set hubble.relay.enabled=true \
–set hubble.ui.enabled=true \
–set k8sServiceHost=”${CONTROL_PLANE_IP}” \
–set k8sServicePort=6443
NAME: cilium STATUS: deployed REVISION: 1
You have successfully installed Cilium with Hubble Relay and Hubble UI.
ポイント:k8sServiceHost を指定する理由
Cilium の init コンテナはクラスタ内サービス IP(10.96.0.1)経由で API サーバーに接続しようとします。kube-proxy が正常動作していない環境では、このサービス IP への経路が張られておらず接続タイムアウトが発生します。k8sServiceHost に control-plane ノードの実 IP を渡すことで回避できます。
起動確認
インストール後、cilium status で稼働状況を確認します。私の環境では cilium-agent と Hubble UI が約2分で起動しました。
DaemonSet cilium Desired: 1, Ready: 1/1, Available: 1/1
DaemonSet cilium-envoy Desired: 1, Ready: 1/1, Available: 1/1
Deployment cilium-operator Desired: 2, Ready: 1/2
Deployment hubble-ui Desired: 1, Ready: 1/1, Available: 1/1
Helm chart version: 1.17.4

Hubble UI でフローを可視化する
Hubble は Cilium に組み込まれた可視化エンジンで、Pod 間のネットワークフローをリアルタイムに観測できます。起動後は kubectl port-forward でローカルに転送してブラウザから確認します。
Forwarding from 127.0.0.1:12000 -> 8081
# ブラウザで http://localhost:12000/ を開く

Hubble UI を開くと namespace のドロップダウンが表示されます。Pod 間の通信をグラフで俯瞰できます。フロー観測は Hubble Relay 経由になるため、Relay の起動も必要です(cilium hubble enable または Helm の hubble.relay.enabled=true)。

CiliumNetworkPolicy でアクセス制御する
Cilium の最大の特徴が CiliumNetworkPolicy(CNP)です。通常の Kubernetes NetworkPolicy とほぼ同じ書き方ですが、L7(HTTP メソッドやパスレベル)のフィルタや DNS ベースのルールも書けます。
手順1:テスト Pod をデプロイする
$ kubectl run web-server -n demo –image=nginx:alpine –labels=app=web
$ kubectl run client-pod -n demo –image=curlimages/curl –labels=app=client \
— sh -c “sleep 3600”
$ kubectl expose pod web-server -n demo –port=80 –name=web-service
$ kubectl get pods -n demo
NAME READY STATUS RESTARTS AGE
client-pod 1/1 Running 0 30s
web-server 1/1 Running 0 30s
手順2:CiliumNetworkPolicy を適用する
次の YAML は「demo namespace 内の app=web という Pod へのアクセスを、app=client ラベルを持つ Pod からの port 80 のみ許可する」ポリシーです。
kind: CiliumNetworkPolicy
metadata:
name: allow-client-to-web
namespace: demo
spec:
endpointSelector:
matchLabels:
app: web # このPodへの通信を制御
ingress:
– fromEndpoints:
– matchLabels:
app: client # app=client からのみ許可
toPorts:
– ports:
– port: “80”
protocol: TCP
ciliumnetworkpolicy.cilium.io/allow-client-to-web created
$ kubectl get cnp -n demo
NAME AGE VALID
allow-client-to-web 5s True
手順3:eBPF ポリシーマップを直接確認する
ここが Cilium の面白いところです。ポリシーを適用すると iptables ルールではなく eBPF マップ に書き込まれます。cilium bpf policy list コマンドで、エンドポイント単位のポリシーを低レイヤーで確認できます。

Endpoint ID: 578 (app=web)
POLICY DIRECTION LABELS PORT/PROTO BYTES PACKETS
Allow Ingress k8s:app=client 80/TCP 546 7
k8s:namespace=demo
$ kubectl exec -n demo client-pod — curl -s -o /dev/null \
-w ‘%{http_code}’ http://10.96.15.165/ –connect-timeout 5
200
BYTES: 546 / PACKETS: 7 というカウンタが実際に通過したパケット数です。iptables の場合は「ルールの一致件数」を iptables -nvL で見ますが、Cilium は eBPF マップを直接確認するためより精度の高い観測ができます。
コンポーネントバージョン一覧(実測)

| コンポーネント | バージョン | 役割 | 状態(実測) |
|---|---|---|---|
| cilium-agent | v1.17.4 | 各ノードで eBPF プログラムを管理 | Running 1/1 |
| cilium-envoy | v1.32.6 | L7 プロキシ(HTTP/gRPC フィルタ用) | Running 1/1 |
| cilium-operator | v1.17.4 | CRD 管理・IPAM 制御 | Running 1/2 |
| hubble-ui | v0.13.2 | フロー可視化 UI(nginx + React) | Running 1/1 |
| hubble-relay | v1.17.4 | Hubble gRPC 集約ハブ | Running |
よくあるエラーと解決策
①「cilium init container: i/o timeout」
Cilium の init コンテナがクラスタ内のサービス IP(10.96.0.1:443)に接続できない場合に発生します。kube-proxy の問題や、CNI なしクラスタでのサービス IP 未設定が原因のことが多いです。Helm インストール時に --set k8sServiceHost=<control-plane-IP> --set k8sServicePort=6443 を追加すると回避できます。
②「too many open files」(kubelet/kube-proxy)
コンテナ環境(kind 内の kind ネスト)で起きやすいカーネルリソース上限の問題です。ホスト側の /proc/sys/fs/file-max を増やすか、単ノードで試すと解消します。
③「ciliumnetworkpolicy.cilium.io not found」
Cilium Operator が CRD を登録する前に YAML を apply しようとすると出ます。cilium status で Operator が Ready になってから適用してください。
まとめ
Cilium は eBPF をフル活用した CNI プラグインで、iptables を使わずにカーネル内でパケット処理するのが最大の特徴です。Ubuntu 24.04 + kind 環境で実際に動かすと、cilium bpf policy list コマンドで eBPF マップのパケットカウンタを直に確認できて、「iptables とは別物だ」という感触がつかめます。
- Helm でのインストールは
helm install cilium cilium/cilium --version 1.17.4一発(Hubble UI も同時にデプロイ可能) CiliumNetworkPolicyは標準NetworkPolicyと互換性があり、L7 フィルタや DNS ポリシーも書ける- Hubble UI(port-forward で
http://localhost:12000/)でフローをリアルタイム可視化できる - 本番クラスタへの導入は Cilium 公式の「Installation Guide」を参照。kube-proxy 置き換えや BPFマスカレードなど追加の設定が必要です
より本格的な Kubernetes 運用をするなら、クラウド VPS での環境構築もご検討ください。
VPS 選びで迷ったら、こちらの比較記事も参考にしてください:https://linuxlab.jp/ubuntu-server-setup/



コメント