通過編輯器創建可視化Kubernetes網絡策略

實現網絡策略是構建基於kubernetes的安全平臺的關鍵部分,但是從簡單的示例到更復雜的現實策略的學習曲線是陡峭的。不僅要使YAML語法和格式正確,而且更重要的是,在網絡策略規範的行爲中有許多微妙之處(例如默認允許/拒絕、名稱空間、通配符、規則組合等)。即使是經驗豐富的Kubernetes YAML-wrangler也可以輕鬆地通過高級網絡策略用例進行思考。

在過去的幾年裏,當我們與你們中的許多人一起在Cilium社區中執行Kubernetes網絡策略時,我們已經瞭解了許多關於網絡策略挑戰的知識。今天,我們很興奮地宣佈一個新的免費工具,用於社區,幫助您Kubernetes網絡策略編寫旅程:editor.cilium.io

Kubernetes網絡策略編輯器幫助您構建、可視化和理解Kubernetes網絡策略。

  • 教程:遵循輔助教程,從還沒有使用網絡策略到一個良好的安全態勢。
  • 互動創建:以輔助和互動的方式創建策略。
  • 可視化和更新:上傳現有的策略,以驗證和更好地理解它們。
  • 安全性評分:檢查策略的安全性評分,以瞭解它們添加到集羣的安全性級別。
  • YAML下載:將策略作爲YAML下載,以便在您最喜歡的CNI的集羣中執行。
  • 共享:通過GitHub gist在團隊之間共享策略,並創建鏈接來可視化您自己的網絡策略。
  • 自動創建策略:上傳哈勃流量日誌,根據觀察到的網絡流量自動生成網絡策略。

嘗試網絡策略編輯器

網絡策略編輯器,真的有用嗎?

爲了更具體地說明這一點,讓我們來探討一下在使用網絡策略時遇到的5個常見問題,無論是新手還是已經使用了一段時間的人。在每個錯誤的背後,你會在工具中找到一個簡短(3-5分鐘)的教程鏈接,引導你完成修復錯誤所需的每個步驟。

錯誤1:沒有使用命名空間選擇器

考慮這樣一個場景:我們希望運行在monitoring命名空間中的集中式Prometheus實例能夠從運行在default命名空間中的Redis Pod中獲取度量數據。請看下面的網絡策略,它應用於default名稱空間中。它允許標籤爲app=prometheus的Pods從標籤爲app=redis的Pods中獲取度量:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-ingress-from-prometheus
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: redis
  policyTypes:
    - Ingress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: prometheus

正如您在編輯器的可視化中所看到的,上面的網絡策略只有在兩個pod位於相同名稱空間中時纔有效。除非顯式地使用namespaceSelector來選擇其他名稱空間,否則podSelector的作用域是策略的名稱空間。

這樣做是正確的嗎?

一個常見的錯誤可能是使用podSelector創建一個入口規則,如當前策略所示。然而,正如您在可視化中看到的,這個網絡策略只允許從默認名稱空間的app=prometheus輸入流量。爲了創建一個跨命名空間允許規則,你必須添加namespaceSelector:{}

具體答案請點擊:https://editor.cilium.io/?policy-tutorial=allow-cross-namespace

錯誤2:不可能是DNS…

通常情況下,工作負載必須被鎖定以限制外部訪問(即egress默認拒絕)。如果希望防止應用程序將通信發送到除同一名稱空間中的Pods之外的任何地方,可以創建以下策略:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-kube-dns
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: foo
  egress:
    - to:
        - podSelector: {}

然而,一旦您部署了這個網絡策略,您的應用程序連接可能會中斷。爲什麼?Pod通常會通過服務的DNS名稱到達其他Kubernetes服務(例如service1.tenant-a.svc.cluster.local),解析這個名稱需要Pod將出口流量發送到在kube-system名稱空間中標籤爲k8s-app=kube-dns的Pod。

如何修復這個問題呢?

策略將添加如下網絡策略出口規則:

- to:
        - namespaceSelector: {}
          podSelector:
            matchLabels:
              k8s-app: kube-dns
      ports:
        - port: 53
          protocol: UDP

注意:該規則明確地只允許對Kubernetes DNS進行DNS查詢,它不允許出口DNS流量到Kubernetes以外的DNS服務器。這是防止DNS流量攻擊的推薦方法。

具體答案請點擊:https://editor.cilium.io/?policy-tutorial=allow-kube-dns

錯誤3:使用傳統的網絡結構

如果您使用傳統的網絡環境,那麼使用32 CIDR規則允許流量到Pod的IP地址,如kubectl描述Pod的輸出所示。例如:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-egress-to-pod
spec:
  podSelector:
    matchLabels:
      app: foo
  egress:
    - to:
        - ipBlock:
            cidr: 10.0.2.125/32

然而,Pod ip是短暫的和不可預測的,並且取決於網絡插件的實現,ipBlock規則可能只允許出口流量到集羣之外的目的地。Kubernetes文檔建議僅對集羣外的IP地址使用ipblock。

怎麼解決這個問題呢?

使用podSelector和namespaceSelector來代替ipBlock:

  • 只允許特定Pod的進出
  • 允許同一命名空間內的所有出口通信
  • 允許集羣內的所有出口流量

具體答案請點擊:https://editor.cilium.io/?policy-tutorial=allow-egress-to-pod

錯誤4:網絡規則如何結合使用

讓我們看一下另一個出口策略示例,該示例試圖允許標籤爲app=foo的Pods建立到端口443上IP爲192.168.1.22的外部VM的出口連接

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
 name: egress-to-private-vm-443
spec:
 podSelector:
    matchLabels:
      app: foo
 egress:
   - to:
       - ipBlock:
           cidr: 192.168.1.22/32
   - ports:
       - port: 443

等等……雖然這是有效的YAML和有效的網絡策略,但YAML中的一個額外字符帶來了巨大的不同,最終允許了比我預期更多的連接。端口前面的-被解釋爲兩個不同的規則,一個允許所有流量到VM IP(在任何端口上),另一個允許所有流量到443端口(不管IP地址是什麼)。網絡策略規範規定規則在邏輯上是的(而不是),這意味着Pod工作負載具有比預期更多的連接。你如何防止這些錯誤? 請查看如下yaml:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-to-private-vm-443
spec:
  podSelector:
    matchLabels:
      app: foo
  egress:
    - to:
        - ipBlock:
            cidr: 192.168.1.22/32
      ports:
        - port: 443

具體答案請點擊:https://editor.cilium.io/?policy-tutorial=combine-policy-rules

錯誤5:混淆了{}的不同用法

在網絡策略中,空花括號(即{})在不同的上下文中有不同的含義,這導致了很多困惑。我們將用最後一個例子作爲一個小測驗。這兩個看起來相似的網絡策略規則都利用了{},它們之間的區別是什麼?猜測一下,然後在下面的網絡策略編輯器中查看每條規則,看看您是否正確。

乍一看,空花括號(例如:{})可能意味着匹配所有內容。然而,這並不總是正確的;

ingress:
  - {}

空花括號在規則級別使用,它們被轉換爲空規則。理論上,它應該匹配所有內容:同一名稱空間中的所有pod,其他名稱空間中的所有pod,甚至來自或來自集羣外部的通信流。然而,實際上它們只匹配集羣中的所有pod,並且有效地表示了以下策略規則:

ingress:
  - from:
    - podSelector: {}
      namespaceSelector: {}

注意:它不包括ipBlock,因此該規則不會匹配任何集羣外的流量。

同時,下面的規則可能看起來幾乎相同:

ingress:
  - from:
    - podSelector: {}

但是,它只在相同名稱空間中的pods上匹配,而不會在來自其他名稱空間的輸入流量上匹配。

具體答案請點擊:https://editor.cilium.io/?policy-tutorial=empty-selectors

總結

希望您覺得這些示例有用,如果您有其他常見的網絡策略陷阱的例子或其他有趣的策略可以與社區分享,我們將非常樂意聽取您的意見。您可以隨意嘗試制定自己的網絡策略或刪除現有的策略,以可視化方式檢查它們是否執行您希望它們執行的操作。


另外,送福利了,最近我準備了關於各大廠的雲原生技術最佳實踐資料,請點擊關注如下公衆號,回覆【雲原生】獲取

本文分享自微信公衆號 - 雲原生技術愛好者社區(programmer_java)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章