面向安全專業人員的 Kubernetes 網絡策略簡介

面向安全專業人員的 Kubernetes 網絡策略簡介

筆記。 翻譯。:本文作者 Reuven Harrison 擁有 20 多年的軟件開發經驗,如今是安全策略管理解決方案公司 Tufin 的 CTO 和聯合創始人。 雖然他認為 Kubernetes 網絡策略足夠強大,可以在集群中對網絡進行分段,但他也認為它們在實踐中並不那麼容易實現。 該材料(相當大)旨在提高專家在這方面的認識,並幫助他們創建必要的配置。

如今,許多公司越來越多地選擇 Kubernetes 來運行他們的應用程序。 人們對這款軟件的興趣如此之高,以至於有人將 Kubernetes 稱為“數據中心的新操作系統”。 漸漸地,Kubernetes(或 k8s)開始被視為業務的關鍵部分,需要組織成熟的業務流程,包括網絡安全。

對於使用 Kubernetes 感到困惑的安全專業人士來說,這個平台的默認策略可能是一個真正的發現:允許一切。

本指南將幫助您了解網絡策略的內部運作方式; 了解它們與常規防火牆規則有何不同。 它還將討論一些陷阱並提供有助於保護 Kubernetes 中的應用程序的建議。

Kubernetes 網絡策略

Kubernetes 網絡策略機制允許您在網絡層(OSI 模型中的第三層)管理部署在平台上的應用程序的交互。 網絡策略缺乏現代防火牆的一些高級功能,例如 OSI 第 7 層控制和威脅檢測,但它們提供了網絡安全的基本層,這是一個很好的起點。

網絡策略控制 Pod 之間的通信

Kubernetes 中的工作負載分佈在 Pod 之間,Pod 由部署在一起的一個或多個容器組成。 Kubernetes 為每個 Pod 分配一個可從其他 Pod 訪問的 IP 地址。 Kubernetes 網絡策略為 Pod 組設置訪問權限,就像雲中的安全組用於控制對虛擬機實例的訪問一樣。

定義網絡策略

與其他 Kubernetes 資源一樣,網絡策略是在 YAML 中設置的。 在下面的示例中,應用程序 balance 打開訪問 postgres:

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

面向安全專業人員的 Kubernetes 網絡策略簡介

(筆記。 翻譯。:與所有後續類似的屏幕截圖一樣,此屏幕截圖不是使用本機 Kubernetes 工具創建的,而是使用 Tufin Orca 工具創建的,該工具由原始文章作者的公司開發,在材料末尾提到。)

定義您自己的網絡策略需要 YAML 的基本知識。 這種語言基於縮進(由空格而不是製表符指定)。 縮進元素屬於其上方最近的縮進元素。 列表的新元素以連字符開頭,所有其他元素均採用以下形式 核心價值.

在 YAML 中描述策略後,使用 Kubectl在集群中創建它:

kubectl create -f policy.yaml

網絡策略規範

Kubernetes網絡策略規範包括四個要素:

  1. podSelector:定義受此策略影響的 Pod(目標)- 必需;
  2. policyTypes:指示此策略中包含哪些類型的策略:入口和/或出口 - 可選,但我建議在所有情況下明確指定它;
  3. ingress: 定義允許的 傳入 目標 Pod 的流量 - 可選;
  4. egress: 定義允許的 外向的 來自目標 Pod 的流量是可選的。

從 Kubernetes 站點借用的示例(我替換為 roleapp),顯示瞭如何使用所有四個元素:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:    # <<<
    matchLabels:
      app: 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 網絡策略簡介
面向安全專業人員的 Kubernetes 網絡策略簡介

請注意,不必包含所有四個元素。 這只是必需的 podSelector,其餘參數可根據需要使用。

如果你省略 policyTypes,該政策解讀如下:

  • 默認情況下假定定義入口側。 如果策略沒有明確指示這一點,系統將假設所有流量都被禁止。
  • 出口側的行為將由相應出口參數的存在或不存在來確定。

為了避免錯誤,我建議 始終明確 policyTypes.

根據上面的邏輯,如果參數 ingress 和/或 egress 省略,策略將拒絕所有流量(請參閱下面的“掃描規則”)。

默認策略 - 允許

如果未定義策略,Kubernetes 默認允許所有流量。 所有 Pod 都可以自由地相互交換信息。 從安全角度來看,這似乎有悖常理,但請記住,Kubernetes 最初是由開發人員創建的,其目標是使應用程序具有互操作性。 網絡策略是後來添加的。

命名空間

命名空間是 Kubernetes 的協作機制。 它們旨在將邏輯環境相互隔離,同時默認允許空間之間進行通信。

與大多數 Kubernetes 組件一樣,網絡策略存在於特定的命名空間中。 在街區裡 metadata 您可以指定策略屬於哪個空間:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: my-namespace  # <<<
spec:
...

如果元數據中沒有顯式指定命名空間,系統將使用 kubectl 中指定的命名空間(默認 namespace=default):

kubectl apply -n my-namespace -f namespace.yaml

我建議 顯式指定命名空間,除非您正在編寫同時針對多個命名空間的策略。

主要的 元素 podSelector 策略中的 將從該策略所屬的命名空間中選擇 pod(它無權訪問其他命名空間中的 pod)。

同樣,podSelector 在入口和出口塊中 只能從自己的命名空間中選擇 pod,當然,除非您將它們與 namespaceSelector (這將在“按名稱空間和 Pod 過濾”部分中討論)。

策略命名規則

策略名稱在同一命名空間內是唯一的。 同一空間中不能存在兩個同名的策略,但不同空間中可以存在同名的策略。 當您想要跨多個空間重新應用相同的策略時,這非常有用。

我特別喜歡其中一種命名方法。 它包括將命名空間名稱與目標 pod 連接起來。 例如:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres  # <<<
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: admin
  policyTypes:
  - Ingress

面向安全專業人員的 Kubernetes 網絡策略簡介

標籤

自定義標籤可以附加到 Kubernetes 對象,例如 pod 和命名空間。 標籤 (標籤 標籤)相當於雲中的標籤。 Kubernetes網絡策略使用標籤來選擇 豆莢它們適用於:

podSelector:
  matchLabels:
    role: db

… 或者 命名空間它們適用於其中。 此示例選擇命名空間中具有匹配標籤的所有 Pod:

namespaceSelector:
  matchLabels:
    project: myproject

需要注意的是:使用時 namespaceSelector 確保您選擇的命名空間包含正確的標籤。 請注意,內置命名空間,例如 default и kube-system,默認不包含標籤。

您可以向空間添加標籤,如下所示:

kubectl label namespace default namespace=default

在本例中,節中的命名空間 metadata 應指空間的實際名稱,而不是標籤:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default   # <<<
spec:
...

來源和目的地

防火牆策略由源規則和目標規則組成。 Kubernetes 網絡策略是針對每個目標、它們所應用的一組 pod 進行定義的,然後為入口和/或出口流量設置規則。 在我們的示例中,策略目標將是命名空間中的所有 Pod default 帶鑰匙標籤 app 和意義 db:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: 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 網絡策略簡介
面向安全專業人員的 Kubernetes 網絡策略簡介

小節 ingress 在此策略中打開到目標 Pod 的傳入流量。 換句話說,入口是源,目標是相應的目的地。 同樣,出口是目的地,目標是其源。

面向安全專業人員的 Kubernetes 網絡策略簡介

這相當於兩條防火牆規則:Ingress→Target; 目標 → 出口。

出口和 DNS(重要!)

限制出站流量 特別注意DNS - Kubernetes 使用此服務將服務映射到 IP 地址。 例如,以下策略將不起作用,因為您沒有允許該應用程序 balance 訪問DNS:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
  policyTypes:
  - Egress

面向安全專業人員的 Kubernetes 網絡策略簡介

您可以通過打開對 DNS 服務的訪問來修復它:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
  - to:               # <<<
    ports:            # <<<
    - protocol: UDP   # <<<
      port: 53        # <<<
  policyTypes:
  - Egress

面向安全專業人員的 Kubernetes 網絡策略簡介

最後一個元素 to 是空的,所以它間接選擇 所有命名空間中的所有 pod,允許 balance 將 DNS 查詢發送到適當的 Kubernetes 服務(通常它在空間中運行 kube-system).

然而這種方法有效 過於寬容和缺乏安全感,因為它允許您在集群外部定向 DNS 查詢。

您可以通過連續三個步驟來改進它。

1.僅允許DNS查詢 通過添加聚類 namespaceSelector:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
  - to:
    - namespaceSelector: {} # <<<
    ports:
    - protocol: UDP
      port: 53
  policyTypes:
  - Egress

面向安全專業人員的 Kubernetes 網絡策略簡介

2.僅允許命名空間中的DNS查詢 kube-system.

為此,您需要向命名空間添加標籤 kube-system: kubectl label namespace kube-system namespace=kube-system - 並使用將其註冊到策略中 namespaceSelector:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: postgres
  - to:
    - namespaceSelector:         # <<<
        matchLabels:             # <<<
          namespace: kube-system # <<<
    ports:
    - protocol: UDP
      port: 53
  policyTypes:
  - Egress

面向安全專業人員的 Kubernetes 網絡策略簡介

3. 偏執狂甚至可以更進一步,將 DNS 請求限製到特定的 DNS 服務 kube-system。 “按命名空間和 Pod 過濾”部分將向您展示如何實現這一目標。

另一種選擇是在命名空間級別解析 DNS。 在這種情況下,不需要為每個服務都打開它:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.dns
  namespace: default
spec:
  podSelector: {} # <<<
  egress:
  - to:
    - namespaceSelector: {}
    ports:
    - protocol: UDP
      port: 53
  policyTypes:
  - Egress

空的 podSelector 選擇命名空間中的所有 Pod。

面向安全專業人員的 Kubernetes 網絡策略簡介

第一場比賽和規則順序

在傳統防火牆中,對數據包的操作(允許或拒絕)由其滿足的第一條規則確定。 在 Kubernetes 中,策略的順序並不重要。

默認情況下,當沒有設置策略時,Pod 之間是允許通信的,Pod 之間可以自由地交換信息。 一旦開始製定策略,每個受至少其中一個策略影響的 Pod 就會根據選擇它的所有策略的析取(邏輯或)而被隔離。 不受任何政策影響的 Pod 保持開放狀態。

您可以使用掃描規則更改此行為。

清理規則(“禁止”)

防火牆策略通常會拒絕任何未明確允許的流量。

Kubernetes 沒有“拒絕”操作,但是通過選擇一組空的源 Pod(入口),可以使用正常(寬鬆)策略來實現相同的效果:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Ingress

面向安全專業人員的 Kubernetes 網絡策略簡介

此策略選擇命名空間中的所有 pod,並保留未定義的入口,拒絕所有傳入流量。

同樣,您可以限制來自命名空間的所有傳出流量:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all-egress
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress

面向安全專業人員的 Kubernetes 網絡策略簡介

請注意 允許流量流向命名空間中 pod 的任何其他策略將優先於此規則 (類似於在防火牆配置中在拒絕規則之前添加允許規則)。

允許全部(任何-任何-任何-允許)

要創建“全部允許”策略,您需要在上述拒絕策略中補充一個空元素 ingress:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all
  namespace: default
spec:
  podSelector: {}
  ingress: # <<<
  - {}     # <<<
  policyTypes:
  - Ingress

面向安全專業人員的 Kubernetes 網絡策略簡介

它提供了訪問 所有命名空間(和所有 IP)中的所有 pod 到命名空間中的任何 pod default。 此行為默認啟用,因此通常不需要進一步定義。 但是,有時可能需要暫時禁用某些特定權限才能診斷問題。

規則可以縮小到只允許訪問 一組特定的 Pod (app:balance) 在命名空間中 default:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all-to-balance
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: balance
  ingress: 
  - {}
  policyTypes:
  - Ingress

面向安全專業人員的 Kubernetes 網絡策略簡介

以下策略允許所有傳入(入口)和傳出(出口)流量,包括訪問集群外部的任何 IP:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all
spec:
  podSelector: {}
  ingress:
  - {}
  egress:
  - {}
  policyTypes:
  - Ingress
  - Egress

面向安全專業人員的 Kubernetes 網絡策略簡介
面向安全專業人員的 Kubernetes 網絡策略簡介

結合多種策略

策略在三個層面上進行邏輯“或”運算; 每個 Pod 的權限是根據影響它的所有策略的分離來設置的:

1. 在田野裡 from и to 可以定義三種類型的元素(全部用 OR 組合):

  • namespaceSelector - 選擇整個命名空間;
  • podSelector - 選擇 Pod;
  • ipBlock - 選擇一個子網。

同時,小節中元素的數量(即使是相同的) from/to 不限。 所有這些都將通過邏輯“或”組合起來。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: indexer
    - podSelector:
        matchLabels:
          app: admin
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress

面向安全專業人員的 Kubernetes 網絡策略簡介

2. 內部政策部分 ingress 可以有很多元素 from (通過邏輯或組合)。 同樣,節 egress 可能包含許多元素 to (也可以通過析取組合):

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: indexer
  - from:
    - podSelector:
        matchLabels:
          app: admin
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress

面向安全專業人員的 Kubernetes 網絡策略簡介

3.不同的策略也可以用邏輯OR組合起來

但當它們組合在一起時,有一個限制: 指出 克里斯·庫尼: Kubernetes 只能將不同的策略結合起來 policyTypes (IngressEgress)。 定義入口(或出口)的策略將相互覆蓋。

命名空間之間的關係

默認情況下,允許命名空間之間交換信息。 這可以通過限制命名空間的傳出和/或傳入流量的限制性策略來更改(請參閱上面的“掃描規則”)。

通過阻止對命名空間的訪問(請參閱上面的“掃描規則”),您可以通過允許來自特定命名空間的連接來對拒絕策略進行例外處理 namespaceSelector:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: database.postgres
  namespace: database
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - namespaceSelector: # <<<
        matchLabels:
          namespace: default
  policyTypes:
  - Ingress

面向安全專業人員的 Kubernetes 網絡策略簡介

結果,命名空間中的所有 pod default 訪問 Pod postgres 在命名空間中 database。 但是,如果您想開放訪問權限怎麼辦? postgres 僅命名空間中的特定 pod default?

按命名空間和 Pod 過濾

Kubernetes 1.11 及以上版本允許您組合運算符 namespaceSelector и podSelector 使用邏輯與。它看起來像這樣:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: database.postgres
  namespace: database
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          namespace: default
      podSelector: # <<<
        matchLabels:
          app: admin
  policyTypes:
  - Ingress

面向安全專業人員的 Kubernetes 網絡策略簡介

為什麼它被解釋為 AND 而不是通常的 OR?

Обратитевнимание,что podSelector 不以連字符開頭。 在 YAML 中這意味著 podSelector 並站在他面前 namespaceSelector 引用相同的列表元素。 因此,它們通過邏輯 AND 進行組合。

前面加一個破折號 podSelector 將產生一個新的列表元素,該元素將與前一個元素組合 namespaceSelector 使用邏輯或。

選擇具有特定標籤的 Pod 在所有命名空間中, 輸入空 namespaceSelector:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: database.postgres
  namespace: database
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - namespaceSelector: {}
      podSelector:
        matchLabels:
          app: admin
  policyTypes:
  - Ingress

面向安全專業人員的 Kubernetes 網絡策略簡介

多個標籤用 AND 組合

具有多個實體(主機、網絡、組)的防火牆規則使用邏輯 OR 進行組合。 如果數據包源匹配,將觸發以下規則 Host_1 OR Host_2:

| Source | Destination | Service | Action |
| ----------------------------------------|
| Host_1 | Subnet_A    | HTTPS   | Allow  |
| Host_2 |             |         |        |
| ----------------------------------------|

相反,在 Kubernetes 中不同的標籤 podSelectornamespaceSelector 用邏輯 AND 組合。例如,以下規則將選擇具有兩個標籤的 pod, role=db И version=v2:

podSelector:
  matchLabels:
    role: db
    version: v2

相同的邏輯適用於所有類型的語句:策略目標選擇器、pod 選擇器和命名空間選擇器。

子網和 IP 地址 (IPBlock)

防火牆使用 VLAN、IP 地址和子網來劃分網絡。

在 Kubernetes 中,IP 地址會自動分配給 pod,並且可能會經常更改,因此標籤用於在網絡策略中選擇 pod 和命名空間。

子網(ipBlocks)在管理傳入(入口)或傳出(出口)外部(南北)連接時使用。 例如,此策略打開命名空間中的所有 pod default 訪問Google DNS服務:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-dns
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 8.8.8.8/32
    ports:
    - protocol: UDP
      port: 53

面向安全專業人員的 Kubernetes 網絡策略簡介

本例中的空 pod 選擇器意味著“選擇命名空間中的所有 pod”。

該策略僅允許訪問8.8.8.8; 禁止訪問任何其他 IP。 因此,本質上,您已經阻止了對內部 Kubernetes DNS 服務的訪問。 如果您仍想打開它,請明確指定。

平時 ipBlocks и podSelectors 是互斥的,因為 Pod 的內部 IP 地址不用於 ipBlocks。 指出 內部 IP Pod,您實際上將允許使用這些地址與 pod 進行連接。 在實踐中,您不知道要使用哪個 IP 地址,這就是為什麼您不應該使用它們來選擇 pod。

作為反例,以下策略包含所有 IP,因此允許訪問所有其他 Pod:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-any
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0

面向安全專業人員的 Kubernetes 網絡策略簡介

您只能開放對外部 IP 的訪問,不包括 Pod 的內部 IP 地址。 例如,如果您的 Pod 的子網是 10.16.0.0/14:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: egress-any
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0
        except:
        - 10.16.0.0/14

面向安全專業人員的 Kubernetes 網絡策略簡介

端口和協議

通常 Pod 監聽一個端口。 這意味著您可以簡單地忽略策略中的端口號並將所有內容保留為默認值。 但是,建議盡可能限制策略,因此在某些情況下您仍然可以指定端口:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: indexer
    - podSelector:
        matchLabels:
          app: admin
    ports:             # <<<
      - port: 443      # <<<
        protocol: TCP  # <<<
      - port: 80       # <<<
        protocol: TCP  # <<<
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress

面向安全專業人員的 Kubernetes 網絡策略簡介

請注意選擇器 ports 適用於塊中的所有元素 tofrom, 其中包含。 要為不同的項目集指定不同的端口,請打破 ingressegress 分為幾個小節 tofrom 並在每個記下您的端口:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default.postgres
  namespace: default
spec:
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: indexer
    ports:             # <<<
     - port: 443       # <<<
       protocol: TCP   # <<<
  - from:
    - podSelector:
        matchLabels:
          app: admin
    ports:             # <<<
     - port: 80        # <<<
       protocol: TCP   # <<<
  podSelector:
    matchLabels:
      app: postgres
  policyTypes:
  - Ingress

面向安全專業人員的 Kubernetes 網絡策略簡介

默認端口工作:

  • 如果完全省略端口的定義(ports),表示所有協議和所有端口;
  • 如果省略協議定義(protocol),表示TCP;
  • 如果省略端口定義 (port),表示所有端口。

最佳實踐:不要依賴默認值,明確指定您需要的內容。

請注意,您需要使用 pod 端口,而不是服務(下一段將詳細介紹)。

為 Pod 或服務定義的策略?

通常,Kubernetes 中的 Pod 通過服務(一個虛擬負載均衡器,將流量重定向到實現該服務的 Pod)相互通信。 您可能認為網絡策略控制對服務的訪問,但事實並非如此。 Kubernetes 網絡策略適用於 Pod 端口,而不適用於服務。

例如,如果服務偵聽端口 80,但將流量重定向到其 pod 的端口 8080,則必須在網絡策略中指定 8080。

這種機制應該被認為是次優的:如果服務的內部設備(偵聽 Pod 的端口)發生變化,則必須更新網絡策略。

使用服務網格的新架構方法 (例如,請參閱下面有關 Istio 的內容 - 大約翻譯) 可以讓你處理這個問題。

是不是Ingress和Egress都要寫?

簡而言之,答案是肯定的,為了讓 pod A 與 pod B 通信,您需要允許它創建傳出連接(為此您需要配置出口策略),並且 pod B 必須能夠接受傳入連接(為此,您需要 ingress-policy)。

然而,實際上,您可以依靠默認策略來允許一個或兩個方向的連接。

如果有一些 pod- 將被一個或多個選擇 出口-政客們,對其施加的限制將由他們的分離決定。 在這種情況下,您需要顯式允許連接到 pod收件人。 如果某個 Pod 未被任何策略選擇,則默認允許其傳出(出口)流量。

同樣,pod'a的命運——收件人由一個或多個選擇 入口-政策將由它們的分離來決定。 在這種情況下,您必須明確允許它接收來自源 Pod 的流量。 如果某個 Pod 未被任何策略選中,則默認允許所有進入該 Pod 的流量。

請參閱下面的“有狀態或無狀態”。

日誌

Kubernetes 網絡策略不知道如何記錄流量。 這使得很難確定策略是否按預期發揮作用,並使安全分析變得非常困難。

外部服務的流量控制

Kubernetes 網絡策略不允許您在出口部分指定完全限定域名 (DNS)。 當嘗試將流量限製到沒有固定 IP 地址的外部目標(例如 aws.com)時,這一事實會帶來很大的不便。

政策檢查

防火牆會警告您甚至拒絕接受錯誤的策略。 Kubernetes 也做了一些驗證。 當通過 kubectl 設置網絡策略時,Kubernetes 可能會聲明該策略不正確並拒絕接受。 在其他情況下,Kubernetes 將採用該策略並填寫缺失的詳細信息。 您可以使用以下命令查看它們:

kubernetes get networkpolicy <policy-name> -o yaml

請記住,Kubernetes 驗證系統並非絕對可靠,可能會遺漏某些類型的錯誤。

執行

Kubernetes 本身並不強制執行網絡策略,而只是一個 API 網關,它將控制負擔置於稱為容器網絡接口 (CNI) 的底層系統上。 在 Kubernetes 集群上設置策略而不分配適當的 CNI 類似於在防火牆管理服務器上設置策略而不隨後在防火牆上設置它們。 您需要確保擁有合適的 CNI,或者在 Kubernetes 平台的情況下,託管在雲中 (有關提供商的列表,請參閱 這裡 - 大約。 譯),啟用將為您設置 CNI 的網絡策略。

請注意,如果您在沒有適當的輔助 CNI 的情況下設置網絡策略,Kubernetes 不會向您發出警告。

有狀態還是無狀態?

我遇到的所有 Kubernetes CNI 都是有狀態的(例如,Calico 使用 Linux conntrack)。 這允許 Pod 接收其發起的 TCP 連接上的響應,而無需重新建立它。 但是,我不知道 Kubernetes 標準可以保證狀態性。

高級安全策略管理

以下是提高 Kubernetes 中安全策略執行效率的一些方法:

  1. Service Mesh 架構模式使用 sidecar 在服務層提供詳細的遙測和流量控制。 舉個例子,可以採取 Istio.
  2. 一些 CNI 供應商已經擴展了他們的工具,使其超出了 Kubernetes 網絡策略的範圍。
  3. 圖芬虎鯨 提供 Kubernetes 網絡策略的透明度和自動化。

Tufin Orca 包管理 Kubernetes 網絡策略(也是上面屏幕截圖的來源)。

更多信息

結論

Kubernetes 網絡策略提供了一套很好的工具來分割集群,但它們並不直觀,並且有很多微妙之處。 我相信,由於這種複雜性,許多現有集群的策略都存在缺陷。 此問題的可能解決方案是自動化策略定義或使用其他分段工具。

我希望本指南能夠幫助您解決一些疑問並解決您可能遇到的問題。

譯者PS

另請閱讀我們的博客:

來源: www.habr.com

添加評論