Kubernetes Egress 網絡策略指南

做者:Viswajith Venugopal

翻譯:Bach才雲web

校對:bot才雲)、星空下的文仔才雲api

Kubernetes 中的網絡策略用於指定 Pod 組之間以及其與外部網絡端點之間的通訊,它就像是 Kubernetes 的防火牆。與大多數 Kubernetes 對象同樣,網絡策略很是靈活,功能也很強大。若是瞭解應用程序中服務的確切通訊模式,咱們就能夠經過網絡策略將通訊限制在咱們想要範圍以內。數組

Ingress 與 Egress安全

網絡策略可用於指定 Pod 的入口(Ingress)流量出口(Egress)流量,其規則以下:服務器

  • 若是容許集羣外部網絡端點到 Pod 的通信,那麼該端點能夠訪問 Pod。
  • 若是容許 Pod 到集羣外部網絡端點的通信,那麼 Pod 也能夠訪問該端點。
  • 若是 Pod(A)到 Pod(B)的流量被容許,那麼流量能夠經過 A 的出口以及 B 的入口。注意這是單向的,流量從 B 到 A,那麼只能從 B 的出口到 A 的入口。

設置 Ingress網絡

在完成入口網絡策略的設置併成功運行後,咱們再設置出口網絡策略。這樣作的緣由有兩個:首先,一次執行兩項操做比較困難,並且咱們很難知道是因爲入口仍是出口配置致使的網絡鏈接失敗;其次,出口網絡策略一般更難以實施。限制出口可能會引起各類錯誤,從而影響應用程序運行。app

雖然肯定網絡端點到 Pod 的通信很是簡單,但要肯定 Pod 到網絡端點的鏈接方式會比較複雜。之因此出現這一問題,這是由於:ssh

  • 做爲常規功能的一部分,Deployment 一般會查詢一堆外部服務,根據它們在訪問這些服務時處理超時的方式,功能可能會受到一些細微而又難以觀察的影響。
  • Deployment 須要可以與 DNS 服務器通訊,以便和其餘任何服務器通訊,除非這些服務器直接經過 IP 與服務聯繫。

對 Pod Egress 進行隔離學習

每一個網絡策略都有一個 podSelector 字段,該字段會選擇一組(0 個或多個)Pod。當網絡策略選擇了一個 Pod 時,就稱該網絡策略適用於該 Pod。 spa

此外,每一個網絡策略均可以根據 policyTypes 字段的值應用於入口和出口。若是 YAML 中未指定此字段,它的值會基於策略中的入口、出口規則默認設置,但默認設置並不靠譜,咱們最好進行明確的設置。

通常狀況下,若是沒有任何出口網絡策略適用於 Pod,那麼它就是非隔離的出口。這裏要注意,隔離是針對入口和出口獨立評估的。一個 Pod 的入口和出口能夠都隔離,也能夠都不隔離,甚至進行單個隔離。若是一個 Pod 的出口沒有進行隔離,那麼全部的流量均可以從這個 Pod 中出來。

當一個出口網絡策略適用於某個 Pod 時,該 Pod 的出口就會被隔離。對於隔離的 Pod,只有在網絡策略容許的狀況下,才容許網絡出口,也就是網絡策略白名單。

設置出口網絡策略的第一步是對 Pod 進行出口隔離。咱們最好先應用「默認拒絕全部」的策略,將全部 Pod 的出口都隔離了。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all-egress
spec:
  podSelector: {}
  egress:
  - to:
    ports:
    - protocol: TCP
      port: 53
    - protocol: UDP
      port: 53
  policyTypes:
  - Egress

不過要注意,默認狀況下這個策略容許流量鏈接到任意 IP 上的 53 端口,以方便 DNS 查找。所以,儘管它能夠防止出口出現問題,但不能防止數據泄露,由於攻擊者能夠將數據發送到 53 端口。

若是想知道 Pod 使用的是哪些 DNS 服務器,咱們能夠經過縮小訪問範圍進行肯定。例如,要將 DNS 範圍縮小到僅提供 kube-dns 服務,能夠執行如下操做:

標記 kube-system 命名空間:

kubectl label namespace kube-system networking/namespace=kube-system

應用如下網絡策略:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all-egress
spec:
  podSelector: {}
  egress:
  - to:
    - namespaceSelector:
        matchLabels:
          networking/namespace: kube-system
      podSelector:
        matchLabels:
          k8s-app: kube-dns
    ports:
    - protocol: TCP
      port: 53
    - protocol: UDP
      port: 53
  policyTypes:
  - Egress

重要提示:因爲網絡策略是帶命名空間資源,所以每一個命名空間都須要建立此策略。咱們能夠運行如下命令:

kubectl -n <namespace> create -f <filename>

另外,最好不要將其應用於 kube-system 命名空間,由於它可能會影響集羣功能。

明確 Pod 到互聯網的出口

在每一個命名空間中都採用了 default-deny-all-egress (默認拒絕全部出口)策略後,Pod 將沒法鏈接到互聯網,可是在大多數的應用程序中,會有一些 Pod 須要鏈接到互聯網。對此,有一種設置方法:爲容許鏈接互聯網的 Pod 指定標籤,並建立一個針對這些標籤的網絡策略。例如,如下網絡策略容許具備 networking/allow-internet-egress=true 標籤的 Pod 發送流量至全部網絡端點(包括集羣外部的端點)。另外,仍是要注意,咱們必須爲每一個命名空間建立該策略:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: internet-egress
spec:
  podSelector:
    matchLabels:
      networking/allow-internet-egress: "true"
  egress:
  - {}
  policyTypes:
  - Egress

這個策略比默認設置具備更高的安全性。不過對於更嚴格的策略集,理想狀況下最好指定更細粒度的 CIDR 塊,並明確列出容許的端口和協議。

明確 Pod 間的點對點通訊

若是將 Pod 隔離,而後明確 Pod 到 Pod 之間的通訊以後,在應用正常工做時,咱們會發現,在使用 default-deny-all-egress 策略後,全部的通訊都被限制了。對此,咱們在入口方向上將每一個鏈接放入白名單後,還須要把出口方向上的鏈接也放入白名單。不管是遵循上面的建議,容許全部名稱空間內部通訊,仍是將各個 Pod 之間的鏈接列入白名單,或者採用自定義的方法,對於構建的每一個入口策略,都須要制定相應的出口策略。

補充出口網絡策略

對於從一組 Pod 到另外一組 Pod 之間進行通訊的入口策略,構建對應的出口策略很是簡單。首先,將 policyTypes 字段更改成僅包含 Egress 的數組,將 spec.podSelector 放在 spec.egress.to.podSelector 中,刪除 ingress.from,並將從中提取的 ingress.from.podSelector 放到新的出口策略 spec.podSelector 中。這樣就完成了命名空間內的一個入口策略。

至於跨命名空間的策略,若是已經用 network/namespace: 用標籤標記了每一個命名空間:

kubectl label namespace <name> networking/namespace=<name>

那麼,咱們須要在入口策略中選擇 ingress.from.namespaceselector 的命名空間做爲出口策略的 metadata.namespace,並將在入口策略的 metadata.namespace 中指定的命名空間,放到出口策略的 egress.to.namespaceSelector 字段中。

這是一個例子:

最後,上述建議僅僅提供了一個學習網絡策略的起點,實際上它會複雜得多。若是想更詳細地對它們進行了解,最好多多查看 Kubernetes 教程以及更多的網絡策略配置。

原文請點擊:https://mp.weixin.qq.com/s/0F...

相關文章
相關標籤/搜索