Kubernetes 網路政策 NetworkPolicy

Kubernetes Network Policy Configuration

NetworkPolicy 概述

Kubernetes NetworkPolicy 是一種資源物件,用於控制 Pod 之間以及 Pod 與外部網路端點之間的網路流量。透過 NetworkPolicy,管理員可以定義精細的網路存取控制規則,實現微分割(microsegmentation)的安全策略。

預設情況下,Kubernetes 叢集中的所有 Pod 都可以與其他 Pod 自由通訊。NetworkPolicy 允許您限制這種開放式的通訊模式,僅允許經過授權的流量通過。

主要特點

  • 基於標籤選擇器:使用 Kubernetes 標籤來選擇目標 Pod
  • 支援 Ingress 和 Egress:可控制進入和離開 Pod 的流量
  • 命名空間隔離:可跨命名空間定義網路規則
  • 協定與連接埠控制:支援 TCP、UDP、SCTP 協定的連接埠級別控制

支援的 CNI 外掛

NetworkPolicy 需要 CNI(Container Network Interface)外掛的支援才能生效。以下是常見支援 NetworkPolicy 的 CNI 外掛:

CNI 外掛NetworkPolicy 支援備註
Calico完整支援企業級功能,效能優異
Cilium完整支援基於 eBPF,支援 L7 政策
Weave Net完整支援簡單易用
Canal完整支援Flannel + Calico 組合
Antrea完整支援VMware 開發,適用於 vSphere
Flannel不支援僅提供基本網路功能

注意:如果您的 CNI 外掛不支援 NetworkPolicy,定義的政策將不會生效,但也不會產生錯誤訊息。

預設政策行為

在沒有任何 NetworkPolicy 的情況下,Kubernetes 的預設行為如下:

  • Ingress:允許所有進入 Pod 的流量
  • Egress:允許所有離開 Pod 的流量

一旦有 NetworkPolicy 選中某個 Pod:

  • 如果政策包含 Ingress 規則,只有符合規則的進入流量才會被允許
  • 如果政策包含 Egress 規則,只有符合規則的離開流量才會被允許

基本 NetworkPolicy 結構

以下是一個基本的 NetworkPolicy YAML 結構:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: example-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: web
  policyTypes:
    - Ingress
    - Egress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: frontend
      ports:
        - protocol: TCP
          port: 80
  egress:
    - to:
        - podSelector:
            matchLabels:
              app: database
      ports:
        - protocol: TCP
          port: 5432

欄位說明

  • podSelector:選擇此政策要套用的 Pod
  • policyTypes:指定政策類型(Ingress、Egress 或兩者)
  • ingress:定義允許進入的流量規則
  • egress:定義允許離開的流量規則

Ingress 規則設定

Ingress 規則控制進入 Pod 的流量。以下範例展示如何允許來自特定 Pod 的 HTTP 流量:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend-ingress
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: api-server
  policyTypes:
    - Ingress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              role: frontend
        - ipBlock:
            cidr: 10.0.0.0/8
            except:
              - 10.0.1.0/24
      ports:
        - protocol: TCP
          port: 8080
        - protocol: TCP
          port: 443

此政策允許:

  • 帶有 role: frontend 標籤的 Pod
  • 來自 10.0.0.0/8 網段(排除 10.0.1.0/24)的流量

存取 app: api-server Pod 的 8080 和 443 連接埠。

Egress 規則設定

Egress 規則控制離開 Pod 的流量。以下範例展示如何限制 Pod 只能存取特定服務:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: restrict-egress
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
    - Egress
  egress:
    - to:
        - podSelector:
            matchLabels:
              app: database
      ports:
        - protocol: TCP
          port: 5432
    - to:
        - podSelector:
            matchLabels:
              app: cache
      ports:
        - protocol: TCP
          port: 6379
    # 允許 DNS 查詢
    - to:
        - namespaceSelector: {}
          podSelector:
            matchLabels:
              k8s-app: kube-dns
      ports:
        - protocol: UDP
          port: 53

重要:設定 Egress 規則時,請記得允許 DNS 查詢(UDP 53),否則 Pod 將無法解析域名。

標籤選擇器使用

NetworkPolicy 支援多種標籤選擇器組合:

matchLabels 選擇器

1
2
3
4
podSelector:
  matchLabels:
    app: web
    environment: production

matchExpressions 選擇器

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
podSelector:
  matchExpressions:
    - key: app
      operator: In
      values:
        - web
        - api
    - key: environment
      operator: NotIn
      values:
        - development

支援的運算子包括:InNotInExistsDoesNotExist

命名空間選擇器

跨命名空間的網路控制使用 namespaceSelector:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: cross-namespace-policy
  namespace: backend
spec:
  podSelector:
    matchLabels:
      app: api
  policyTypes:
    - Ingress
  ingress:
    - from:
        # 允許來自 frontend 命名空間的流量
        - namespaceSelector:
            matchLabels:
              name: frontend
          podSelector:
            matchLabels:
              app: web
        # 允許來自同一命名空間的流量
        - podSelector:
            matchLabels:
              app: internal-service
      ports:
        - protocol: TCP
          port: 8080

注意:當 namespaceSelector 和 podSelector 在同一個 from 項目中時,兩個條件會使用 AND 邏輯;當它們是獨立的 from 項目時,使用 OR 邏輯。

阻擋所有流量範例

阻擋所有 Ingress 流量

1
2
3
4
5
6
7
8
9
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all-ingress
  namespace: production
spec:
  podSelector: {}
  policyTypes:
    - Ingress

阻擋所有 Egress 流量

1
2
3
4
5
6
7
8
9
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all-egress
  namespace: production
spec:
  podSelector: {}
  policyTypes:
    - Egress

阻擋所有流量(Ingress 和 Egress)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all
  namespace: production
spec:
  podSelector: {}
  policyTypes:
    - Ingress
    - Egress

允許所有流量(白名單基礎上的開放)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all-ingress
  namespace: production
spec:
  podSelector: {}
  policyTypes:
    - Ingress
  ingress:
    - {}

最佳實踐

  1. 預設拒絕原則:先部署拒絕所有流量的政策,再逐步開放必要的通訊
  2. 最小權限原則:僅開放應用程式所需的最小網路存取權限
  3. 使用標籤一致性:建立標準化的標籤命名規範
  4. 測試政策:在生產環境部署前,先在測試環境驗證政策
  5. 文件記錄:為每個 NetworkPolicy 添加註解說明其用途

參考資料

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy