在 GKE 叢集中使用 Cloud Service Mesh 輸出閘道的最佳做法
本文說明如何使用 Cloud Service Mesh 出口閘道和其他 Google Cloud 控制項,保護在 Google Kubernetes Engine (GKE) 叢集中部署的工作負載的傳出流量 (出口)。這些控制項可根據來源應用程式的身分、團隊的命名空間、目的地網域,以及傳出要求的其他屬性,限制與外部服務的連線。
本文件的目標對象包括網路、平台和安全性工程師,他們負責管理一或多個軟體提交團隊使用的 GKE 叢集。對於必須證明遵守法規 (例如 GDPR 和 PCI) 的機構而言,本文所述的控管措施可能特別實用。
簡介
傳統的網路安全性做法,是圍繞一組應用程式定義安全邊界。防火牆會用於這些外圍,根據來源和目的地 IP 位址允許或拒絕流量,同時信任外圍內的應用程式和流量。不過,這項信任關係涉及風險。惡意內部人員或任何人都能突破邊界,在網路中自由移動、存取及外洩資料、攻擊第三方系統,以及干擾管理系統。
當在 Kubernetes 叢集中執行的工作負載建立與網際網路上主機的輸出連線時,套用傳統的 IP 安全控管機制可能會變得複雜,原因如下:
Pod IP 位址無法充分代表建立連線的工作負載身分。在 Kubernetes 環境中,Pod IP 位址會暫時性指派,並隨著 Pod 的進出頻繁回收。
通常無法為特定目的地主機識別一組固定的 IP 位址。IP 位址經常變動,且因地區而異,可能來自大範圍或代表快取、proxy 或 CDN。
多個團隊共用相同的多租戶叢集,並共用來源 IP 位址範圍,可能會有不同的外部連線需求。
Cloud Service Mesh 是全代管服務網格, Google Cloud以開放原始碼 Istio 服務網格為基礎。服務網格可讓您以統一方式連結、管理及保護應用程式通訊。服務網格採用以應用程式為主的做法,並使用可信任的應用程式身分,而非以網路 IP 為主的做法。
您可以公開部署服務網格,而無須修改現有的應用程式程式碼。使用服務網格可提供網路行為的宣告式控管機制,有助於將負責提供及發布應用程式功能的開發團隊工作,與網路管理員的職責分開。
Cloud Service Mesh 提供部署獨立轉送 Proxy (稱為輸出閘道) 的選項,可在網格邊緣部署。本指南說明如何將出口閘道 Proxy 的功能與 Google Cloud 功能結合,以便控管、授權及觀察部署至 GKE 叢集的工作負載的傳出流量。
縱深防禦架構
下圖顯示採用深入防禦方法的架構,可針對多個團隊使用的叢集,精細控管外連流量。這些控制項同時採用第 4 層 (傳輸) 和第 7 層 (應用程式) 網路控制項。
這個架構會使用下列資源和控制項:
私人 GKE 叢集:私人 GKE 叢集中的節點只會使用內部 IP 位址,且預設不會連上網際網路。
Cloud NAT:Cloud NAT 可讓私人叢集連出網際網路。
虛擬私有雲 (VPC) 防火牆規則:您可以設定 VPC 防火牆規則,將第 4 層 (傳輸) 控管套用至 GKE 叢集中的節點連線。您可以根據服務帳戶或網路標記,將 VPC 防火牆規則套用至 VM。
使用不同服務帳戶的 GKE 節點集區:您可以根據節點所屬的節點集區,設定要套用的不同防火牆規則。
Kubernetes 命名空間:您可以為每個團隊建立命名空間,提供隔離和委派的管理控制功能。網路管理員會使用專屬命名空間來部署外送閘道,並設定外部主機的路由。
Kubernetes 網路政策:網路政策可讓您將第 4 層控管套用至 Pod。每項網路政策的範圍都限定在命名空間中,並可進一步限定為命名空間中的特定 Pod。
輸出閘道:網格內離開 Pod 的流量會經由專屬節點上執行的專屬輸出閘道 Proxy 轉送。您可以使用水平 Pod 自動配置器部署出口閘道,讓備用資源數量隨著流量上下調整。
授權政策:您可以使用網格授權政策,將第 7 層 (應用程式) 控管機制套用至網格內的 Pod 之間流量,以及離開網格的流量。
側邊車資源:您可以使用側邊車資源,控制在每個工作負載 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 叢集符合這項要求。您可以在私人叢集中設定 VPC 原生模式,為 Pod 和服務指派來自虛擬私有雲中次要範圍的 IP 位址。虛擬私有雲原生 Pod IP 位址本身可以在虛擬私有雲網路中直接轉送。
部分工作負載可能需要存取虛擬私有雲網路和網際網路以外的服務。如要讓工作負載連線至外部主機,但不必讓主機具備公用 IP 位址,請設定 Cloud NAT 提供網路位址轉譯 (NAT)。
請確認 Cloud NAT 已設定完成,以便出口閘道可與外部目的地建立足夠數量的同時連線。如要避免通訊埠用盡,以及連線重複使用延遲的問題,請適當設定每個 VM 的通訊埠數量下限。詳情請參閱「Cloud NAT 位址和連接埠總覽」。增加出口網關副本的數量,有助於降低與端點無關的對應衝突的機率。
設定 Google API 和服務的私人 Google 存取權
您的工作負載可能需要存取 Google API 和服務。搭配自訂 DNS 區域使用私人 Google 存取權,即可透過一組四個 IP 位址,連線至私人 VPC 子網路和 Google API。使用這些 IP 位址時,Pod 不需要有外部 IP 位址,而且流量永遠不會離開 Google 網路。您可以使用 private.googleapis.com
(199.36.153.8/30
) 或 restricted.googleapis.com
(199.36.153.4/30
),取決於您是否使用 VPC Service Controls。
使用 Workload Identity 和 IAM 進一步強化 Google API 和服務的安全性
如要讓 GKE 工作負載透過 Google API 進行驗證,並讓管理員使用 IAM 套用「最低權限」授權控管機制,建議您使用 Workload Identity。
使用私人 Google 存取權、Workload Identity 和 IAM 時,您可以安全地允許工作負載 Pod 略過輸出閘道,直接連線至 Google API 和服務。
使用 Kubernetes 命名空間進行管理
命名空間是一種組織資源,可在有大量使用者、團隊或租戶的環境中派上用場。可視為虛擬叢集,可將 Kubernetes 資源群組的管理責任委派給不同的管理員。
命名空間是隔離管理控制項的重要功能。不過,根據預設,這些服務不會提供節點隔離、資料平面隔離或網路隔離功能。
Cloud Service Mesh 會在 Kubernetes 命名空間上建構,並將其用於服務網格中的租用單位。Mesh 授權政策和側邊資源可根據命名空間、身分和網路流量的第 7 層 (應用程式) 屬性,限制可見度和存取權。
同樣地,您也可以使用 Kubernetes 網路政策,在第 4 層 (傳輸) 允許或拒絕網路連線。
在專屬閘道節點上執行輸出閘道
在專屬閘道節點集區的節點上執行輸出閘道,可帶來多項優勢。面向外部的節點可使用強化設定,您也可以設定 VPC 防火牆規則,防止工作負載直接存取外部主機。您可以使用叢集自動配置器,為節點集區獨立設定自動調度功能。
如要對出口閘道進行獨立管理,請將其部署至專屬的 istio-egress
命名空間。不過,命名空間是叢集層級資源,無法用於控制部署作業在哪些節點上執行。如要控管部署作業,請為閘道外送部署作業使用節點選取器,以便在標示為閘道節點集區成員的節點上執行。
請確認只有閘道 Pod 可在閘道節點上執行。其他 Pod 應從閘道節點中移除,否則可能會繞過輸出控制項。您可以使用taint 和容許條件,防止工作負載在特定節點上執行。您應將閘道節點集區中的節點標記為不良,並在出口閘道部署中新增對應的容許值。
將 VPC 防火牆規則套用至特定節點
您可以設定服務網格路由,將在預設節點集區中執行的工作負載輸出流量,透過在閘道節點集區中執行的輸出閘道轉送。不過,您不應將網狀結構的路由設定視為安全界線,因為工作負載有許多方法可以繞過網狀結構 Proxy。
如要避免應用程式工作負載直接連線至外部主機,請將限制性傳出防火牆規則套用至預設節點集區中的節點。將個別防火牆規則套用至閘道節點,讓在其中執行的輸出閘道 Pod 能夠連線至外部主機。
建立 VPC 防火牆規則時,您必須指定防火牆規則允許或拒絕的通訊埠和通訊協定,以及適用的流量方向。輸出規則適用於輸出流量,輸入規則適用於輸入流量。出口的預設值為 allow
,入口的預設值為 deny
。
防火牆規則會依您指定的優先順序依序套用。防火牆規則會區分狀態,也就是說,如果允許 VM 的特定流量,則也會允許使用相同連線的傳回流量。
下圖顯示如何根據指派給節點的服務帳戶,將個別防火牆規則套用至兩個不同節點叢集中的節點。在這種情況下,預設 deny all
防火牆規則會拒絕整個 VPC 的輸出存取權。為避免覆寫叢集運作所需的預設防火牆規則,deny all
規則應使用較低的優先順序,例如 65535。然後將優先順序更高的輸出防火牆規則套用至閘道節點,讓這些節點可直接連線至通訊埠 80 和 443 的外部主機。預設節點集區無法存取外部主機。
使用 Kubernetes 網路政策做為 Pod 和命名空間的防火牆
使用 Kubernetes 網路政策,在縱深防禦策略中套用額外的安全層。網路政策的範圍為命名空間,且會在第 4 層 (傳輸) 運作。您可以使用網路政策限制傳入和傳出:
- 在命名空間之間
- 傳送至命名空間內的 Pod
- 到特定通訊埠和 IP 區塊。
任何網路政策選取命名空間中的 Pod 後,系統會拒絕所有未明確允許的連線。套用多項聯播網政策時,結果會是累加的,也就是政策的聯合。政策的套用順序不拘。
以下列舉一些網路政策範例:
- 允許從工作負載命名空間傳出的連線,連往
istio-system
和istio-egress
命名空間。Pod 必須能夠連線至控制平面和外送閘道。 - 允許工作負載從工作負載命名空間對
kube-system
命名空間中的 53 連接埠發出 DNS 查詢。 - 您可以選擇允許同一個命名空間中的各工作負載彼此連線。
- 您可以選擇允許不同應用程式團隊使用的命名空間之間的輸出連線。
- 允許從工作負載命名空間到 Google API 的 VIP 的輸出連線 (使用私人 Google 存取權公開)。Cloud Service Mesh 會提供受管理的 CA,並將其公開為 API,因此側邊 Proxy 必須能夠連線至該 CA。某些工作負載也可能需要存取 Google API。
- 允許從工作負載命名空間連出的連線,連線至 GKE 中繼資料伺服器,以便補充 Proxy 和工作負載執行中繼資料查詢,並驗證 Google API。
根據預設,當側邊代理程式插入工作負載 Pod 時,系統會編寫 iptables
規則,讓代理程式擷取所有進出 TCP 流量。不過,如先前所述,工作負載有許多方法可以略過 Proxy。虛擬私有雲防火牆規則可防止執行工作負載的預設節點直接存取 egress。您可以使用 Kubernetes 網路政策,確保工作負載命名空間無法直接傳送外部流量,且只能傳送至 istio-egress
命名空間。
如果您也要透過網路政策控管入站流量,則需要建立入站政策,以便與出站政策相符。
服務網格設定和安全性
服務網格中執行的工作負載不會根據 IP 位址進行識別。Cloud Service Mesh 會為每個工作負載以 X.509 憑證和金鑰的形式,指派強大且可驗證的身分。系統會使用經過驗證且已加密的相互傳輸層安全性 (mTLS) 連線,建立工作負載之間的安全通訊。
您可以使用 mTLS 驗證,並為每個應用程式提供明確定義的身分,藉此使用網格授權政策,精細控管工作負載與外部服務通訊的方式。
雖然流量可以直接從附加 Proxy 離開網格,但如果您需要額外控管,建議您按照本指南所述,將流量路由至輸出閘道。
管理專屬命名空間的傳出控制項設定
允許網路管理員使用專屬的 istio-egress
命名空間,針對出口相關的網狀網絡設定集中管理控制項。如先前建議,您可以將出口閘道部署至 istio-egress
命名空間。您可以在這個命名空間中建立及管理服務項目、閘道和授權政策。
需要明確設定外部目的地
請確認網格 Proxy 只針對服務網格註冊中心中明確定義的外部主機,編寫路由。在每個命名空間的預設側邊資源中,將出站流量政策模式設為 REGISTRY_ONLY
。為網格設定傳出流量政策時,不應單獨視為安全邊界控管。
使用服務項目定義外部目的地
設定服務項目,即可在網格的服務註冊表中明確註冊外部主機。根據預設,所有命名空間都能查看服務項目。使用 exportTo 屬性,控管服務項目可供哪些命名空間存取。服務項目會決定在 Mesh Proxy 中設定的傳出路徑,但不應單獨視為安全控管機制,用於決定工作負載可連線至哪些外部主機。
使用閘道資源設定外送閘道行為
使用「閘道」資源設定外送閘道的負載平衡行為。您可以為特定組合的主機、通訊協定和通訊埠設定負載平衡器,並與輸出閘道部署作業建立關聯。舉例來說,閘道可能會針對任何外部主機的輸出通訊埠 80 和 443 進行設定。
在 Cloud Service Mesh 中,自動 mTLS 預設為啟用狀態。透過自動 mTLS,用戶端 sidecar proxy 會自動偵測伺服器是否有 sidecar。用戶端 sidecar 會將 mTLS 傳送至含 sidecar 的工作負載,並將純文字流量傳送至不含 sidecar 的工作負載。即使啟用自動 mTLS,從附屬 Proxy 傳送至外寄閘道的流量也不會自動使用 mTLS。如要指出應如何保護到出口閘道的連線,您必須在閘道資源上設定 TLS 模式。請盡可能使用 mTLS,為從附屬代理程式連線至出口閘道的連線提供安全性。
您可以允許工作負載自行啟動 TLS (HTTPS) 連線。如果工作負載會產生 TLS 連線 (通常是位於 443 埠),您必須將閘道設為使用 passthrough
模式,以便連線至該埠。不過,使用 passthrough
模式表示閘道無法根據工作負載的身分或加密要求的屬性套用授權政策。此外,目前不能同時使用 mTLS 和 passthrough
。
設定虛擬服務和目的地規則,將流量轉送至閘道
使用虛擬服務和目的地規則,設定從側邊代理程式透過輸出閘道轉送至外部目的地的流量。虛擬服務會定義比對特定流量的規則。系統會將符合條件的流量傳送至目的地。目的地規則可定義子集 (例如外送閘道或外部主機),以及在流量轉送至目的地時應如何處理流量。
針對多個目的主機使用單一目的地規則,明確指定從附加 Proxy 到閘道的流量應如何加以保護。如先前所述,建議的工作負載方法是讓工作負載傳送純文字要求,並由附加元件 Proxy 建立與閘道建立 mTLS 連線。
針對每個外部主機使用目的地規則設定出口閘道,以便在轉送至目的地時,將純 HTTP 要求「升級」為使用 TLS (HTTPS) 連線。將純文字連線升級為 TLS 通常稱為「TLS 來源」。
使用 Sidecar 資源控管 Proxy 設定的範圍
為每個命名空間設定預設的 Sidecar 資源,以便控管 Sidecar Proxy 的行為。請使用 Sidecar 資源的egress 屬性,控制並減少在 Proxy 的傳出端事件監聽器中設定的目標主機。一般而言,最基本的設定可能會為每個命名空間加入下列目的地:
- 位於相同命名空間中的 Pod
- Google API 和服務
- GKE 中繼資料伺服器
- 已使用服務項目設定的特定外部主機
側車 Proxy 中的輸出連線監聽器設定不應單獨視為安全控制項。
最佳做法是使用 Sidecar 資源來限制 Proxy 設定的大小。根據預設,網格中的每個 Sidecar Proxy 都會設定為允許傳送流量至每個 Proxy。只要將 Proxy 的設定限制為僅與需要進行通訊的主機,即可大幅減少 Sidecar Proxy 和控制層的記憶體用量。
使用授權政策允許或拒絕外送閘道中的流量
AuthorizationPolicy 是一種資源,可讓您為網格流量設定精細的存取權控管政策。您可以建立政策,根據來源、目的地或流量本身的屬性 (例如 HTTP 要求的主機或標頭) 允許或拒絕流量。
如要根據來源工作負載的 ID 或命名空間允許或拒絕連線,必須使用 mTLS 驗證輸出閘道的連線。從附屬程式連線至輸出閘道的連線不會自動使用 mTLS,因此連線至閘道的目的地規則必須明確指定 ISTIO_MUTUAL
TLS 模式。
如要使用授權政策在閘道中允許或拒絕要求,工作負載應將純 HTTP 要求傳送至網格之外的目的地。接著,側邊代理程式可以使用 mTLS 將要求轉送至閘道,而閘道則可建立與外部主機的安全 TLS 連線。
為了支援不同團隊和應用程式的要求,請為每個命名空間或工作負載設定個別的「最低權限」授權政策。舉例來說,您可以根據來源工作負載的命名空間和要求屬性,指定規則,以便在出口閘道套用不同的政策,如下所示:
如果來源命名空間是 team-x,且目的主機是 example.com,請允許流量。
如果來源命名空間為 team-y,目的地主機為 httpbin.org,路徑為 /status/418,則允許流量。
所有其他要求都會遭拒。
設定輸出閘道,以便產生前往目的地的 TLS (HTTPS) 連線
設定目的地規則,讓輸出閘道產生與外部目的地建立 TLS (HTTPS) 連線。
如要讓 TLS 來源在輸出閘道運作,工作負載必須傳送純 HTTP 要求。如果工作負載啟動 TLS,外寄閘道會在原始 TLS 上包裝 TLS,而對外部服務的要求將會失敗。
由於工作負載會傳送純文字 HTTP 要求,請設定工作負載的附屬 Proxy,以便在傳送至閘道時建立 mTLS 連線。然後,出口閘道會終止 mTLS 連線,並建立至目的主機的一般 TLS (HTTPS) 連線。
這種方法有幾個優點:
您可以使用授權政策,根據來源工作負載和要求的屬性允許或拒絕流量。
工作負載 Pod 和輸出閘道之間的流量會經過加密和驗證 (mTLS),輸出閘道和目的地之間的流量則會經過加密 (TLS/HTTPS)。
在網格中,側邊 Proxy 可以觀察 HTTP 要求的屬性 (例如標頭),並採取相應行動,提供可觀察性和控制的其他選項。
應用程式程式碼可簡化。開發人員不必處理憑證或 HTTPS 用戶端程式庫,服務中介網可透過標準和最新的密碼,確保通訊安全。
輸出閘道建立至外部服務的 TLS 連線,可用於許多 Pod 的流量。重複使用連線可提高效率,並降低達到連線限制的風險。
DNS、主機名稱和萬用字元
根據目的地主機轉送、拒絕或允許流量時,您必須完全信任 DNS 系統的完整性,才能將 DNS 名稱解析為正確的 IP 位址。在 Kubernetes Engine 叢集中,Kubernetes DNS 服務會處理 DNS 查詢,並將外部查詢委派給 GKE 中繼資料伺服器和內部 DNS。將服務項目的解析屬性設為 DNS,以便在路由至外部主機時,由附加元件 Proxy 負責執行 DNS 查詢。
Cloud Service Mesh 可根據萬用字元主機轉送流量。最簡單的情況是,主機共用通用名稱,且主機在通用的伺服器組上代管,舉例來說,如果單一組伺服器可為 *.example.com
比對的網域提供服務,則可使用萬用字元主機。
標準出口閘道無法根據更一般且任意的萬用字元主機 (例如 *.com
) 轉送,這是因為 Istio 使用的 Envoy 代理程式有特定限制。Envoy 只能將流量轉送至預先定義的主機、預先定義的 IP 位址,或要求的原始目的地 IP 位址。使用出口閘道時,要求的原始目的地 IP 會遺失,因為系統會將其替換為閘道的 IP,且無法預先設定任意目的地主機。
管理政策違規處置
使用 Kubernetes 角色型存取權控管 (RBAC)
只有經過授權的管理員才能設定出口控管。設定 Kubernetes 角色式存取權控管 (RBAC),避免未經授權的使用者規避出口控管機制。套用 RBAC 角色,讓只有網路管理員可以管理 istio-egress
、istio-system,
和 kube-system
命名空間,以及下列資源:
- 補充資訊
- ServiceEntry
- 閘道
- AuthorizationPolicy
- NetworkPolicy
限制使用容忍值
如前文所述,您可以使用 taint 和容許條件,避免工作負載 Pod 部署到閘道節點。不過,根據預設,沒有任何措施可防止工作負載在閘道節點上部署時使用容許值,因此會允許略過出口控管。如果可以對部署管道實施集中管理,您可以使用這些管道,對使用特定容忍值鍵實施限制。
另一種做法是使用 Kubernetes 存取控制。Anthos 包含一個名為 Policy Controller 的元件,可充當 Kubernetes 存取控制器,驗證部署作業是否符合您指定的政策限制。
確保記錄流量
通常需要記錄所有跨越網路邊界的流量。如果您必須證明自己遵守常見的資料保護法規,則必須記錄流量。流量記錄會直接傳送至 Cloud Logging,您也可以透過 Google Cloud 控制台中的 Cloud Service Mesh 資訊主頁存取。您可以根據各種屬性篩選記錄,包括來源/目的地、身分、命名空間、流量屬性和延遲時間。
如要透過 kubectl
輕鬆進行偵錯,請使用 accessLogFile 設定,在安裝 Cloud Service Mesh 時啟用流量記錄功能,將流量記錄到 stdout
。
每當 Mesh CA 為工作負載建立憑證時,系統就會將稽核記錄傳送至 Cloud Logging。
建議在多叢集網格中,為輸出閘道使用不同的叢集
Cloud Service Mesh 可部署在多個 GKE 叢集中。多叢集網格可提供控制輸出流量的新可能性,但也存在一些限制。
您可以將閘道部署至不執行一般工作負載的專屬節點集區,而非部署至專屬節點集區。使用獨立的叢集可在工作負載和閘道之間提供類似的隔離功能,同時避免需要使用污點和容許值。輸出閘道可與入口閘道或其他集中式服務共用個別叢集。
您可以在多叢集部署中使用 Kubernetes 網路政策,但由於這些政策是在第 4 層 (傳輸) 運作,因此無法根據目的地命名空間或 Pod 限制跨叢集連線。
後續步驟
- 參閱 GKE 強化指南
- 瞭解如何使用 Anthos Config Management 管理所有基礎架構的設定和政策
- 如需更多參考架構、圖表和最佳做法,請瀏覽 雲端架構中心。