剛接手公司K8s集羣時,我發現所有Pod之間都能隨意通信。有次開發環境的測試Pod誤連了生產數據庫,雖然沒造成損失,但讓我意識到必須給Pod間的網絡加道"門"——這就是NetworkPolicy的用武之地。
為什麼需要NetworkPolicy?
Kubernetes默認的網絡策略是"全部允許",任何Pod都能訪問其他Pod,這在複雜系統裏很危險。想象一下:如果黑客入侵了一個邊緣服務的Pod,就能直接訪問核心數據庫,後果不堪設想。NetworkPolicy就像網絡防火牆,能基於標籤精細控制Pod間的流量。
基礎概念與前提
使用NetworkPolicy有個前提:集羣網絡插件必須支持它,比如Calico、Cilium,而Flannel這類簡單插件是不支持的。可以用這個命令檢查:
kubectl get networkpolicy --all-namespaces
如果返回"the server doesn't have a resource type "networkpolicy"",説明當前插件不支持,得先換插件。
NetworkPolicy的核心是"選擇器":通過Pod標籤和命名空間標籤來指定規則適用的對象,然後定義入站(ingress)和出站(egress)規則。
常用規則示例
1. 默認拒絕所有入站流量
在生產命名空間創建默認拒絕規則,這是最安全的起點:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: production
spec:
podSelector: {} # 匹配命名空間下所有Pod
policyTypes:
- Ingress
2. 允許特定服務訪問數據庫
假設數據庫Pod有標籤app: mysql,只允許帶app: backend標籤的Pod訪問3306端口:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: mysql-allow-backend
namespace: production
spec:
podSelector:
matchLabels:
app: mysql
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: backend
ports:
- protocol: TCP
port: 3306
3. 限制Pod的出站流量
阻止前端Pod訪問除API服務外的其他資源:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: frontend-restrict-egress
namespace: production
spec:
podSelector:
matchLabels:
app: frontend
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchLabels:
app: api
ports:
- protocol: TCP
port: 8080
實際應用中的坑
上週配置規則時,發現新規則沒生效,排查後發現是標籤寫錯了。Pod的標籤是app: api-service,但規則裏寫成了app: api,這種細節很容易出錯。
另一個教訓是:創建默認拒絕規則後,一定要先配置允許規則再部署應用,否則新Pod會完全斷網。我一般先在測試命名空間用kubectl apply -f policy.yaml驗證,沒問題再推到生產。
最佳實踐
- 遵循"最小權限原則":只允許必要的流量
- 先創建默認拒絕規則,再逐步添加允許規則
- 給Pod打清晰的標籤,比如
app、env、role,方便規則匹配 - 定期用
kubectl describe networkpolicy <name>檢查規則狀態
NetworkPolicy看似簡單,實則是K8s安全體系的重要一環。合理配置後,既能防止內部服務越權訪問,也能在發生安全事件時縮小影響範圍。就像給每個Pod裝了智能門鎖,該放的放,該攔的攔,整個集羣的網絡才真正可控。