在 GKE 叢集中使用 Cloud Service Mesh 輸出閘道的最佳做法

本文說明如何使用 Cloud Service Mesh 輸出閘道和其他 Google Cloud 控制項,確保從 Google Kubernetes Engine (GKE) 叢集部署的工作負載傳出的流量 (輸出) 安全無虞。這些控制項可根據來源應用程式的身分、團隊的命名空間、目的地網域,以及外送要求的其他屬性,限制與外部服務的連線。

本文件的適用對象包括網路、平台和安全防護工程師,他們負責管理一或多個軟體交付團隊使用的 GKE 叢集。對於必須證明符合法規 (例如 GDPRPCI) 的機構而言,本文所述的控制項可能特別實用。

簡介

傳統的網路安全方法是在一組應用程式周圍定義安全邊界。這些邊界會使用防火牆,根據來源和目的地 IP 位址允許或拒絕流量,同時信任邊界內的應用程式和流量。不過,這種信任關係涉及風險。惡意內部人員或任何入侵周邊防禦系統的人,都能在網路內自由移動、存取及外洩資料、攻擊第三方系統,以及干擾管理系統。

當 Kubernetes 叢集上執行的工作負載建立連出連線至網際網路上的主機時,套用傳統的 IP 型安全控管機制可能會很複雜,原因如下:

  • Pod IP 位址無法充分代表建立連線的工作負載身分。在 Kubernetes 環境中,Pod IP 位址是暫時指派,且會隨著 Pod 的來來去去而頻繁回收。

  • 通常無法為特定目的地主機識別一小組固定的 IP 位址。IP 位址經常變更,且因地區而異,可能取自大範圍的位址,或代表快取、Proxy 或 CDN

  • 多個團隊共用同一個多租戶叢集,並共用來源 IP 範圍,可能會有不同的外部連線需求。

Cloud Service Mesh 是以開放原始碼 Istio 服務網格為基礎的 Google Cloud全代管服務網格。服務網格可讓您以一致的方式連結、管理及保護應用程式通訊。服務網格採用以應用程式為中心的方法,並使用可信的應用程式身分,而不是以網路 IP 為中心的方法。

您可以透明地部署服務網格,不必修改現有的應用程式程式碼。使用服務網格可提供網路行為的宣告式控制,有助於將負責交付及發布應用程式功能的開發團隊工作,與網路管理員的職責分開。

Cloud Service Mesh 提供部署選項,可在網格邊緣部署獨立轉送 Proxy (稱為輸出閘道)。本指南說明如何結合出口閘道 Proxy 的功能與 Google Cloud 功能,控管、授權及監控從部署至 GKE 叢集的工作負載傳出的流量。

概念元件

縱深防禦架構

下圖顯示的架構採用縱深防禦方法,針對多個團隊使用的叢集,精細控管輸出流量。這些控制項是根據第 4 層 (傳輸)第 7 層 (應用程式) 網路控制項而定。

整體架構

這項架構使用下列資源和控制項:

  • 私人 GKE 叢集: 私人 GKE 叢集中的節點只會使用內部 IP 位址,且預設不會連上網際網路。

  • Cloud NAT:Cloud NAT 可允許私人叢集連出網際網路。

  • 虛擬私有雲 (VPC) 防火牆規則: 您可以設定 VPC 防火牆規則,對 GKE 叢集中節點的連線套用第 4 層 (傳輸) 控制項。您可以根據服務帳戶網路標記,將虛擬私有雲防火牆規則套用至 VM。

  • GKE 節點集區 (使用不同服務帳戶):您可以設定不同的防火牆規則,視節點所屬的節點集區套用規則。

  • Kubernetes命名空間: 為每個團隊建立命名空間,提供隔離功能和委派的管理控制權。網路管理員會使用專屬命名空間部署輸出閘道,並設定外部主機的路由。

  • Kubernetes 網路政策: 網路政策可讓您對 Pod 套用第 4 層控制項。每項網路政策都以命名空間為範圍,且可更精細地以命名空間中的特定 Pod 為範圍。

  • 輸出閘道:網格內 Pod 傳出的流量會透過專用節點上執行的專用輸出閘道 Proxy 導向。您會部署具有水平 Pod 自動調度器的出站閘道,以便備用資源數量可隨流量增減。

  • 授權政策: 您可以使用網格授權政策,對網格內 Pod 之間的流量,以及離開網格的流量套用第 7 層 (應用程式) 控制項。

  • 補充資源: 您可以使用補充資源,控管每個工作負載 Pod 中執行的補充 Proxy 設定範圍。您可以使用 Sidecar 資源,設定工作負載可見的命名空間、Pod 和外部服務。

  • 私人 Google 存取權: 這個選項可讓私人叢集中的節點和 Pod 存取 Google API,並從 Container Registry 提取 Docker 映像檔。

  • GKE Workload Identity:使用 Workload Identity 時,您可以透過 Identity and Access Management (IAM),依據最低權限原則,將 API 權限授予特定工作負載,不必處理密碼。

設定輸出控管機制

如果您使用輸出閘道保護網格的輸出流量,建議您設定本節所述的縱深防禦控制項。

搭配 Cloud NAT 使用私人 GKE

如果安全性很重要,許多機構的第一個要求就是避免為工作負載指派公用 IP 位址。私人 GKE 叢集符合這項要求。您可以在私人叢集上設定虛擬私有雲原生模式,讓 Pod 和服務從虛擬私有雲的次要範圍指派 IP 位址。虛擬私有雲原生 Pod IP 位址本身可以在虛擬私有雲網路中直接轉送。

部分工作負載可能需要存取虛擬私有雲網路外部的服務和網際網路。如要讓工作負載連線至外部主機,且不需要公開 IP 位址,請設定 Cloud NAT 來提供網路位址轉譯 (NAT)。

請確認 Cloud NAT 已設定完成,讓輸出閘道能同時建立足夠數量的連線,連至外部目的地。您可以適當設定每個 VM 的通訊埠數量下限,避免通訊埠耗盡,以及連線重複使用延遲的問題。詳情請參閱 Cloud NAT 位址和連接埠總覽。增加輸出閘道副本數量有助於減少與端點無關的對應衝突

設定 Google API 和服務的私人 Google 存取權

工作負載可能需要存取 Google API 和服務。搭配自訂 DNS 區域使用私人 Google 存取權,即可透過一組四個 IP 位址,允許私人虛擬私有雲子網路連線至 Google API。使用這些 IP 位址時,Pod 不需要外部 IP 位址,流量也不會離開 Google 網路。您可以視是否使用 VPC Service Controls,使用 private.googleapis.com (199.36.153.8/30) 或 restricted.googleapis.com (199.36.153.4/30)。

使用 Workload Identity 和 IAM 進一步保護 Google API 和服務

建議使用 Workload Identity,讓 GKE 工作負載向 Google API 驗證身分,並讓管理員透過 IAM 套用「最低權限」授權控制項。

使用私人 Google 存取權、Workload Identity 和 IAM 時,您可以安全地允許工作負載 Pod 略過輸出閘道,直接連線至 Google API 和服務。

使用 Kubernetes 命名空間進行管理控制

命名空間是一種組織資源,適用於有許多使用者、團隊或租戶的環境。您可以將命名空間視為虛擬叢集,並將 Kubernetes 資源群組的管理責任委派給不同的管理員。

命名空間是隔離管理控制項的重要功能。 不過,根據預設,這些節點不會提供節點隔離、資料平面隔離或網路隔離。

Cloud Service Mesh 會以 Kubernetes 命名空間為基礎,將其做為服務網格中的租戶單元。網格授權政策和 Sidecar 資源可根據命名空間、身分和第 7 層 (應用程式) 網路流量屬性,限制可見度和存取權。

同樣地,您可以使用 Kubernetes 網路政策,允許或拒絕第 4 層 (傳輸) 的網路連線。

在專屬閘道節點上執行輸出閘道

在專屬閘道節點集區的節點上執行輸出閘道,有以下幾項優點。對外節點可以使用強化設定,您可以設定 VPC 防火牆規則,防止工作負載直接連線至外部主機。您可以使用叢集自動配置器,獨立自動調度節點集區的資源。

如要允許個別管理輸出閘道,請將其部署至專屬的 istio-egress 命名空間。不過,命名空間是叢集範圍的資源,無法用來控管部署作業要在哪些節點上執行。如要控管部署作業,請為外送閘道部署作業使用節點選取器,確保部署作業在標示為閘道節點集區成員的節點上執行。

確認只有閘道 Pod 可以在閘道節點上執行。其他 Pod 應從閘道節點排斥,否則可能會略過輸出控制項。使用污點和容許條件,即可防止工作負載在特定節點上執行。您應汙染閘道節點集區中的節點,並在輸出閘道部署作業中新增對應的容許度。

將虛擬私有雲防火牆規則套用至特定節點

您可設定服務網格轉送,將預設節點集區中執行的工作負載輸出流量,導向至閘道節點集區中執行的輸出閘道。不過,網格的路由設定不應視為安全邊界,因為工作負載可透過各種方式繞過網格 Proxy。

如要防止應用程式工作負載直接連線至外部主機,請對預設節點集區中的節點套用限制性輸出防火牆規則。對閘道節點套用個別的防火牆規則,讓在這些節點上執行的輸出閘道 Pod 可以連線至外部主機。

建立 VPC 防火牆規則時,您會指定防火牆規則允許或拒絕的連接埠和通訊協定,以及規則適用的流量方向。輸出規則適用於輸出流量,輸入規則則適用於輸入流量。輸出內容的預設值為 allow,輸入內容的預設值為 deny

防火牆規則會依優先順序編號套用,您可以指定優先順序編號。防火牆規則會區分狀態,也就是說,如果允許來自 VM 的特定流量,系統也會允許使用相同連線的傳回流量。

下圖顯示如何根據指派給節點的服務帳戶,將不同的防火牆規則套用至兩個不同節點集區中的節點。在本例中,預設 deny all 防火牆規則會拒絕整個 VPC 的輸出存取權。為避免覆寫叢集運作所需的預設防火牆規則,deny all 規則應使用低優先順序,例如 65535。系統會對閘道節點套用優先順序較高的加法輸出防火牆規則,允許節點直接連線至通訊埠 80 和 443 上的外部主機。預設節點集區無法存取外部主機。

防火牆節點集區

使用 Kubernetes 網路政策做為 Pod 和命名空間的防火牆

使用 Kubernetes 網路政策,套用額外的安全層,做為深入防禦策略的一環。網路政策的範圍僅限於命名空間,且在第 4 層 (傳輸層) 運作。您可以使用網路政策限制輸入和輸出:

  • 命名空間之間
  • 傳送至命名空間中的 Pod
  • 特定通訊埠和 IP 區塊。

網路政策選取命名空間中的 Pod 後,系統會拒絕所有未明確允許的連線。如果套用多項聯播網政策,結果會是政策的聯集,政策套用順序無關緊要。

以下提供幾個網路政策範例:

  • 允許工作負載命名空間連出至 istio-systemistio-egress 命名空間。Pod 必須能夠連線至控制層和外送閘道。
  • 允許工作負載從工作負載命名空間對 kube-system 命名空間中的 53 埠發出 DNS 查詢。
  • (選用) 允許相同命名空間中的工作負載彼此連線。
  • 視需要允許不同應用程式團隊使用的命名空間之間建立輸出連線。
  • 允許從工作負載命名空間到 Google API 的 VIP 的輸出連線 (透過私人 Google 存取權公開)。Cloud Service Mesh 提供代管 CA,並以 API 的形式公開,因此 Sidecar Proxy 必須能夠連線至該 CA。此外,部分工作負載可能需要存取 Google API。
  • 允許從工作負載命名空間連出至 GKE 中繼資料伺服器的連線,這樣一來,補充 Proxy 和工作負載就能進行中繼資料查詢,並向 Google API 進行驗證。

根據預設,當 Sidecar Proxy 注入工作負載 Pod 時,系統會編寫 iptables 規則,讓 Proxy 擷取所有輸入和輸出 TCP 流量。不過,如先前所述,工作負載可以略過 Proxy。虛擬私有雲防火牆規則會禁止預設節點直接存取 egress,這些節點會執行工作負載。您可以使用 Kubernetes 網路政策,確保工作負載命名空間無法直接對外傳送流量,且可以傳送流量至 istio-egress 命名空間。

如果您也透過網路政策控管 Ingress,則必須建立與 Egress 政策對應的 Ingress 政策。

服務網格設定和安全性

系統不會根據 IP 位址識別服務網格中執行的工作負載。Cloud Service Mesh 會為每個工作負載指派高強度、可驗證的身分,形式為 X.509 憑證和金鑰。工作負載之間會透過經過驗證和加密的雙向 TLS (mTLS) 連線,建立信任的通訊。

為每個應用程式使用 mTLS 驗證和明確定義的身分,可讓您透過網格授權政策,精細控管工作負載與外部服務的通訊方式。

雖然流量可以直接從 Sidecar Proxy 離開網格,但如果您需要額外控制,建議按照本指南所述,透過輸出閘道轉送流量。

在專屬命名空間中管理輸出控制項的設定

網路管理員可使用專用的 istio-egress 命名空間,集中管理輸出相關的網格設定控制項。如先前建議,您將輸出閘道部署至 istio-egress 命名空間。您可以在這個命名空間中建立及管理服務項目、閘道和授權政策。

必須明確設定外部目的地

確保網格 Proxy 只會透過明確定義在服務網格登錄檔中的外部主機,設定路徑。在每個命名空間的預設Sidecar 資源中,將輸出流量政策模式設為 REGISTRY_ONLY。設定網格的輸出流量政策本身不應視為安全範圍控制項。

使用服務項目定義外部目的地

設定服務項目,在網格的服務登錄中明確註冊外部主機。根據預設,所有命名空間都能看到服務項目。使用 exportTo 屬性,控管服務項目可見的命名空間。服務項目會決定網格 Proxy 中設定的傳出路徑,但本身不應視為安全控管措施,用來判斷工作負載可連線至哪些外部主機。

使用 Gateway 資源設定輸出閘道行為

使用「Gateway」資源設定輸出閘道的負載平衡行為。您可以為特定主機、通訊協定和通訊埠組合設定負載平衡器,並與輸出閘道部署作業建立關聯。舉例來說,閘道可能會設定為輸出至任何外部主機的通訊埠 80 和 443。

Cloud Service Mesh 預設會啟用自動 mTLS。透過自動 mTLS,用戶端 Sidecar Proxy 會自動偵測伺服器是否具有 Sidecar。用戶端 Sidecar 會將 mTLS 傳送至含有 Sidecar 的工作負載,並將純文字流量傳送至不含 Sidecar 的工作負載。即使使用自動 mTLS,從 Sidecar Proxy 傳送至輸出閘道的流量也不會自動使用 mTLS。如要指出與輸出閘道的連線應如何受到保護,您必須在 Gateway 資源上設定 TLS 模式。請盡可能使用 mTLS,從 Sidecar Proxy 連線至輸出閘道。

您可以允許工作負載自行啟動 TLS (HTTPS) 連線。如果工作負載會發起 TLS 連線 (通常是透過通訊埠 443),您必須將閘道設定為對該通訊埠的連線使用 passthrough 模式。不過,使用 passthrough 模式表示閘道無法根據工作負載的身分或加密要求的屬性套用授權政策。此外,目前無法同時使用 mTLS 和 passthrough

TLS 傳遞

設定虛擬服務和目的地規則,透過閘道轉送流量

使用虛擬服務目的地規則,設定從 Sidecar 代理程式到外部目的地的流量轉送路徑 (透過輸出閘道)。虛擬服務會定義比對特定流量的規則。然後將相符的流量傳送至目的地。目的地規則可定義子集 (例如輸出閘道或外部主機),以及流量在轉送至目的地時的處理方式。

針對多個目的地主機使用單一目的地規則,明確指定從 Sidecar Proxy 到閘道的流量應如何受到保護。如先前所述,建議工作負載傳送純文字要求,並由 Sidecar Proxy 發起與閘道的 mTLS 連線。

為每個外部主機使用目的地規則,將輸出閘道設為在轉送至目的地時「升級」純 HTTP 要求,改用 TLS (HTTPS) 連線。將純文字連線升級為 TLS,通常稱為「TLS 來源」

使用 Sidecar 資源控管 Proxy 設定的範圍

為每個命名空間設定預設的補充資源,控管補充 Proxy 的行為。使用 Sidecar 資源的輸出屬性,控管並盡量減少在 Proxy 的輸出接聽程式中設定的目的地主機。典型的基本設定可能包含每個命名空間的下列目的地:

  • 位於相同命名空間的 Pod
  • Google API 和服務
  • GKE 中繼資料伺服器
  • 使用服務項目設定的特定外部主機

補充 Proxy 中的輸出監聽器設定本身不應視為安全控管措施。

最佳做法是使用 Sidecar 資源,限制 Proxy 設定的大小。根據預設,網格中的每個 Sidecar Proxy 都會設定為允許將流量傳送至其他 Proxy。將 Proxy 的設定限制為僅與需要通訊的主機,即可大幅減少 Sidecar Proxy 和控制層的記憶體用量。

使用授權政策允許或拒絕輸出閘道的流量

AuthorizationPolicy 是一種資源,可讓您為網格流量設定精細的存取權控管政策。您可以根據來源、目的地或流量本身的屬性 (例如 HTTP 要求的主機或標頭),建立允許或拒絕流量的政策。

如要根據來源工作負載的身分或命名空間允許或拒絕連線,必須使用 mTLS 驗證與輸出閘道的連線。從 Sidecar 到輸出閘道的連線不會自動使用 mTLS,因此連線至閘道的目的地規則必須明確指定 ISTIO_MUTUAL TLS 模式

如要使用授權政策在閘道允許或拒絕要求,工作負載應將純 HTTP 要求傳送至網格外部的目的地。然後,附屬代理伺服器可以使用 mTLS 將要求轉送至閘道,而閘道可以發起與外部主機的安全 TLS 連線。

為支援不同團隊和應用程式的輸出需求,請為每個命名空間或工作負載設定個別的「最低權限」授權政策。舉例來說,您可以根據來源工作負載的命名空間和要求的屬性指定規則,在輸出閘道套用不同政策,如下所示:

  • 如果來源命名空間是 team-x,且目的地主機是 example.com,則允許流量。

    授權政策範例

  • 如果來源命名空間為 team-y,且目的地主機為 httpbin.org,且路徑為 /status/418,則「允許」流量。

    使用 httpbin 的授權政策

所有其他要求都會遭到拒絕。

設定輸出閘道,發起與目的地的 TLS (HTTPS) 連線

設定目的地規則,讓輸出閘道發起 TLS (HTTPS) 連線至外部目的地。

如要讓輸出閘道發起 TLS 連線,工作負載必須傳送純 HTTP 要求。如果工作負載啟動 TLS,輸出閘道會在原始 TLS 上方包裝 TLS,導致對外部服務的要求失敗。

由於工作負載會傳送純文字 HTTP 要求,請設定工作負載的 Sidecar Proxy,在傳送要求至閘道時建立 mTLS 連線。然後,出口閘道會終止 mTLS 連線,並發起到目的地主機的一般 TLS (HTTPS) 連線。

輸出閘道的傳輸層安全標準 (TLS) 啟動

這種方法有幾個優點:

  • 您可以根據來源工作負載和要求的屬性,使用授權政策允許或拒絕流量。

  • 工作負載 Pod 與輸出閘道之間的流量會經過加密及驗證 (mTLS),輸出閘道與目的地之間的流量則會經過加密 (TLS/HTTPS)。

  • 在網格內,Sidecar Proxy 可以觀察 HTTP 要求的屬性 (例如標頭) 並據此採取行動,提供更多可觀察性和控制選項。

  • 應用程式程式碼可以簡化。開發人員不必處理憑證或 HTTPS 用戶端程式庫,服務網格可確保使用標準且最新的密碼進行安全通訊。

  • 輸出閘道傳送至外部服務的 TLS 連線可重複用於多個 Pod 的流量。重複使用連線的效率較高,且可降低達到連線限制的風險。

DNS、主機名稱和萬用字元

根據目的地主機轉送、拒絕或允許流量時,您必須完全信任 DNS 系統的完整性,才能將 DNS 名稱解析為正確的 IP 位址。在 Kubernetes Engine 叢集上,Kubernetes DNS 服務會處理 DNS 查詢,並將外部查詢委派給 GKE 中繼資料伺服器和內部 DNS。將服務項目的解析屬性設為 DNS,即可將流量路由至外部主機,讓 Sidecar Proxy 負責發出 DNS 查詢。

Cloud Service Mesh 可根據萬用字元主機轉送流量。最簡單的情況是,主機共用一個通用名稱,且託管在同一組伺服器上,這時可以使用萬用字元。舉例來說,如果一組伺服器可以服務 *.example.com 比對的網域,則可以使用萬用字元主機。

由於 Istio 使用的 Envoy Proxy 有某些限制,標準輸出閘道無法根據更一般且任意的萬用字元主機 (例如 *.com) 轉送流量。Envoy 只能將流量轉送至預先定義的主機、預先定義的 IP 位址,或是要求的原始目的地 IP 位址。使用輸出閘道時,要求原始目的地 IP 會遺失,因為系統會將其取代為閘道的 IP,且無法預先設定任意目的地主機。

政策的行政強制執行

使用 Kubernetes 角色型存取控制 (RBAC)

只有獲得授權的管理員才能設定輸出控制項。 設定 Kubernetes 角色型存取權控管 (RBAC),避免未經授權規避輸出控制項。套用 RBAC 角色,確保只有網路管理員可以管理 istio-egressistio-system,kube-system 命名空間,以及下列資源:

  • Sidecar
  • ServiceEntry
  • 閘道
  • AuthorizationPolicy
  • NetworkPolicy

限制容許度的使用

先前所述,您可以使用 taint 和容許條件,防止工作負載 Pod 部署在閘道節點上。不過,根據預設,系統不會阻止工作負載部署閘道節點的容許度,因此允許略過輸出控制項。如果可以對部署管道強制執行集中式管理控制,您可以使用這些管道,對特定容許鍵的使用強制執行限制。

另一種做法是使用 Kubernetes 准入控制。Anthos 包含名為「Policy Controller」的元件,可做為 Kubernetes 准入控制器,並驗證部署作業是否符合您指定的政策限制。

確保系統會記錄流量

通常需要記錄所有跨越網路邊界的流量。 如果您必須證明自己符合常見的資料保護法規,流量記錄就不可或缺。流量記錄會直接傳送至 Cloud Logging,並可從 Google Cloud 控制台的 Cloud Service Mesh 資訊主頁存取。您可以根據各種屬性 (包括來源/目的地、身分、命名空間、流量屬性和延遲時間) 篩選記錄。

如要使用 kubectl 輕鬆進行偵錯,請在安裝 Cloud Service Mesh 時,使用 accessLogFile 設定啟用流量記錄功能,將記錄檔傳送至 stdout

每當 Mesh CA 為工作負載建立憑證時,系統就會將稽核記錄傳送至 Cloud Logging。

在多叢集網格中,考慮使用獨立叢集做為輸出閘道

Cloud Service Mesh 可部署至多個 GKE 叢集。多叢集網格可控制輸出流量,但也存在一些限制。

您可以將輸出閘道部署至不執行一般工作負載的獨立叢集,不必部署至專屬節點集區。使用獨立叢集可在工作負載和閘道之間提供類似的隔離效果,同時避免需要汙點和容許度。輸出閘道可以與輸入閘道或其他中央服務共用獨立叢集。

您可以在多叢集部署作業中使用 Kubernetes 網路政策,但由於這些政策是在第 4 層 (傳輸) 運作,因此無法根據目的地命名空間或 Pod 限制跨叢集連線。

後續步驟