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
|
支援的運算子包括:In、NotIn、Exists、DoesNotExist。
命名空間選擇器
跨命名空間的網路控制使用 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:
- {}
|
最佳實踐
- 預設拒絕原則:先部署拒絕所有流量的政策,再逐步開放必要的通訊
- 最小權限原則:僅開放應用程式所需的最小網路存取權限
- 使用標籤一致性:建立標準化的標籤命名規範
- 測試政策:在生產環境部署前,先在測試環境驗證政策
- 文件記錄:為每個 NetworkPolicy 添加註解說明其用途
參考資料