設計 GKE 上 Agent Substrate 的基礎架構

Google Kubernetes Engine (GKE) 可讓您擴充 GKE 上的 Agent Substrate 叢集,支援高並行 AI 代理工作負載,同時盡可能降低閒置運算成本。只要將專屬系統基礎架構節點集區與自訂 ComputeClass 和運算資源緩衝區結合,即可隔離重要系統元件、自動在 Compute Engine 機器系列中執行硬體備用作業,並保持待命 Worker 容量。

請參閱這份文件,瞭解如何調整 GKE 叢集元件、隔離系統基礎架構和資料庫節點集區、為 WorkerPool 資源設定自動節點佈建,以及規劃叢集維護和升級作業。本文適用對象為在 GKE 基礎架構上佈建及管理 Agent Substrate 的平台管理員。

事前準備

為叢集基礎架構設定資源調度前,請確認環境符合下列需求:

  • GKE 叢集模式和版本:您必須使用 GKE Standard 叢集,且控制層和節點集區都必須執行 1.37 以上版本。GKE 上的 Agent Substrate 不支援 GKE Autopilot 叢集。
  • 在 GKE 上安裝 Agent Substrate:您必須已在 GKE 上安裝 Agent Substrate,或打算在 GKE 上安裝 Agent Substrate,並啟用系統基礎架構節點隔離功能。如需安裝步驟,請參閱「在 GKE 上安裝 Agent Substrate」。

調整 Agent Substrate 叢集大小

請根據尖峰並行率和尖峰恢復率 (而非平均值) 調整叢集大小。worker 節點必須能容納同時執行的 Actor 數量上限,且系統基礎架構元件和儲存空間路徑必須能跟上 Actor 恢復和暫停的最快速度。

預估工作負載高峰

如果沒有實際工作環境測量結果,請根據註冊的 Actor 總數 (total_actors)、同時執行的 Actor 平均比例 (average_active_fraction)、流量暴增倍數 (burst_factor),以及 Actor 每回合保持活躍的平均時間長度 (average_seconds_active_per_resume),估算最多同時線上觀眾人數和恢復率:

peak_running_actors = total_actors × average_active_fraction × burst_factor
peak_resume_rate    = peak_running_actors / average_seconds_active_per_resume

舉例來說,假設您總共有 100,000 個 Actor,平均有 10% 處於活躍狀態 (10,000 個 Actor),且突發係數為 2,則叢集必須支援 20,000 個尖峰執行 Actor。如果每個 Actor 平均執行 100 秒後暫停,則維持該峰值需要每秒恢復 200 次和每秒暫停 200 次。

GKE 上的 Agent Substrate 不會自動暫停閒置的 Actor,必須由應用程式或自動調度管理工具觸發暫停。

調整資料層大小

本節說明調整資料層大小的最佳做法,包括 Worker Pod、GKE 節點、快照頻寬和 atelet 節點代理程式。

計算 worker Pod 和 GKE 節點

WorkerPool 中的每個 Worker Pod 都會託管多個 Actor。如果 Worker 託管的 Actor 數量少於 ateworker 容器上 --max-actors 旗標設定的限制 (預設為 1000),且剩餘的 CPU 和記憶體容量足以符合 ActorTemplate 限制,則 Worker 可以接受新的 Actor。如要進一步瞭解 Worker 限制與 Actor 限制之間的互動,請參閱開放原始碼指南,瞭解如何在 Agent Substrate API 中調整資源大小。

計算所需的工作站 Pod 數量,並保留 20% 的可用排程容量 (0.8 係數):

slots_per_worker = min(max_actors, worker_memory / actor_memory, worker_cpu / actor_cpu)
total_workers    = peak_running_actors / (slots_per_worker × 0.8)

在這個公式中,max_actors 變數預設為 1000 (由 --max-actors 旗標設定)。從 worker_memory 值中減去 Worker 為自身程序預留的記憶體。如果是 microVM WorkerPool 資源,請將 Worker 回報的每個 Actor 虛擬機器監控器 (VMM) 記憶體負擔加到 actor_memory 值,因為配置會將該負擔計入 Worker 容量。

每個節點有一個 Worker Pod,因此 Worker 數量等於 GKE worker 節點數量。請勿將節點 100% 的可分配 CPU 和記憶體分配給 Worker Pod,請在每個節點上為 atelet DaemonSet (位於 ate-system 命名空間) 和 GKE 系統 Daemon 保留容量。GKE Standard 每個叢集最多支援 65,000 個節點,每個節點最多支援 512 個 Pod。預設上限為每個節點 110 個 Pod (可使用 --max-pods-per-node 旗標設定),大型叢集則有其他需求。

調整快照頻寬和節點磁碟大小

每個 Actor 暫停作業都會將快照寫入 /var/lib/ate 目錄路徑下的本機節點磁碟。在 SYNCHRONOUS 模式下,atelet 代理程式會在暫停作業傳回前,將快照上傳至 Cloud Storage。在 ASYNCHRONOUS 模式下,atelet 代理程式會在拍攝快照後,延遲約 --snapshot-upload-delay 旗標值 (預設為 5m) 的時間,再排定上傳至 Cloud Storage。Agent Substrate 會在節點上快取最新快照,快取時間長度由 --snapshot-detach-delay 旗標設定,預設值為 30m。在該時間範圍內恢復的 Actor 會排定在同一個節點上,並從本機磁碟還原,而不是從 Cloud Storage 下載快照。

預估未壓縮的快照大小 (snapshot_size),方法是將 ActorTemplate 記憶體限制加上寫入可寫入根檔案系統或永久目錄的任何資料。稀疏檔案處理和 zstd 壓縮功能可縮減壓縮快照大小 (compressed_snapshot_size),減少與 Cloud Storage 之間的傳輸量。Agent Substrate 最多可為每個 Actor 儲存兩個快照 (前一個快照和進行中的快照):

  • Cloud Storage 頻寬峰值 (每個方向): peak_resume_rate × compressed_snapshot_size
  • 每個節點的節點磁碟寫入處理量尖峰: 2 × peak_resume_rate × snapshot_size / total_nodes (繼續下載和暫停檢查點都會寫入節點磁碟)。

GKE 中的預設 100 GiB hyperdisk-balanced 開機磁碟提供 3,600 IOPS 和 290 MiB/s 的處理量 (預設效能會隨著磁碟大小而調整),這可能會限制客體 I/O 負載過重時的快照作業。建立 worker 節點集區時,請在 /var/lib/ate/snapshots 目錄路徑掛接專用磁碟,或使用 gcloud container node-pools create 指令搭配 --boot-disk-provisioned-iops 和 --boot-disk-provisioned-throughput 旗標,提高開機磁碟效能。

查看 Security Token Service 配額

每次將快照移轉至 Cloud Storage 或從 Cloud Storage 移轉快照時,都需要限定於執行者的權杖,ate-api-server 元件會向 Security Token Service (STS) API 要求該權杖。ate-api-server 元件每 20 到 40 分鐘會向每個 Actor 提出最多一項 STS 要求 (通常是在該時間範圍內首次繼續播放時),並重複使用權杖,直到權杖到期前 20 分鐘為止。

STS Exchange token global requests 配額預設為每項專案每分鐘 6,000 個要求,並與 Workload Identity Federation for GKE 共用:

  • 必要的 STS 配額 (每分鐘要求數):預估值最多為上次快照移轉時間超過 20 分鐘前的執行者恢復作業尖峰速率的 60 倍,加上 GKE Workload Identity 聯盟的容量。如果不知道該比率,請使用 60 × peak_resume_rate 公式做為備用方案。舉例來說,每秒 200 個繼續作業要求,每分鐘最多需要 12,000 個要求。
  • 如何提高配額:在 Google Cloud 控制台的「Quotas & System Limits」(配額與系統限制) 頁面申請提高配額。即使專案未啟用 Security Token Service API,快照移轉作業仍可運作,但您必須啟用 API,配額才會顯示在「Quotas & System Limits」(配額與系統限制) 頁面。詳情請參閱 Workload Identity Federation for GKE 說明文件中的「Security Token Service 的 Exchange Token API 配額」。

調整 atelet 節點代理

atelet DaemonSet 會在每個 worker 節點上執行一個 Pod,用於還原 Actor 並建立檢查點。在每個 atelet Pod 中,objectstore-plugin 容器會壓縮快照,並在 Cloud Storage 之間傳輸快照。

下表說明 atelet 和 objectstore-plugin 容器的主要大小設定:

設定 預設 尺寸指南
atelet 和 objectstore-plugin 容器 CPU 和記憶體 要求:50 mCPU、128 MiB 記憶體;無限制 如要設定 Burstable QoS,請省略兩個容器的記憶體限制,因為達到記憶體限制會停止節點代理,並停止節點上的所有繼續作業。提高 CPU 和記憶體要求,以符合在完整節點上測得的尖峰用量 (以尖峰恢復率計算),確保工作站 Pod 不會耗用 atelet 代理程式所需的資源。
--upload-memory-budget 旗標 (objectstore-plugin 容器) 和 --snapshot-upload-workers 旗標 (atelet 容器) 512 MiB 預算;2 個上傳工作站

如要避免並行快照上傳作業在暫停率偏高的多 Actor 節點上排入佇列,請按照下列步驟操作:

  • 提高 --upload-memory-budget 旗標的值 (並將 objectstore-plugin 容器記憶體要求設為高於這項預算)。
  • 提高 --snapshot-upload-workers 旗標的值。
--drain-timeout 旗標和 terminationGracePeriodSeconds 欄位 5 分鐘 (--drain-timeout 旗標);330 秒 (terminationGracePeriodSeconds 欄位) 控制 atelet 代理程式在節點耗盡或升級期間停止 Pod 時,完成執行中還原和快照上傳作業的時間長度。如果提高大型快照的 --drain-timeout 旗標值,請一併提高 atelet DaemonSet 的 terminationGracePeriodSeconds 欄位值,這樣 kubelet 代理程式就不會在上傳完成前停止 atelet 代理程式。

調整系統基礎架構元件和資料庫的大小

針對 ate-system 命名空間中可水平擴充的無狀態系統元件 Deployment,請預估所需的副本數量,並保留 35% 的可用容量 (0.65 係數),再加上一個備用副本 (+ 1),以容許節點中斷:

replicas = ceil(peak_load / (capacity_per_replica × 0.65)) + 1

共用依附元件 (例如 PostgreSQL CPU 或連線限制) 達到容量上限後,水平擴充就無法再提高處理量。一併調整系統基礎架構元件和資料庫的大小。如要進一步瞭解元件旗標,請參閱開放原始碼運算子安裝指南。

下表說明各系統基礎架構元件的資源和資源調度規則:

元件 QoS 和資源規則 資源調度與連線調整
輸入路由器 (atenet-router) 設定保證 QoS:設定相符的 CPU 和記憶體要求與限制,讓 Go 執行階段根據容器 CPU 預算調整執行緒數量。 根據每秒最高輸入要求數、mTLS 負擔和要求酬載大小,水平擴充副本。
API 伺服器 (ate-api-server) 設定保證 QoS:設定相符的 CPU 和記憶體要求與限制,讓 Go 執行階段根據容器 CPU 預算調整執行緒數量。 根據每秒恢復和暫停週期的尖峰 (每個恢復和暫停週期約 4 毫秒的 CPU) 和 ingress 要求查詢負載,調度副本資源。明確設定 ateapi.postgres.poolMaxConns。每個副本最多可開啟 poolMaxConns + 6 個資料庫連線,且所有副本的連線總數必須低於 PostgreSQL max_connections 設定。
資料庫 (PostgreSQL) 設定可高載 QoS 並保證記憶體:將記憶體要求設為與限制相同,將 shared_buffers 快取鎖定在記憶體中,並防止記憶體不足 (OOM) 淘汰。在專屬 ate-postgres 節點上執行時,請省略 CPU 限制,以免核心 CPU 節流降低檢查點和 autovacuum 爆發的速度。 垂直擴充這個單一執行個體 StatefulSet。佈建足夠的 CPU,在尖峰負載時將使用率維持在 80% 以下;佈建足夠的 RAM,用於快取 Actor 資料表 (shared_buffers 參數設為約 25% 的記憶體);以及在安裝時使用 ateapi.postgres.storageClass 設定,設定 SSD 支援的 StorageClass (例如 C4 或 N4 上的 dynamic-rwo StorageClass,或 C3 或 N2 上的 premium-rwo StorageClass)。請提高 postgres-config ConfigMap (postgresql.conf 檔案) 中的 max_connections 參數,以容納所有 ate-api-server 副本。
輸出 Proxy (atenet-egress) 資源規則:將 CPU 要求設為 512 mCPU (上限 8 個 vCPU),並將記憶體要求設為 512 MiB (上限 1 GiB)。如果傳出 Actor 流量的延遲時間增加,請提高要求和限制。 根據 Actor 傳出要求流量,水平擴充副本。
Worker 控制器 (ate-controller) 資源規則:保留一個副本 (不選取領導者)。根據 WorkerPool 大幅水平擴展期間的用量高峰,設定 CPU 和記憶體要求。 如果新的 Worker Pod 在大型機群中註冊的時間過長,請提高 --worker-sync-concurrency 旗標的值 (預設為 2)。
憑證控制器 (podcertificate-controller) 資源規則:在 podcertificate-controller-system 命名空間中執行,為新的 Worker Pod 簽署 mTLS 憑證,然後 Pod 才能接受 Actor。 如果 worker 數量達數千個,請提高 podcert.workersPerSigner 設定 (預設為 0,會保留資訊清單預設值,即每個簽署者 1 個 worker)、--kube-api-qps 旗標 (預設為 5) 和 --kube-api-burst 旗標 (預設為 10) 的值。
識別資訊提供者 (ate-idp-server) 資源規則:在 ate-system 命名空間中提供 OpenID Connect (OIDC) 導覽文件和 JSON Web Key Set (JWKS),用於驗證 Actor JSON Web Token (JWT)。根據 JWKS 查詢量高峰,設定 CPU 和記憶體要求。 如果依賴方以高要求比率查詢 JWKS 端點,但未快取鍵,請水平擴充副本。
憑證提供者 (k8s-credential-provider) 資源規則:啟用 Kubernetes Secret 憑證插入功能時,在 ate-system 命名空間中執行。根據傳出憑證插入量,設定 CPU 和記憶體要求。 根據需要 atenet-egress Proxy 插入 Kubernetes Secret 憑證的傳出 Actor 要求速率,水平擴充副本。

隔離系統基礎架構和 worker 節點集區

在正式環境叢集中,worker 節點上的高流失率 Actor 排程和快照流量,可能會與系統基礎架構元件競爭 CPU、記憶體和磁碟 I/O。將 GKE 叢集分成三個不同的節點集區層:

  • 資料庫節點集區 (ate-postgres 標籤):PostgreSQL StatefulSet 的專用節點集區,用於儲存所有 Actor 和 Worker 中繼資料。
  • 系統基礎架構節點集區 (ate-system-infra 標籤):專用於其餘系統基礎架構服務 (atenet-router、ate-api-server、atenet-egress、ate-controller、ate-idp-server 和 k8s-credential-provider 元件) 的節點集區。
  • worker 節點集區 (WorkerPool):由 GKE 自訂 ComputeClass 和 GKE 運算資源緩衝區管理的動態擴充節點集區,用於託管執行中的 Actor 沙箱。

在 GKE 上安裝 Agent Substrate 時,您可以使用 cordonSystemInfraComponents 設定 (或 --cordon-system-infra-components 旗標),將資料庫和系統基礎架構元件隔離至專屬節點。安裝前,您必須建立兩個節點集區,並加上必要標籤和 NoSchedule 污點:

# 1. Create the dedicated PostgreSQL node pool
gcloud container node-pools create ate-postgres-pool \
    --cluster=CLUSTER_NAME \
    --location=LOCATION \
    --node-locations=POSTGRES_ZONE \
    --machine-type=POSTGRES_MACHINE_TYPE \
    --num-nodes=1 \
    --node-labels=ate.dev/workloadType=ate-postgres \
    --node-taints=ate.dev/workloadType=ate-postgres:NoSchedule

# 2. Create the dedicated system infrastructure node pool
gcloud container node-pools create ate-system-infra-pool \
    --cluster=CLUSTER_NAME \
    --location=LOCATION \
    --machine-type=SYSTEM_INFRA_MACHINE_TYPE \
    --num-nodes=2 \
    --node-labels=ate.dev/workloadType=ate-system-infra \
    --node-taints=ate.dev/workloadType=ate-system-infra:NoSchedule

更改下列內容:

  • CLUSTER_NAME:GKE Standard 叢集的名稱。
  • LOCATION:叢集控制層的 Compute Engine 可用區或區域。
  • POSTGRES_ZONE:單一副本 PostgreSQL StatefulSet 的單一 Compute Engine 可用區。如果是區域叢集,請指定叢集區域內的一個可用區,讓節點集區在要建立 StatefulSet 永久磁碟的可用區中佈建單一節點。如果是可用區叢集,請指定叢集的可用區。
  • POSTGRES_MACHINE_TYPE:PostgreSQL 執行個體適用的 Compute Engine 機型。
  • SYSTEM_INFRA_MACHINE_TYPE:根據系統基礎架構元件調整大小的 Compute Engine 機型 (例如 c3-standard-8 機型)。

在區域叢集中,--num-nodes 旗標會套用至每個可用區 (例如,在三個可用區中設定 --num-nodes=2 旗標會建立六個節點)。如要將 ate-system-infra-pool 節點集區放在特定可用區,請新增 --node-locations 旗標。

如果在安裝期間啟用 cordonSystemInfraComponents 設定,且缺少任一節點集區,則對應的系統 Pod 會維持在 Pending 狀態。

使用自訂 ComputeClass 自動指定硬體

GKE 自訂 ComputeClass 可讓您定義 WorkerPool 節點的 Compute Engine 機器系列優先順序清單,並在可用區資源不足時,自動轉用次要機器系列。

依執行階段選取 Compute Engine 機器系列

為每個沙箱執行階段設定個別的 ComputeClass:

  • MicroVM 執行階段 (Cloud Hypervisor):在 ComputeClass 優先順序中設定 enableNestedVirtualization: true 欄位,並指定支援巢狀虛擬化的 x86 Compute Engine 機器系列 (例如 N4、C3、C4 或 N2),或使用原生執行 KVM 且不需要 enableNestedVirtualization 欄位的 x86 裸機機型。不支援「巢狀虛擬化限制」中列出的 Arm 架構 VM 和機器系列。
  • gVisor 執行階段:指定一般用途或運算最佳化 x86 Compute Engine 機器系列 (例如 N4、C3、C4 或 N2),不啟用巢狀虛擬化。GKE 上的 Agent Substrate 不支援在混合 CPU 微架構 (例如 E2) 和 Arm 架構 VM 上執行的機器系列。ActorTemplate 選取的所有 WorkerPool 資源都必須共用相同的 CPU 架構。

如需詳細比較,請參閱「選取沙箱執行階段」。

Agent Substrate 必要的 ComputeClass 規則

在 GKE worker 節點上為 Agent Substrate 建立 ComputeClass 時,請遵循下列規則:

  • 使用節點式 ComputeClass:請勿使用 Pod 式計費 (podFamily 欄位),因為這類計費方式不支援巢狀虛擬化。
  • 請勿設定 nodePoolConfig.sandbox.type: microvm 欄位:這項設定會為 Pod 型工作負載啟用 GKE Sandbox 的 Kata 執行階段,並套用 sandbox.gke.io/runtime=microvm 污點,防止 GKE Worker 上的 Agent Substrate 排程。GKE 上的 Agent Substrate 會自行管理 microVM 執行階段,且只需要在標準 Container-Optimized OS (cos_containerd 映像檔類型) 節點上啟用 Compute Engine 巢狀虛擬化功能。
  • 設定 Linux 核心 sysctl 設定,以提高沙箱密度:如果 worker 節點同時執行的沙箱數量超過約 800 個,您必須提高 Linux 核心限制,以便監控檔案系統 (fs.inotify.* 參數) 和位址解析協定 (ARP) 鄰近表格 (net.ipv4.neigh.default.gc_thresh* 參數)。安裝程式只會將這些設定套用至其建立的叢集。設定自訂 ComputeClass (使用 priorityDefaults.nodeSystemConfig.linuxNodeConfig.sysctls 欄位) 或預先建立 worker 節點集區 (使用 --system-config-from-file 旗標) 時,請自行套用下列 sysctl 值:

    • fs.inotify.max_user_instances:65536
    • fs.inotify.max_user_watches:1048576
    • net.ipv4.neigh.default.gc_thresh1:4096
    • net.ipv4.neigh.default.gc_thresh2:16384
    • net.ipv4.neigh.default.gc_thresh3:32768

    如要進一步瞭解如何設定節點 sysctl 參數,請參閱「Sysctl 設定選項」。

選擇 microVM WorkerPool 資源的擴充模式

MicroVM Worker Pod 會要求 ate.dev/kvm: 1 擴充資源,只有在節點啟動且 atelet 代理程式啟動後,atelet 裝置外掛程式才會公告該資源。由於 GKE 自動佈建節點功能不會在未佈建的節點範本上看到 ate.dev/kvm 擴充資源,因此待處理的 microVM Worker Pod 無法觸發 GKE,從零個副本自動建立新的節點集區。不過,如果節點集區已有至少一個執行中的節點,GKE 就能擴充該節點集區。

下表比較在 GKE 上調度 microVM WorkerPool 資源時,支援的模式:

模式 運作方式 是否縮減至 0 個節點? 資源無法使用時,是否有多個優先順序的備用方案? 最佳使用時機
含有 minimumCapacity 欄位的自動建立集區 使用明確的 machineType 優先順序設定 nodePoolAutoCreation.enabled: true 和 minimumCapacity.targetNodeCount: 1 欄位。 否 (維持 1 個暖節點運作) 僅限在類別層級 minimumCapacity 欄位的初始佈建階段;如要使用中途爆量備用功能,必須在 spec.priorities[] 欄位的每個備用項目中設定 minimumCapacity.targetNodeCount: 1 欄位 (每個優先順序保留 1 個暖節點) 您希望自動建立節點集區,並一律保持至少 1 個 worker 節點運作。
自動建立的集區 (含運算資源緩衝區) 將 nodePoolAutoCreation.enabled: true 欄位與 PodTemplate 省略 ate.dev/kvm 擴充資源的作用中或待命 CapacityBuffer 結合。 暫停至待機狀態 (例如,在預設 100 GiB 開機磁碟的 c3-standard-4 節點上,約為執行中運算費用的 8%) 是 (緩衝區預留位置會觸發節點自動佈建備用機制,並套用至所有優先順序) 您希望快速擴充叢集 (1 到 4 秒內啟用,或 20 到 35 秒內恢復待命節點,50 到 85 秒內新的 Worker 準備就緒),且閒置成本低。
預先建立的 0 節點集區,含有節點範本標籤 預先建立含有 clusterautoscaler-nodetemplate-resources.ate.dev/kvm=4096 標籤的自動調度資源 0 節點集區,並在 ComputeClass 的 spec.priorities[].nodepools 欄位中參照這些集區。 是 (真正 0 節點,無閒置運算成本) 是,在預先建立的節點集區中 您希望將資源調度率降至零,而不必維護待命運算資源緩衝區。

範例:含有 minimumCapacity 欄位的 ComputeClass

使用 minimumCapacity 欄位時,spec.priorities 欄位中的每個項目都必須指定明確的 machineType 欄位,而不是只指定 machineFamily 欄位:

apiVersion: cloud.google.com/v1
kind: ComputeClass
metadata:
  name: substrate-microvm
spec:
  priorityDefaults:
    enableNestedVirtualization: true
    nodeSystemConfig:
      linuxNodeConfig:
        sysctls:
          fs.inotify.max_user_instances: 65536
          fs.inotify.max_user_watches: 1048576
          net.ipv4.neigh.default.gc_thresh1: 4096
          net.ipv4.neigh.default.gc_thresh2: 16384
          net.ipv4.neigh.default.gc_thresh3: 32768
  priorities:
  - machineType: n4-standard-4
  - machineType: c3-standard-4
  - machineType: n2-standard-4
  nodePoolAutoCreation:
    enabled: true
  minimumCapacity:
    targetNodeCount: 1
  nodePoolConfig:
    imageType: cos_containerd
  whenUnsatisfiable: DoNotScaleUp

如要將 WorkerPool 指定至這個 ComputeClass,請將 nodeSelector: {cloud.google.com/compute-class: substrate-microvm} 欄位新增至 WorkerPool Pod 範本。

當 ComputeClass 在不同的 x86 機器系列 (例如從 N4 到 C3 或 N2) 之間切換時,如要以記憶體擬真度 (SNAPSHOT_FIDELITY_MEMORY 模式) 還原耐用快照,Worker 的 CPU 功能必須是快照 CPU 功能的超集。如果沒有相容的 Worker 有容量,Agent Substrate 會將還原降級為根檔案系統保真度 (SNAPSHOT_FIDELITY_ROOTFS 模式),在重新啟動 Actor 程序時,保留根檔案系統和耐用磁碟區資料。

範例:使用預先建立的 0 節點集區,從零開始調度資源

  1. 將高密度 Linux 核心 sysctl 設定儲存為 system-config.yaml 檔案:

    linuxConfig:
      sysctl:
        fs.inotify.max_user_instances: '65536'
        fs.inotify.max_user_watches: '1048576'
        net.ipv4.neigh.default.gc_thresh1: '4096'
        net.ipv4.neigh.default.gc_thresh2: '16384'
        net.ipv4.neigh.default.gc_thresh3: '32768'
    
  2. 使用 --system-config-from-file=system-config.yaml 旗標和 clusterautoscaler-nodetemplate-resources.ate.dev/kvm=4096 標籤,預先建立主要和備用巢狀虛擬化節點集區,節點數量為 0,讓 GKE 叢集自動配置器知道空白集區提供 ate.dev/kvm 擴充資源:

    # Primary N4 pool (0 nodes)
    gcloud container node-pools create microvm-n4-pool \
        --cluster=CLUSTER_NAME \
        --location=LOCATION \
        --machine-type=n4-standard-4 \
        --enable-nested-virtualization \
        --system-config-from-file=system-config.yaml \
        --num-nodes=0 \
        --enable-autoscaling --total-min-nodes=0 --total-max-nodes=10 \
        --node-labels=cloud.google.com/compute-class=substrate-microvm-zero,clusterautoscaler-nodetemplate-resources.ate.dev/kvm=4096 \
        --node-taints=cloud.google.com/compute-class=substrate-microvm-zero:NoSchedule
    
    # Fallback C3 pool (0 nodes)
    gcloud container node-pools create microvm-c3-pool \
        --cluster=CLUSTER_NAME \
        --location=LOCATION \
        --machine-type=c3-standard-4 \
        --enable-nested-virtualization \
        --system-config-from-file=system-config.yaml \
        --num-nodes=0 \
        --enable-autoscaling --total-min-nodes=0 --total-max-nodes=10 \
        --node-labels=cloud.google.com/compute-class=substrate-microvm-zero,clusterautoscaler-nodetemplate-resources.ate.dev/kvm=4096 \
        --node-taints=cloud.google.com/compute-class=substrate-microvm-zero:NoSchedule
    

    更改下列內容:

    • CLUSTER_NAME:GKE Standard 叢集的名稱。
    • LOCATION:叢集的 Compute Engine 可用區或區域。使用 --total-min-nodes 和 --total-max-nodes 旗標,即可設定整個節點集區 (而非個別可用區) 的自動調度資源範圍。
  3. 在 ComputeClass 中,按照優先順序參照預先建立的集區:

    apiVersion: cloud.google.com/v1
    kind: ComputeClass
    metadata:
      name: substrate-microvm-zero
    spec:
      nodePoolAutoCreation:
        enabled: false
      priorities:
      - nodepools:
        - microvm-n4-pool
      - nodepools:
        - microvm-c3-pool
      whenUnsatisfiable: DoNotScaleUp
    

    priorityDefaults 欄位不適用於使用 nodepools 欄位的優先順序,因為節點設定來自預先建立的節點集區。與自動建立的備用優先順序一樣,如果備用機器系列的 CPU 功能並非快照 CPU 功能的超集,在該系列上恢復 Actor 會將還原降級為 SNAPSHOT_FIDELITY_ROOTFS 模式,並重新啟動 Actor 的程序。

如要進一步瞭解 ComputeClass 設定,請參閱「使用自訂 ComputeClass 控制自動調度資源的節點屬性」。

設定 WorkerPool 爆發式資源調度的運算資源緩衝區

當 Actor 流量尖峰超過執行中 WorkerPool Pod 的容量時,新的 Worker Pod 必須等待 Compute Engine 節點佈建、atelet 代理程式初始化和沙箱資產預熱,才能提供 Actor。GKE 運算資源緩衝區會將節點佈建和 atelet 資產預熱作業移出關鍵路徑:

  • 主動式運算資源緩衝區 (buffer.x-k8s.io/active-capacity 策略):讓預先佈建的節點保持運作並準備就緒,以便在 1 到 4 秒內排定新的 worker Pod,費用為 Compute Engine VM 的完整運作成本。
  • 待命運算資源緩衝區 (buffer.gke.io/standby-capacity 策略):佈建節點,並在 GKE 暫停 Compute Engine VM 之前,讓 atelet 代理程式在待命初始化期間,初始化及預熱磁碟上的沙箱資產 (runsc 二進位檔或 Cloud Hypervisor 和 Kata 映像檔)。這個時間範圍預設為五分鐘 (5m),並由 CapacityBuffer 上的 buffer.gke.io/standby-capacity-init-time 註解設定。如果資產預熱時間超過五分鐘,請提高這個註解的值。發生爆量時,GKE 會在約 20 到 35 秒內恢復暫停的節點,並在約 50 到 85 秒內完成端對端 WorkerPool 準備作業 (排定 Worker Pod、核發 Pod 憑證,以及向 ate-api-server 元件註冊容量)。暫停期間,您只需支付暫停的 VM 記憶體和開機磁碟儲存空間費用。舉例來說,在預設 100 GiB hyperdisk-balanced 開機磁碟的 c3-standard-4 節點上,暫停儲存空間的費用約為執行運算費用的 8%;確切百分比會因機器型態、開機磁碟大小,以及佈建的 IOPS 或處理量而異。

如要進一步瞭解緩衝策略,請參閱「縮短啟動延遲時間的策略」。

運算資源緩衝區的限制和規則

在 GKE 上為 Agent Substrate 設定運算資源緩衝區時,請套用下列規則:

  • 待命緩衝區的 Compute Engine 機器型態限制:如果 VM 附加本機 SSD,或機器型態的記憶體超過 208 GB (例如 c3-highmem-88 機型或裸機型態),則不支援 Compute Engine 執行個體暫停功能。如果是大型 worker 節點型態或具備本機 SSD 的節點,請使用使用中運算資源緩衝區,而非待命緩衝區。
  • 避免將 scalableRef 欄位指向 0 副本 WorkerPool 或 microVM Deployment:
    • 當集區縮減至 0 個副本時,GKE CapacityBuffer 控制器無法解析自訂資源 (kind: WorkerPool)。
    • 如果是 microVM WorkerPool 資源,也請勿將 scalableRef 欄位指向基礎 Deployment,因為 Deployment Pod 範本包含 ate.dev/kvm: 1 擴充資源 (可防止自動佈建節點功能水平擴展空白集區)。請改為參照 PodTemplate (在 podTemplateRef 欄位中) 來設定緩衝區,該範本會選取 ComputeClass,而不要求 ate.dev/kvm 擴充資源。
    • 如果是 gVisor WorkerPool 資源 (不要求 ate.dev/kvm 擴充資源),您可以將 scalableRef 欄位直接指向 WorkerPool 基礎 Deployment,或使用 PodTemplate。

範例:使用 PodTemplate 的待命 CapacityBuffer

下列資訊清單定義了 PodTemplate 和待命 CapacityBuffer,適用於 microVM 或 gVisor WorkerPool 資源:

apiVersion: v1
kind: PodTemplate
metadata:
  name: substrate-worker-buffer-template
  namespace: WORKERPOOL_NAMESPACE
template:
  spec:
    nodeSelector:
      cloud.google.com/compute-class: COMPUTE_CLASS_NAME
    containers:
    - name: buffer-placeholder
      image: registry.k8s.io/pause:3.9
      resources:
        requests:
          cpu: "WORKER_CPU_REQUEST"
          memory: "WORKER_MEMORY_REQUEST"
---
apiVersion: autoscaling.x-k8s.io/v1beta1
kind: CapacityBuffer
metadata:
  name: substrate-standby-buffer
  namespace: WORKERPOOL_NAMESPACE
spec:
  podTemplateRef:
    name: substrate-worker-buffer-template
  replicas: BUFFER_REPLICAS
  provisioningStrategy: buffer.gke.io/standby-capacity

更改下列內容:

  • WORKERPOOL_NAMESPACE:WorkerPool 的 Kubernetes 命名空間 (例如 my-workerpool)。
  • COMPUTE_CLASS_NAME:WorkerPool 指定的自訂 ComputeClass 名稱 (例如 substrate-microvm)。
  • WORKER_CPU_REQUEST 和 WORKER_MEMORY_REQUEST:WorkerPool 中單一 worker Pod 的 CPU 和記憶體要求 (例如 4 個 vCPU 節點上的 2 個 CPU 和 4Gi 記憶體),為 atelet 代理程式和 GKE 系統 Daemon 預留節點容量。將這些值與一個 worker Pod 的要求比對,有助於確保每個緩衝區副本佈建一個待命 worker 節點,而不是將多個緩衝區預留位置封裝到單一節點。
  • BUFFER_REPLICAS:要預熱的待命 worker 節點數量 (例如 4 個節點)。

使用待命運算資源緩衝區時,請在 atelet DaemonSet 中新增 buffer.gke.io/standby-capacity-node-suspended 污點的容忍度 (使用 operator: "Exists" 欄位),這樣替代 atelet Pod 就能在暫停的待命節點上保持排程 (例如在 DaemonSet 滾動式更新期間)。如需 DaemonSet 設定範例,請參閱「在待命緩衝區預先載入映像檔」。

如果多個工作負載共用同一個 ComputeClass,請在 WorkerPool Pod 範本和緩衝區 PodTemplate 中,新增相符的工作負載區隔容忍度和 nodeSelector 標籤,讓 GKE 佈建其他工作負載未要求的專屬污點節點。此外,請在 atelet DaemonSet 中新增相符的容忍度,以便在這些專用節點上排定 atelet 代理程式。如需逐步操作說明,請參閱「設定運算資源緩衝區」。

管理升級和自動配置器互動

本節說明如何管理 atelet DaemonSet 更新、叢集自動配置器縮減事件和節點升級,而不中斷執行中的 Actor。

使用待命緩衝區更新 atelet DaemonSet

暫停的待命緩衝區節點會帶有 buffer.gke.io/standby-capacity-node-suspended 污點和無法連線的污點,因此暫停節點上的 kubelet 代理無法確認 Pod 刪除作業。確認 atelet DaemonSet 容許 buffer.gke.io/standby-capacity-node-suspended 汙點 (使用 operator: "Exists" 欄位)。即使有該容忍度,在 atelet DaemonSet (具有 maxUnavailable: 1 欄位) 的標準滾動式更新期間,暫停節點上的 Pod 會進入 Terminating 狀態,並可能阻止更新在執行中的節點上進行。

在具有暫停待命節點的叢集上更新 atelet DaemonSet 之前,請執行下列任一操作:

  • 為避免無法連線的待命節點耗盡更新預算,請將 atelet DaemonSet 的 spec.updateStrategy.rollingUpdate.maxUnavailable 欄位設為大於暫停待命節點數量上限的值。
  • 更新 atelet DaemonSet 前,請暫時將待命 CapacityBuffer 副本數量調整為 0,並等待叢集自動配置器移除所有暫停的待命緩衝區節點 (通常需要 10 到 15 分鐘)。如要檢查是否有任何節點仍回報 Suspended 條件狀態為 True,請執行下列指令:

    kubectl get nodes -o custom-columns='NAME:.metadata.name,SUSPENDED:.status.conditions[?(@.type=="Suspended")].status'
    

在縮減資源和升級期間保護使用中的 Actor

由於執行中的 Actor 是在 atelet 代理程式管理的沙箱中執行,而非個別 Kubernetes Pod,因此即使該節點上的 Worker Pod 託管執行中的 Actor,GKE 叢集自動配置器仍可能顯示節點的 CPU 和記憶體要求偏低。節點耗盡時,kubelet 代理程式會將 SIGTERM 信號傳送至 Worker Pod,Worker 則會將 SIGTERM 信號轉送至其託管的每個 Actor 的每個容器的主要程序。每個執行中的 Actor 最多有 30 分鐘的時間可暫停,之後 Worker 就會停止。為每個有狀態的 Actor 提供 SIGTERM 處理常式,該處理常式不會在信號上結束,並會以 DURABILITY_MODE_SYNCHRONOUS 模式呼叫 SuspendActor 方法。如果 Actor 的主要程序在 SIGTERM 信號上結束,會立即遺失未儲存的狀態。如果 Worker Pod 在託管中的 Actor 仍處於活躍狀態時停止,Actor 就會進入 ACTOR_STATE_CRASHED 狀態。

為盡可能減少縮減事件和 GKE 叢集升級期間的中斷情形,請採用下列做法:

  • 請避免將 Spot VM 用於有狀態的 WorkerPool 節點,因為 Spot VM 先占功能在停止節點前,只會提供 15 秒到 2 分鐘的終止通知。
  • 在自動調度管理工具中協調排空作業,確保在 Worker Pod 停止前,為執行中的 Actor 建立檢查點並暫停,或防止叢集自動調度資源工具剔除執行中的 Worker Pod (例如使用 cluster-autoscaler.kubernetes.io/safe-to-evict: "false" Pod 註解)。如果您在 WorkerPool Pod 範本中靜態設定 safe-to-evict: "false" 註解,則當 Worker Pod 排定在節點上時,叢集自動配置器不會縮減節點,即使該 Worker 託管零個活躍 Actor 也是如此。如要釋出閒置節點,您必須縮減 WorkerPool 副本,或動態管理註解。如要進一步瞭解 Worker 淘汰生命週期,以及如何使用 RevertActor 方法復原當機的 Actor,請參閱 Agent Substrate API 指南中的「淘汰」一節。
  • 設定 GKE 激增升級,並查看在資源受限的環境中升級,以便在現有 worker 節點遭到封鎖和排空之前,佈建新的 worker 節點。

後續步驟