天天看點

一文搞懂Kubernetes網絡政策(上)

從CNCF基金會的成立,到Kubernetes社群蓬勃發展,曆經6載,17年異軍突起,在mesos、swarm等項目角逐中,拔得頭籌,繼而一統容器編排,其成功的關鍵原因可概括為以下幾點:

  • 項目上司者們的堅守與遠見
  • 社群的良好的運作與社群文化
  • 社群與企業落地的正回報

今天zouyee為大家帶來《一文搞懂Kubernetes網絡政策(上)》,其中《kuberneter排程由淺入深:架構》正在編寫中,敬請期待,目前涉及版本均為​

​1.20.+​

​。

一、Network Policy簡介

随着微服務架構的日漸盛行,Serverless架構的逐漸落地,應用上雲後帶來了子產品間網絡調用需求的大規模增長,Kubernetes 自 1.3 引入了 Network Policy,其提供以應用為中心, 基于政策的網絡控制,用于隔離應用以減少攻擊面。

Pod之間能否通信可通過如下三種組合進行确認:

  1. 其他被允許的 Pods(例如:Pod 無法限制對自身的通路)
  2. 被允許通路的namespace
  3. IP CIDR(例如:與 Pod 運作所在節點的通信總是被允許的)

在定義基于 Pod 或namespace的 NetworkPolicy 時,可以使用​

​标簽選擇器​

​來設定哪些流量可以進入或離開 Pod。同時,當建立基于 IP 的 NetworkPolicy 時,可以基于 IP CIDR 來定義政策。

以下結構體示意圖輔助了解,後面章節有具體說明:

一文搞懂Kubernetes網絡政策(上)
版本變遷
Kubernetes 版本 Networking API 版本 說明
v1.5-v1.6 extensions/v1beta1 需要在kube-apiserver開啟 ​

​extensions/v1beta1/networkpolicies​

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​

​ 中的任何目的地。

該網絡政策總結如下:

  1. 隔離​

    ​default​

    ​​名字空間下​

    ​role=db​

    ​ 的 Pod 。
  2. 出口限制:允許符合以下條件的 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)
  1. 入口限制:允許從帶有​

    ​role=db​

    ​标簽的名字空間下的任何 Pod 到 CIDR 10.0.0.0/24 下 5978 TCP 端口。
2.2 簡單示例

以 calico 為例看一下 Network Policy 的具體用法。

  1. 配置 kubelet 使用 CNI 網絡插件(預設已經配置,無需更改)

​kubelet --network-plugin=cni --cni-conf-dir=/etc/cni/net.d --cni-bin-dir=/opt/cni/bin ...​

  1. 安裝 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      
  1. 部署應用

部署 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​​

公衆号:DCOS

繼續閱讀