Kubernetes ネットワーキング: CNI、eBPF を備えた Cilium、およびネットワーク ポリシー
Kubernetes は巧みな方法でネットワークを抽象化します。各ポッドはルーティング可能な IP アドレスを取得し、 同じポッド内のコンテナはネットワーク名前空間を共有し、ポッドは NAT を使用せずに任意のノード上で相互に通信できます。しかし、見かけのシンプルさは隠されています 本当に複雑です。このモデルは実際にどのように機能するのでしょうか?誰が扱うのか IP を割り当て、ノード間でトラフィックをルーティングし、ネットワーク ポリシーを実装しますか?
答えは次のとおりです コンテナネットワークインターフェース(CNI)、という規格です。 ネットワーク プラグインを Kubernetes と統合する方法を定義します。この記事では Kubernetes ネットワーク モデルを内部から探ります: kube-proxy がどのように機能するのか、なぜ eBPFを使用した繊毛 従来のソリューションを置き換えるものですか、またその方法は ネットワーク ポリシーを実装して、運用クラスター内のワークロードを分離します。
何を学ぶか
- Kubernetes ネットワーク モデル: ポッドごとの IP、フラット ネットワーク、NAT なし
- Container Network Interface (CNI) の仕組みとその主要なプラグイン
- kube-proxy (iptables/IPVS) と eBPF を使用した Cilium の違い
- eBPF は iptables と比較してレイテンシが -30%、スループットが +60% になるため
- Cilium を CNI としてインストールして構成する方法
- ネットワーク ポリシー: 構文、実践例、デフォルト拒否および名前空間の分離
- レイヤ 7 ルールの CiliumNetworkPolicy (HTTP、gRPC、Kafka)
Kubernetes ネットワーク モデル
Kubernetes は、ネットワーク モデルに 4 つの基本要件を課します。 CNI 実装は以下に準拠する必要があります。
- すべての Pod は NAT なしで他のすべての Pod と通信できます
- すべてのノードは NAT なしですべての Pod と通信できます
- ポッドが独自のものとして認識する IP と、他のポッドがそれに到達するために使用するのと同じ IP です。
- ポッド内のコンテナはネットワークの名前空間と IP を共有します
この「フラット ネットワーク モデル」により、アプリケーションの推論が大幅に簡素化されます。 マイクロサービスは、呼び出すサービスが同じノード上にあるのか、それとも別のノード上にあるのかを知る必要がありません。 リモート。複雑さはクラスター ネットワーク層に移されます。
ポッド間の通信の仕組み
ポッド A が別のノード上のポッド B と通信したい場合の一般的なフローは次のとおりです。 次に、オーバーレイ ネットワーク (VXLAN など) に基づくソリューションを示します。
- パッケージはインターフェイスを介してポッド A のコンテナから出ます。
eth0 - からノード名前空間に入ります。
veth pair - CNI プラグインはそれをインターセプトし、VXLAN (または GRE、Geneve など) にカプセル化します。
- パケットは物理ネットワークを通過して Pod B ノードに到達します。
- 宛先ノードの CNI がパケットのカプセル化を解除します。
- パケットは veth ペアを介してポッド B に到着します
BGP またはネイティブ ルーティング (ネイティブ ルーティング モードの Cilium など) に基づくソリューションを使用すると、 カプセル化は必要なく、パフォーマンスが大幅に向上します。
コンテナネットワークインターフェース(CNI)
CNI は、コンテナー ランタイムがどのように呼び出しを行うかを定義する CNCF 仕様です。 ネットワークプラグイン。 Kubernetes は CNI を使用してネットワーク管理をプラグインに委任します。 kubelet がポッドを作成するとき、設定された CNI プラグインを呼び出してアドレスを割り当てます。 IPを設定し、ネットワークインターフェースを設定します。
主要な CNI プラグイン
| プラグイン | テクノロジー | ネットワークポリシー | L7 ポリシー | 使用事例 |
|---|---|---|---|---|
| フランネル | VXLAN オーバーレイ | いいえ (ネイティブ) | No | 開発、単純なクラスター |
| キャリコ | BGP/オーバーレイ | Si | No | オンプレミス、パフォーマンス |
| 繊毛 | eBPF | Si | はい (HTTP、gRPC) | 生産、サービスメッシュ |
| AWS VPC CNI | ENIネイティブ | はい (シンガポール) | No | EKS |
| アズールCNI | ネイティブ VNet | はい (NSG) | No | AKS |
kube-proxy: 古いアプローチ
kube-proxy は、サービスの実装を担当する Kubernetes コンポーネントです。 クライアントがサービスを呼び出すと、kube-proxy はトラフィックがいずれかのサービスに到着することを保証します。 ポッドのバックエンド。伝統的に使用されている iptables この目的のために。
iptables の問題は、複雑さがルールの数に比例して増加することです。 10,000 のサービスと 100,000 のエンドポイントを備えたクラスターでは、iptables は数百万のルールを管理します。 すべてのパケットはこの一連のルールを通過する必要があり、重大な影響を及ぼします。 ノードのレイテンシーと CPU に影響します。
ツリー内の代替手段 e IPVS (IP 仮想サーバー)、ハッシュ テーブルを使用します。 iptables リニア スキャンの代わりに O(1) ルックアップの場合。ただし、IPVS には制限もあります。 高度なポリシーはサポートされていないため、追加の iptables ルールの管理が必要です。
iptablesのスケーリングの問題
10,000 のサービスがある場合、iptables を使用した kube-proxy はサービスだけで約 40,000 のルールを作成します。 これらのルールの更新時間は、ミリ秒から数分に増加します。クラスター化された サイズが大きいと、スケーリング イベントやデプロイメントの更新中に待ち時間が長くなります。 これが、Cilium が kube-proxy を置き換える主な理由の 1 つです。
Cilium と eBPF: Kubernetes ネットワーキングの将来
eBPF (拡張 Berkeley Packet Filter) は Linux カーネル テクノロジです これにより、サンドボックス プログラムを変更せずにカーネル内で直接実行できるようになります。 カーネルモジュールなし。 Cilium は eBPF を使用してネットワーク トラフィックを傍受し、処理します カーネル レベルで、iptables と kube-proxy を完全にバイパスします。
eBPF を使用した Cilium の利点
- パフォーマンス: iptables と比較して、レイテンシーが最大 30% 削減され、スループットが 60% 増加しました。
- スケーラビリティ: iptables リニア スキャンの代わりに BPF マップを使用した O(1) ルックアップ
- 可観測性: Hubble は L3/L4/L7 トラフィックのリアルタイムの可視性を提供します
- レイヤ 7 ポリシー: HTTP パス、メソッド、ヘッダー、gRPC メソッド、Kafka トピックに基づくポリシー
- サイドカーなしのサービス メッシュ: mTLS とロード バランシングがカーネルに実装され、サイドカー オーバーヘッドがゼロ
- Kube プロキシの置き換え: Cilium は kube-proxy を完全に置き換えることができます
繊毛のインストール
Helm を使用して Kubernetes クラスターに Cilium をインストールし、置き換えるように構成します。 kube-proxy を設定し、可観測性のためにハッブルを有効にします。
# Aggiungi il repo Helm di Cilium
helm repo add cilium https://helm.cilium.io/
helm repo update
# Installa Cilium con kube-proxy replacement e Hubble abilitati
helm install cilium cilium/cilium \
--version 1.16.0 \
--namespace kube-system \
--set kubeProxyReplacement=true \
--set k8sServiceHost=API_SERVER_HOST \
--set k8sServicePort=API_SERVER_PORT \
--set hubble.relay.enabled=true \
--set hubble.ui.enabled=true \
--set ipam.mode=kubernetes
# Verifica installazione
cilium status --wait
# Verifica connettivita
cilium connectivity test
本番環境の Cilium: 高度な構成
運用クラスターの場合、完全な Helm 値の構成は次のとおりです。 パフォーマンスを最大化するためのネイティブ ルーティング (VXLAN カプセル化なし):
# cilium-values-production.yaml
kubeProxyReplacement: true
k8sServiceHost: "10.0.0.1" # indirizzo API server
k8sServicePort: "6443"
# Native routing mode (senza overlay VXLAN)
# Richiede che la rete sottostante supporti il routing dei pod CIDR
tunnel: disabled
autoDirectNodeRoutes: true
ipv4NativeRoutingCIDR: "10.244.0.0/16"
# IPAM
ipam:
mode: kubernetes
# BGP per annunciare i pod CIDR ai router
bgp:
enabled: true
announce:
podCIDR: true
lbIP: true
# Hubble - osservabilita Layer 7
hubble:
enabled: true
metrics:
enabled:
- dns:query;ignoreAAAA
- drop
- tcp
- flow
- icmp
- http
relay:
enabled: true
replicas: 2
ui:
enabled: true
# Monitoring con Prometheus
prometheus:
enabled: true
serviceMonitor:
enabled: true
# Encryption (WireGuard)
encryption:
enabled: true
type: wireguard
# Load Balancing con DSR (Direct Server Return)
loadBalancer:
mode: dsr # elimina un hop di rete nel path di ritorno
# Limita connessioni per Pod
bpf:
mapDynamicSizeRatio: 0.0025
Kubernetes のネットワーク ポリシー
デフォルトでは、Kubernetes クラスター内のすべての Pod は相互に自由に通信できます。 これは開発には便利ですが、運用環境ではセキュリティ上の問題になります。の ネットワークポリシー ポッドの入口と出口のルールを定義できます。
注意: CNI プラグインが必要です
NetworkPolicies は Kubernetes リソースですが、その実装は CNI プラグイン。 Flannel は NetworkPolicy をネイティブにサポートしていません。それらを使用するには、Cilium が必要です。 Calico、またはそれらを実装する別の CNI。リソースはサーバー API によって受け入れられます ただし、CNI がサポートしていない場合は無視されます。
デフォルトの拒否: 基本的なベスト プラクティス
ワークロードを分離してポリシーを適用するための最初のステップ デフォルトの拒否 各名前空間で。これにより、明示的に許可されていないすべてのトラフィックが拒否されます。
# default-deny-all.yaml
# Nega tutto il traffico ingress e egress nel namespace
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {} # seleziona TUTTI i pod nel namespace
policyTypes:
- Ingress
- Egress
---
# Permetti il traffico DNS (necessario per la risoluzione dei nomi)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns
namespace: production
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
一般的なアプリケーションのネットワークポリシー
フロントエンド、バックエンド、データベースの 3 層アプリケーションを分離する方法を見てみましょう。 フロントエンドのみが外部からのトラフィックを受け入れ、バックエンドのみが DB に到達できます。
# network-policies-app.yaml
# Frontend: accetta traffico dall'ingress controller
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-ingress-to-frontend
namespace: production
spec:
podSelector:
matchLabels:
app: frontend
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: ingress-nginx
podSelector:
matchLabels:
app.kubernetes.io/name: ingress-nginx
ports:
- protocol: TCP
port: 8080
egress:
- to:
- podSelector:
matchLabels:
app: backend
ports:
- protocol: TCP
port: 8000
- ports:
- protocol: UDP
port: 53
---
# Backend: accetta solo dal frontend, puo raggiungere DB
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
namespace: production
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8000
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432
- ports:
- protocol: UDP
port: 53
---
# Database: accetta solo dal backend
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-backend-to-database
namespace: production
spec:
podSelector:
matchLabels:
app: database
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: backend
ports:
- protocol: TCP
port: 5432
CiliumNetworkPolicy: ポリシー層 7
標準の Kubernetes ネットワーク ポリシーは、レイヤー 3/4 (IP およびポート) で動作します。繊毛が伸びる これと Ciliumネットワークポリシー、コンテンツベースのポリシーが可能になります 通信: HTTP パス、gRPC メソッド、Kafka トピック、DNS クエリ。
Cilium を使用した HTTP ポリシー
フロントエンドが特定のバックエンド エンドポイントのみを呼び出すことを許可します。
# cilium-http-policy.yaml
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: frontend-to-backend-l7
namespace: production
spec:
endpointSelector:
matchLabels:
app: backend
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: "8000"
protocol: TCP
rules:
http:
- method: "GET"
path: "/api/v1/products.*"
- method: "POST"
path: "/api/v1/orders"
- method: "GET"
path: "/health"
Cilium を使用した DNS ポリシー
ポッドが解決できる DNS ドメインを制限します (データ漏洩の防止に役立ちます)。
# cilium-dns-policy.yaml
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: restrict-dns-egress
namespace: production
spec:
endpointSelector:
matchLabels:
app: backend
egress:
# Permetti solo DNS verso il cluster DNS
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
k8s:k8s-app: kube-dns
toPorts:
- ports:
- port: "53"
protocol: ANY
rules:
dns:
- matchPattern: "*.internal.company.com"
- matchPattern: "*.svc.cluster.local"
- matchPattern: "api.stripe.com"
ハッブル: ネットワークの可観測性
ハッブルとキリウムの可観測層。リアルタイムの可視性を提供します すべてのクラスタ ネットワーク トラフィック。通信 ID は次のとおりです。 IP アドレスの代わりに Kubernetes ラベルを付けます。
# Installa il CLI di Hubble
export HUBBLE_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/hubble/master/stable.txt)
curl -L --fail --remote-name-all \
https://github.com/cilium/hubble/releases/download/$HUBBLE_VERSION/hubble-linux-amd64.tar.gz
tar xzvf hubble-linux-amd64.tar.gz
sudo mv hubble /usr/local/bin
# Port-forward al relay Hubble
cilium hubble port-forward &
# Osserva il traffico in tempo reale
hubble observe --namespace production --follow
# Filtra per Pod specifici
hubble observe \
--namespace production \
--from-pod frontend-7d9d6b8f-abc12 \
--to-pod backend-5c4f8d9-xyz99 \
--follow
# Mostra solo i drop (traffico bloccato dalle policy)
hubble observe \
--namespace production \
--verdict DROPPED \
--follow
# Statistiche per service
hubble observe \
--namespace production \
--output json | jq '.flow.destination.namespace'
ネットワークポリシーのデバッグとトラブルシューティング
NetworkPolicy のデバッグは、Kubernetes で最も一般的な課題の 1 つです。ここに 1 つのアプローチがあります 体系的:
# 1. Verifica quali NetworkPolicy si applicano a un Pod
kubectl get networkpolicies -n production -o wide
# 2. Test di connettivita con un Pod temporaneo
kubectl run test-pod \
--image=nicolaka/netshoot \
--rm \
-it \
--restart=Never \
-n production \
-- bash
# All'interno del Pod:
# Test TCP
nc -zv backend-service 8000
# Test DNS
nslookup backend-service.production.svc.cluster.local
# Test HTTP
curl -v http://backend-service:8000/health
# 3. Con Cilium, usa il tool di policy verification
cilium policy get # mostra tutte le policy caricate
# 4. Testa la connettivita specifica
kubectl exec -n production frontend-pod -- \
curl -v http://backend-service:8000/api/v1/products
# 5. Con Hubble, vedi perche un pacchetto viene droppato
hubble observe \
--namespace production \
--verdict DROPPED \
--from-pod frontend-7d9d6b8f \
--follow
複数の名前空間の分離
マルチテナント クラスタでは、名前空間を分離することが重要です。デフォルトでは、ネットワークポリシー 名前空間間のトラフィックはブロックされません。完全な分離を実装する方法は次のとおりです。
# Isola completamente un namespace da tutti gli altri
# (ma permette il traffico interno al namespace)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: namespace-isolation
namespace: tenant-a
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
ingress:
# Permetti solo traffico dallo stesso namespace
- from:
- podSelector: {}
# Permetti da monitoring namespace
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: monitoring
egress:
# Permetti solo traffico verso lo stesso namespace
- to:
- podSelector: {}
# Permetti DNS
- ports:
- protocol: UDP
port: 53
# Permetti verso monitoring namespace
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: monitoring
パフォーマンス ベンチマーク: Cilium と kube-proxy
ベンチマークは、eBPF を使用した Cilium と iptables を使用した kube-proxy の間に大きな違いがあることを示しています 多数のサービスを含むクラスターの場合:
| メトリック | kubeプロキシiptables | 繊毛 eBPF | 改善 |
|---|---|---|---|
| P50 レイテンシー (10K svc) | 450μs | 130μs | -71% |
| P99 レイテンシ (10K SVC) | 2.1ミリ秒 | 320μs | -85% |
| スループット(Gbps) | 22Gbps | 36Gbps | +64% |
| CPU アップデート ルール (10K svc) | 180秒 | 2秒 | -99% |
| 接続数/秒 | 220K | 380K | +73% |
Kubernetes ネットワーキングのベスト プラクティス
実稼働ネットワークのチェックリスト
- 今すぐ適切な CNI を選択してください。 本番環境および複雑な CNI をみがれます。高度なネットワーク ポリシーまたはサービス メッシュを計画している場合は、Cilium を検討してください。
- すべての名前空間のデフォルト拒否: 常にすべてを拒否するポリシーから始めて、例外を追加します
- ポッド上の一貫したラベル: NetworkPolicy はラベルに依存します。明確な規則を使用する (アプリ、層、バージョン)
- 導入前にポリシーをテストします。 アメリカ合衆国
cilium connectivity testまたはポッドをテストして確認します - ハッブルを有効にする: 運用環境では、トラフィックの可視性はデバッグとコンプライアンスにとって重要です
- トラックドロップ: Prometheus で予期せずドロップされたトラフィックに対するアラートを構成する
- DNS をブロックしないでください。 出口ポリシーで UDP/TCP 53 の kube-dns を許可することを常に忘れないでください。
- 文書ポリシー: Kubernetes アノテーションを使用して各 NetworkPolicy の目的を説明します
避けるべきアンチパターン
ネットワークポリシーに関する一般的なエラー
- 緩すぎるポリシー: 使用
namespaceSelector: {}matchLabels を使用しない場合、侵害された名前空間を含むすべての名前空間からのトラフィックが許可されます - DNS を忘れる: すべての出力をブロックし、ポート 53 を忘れると、Pod はホスト名を解決できなくなります。
- ラベルが更新されていません: 正しいラベルのない新しいポッドを追加した場合、ネットワークポリシーはそれらを保護しません
- 開発中のテストのみ: ネットワークポリシーは、運用環境で予期しないトラフィックをブロックできます。常に現実的なトラフィックを使用してステージングでテストする
- セレクターの代わりに IP を使用します。 ポッド IP が変更されます。常に podSelector と namespaceSelector を使用し、内部トラフィックには ipBlock を使用しないでください。
結論と次のステップ
Kubernetes ネットワーキング モデルは、フラットな IP/Pod アプローチを採用しており、デザインがエレガントです シンプルでありながら実装は洗練されています。 CNI プラグインの選択は、次の 1 つです。 実稼働クラスターの最も重要なアーキテクチャ上の決定: に影響を与える パフォーマンス、セキュリティ、可観測性の機能が利用可能です。
eBPF を備えた Cilium は、現在利用可能な最も高度な CNI です。kube-proxy を次のように置き換えます。 優れたパフォーマンス、レイヤー 7 ポリシーの提供、ハッブルとの可観測性の統合、 mTLS の従来のサービス メッシュを置き換えることができます。本番環境の新しいクラスターの場合、 CNCF コミュニティや Google、Amazon、 マネージド Kubernetes サービスでこれを使用している Microsoft。
デフォルト拒否アプローチを使用して正しく実装されたネットワーク ポリシーにより、 ポッドが侵害された場合、攻撃対象領域が大幅に減少します。私はそうではありません 実稼働環境ではオプションです。これらは基本的な安全要件です。
Kubernetes at Scale シリーズの今後の記事
関連シリーズ
- 本番環境における MLOps と機械学習 — Kubernetes 上の GPU ワークロード
- プラットフォームエンジニアリング — K8 上の社内開発者プラットフォーム
- 可観測性と OpenTelemetry — クラスター監視







