從CNCF基金會的成立,到Kubernetes社群蓬勃發展,曆經6載,17年異軍突起,在mesos、swarm等項目角逐中,拔得頭籌,繼而一統容器編排,其成功的關鍵原因可概括為以下幾點:
- 項目上司者們的堅守與遠見
- 社群的良好的運作與社群文化
- 社群與企業落地的正回報
今天zouyee為大家帶來《一文搞懂Kubernetes網絡政策(上)》,其中《kuberneter排程由淺入深:架構》正在編寫中,敬請期待,目前涉及版本均為
1.20.+
。
一、Network Policy簡介
随着微服務架構的日漸盛行,Serverless架構的逐漸落地,應用上雲後帶來了子產品間網絡調用需求的大規模增長,Kubernetes 自 1.3 引入了 Network Policy,其提供以應用為中心, 基于政策的網絡控制,用于隔離應用以減少攻擊面。
Pod之間能否通信可通過如下三種組合進行确認:
- 其他被允許的 Pods(例如:Pod 無法限制對自身的通路)
- 被允許通路的namespace
- IP CIDR(例如:與 Pod 運作所在節點的通信總是被允許的)
在定義基于 Pod 或namespace的 NetworkPolicy 時,可以使用
标簽選擇器
來設定哪些流量可以進入或離開 Pod。同時,當建立基于 IP 的 NetworkPolicy 時,可以基于 IP CIDR 來定義政策。
以下結構體示意圖輔助了解,後面章節有具體說明:

版本變遷
Kubernetes 版本 | Networking API 版本 | 說明 |
v1.5-v1.6 | extensions/v1beta1 | 需要在kube-apiserver開啟 |
v1.7 | networking.k8s.io/v1 | |
v1.8 | networking.k8s.io/v1 | 新增 Egress 和 IPBlock 的支援 |
二、簡要介紹
預設情況下,Pod 是非隔離的,它們接受任何流量。
Pod 在被某 NetworkPolicy 選中時進入隔離狀态。 一旦名字空間中有 NetworkPolicy 選擇了特定的 Pod,該 Pod 會拒絕該 NetworkPolicy 所不允許的連接配接。 (名字空間下其他未被 NetworkPolicy 所選擇的 Pod 會繼續接受所有的流量)
網絡政策不會沖突。 如果任何一個或多個政策選擇了一個 Pod, 則該 Pod 受限于這些政策的 入站(Ingress)/出站(Egress)規則的并集。
⚠️在使用 Network Policy 時,網絡插件需要支援 Network Policy,如 Calico、Romana、Weave Net 和 Trireme 等,其中Engress為 出口流量,Ingress為 入口流量。
2.1 結構體說明
staging/src/k8s.io/api/networking/v1/types.go
下面是 NetworkPolicy 的一個示例,如需完整說明,可參看結構定義文檔:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: network-policy-sample
namespace: default
spec:
podSelector:
matchLabels:
role: db
policyTypes:
- Ingress
- Egress
ingress:
- from:
- ipBlock:
cidr: 172.17.0.0/16
except:
- 172.17.1.0/24
- namespaceSelector:
matchLabels:
project: myproject
- podSelector:
matchLabels:
role: frontend
ports:
- protocol: TCP
port: 6379
egress:
- to:
- ipBlock:
cidr: 10.0.0.0/24
ports:
- protocol: TCP
port: 5978
必需字段:與所有其他的 Kubernetes 對象一樣,NetworkPolicy 需要
apiVersion
、
kind
和
metadata
字段。
spec:NetworkPolicy 規約中包含了在名字空間中定義特定網絡政策所需的所有資訊。
podSelector:每個 NetworkPolicy 都包括一個
podSelector
,它選擇适用該該政策的 Pod。示例中的政策選擇帶有 “role=db” 标簽的 Pod。 若
podSelector
為空的,則選擇名字空間下所有 Pod。
policyTypes: 每個 NetworkPolicy 都包含一個
policyTypes
清單,其中包含
Ingress
或
Egress
或(兩者亦可)。
policyTypes
字段表示給定的政策是應用于 所選 Pod 的入口流量還是來出口流量(兩者亦可)。 如果 NetworkPolicy 未指定
policyTypes
則預設情況下始終設定
Ingress
; 如果 NetworkPolicy 有任何出口規則的話則設定
Egress
。
ingress: 每個 NetworkPolicy 可包含一個
ingress
規則的白名單清單。 每個規則都允許同時比對
from
和
ports
部分的流量。示例政策中包含一條 簡單的規則: 它比對某個特定端口,第一個通過
ipBlock
指定,第二個通過
namespaceSelector
指定,第三個通過
podSelector
指定。
egress: 每個 NetworkPolicy 可包含一個
egress
規則的白名單清單。 每個規則都允許比對
to
和
port
部分的流量。該示例政策包含一條規則, 該規則指定端口上的流量比對到
10.0.0.0/24
中的任何目的地。
該網絡政策總結如下:
- 隔離
名字空間下default
的 Pod 。role=db
- 出口限制:允許符合以下條件的 Pod 連接配接到
名字空間下标簽為default
的所有 Pod 的 6379 TCP 端口:role=db
-
名字空間下帶有default
标簽的所有 Podrole=frontend
- 帶有
标簽的所有名字空間中的 Podproject=myproject
- IP 位址範圍為
和172.17.0.0–172.17.0.255
(即除了 172.17.1.0/24 之外的所有 172.17.0.0/16)172.17.2.0–172.17.255.255
- 入口限制:允許從帶有
标簽的名字空間下的任何 Pod 到 CIDR 10.0.0.0/24 下 5978 TCP 端口。role=db
2.2 簡單示例
以 calico 為例看一下 Network Policy 的具體用法。
- 配置 kubelet 使用 CNI 網絡插件(預設已經配置,無需更改)
kubelet --network-plugin=cni --cni-conf-dir=/etc/cni/net.d --cni-bin-dir=/opt/cni/bin ...
- 安裝 calio 網絡插件
# 注意修改 CIDR,需要跟 k8s pod-network-cidr 一緻,預設為 192.168.0.0/16
# 目前選擇的是小于50節點的安裝方式,具體安裝可檢視
# https://docs.projectcalico.org/getting-started/kubernetes/self-managed-onprem/onpremises
kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml
- 部署應用
部署 nginx 服務
$ kubectl create deployment nginx --image=nginx
deployment "nginx" created
$ kubectl expose deployment nginx --port=80
service "nginx" exposed
測試網絡
$ kubectl get svc,pod
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.233.0.1 <none> 443/TCP 186d
service/nginx ClusterIP 10.233.27.142 <none> 80/TCP 2s
NAME READY STATUS RESTARTS AGE
pod/nginx-f89759699-kfmbj 1/1 Running 0 62s
$ kubectl run busybox --rm -ti --image=busybox /bin/sh
If you don't see a command prompt, try pressing enter.
/ # wget --spider --timeout=1 nginx
Connecting to nginx (10.233.27.142:80)
remote file exists
/ #
4)測試網絡政策
$ cat nginx-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: access-nginx
spec:
podSelector:
matchLabels:
app: nginx
ingress:
- from:
- podSelector:
matchLabels:
access: "true"
$ kubectl create -f nginx-policy.yaml
networkpolicy "access-nginx" created
# 不帶 access=true 标簽的 Pod 還是無法通路 nginx 服務
$ kubectl run busybox --rm -ti --image=busybox /bin/sh
If you don't see a command prompt, try pressing enter.
/ # wget --spider --timeout=1 nginx
Connecting to nginx (10.233.27.142:80)
wget: download timed out
/ #
# 而帶有 access=true 标簽的 Pod 可以通路 nginx 服務
$ kubectl run busybox --rm -ti --labels="access=true" --image=busybox /bin/sh
If you don't see a command prompt, try pressing enter.
/ # wget --spider --timeout=1 nginx
Connecting to nginx (10.233.27.142:80)
/ #
參考文檔
- Kubernetes network policies
- Declare Network Policy
- Kubernetes Network Policy Recipes
- fesikyer network policy