- 1 前置條件
- 2 控制范圍
- 3 隔離類型
- 4 如何識別
- 5 主要字段
- 6 案例演示
前置條件
網絡策略通過網絡插件來實現。 要使用網絡策略,你必須使用支持 NetworkPolicy 的網絡解決方案。 創建一個 NetworkPolicy 資源對象而沒有控制器來使它生效的話,是沒有任何作用的。那么如何查看我們的集群中是否有這個資源呢?如果你使用的CNI網絡查件是Flannel, 是不支持的, Calico是支持的.
檢查API版本兼容性
]# kubectl api-versions | grep networking.k8s.io
networking.k8s.io/v1
]# kubectl api-resources | grep -i networkpolicy
globalnetworkpolicies crd.projectcalico.org/v1 false GlobalNetworkPolicy
networkpolicies crd.projectcalico.org/v1 true NetworkPolicy
networkpolicies netpol networking.k8s.io/v1 true NetworkPolicy
下面我們簡單創建一個networkpolicy資源來檢查下是否能正常使用.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:name: test-policy
spec:podSelector: {}policyTypes:- Ingress]# kubectl apply -f networkpolicy_functest.yaml
]# kubectl get networkpolicy #可以看到創建成功了
控制范圍
OSI 第 3 層或第 4 層. 如果你想在7層控制流量,可以考慮使用istio,后面我會專門演示istio的使用案例
隔離類型
- 出口的隔離 policyTypes: “Egress”
- 入口的隔離 policyTypes: “Ingress”
如何識別
???Pod 可以與之通信的實體是通過如下三個標識符的組合來辯識的:
- 其他被允許的 Pod(例外:Pod 無法阻塞對自身的訪問)
- 被允許的名字空間
- IP 組塊(例外:與 Pod 運行所在的節點的通信總是被允許的, 無論 Pod 或節點的 IP 地址)
主要字段
apiVersion : 必須字段,不同版本可能group和version有所差別,通過explain命令可以查看當前k8s版本支持的apiVersion,如下圖所示,我的k8s版本是1.28,所以他的networkpolicy 接口的apiVersion應該是 networking.k8s.io/v1
kind : 必須字段, 填NetworkPolicy
metadata : 必須字段,需要指定一些元數據,例如name
spec : 包含了在一個名字空間中定義特定網絡策略所需的所有信息
podSelector : 對該策略所適用的一組 Pod 進行選擇。示例中的策略選擇帶有 “role=db” 標簽的 Pod。 空的 podSelector 選擇名字空間下的所有 Pod。
policyTypes : 包含 Ingress 或 Egress 或兩者兼具。policyTypes 字段表示給定的策略是應用于進入所選 Pod 的入站流量還是來自所選 Pod 的出站流量,或兩者兼有。 如果 NetworkPolicy 未指定 policyTypes 則默認情況下始終設置 Ingress; 如果 NetworkPolicy 有任何出口規則的話則設置 Egress。
ingress : 每個 NetworkPolicy 可包含一個 ingress 規則的白名單列表。 每個規則都允許同時匹配 from 和 ports 部分的流量。
egress : 每個 NetworkPolicy 可包含一個 egress 規則的白名單列表。 每個規則都允許匹配 to 和 ports 部分的流量。
下面我們來分析一個示例:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:name: test-network-policynamespace: default
spec:podSelector:matchLabels:role: dbpolicyTypes:- Ingress- Egressingress:- from:- ipBlock:cidr: 172.17.0.0/16except:- 172.17.1.0/24- namespaceSelector:matchLabels:project: myproject- podSelector:matchLabels:role: frontendports:- protocol: TCPport: 6379egress:- to:- ipBlock:cidr: 10.0.0.0/24ports:- protocol: TCPport: 5978該示例表達的是:1. 隔離 default 名字空間下 role=db 的 Pod 2. Ingress 規則)允許以下 Pod 連接到 default 名字空間下的帶有 role=db 標簽的所有 Pod 的 6379 TCP 端口:- default 名字空間下帶有 role=frontend 標簽的所有 Pod- 帶有 project=myproject 標簽的所有名字空間中的 Pod- IP 地址范圍為 172.17.0.0–172.17.0.255 和 172.17.2.0–172.17.255.255 (即,除了 172.17.1.0/24 之外的所有 172.17.0.0/16)3. (Egress 規則)允許 default 名字空間中任何帶有標簽 role=db 的 Pod 到 CIDR 10.0.0.0/24 下 5978 TCP 端口的連接。
## 案例演示
下面我來演示一個案例. 我已經安裝好了一個k8s集群 版本是1.28的, 而且部署好了monitoring. 我們就簡單的拿grafana來舉個例子, grafana我開放了兩種訪問方式,
一種是4層,通過NodePort方式,
一種是創建了Ingress七層訪問,不過他們的最終鏈路都是一樣的
可以看到不管是瀏覽器還是curl,都正常跳轉和返回數據
可以看到目前我訪問grafana頁面正常,下面是我的ing和svc資源
下面我創建networkpolicy資源,yaml如下
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:name: grafana-network-policynamespace: monitoring
spec:podSelector:matchLabels:app.kubernetes.io/name: grafana policyTypes:- Ingressingress:- from:- ipBlock:cidr: 10.233.58.225/32ports:- protocol: TCPport: 80
我來apply 一下
ok. 已經生效. 我們再次訪問grafana測試下
為了驗證下這個networkpolicy確實只作用于monitoring命名空間下的grafana這個pod上,我們進入Alert
Pod去nc 探測grafana svc的端口是否被阻斷。
那我們進入Grafana的pod上去反向探測下alert端口。
可以看到,符合預期. 下面我們刪除networkpolicy.在測試下
再次從alert pod內部去nc grafana的Svc:80端口。
網頁也恢復正常. 后面我會測試7層 service mesh相關的Istio案例.