今天要來建立牧場的智慧圍欄系統!就像牧場主需要設置不同的圍欄來管理牛群,確保不同品種的牛隻各安其所,互不干擾,Network Policy 就是 Kubernetes 世界的數位圍欄。有了前兩天 Cilium 的基礎和 Hubble 的監控工具,今天我們要實際動手設置網路隔離策略,讓不同的租戶之間井水不犯河水!
Network Policy 是 Kubernetes 中控制 Pod 之間網路流量的安全機制,就像是你的 Pod 前面的數位警察,它會檢查每個想要進入或離開 Pod 的網路封包,決定是放行還是阻擋。
基本工作原理:
傳統的 Network Policy 只能控制第 3 層(IP)和第 4 層(Port),但 Cilium 可以做到更精細的控制:
L3-L4 層控制(傳統):
L7 層控制(Cilium 獨有):
標準的 Kubernetes NetworkPolicy,支援 L3 和 L4 策略:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: basic-policy
namespace: production
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
Cilium 的擴展格式,支援 L3-L7 層策略:
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: advanced-policy
namespace: production
spec:
endpointSelector:
matchLabels:
app: api-server
ingress:
- fromEndpoints:
- matchLabels:
app: web-frontend
toPorts:
- ports:
- port: "8080"
protocol: TCP
rules:
http:
- method: "GET"
path: "/api/users"
- method: "POST"
path: "/api/login"
集群範圍的策略,適用於所有 Namespace:
apiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
name: global-deny-policy
spec:
endpointSelector: {}
egress:
- toEntities:
- "host"
- "remote-node"
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
傳統網路策略基於 IP 地址,在動態容器環境中會遇到問題:
Cilium 引入基於身分的安全模型,使用 Kubernetes 的標籤系統:
關鍵概念:
基於標籤選擇 Pod 群組:
endpointSelector:
matchLabels:
app: database
tier: backend
environment: production
定義策略適用的目標端點:
spec:
endpointSelector:
matchLabels:
role: api-server
基於 Kubernetes 身分而非 IP 地址的安全模型:
基於我們現有的 Rancher 環境,在 data
Project 中已有兩個 Namespace:
我們將實作這兩個 Namespace 之間的網路隔離。
# 在 analytics-project namespace 部署測試 Pod
apiVersion: v1
kind: Pod
metadata:
name: analytics-test
namespace: analytics-project
labels:
app: analytics
team: analytics
spec:
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 200m
memory: 256Mi
---
# Service 讓 Pod 可被訪問
apiVersion: v1
kind: Service
metadata:
name: analytics-service
namespace: analytics-project
spec:
selector:
app: analytics
ports:
- port: 80
targetPort: 80
---
# 在 ml-project namespace 部署測試 Pod
apiVersion: v1
kind: Pod
metadata:
name: ml-test
namespace: ml-project
labels:
app: ml-workload
team: ml
spec:
containers:
- name: busybox
image: busybox:latest
command: ['sleep', '3600']
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 100m
memory: 128Mi
---
# BusyBox Service(用於測試連線)
apiVersion: v1
kind: Service
metadata:
name: ml-service
namespace: ml-project
spec:
selector:
app: ml-workload
ports:
- port: 8080
targetPort: 8080
# 透過 kubectl 部署
kubectl apply -f data-project-test-pods.yaml
# 確認 Pod 運行狀態
kubectl get pods -n analytics-project
kubectl get pods -n ml-project
# analytics-project 的隔離策略
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: analytics-isolation
namespace: analytics-project
spec:
endpointSelector:
matchLabels:
team: analytics
ingress:
- fromEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: analytics-project
egress:
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: analytics-project
# 允許 DNS 查詢
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
k8s-app: kube-dns
---
# ml-project 的隔離策略
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: ml-isolation
namespace: ml-project
spec:
endpointSelector:
matchLabels:
team: ml
ingress:
- fromEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: ml-project
egress:
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: ml-project
# 允許 DNS 查詢
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
k8s-app: kube-dns
# 套用隔離策略
kubectl apply -f data-project-isolation.yaml
# 確認策略已載入
kubectl get ciliumnetworkpolicy -n analytics-project
kubectl get ciliumnetworkpolicy -n ml-project
# 在 analytics-project 的 Pod 中測試連接同 namespace 的服務
kubectl exec -it analytics-test -n analytics-project -- wget -qO- analytics-service.analytics-project.svc.cluster.local
# 應該能成功訪問
# 從 ml-project 的 Pod 嘗試連接 analytics-project 的服務
kubectl exec -it ml-test -n ml-project -- wget -qO- analytics-service.analytics-project.svc.cluster.local --timeout=5
# 應該超時失敗,因為被 Network Policy 阻擋
首先建立 Hubble 連線:
# 建立 port-forward 連線到 Hubble Relay(需要保持運行)
cilium hubble port-forward &
# 或者手動建立 port-forward
kubectl port-forward -n kube-system svc/hubble-relay 4245:80 &
開始觀察流量:
# 觀察所有網路流量
hubble observe
# 只觀察被阻擋的流量
hubble observe --verdict DROPPED
# 觀察特定 namespace 的流量
hubble observe --namespace analytics-project
# 觀察跨 namespace 的流量(應該看到被 DROP)
hubble observe --from-namespace ml-project --to-namespace analytics-project
觀察結果說明:
# 正常的 DNS 查詢流量範例
Sep 1 23:26:35.290: analytics-project/analytics-test:42368 (ID:9164) -> kube-system/rke2-coredns-rke2-coredns-65dc69968-ll9mp:53 (ID:1496) to-endpoint FORWARDED (UDP)
Sep 1 23:26:35.291: analytics-project/analytics-test:42368 (ID:9164) <- kube-system/rke2-coredns-rke2-coredns-65dc69968-ll9mp:53 (ID:1496) to-overlay FORWARDED (UDP)
# 常見的系統訊息(正常現象)
EVENTS LOST: HUBBLE_RING_BUFFER CPU(0) 1
DROPPED 流量觀察範例:
# 使用 hubble observe --verdict DROPPED 觀察被丟棄的流量
Sep 1 23:23:06.370: d8:0d:17:a4:4c:b2 (unknown) <> 00:31:26:32:3e:3c (unknown) VLAN traffic disallowed by VLAN filter DROPPED (Ethernet)
Sep 1 23:27:18.110: fe80::a028:36ff:fe05:8418 (ID:9164) <> ff02::2 (unknown) Unsupported L3 protocol DROPPED (ICMPv6 RouterSolicitation)
輸出訊息解讀:
FORWARDED
:流量被允許通過DROPPED
:流量被丟棄(可能因為 Network Policy、VLAN 過濾器或不支援的協定)to-endpoint
:流量送往目標端點to-overlay
:流量透過網路覆蓋層傳輸EVENTS LOST
:緩衝區滿了導致部分事件遺失(正常現象)常見的 DROPPED 原因:
VLAN traffic disallowed by VLAN filter
:VLAN 層級的流量過濾(系統層級)Unsupported L3 protocol
:不支援的第三層協定(如 ICMPv6)Policy denied
:被 Network Policy 明確拒絕的流量# 檢查 Network Policy 狀態
kubectl describe ciliumnetworkpolicy analytics-isolation -n analytics-project
kubectl describe ciliumnetworkpolicy ml-isolation -n ml-project
# 檢查 Cilium 整體狀態
cilium status
# 檢查連通性(這個指令可能會花較長時間)
cilium connectivity test --test-namespace analytics-project --verbose
# 檢查 Cilium 策略載入狀況
cilium status
# 查看網路策略配置
kubectl get ciliumnetworkpolicy -A
# 檢查策略詳細資訊
kubectl describe ciliumnetworkpolicy analytics-isolation -n analytics-project
kubectl describe ciliumnetworkpolicy ml-isolation -n ml-project
# 從 analytics Pod 測試同一 namespace 的連線(應該成功)
kubectl exec -it analytics-test -n analytics-project -- wget -qO- analytics-service.analytics-project.svc.cluster.local
# 測試被阻擋的跨 namespace 連線(應該超時失敗)
kubectl exec -it ml-test -n ml-project -- wget -qO- analytics-service.analytics-project.svc.cluster.local --timeout=5
# 建議的部署順序:
# 1. 先在測試環境驗證策略
# 2. 從寬鬆策略開始,逐步收緊
# 3. 使用 Hubble 持續監控策略效果
# 4. 建立緊急回復機制
# 建議的標籤分類:
labels:
app: frontend # 應用名稱
tier: web # 應用層級
environment: production # 環境類型
tenant: company-a # 租戶識別
security-zone: dmz # 安全區域
# 設定告警監控:
# - 策略違規事件增加
# - 大量 DROPPED 流量
# - 預期通信被阻擋
# - 策略載入失敗
今天我們實戰了 Cilium Network Policy 的網路隔離功能!從基本概念到實際部署,學會了如何使用 L3-L7 層的網路策略來實現多租戶隔離。透過身分識別模型,我們能建立更靈活且安全的網路隔離機制。
明天我們要繼續完善基礎設施建設,學習 MetalLB 負載均衡器的部署與設定,為我們的牧場建立強健的流量分發系統!
💡 牧場主小提示:Network Policy 就像牧場的智慧圍欄系統,設置得當能讓不同牛群井然有序,設置不當會讓牛隻困在圈裡餓肚子!記住:預設拒絕、明確允許,先寬後嚴、持續監控。搭配 Hubble 觀測,你就是網路安全的牧場專家!