iT邦幫忙

2025 iThome 鐵人賽

DAY 19
1
DevOps

牧場主的 K8s 放牧日記系列 第 19

Day 19: Cilium Network Policy 網路隔離實戰 - 牧場的智慧圍欄系統

  • 分享至 

  • xImage
  •  

牧場主今日工作

今天要來建立牧場的智慧圍欄系統!就像牧場主需要設置不同的圍欄來管理牛群,確保不同品種的牛隻各安其所,互不干擾,Network Policy 就是 Kubernetes 世界的數位圍欄。有了前兩天 Cilium 的基礎和 Hubble 的監控工具,今天我們要實際動手設置網路隔離策略,讓不同的租戶之間井水不犯河水!

Network Policy 基礎概念

什麼是 Network Policy?

Network Policy 是 Kubernetes 中控制 Pod 之間網路流量的安全機制,就像是你的 Pod 前面的數位警察,它會檢查每個想要進入或離開 Pod 的網路封包,決定是放行還是阻擋。

基本工作原理

  • 預設行為:沒有 Network Policy 時,所有 Pod 都可以自由通信
  • 安全策略:一旦套用 Network Policy,就採用「預設拒絕」原則
  • 選擇性允許:明確定義哪些流量可以通過

Cilium Network Policy 的層級優勢

傳統的 Network Policy 只能控制第 3 層(IP)和第 4 層(Port),但 Cilium 可以做到更精細的控制:

L3-L4 層控制(傳統):

  • 基於 IP 地址和端口
  • 協定類型(TCP、UDP)
  • 網路介面控制

L7 層控制(Cilium 獨有):

  • HTTP 方法(GET、POST)
  • URL 路徑過濾
  • HTTP 標頭檢查
  • gRPC 方法控制

https://ithelp.ithome.com.tw/upload/images/20250902/20141794unfVaBqayF.png

Cilium Network Policy 類型

1. 標準 NetworkPolicy

標準的 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

2. CiliumNetworkPolicy

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"

3. CiliumClusterwideNetworkPolicy

集群範圍的策略,適用於所有 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 模型的問題

傳統網路策略基於 IP 地址,在動態容器環境中會遇到問題:

  • Pod IP 會動態變化
  • IP 地址不易管理和追蹤
  • 難以實現細粒度的控制

Cilium 身分識別模型

Cilium 引入基於身分的安全模型,使用 Kubernetes 的標籤系統:

關鍵概念

Label Selector

基於標籤選擇 Pod 群組:

endpointSelector:
  matchLabels:
    app: database
    tier: backend
    environment: production

Endpoint Selector

定義策略適用的目標端點:

spec:
  endpointSelector:
    matchLabels:
      role: api-server

Identity-Based Security

基於 Kubernetes 身分而非 IP 地址的安全模型:

  • 使用 Pod 標籤作為身分識別
  • 自動適應 Pod 的生命週期變化
  • 提供更直觀的策略管理

實戰演練:data Project 內的 Namespace 隔離

環境準備

基於我們現有的 Rancher 環境,在 data Project 中已有兩個 Namespace:

  • analytics-project: 數據分析團隊使用
  • ml-project: 機器學習團隊使用

我們將實作這兩個 Namespace 之間的網路隔離。

1. 部署測試 Pod

# 在 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

2. 部署測試 Pod

# 透過 kubectl 部署
kubectl apply -f data-project-test-pods.yaml

# 確認 Pod 運行狀態
kubectl get pods -n analytics-project
kubectl get pods -n ml-project

實作 Namespace 間隔離策略

策略:data Project 內的 Namespace 隔離

# 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

測試隔離效果

1. 測試同一 Namespace 內的通信(應該成功)

# 在 analytics-project 的 Pod 中測試連接同 namespace 的服務
kubectl exec -it analytics-test -n analytics-project -- wget -qO- analytics-service.analytics-project.svc.cluster.local

# 應該能成功訪問

2. 測試跨 Namespace 的通信(應該被阻擋)

# 從 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 阻擋

3. 使用 Hubble 觀察流量

首先建立 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. 漸進式部署策略

# 建議的部署順序:
# 1. 先在測試環境驗證策略
# 2. 從寬鬆策略開始,逐步收緊
# 3. 使用 Hubble 持續監控策略效果
# 4. 建立緊急回復機制

2. 標籤設計原則

# 建議的標籤分類:
labels:
  app: frontend           # 應用名稱
  tier: web              # 應用層級
  environment: production # 環境類型
  tenant: company-a      # 租戶識別
  security-zone: dmz     # 安全區域

3. 監控與告警

# 設定告警監控:
# - 策略違規事件增加
# - 大量 DROPPED 流量
# - 預期通信被阻擋
# - 策略載入失敗

今日總結與明日預告

今天我們實戰了 Cilium Network Policy 的網路隔離功能!從基本概念到實際部署,學會了如何使用 L3-L7 層的網路策略來實現多租戶隔離。透過身分識別模型,我們能建立更靈活且安全的網路隔離機制。

明天我們要繼續完善基礎設施建設,學習 MetalLB 負載均衡器的部署與設定,為我們的牧場建立強健的流量分發系統!

💡 牧場主小提示:Network Policy 就像牧場的智慧圍欄系統,設置得當能讓不同牛群井然有序,設置不當會讓牛隻困在圈裡餓肚子!記住:預設拒絕、明確允許,先寬後嚴、持續監控。搭配 Hubble 觀測,你就是網路安全的牧場專家!


上一篇
Day 18: Cilium 網路觀測與除錯工具 - 牧場的智慧監控系統
下一篇
Day 20: MetalLB 負載均衡實戰 - 牧場的智慧流量分配系統
系列文
牧場主的 K8s 放牧日記21
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言