運算和自動擴展 - Amazon EKS

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

運算和自動擴展

身為開發人員,您將預估應用程式的資源需求,例如 CPU 和記憶體,但如果您沒有持續調整,它們可能會過期,這可能會增加成本並提高效能和可靠性。持續調整應用程式的資源需求比第一次正確調整它們更為重要。

以下提及的最佳實務將協助您建置和操作具有成本感知的工作負載,以實現業務成果,同時將成本降至最低,並讓您的組織將其投資報酬率最大化。最佳化叢集運算成本的重要高階順序如下:

  1. 適當大小的工作負載

  2. 減少未使用的容量

  3. 最佳化運算容量類型 (例如 Spot) 和加速器 (例如 GPUs)

適當調整工作負載大小

在大多數 EKS 叢集中,大量成本來自用來執行容器化工作負載的 EC2 執行個體。若未了解工作負載需求,您將無法調整運算資源的大小。因此,您必須使用適當的請求和限制,並視需要調整這些設定。此外,執行個體大小和儲存體選擇等相依性可能會影響工作負載效能,進而對成本和可靠性造成各種意外後果。

請求應與實際使用率相符。如果容器的請求太高,則會有未使用的容量,這是叢集總成本的一大因素。Pod 中的每個容器,例如應用程式和附屬,都應設定自己的請求和限制,以確保彙總 Pod 限制盡可能準確。

利用諸如 GoldilocksKRRKubecost 等工具來估計容器的資源請求和限制。根據應用程式的性質、效能/成本需求,以及評估哪些指標最適合擴展、應用程式效能下降的時間點 (飽和點),以及如何相應調整請求和限制的複雜性。如需本主題的進一步指引,請參閱應用程式正確調整大小

我們建議您使用 Horizontal Pod Autoscaler (HPA) 來控制應用程式應執行的複本數量、使用 Vertical Pod Autoscaler (VPA) 來調整應用程式每個複本所需的請求和限制數量,以及使用 KarpenterCluster Autoscaler 等節點自動擴展器來持續調整叢集中的節點總數。本文件稍後章節會記錄使用 Karpenter 和 Cluster Autoscaler 的成本最佳化技術。

垂直 Pod Autoscaler 可以調整指派給容器的請求和限制,讓工作負載以最佳方式執行。您應該在稽核模式下執行 VPA,這樣它就不會自動進行變更並重新啟動您的 Pod。它會根據觀察到的指標建議變更。對於影響生產工作負載的任何變更,您應該先在非生產環境中檢閱和測試這些變更,因為這些變更可能會影響應用程式的可靠性和效能。

減少耗用量

節省成本的最佳方法是佈建較少的資源。其中一種方法是根據工作負載的目前需求來調整工作負載。您應該從確保您的工作負載定義其需求並動態擴展開始任何成本最佳化工作。這將需要從您的應用程式取得指標和設定組態,例如 PodDisruptionBudgetsPod 準備階段,以確保您的應用程式可以安全地動態擴展和縮減。請務必考慮限制性 PodDisruptionBudgets 可防止 Cluster Autoscaler 和 Karpenter 縮減節點,因為 Cluster Autoscaler 和 Karpenter 都遵守 PodDisruptionBudgets。PodDisruptionBudget 中的 'minAvailable' 值應一律低於部署中的 Pod 數量,而且您應該在兩個之間保持良好的緩衝,例如,在 6 個 Pod 的部署中,您想要始終至少執行 4 個 Pod,請將 PodDisruptionBidget 中的 'minAvailable' 設定為 4。這將允許 Cluster Autoscaler 和 Karpenter 在節點縮減規模事件期間安全地從未充分利用的節點耗盡和移出 Pod。請參閱 Cluster Autoscaler 常見問答集文件。

Horizontal Pod Autoscaler 是一種靈活的工作負載自動擴展器,可以調整所需的複本數量,以滿足應用程式的效能和可靠性需求。它具有彈性的模型,可根據 CPU、記憶體或自訂指標等各種指標,例如佇列深度、Pod 的連線數量等,來定義何時擴展和縮減。

Kubernetes Metrics Server 可針對 CPU 和記憶體用量等內建指標進行擴展,但如果您想要根據 Amazon CloudWatch 或 SQS 佇列深度等其他指標進行擴展,則應考慮事件驅動型自動擴展專案,例如 KEDA。請參閱此部落格文章,了解如何搭配 CloudWatch 指標使用 KEDA。如果您不確定要根據哪些指標進行監控和擴展,請查看監控重要指標的最佳實務

減少工作負載耗用量會在叢集中產生多餘的容量,而使用適當的自動擴展組態可讓您自動縮減節點,並減少總支出。建議您不要嘗試手動最佳化運算容量。Kubernetes 排程器和節點自動擴展器旨在為您處理此程序。

減少未使用的容量

確定應用程式的正確大小、減少過多請求後,您可以開始減少佈建的運算容量。如果您已花時間從上述區段正確調整工作負載大小,您應該可以動態執行此操作。AWS 中的 Kubernetes 使用兩個主節點自動擴展器。

Karpenter 和 Cluster Autoscaler

當 Pod 建立或移除且運算需求變更時,Karpenter 和 Kubernetes Cluster Autoscaler 都會擴展叢集中的節點數量。兩者的主要目標是相同的,但 Karpenter 採用不同的節點管理佈建和取消佈建方法,這有助於降低成本和最佳化整個叢集的用量。

隨著叢集的大小和工作負載的增加,預先設定節點群組和執行個體變得更加困難。如同工作負載請求,設定初始基準並根據需要持續調整也很重要。

如果您使用的是 Cluster Autoscaler,它會遵守每個 Auto Scaling 群組 (ASG) 的「最小值」和「最大值」,並且只調整「所需」值。設定基礎 ASG 的這些值時請務必注意,因為 Cluster Autoscaler 無法將 ASG 縮減到超過其「最小」計數。將「所需」計數設定為正常上班時間所需的節點數量,並將「最小」設定為非上班時間所需的節點數量。請參閱 Cluster Autoscaler 常見問答集文件。

Cluster Autoscaler Priority Expander

Kubernetes Cluster Autoscaler 的運作方式是隨著應用程式擴展和縮減,擴展和縮減節點群組,稱為節點群組。如果您不動態擴展工作負載,則 Cluster Autoscaler 不會協助您節省成本。Cluster Autoscaler 需要叢集管理員事先建立節點群組,工作負載才能使用。節點群組需要設定為使用具有相同「設定檔」的執行個體,即大約相同數量的 CPU 和記憶體。

您可以有多個節點群組,而且 Cluster Autoscaler 可以設定為設定優先順序擴展層級,而且每個節點群組可以包含大小不同的節點。節點群組可以有不同的容量類型,而優先順序擴展器可以用來先擴展成本較低的群組。

以下是叢集組態程式碼片段的範例,該程式碼片段使用 ConfigMap`來排定保留容量的優先順序,然後再使用隨需執行個體。您可以使用相同的技術,將 Graviton 或 Spot 執行個體優先於其他類型。

apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: my-cluster managedNodeGroups: - name: managed-ondemand minSize: 1 maxSize: 7 instanceType: m5.xlarge - name: managed-reserved minSize: 2 maxSize: 10 instanceType: c5.2xlarge
apiVersion: v1 kind: ConfigMap metadata: name: cluster-autoscaler-priority-expander namespace: kube-system data: priorities: |- 10: - .*ondemand.* 50: - .*reserved.*

根據預設,使用節點群組可協助基礎運算資源執行預期項目,例如跨AZs分散節點,但並非所有工作負載都有相同的需求或期望,最好讓應用程式明確宣告其需求。如需 Cluster Autoscaler 的詳細資訊,請參閱最佳實務一節

取消排程器

Cluster Autoscaler 可以根據需要排程的新 Pod 或節點使用率不足,從叢集新增和移除節點容量。在排程到節點之後,它不會接受 Pod 置放的冪冪檢視。如果您使用的是 Cluster Autoscaler,您也應該查看 Kubernetes 取消排程器,以避免浪費叢集中的容量。

如果您在叢集中有 10 個節點,且每個節點的使用率為 60%,則表示您未使用叢集中佈建容量的 40%。使用 Cluster Autoscaler,您可以將每個節點的使用率閾值設定為 60%,但只有在使用率低於 60% 之後,才會嘗試縮減單一節點。

使用取消排程器,它可以在已排程 Pod 或節點新增至叢集之後查看叢集容量和使用率。它會嘗試將叢集的總容量保持在指定的閾值以上。它也可以根據節點污點或聯結叢集的新節點來移除 Pod,以確保 Pod 在其最佳的運算環境中執行。請注意,取消排程器不會排程取代移出的 Pod,但會依賴預設排程器。

Karpenter 合併

Karpenter 採用「無群組」方法來管理節點。此方法對於不同的工作負載類型更靈活,且叢集管理員需要較少的前期組態。Karpenter 不會視需要預先定義群組和擴展每個群組,而是使用佈建器和節點範本來廣泛定義可建立的 EC2 執行個體類型,以及建立執行個體時的執行個體相關設定。

儲存貯體封裝是將更多工作負載封裝到較少、大小最佳之執行個體上,藉此利用更多執行個體資源的做法。雖然這有助於透過僅佈建工作負載使用的資源來降低運算成本,但它具有權衡。啟動新的工作負載可能需要更長的時間,因為必須將容量新增至叢集,尤其是在大型擴展事件期間。設定儲存貯體封裝時,請考慮成本最佳化、效能和可用性之間的平衡。

Karpenter 可以持續監控和 Binpack,以改善執行個體資源使用率並降低運算成本。Karpenter 也可以為您的工作負載選取更具成本效益的工作者節點。這可以透過在佈建器中將「合併」旗標開啟為 true 來實現 (下面的範例程式碼片段)。以下範例顯示啟用整合的範例佈建器。在撰寫本指南時,Karpenter 不會將執行中的 Spot 執行個體取代為價格較低的 Spot 執行個體。如需 Karpenter 整合的詳細資訊,請參閱此部落格

apiVersion: karpenter.sh/v1 kind: Provisioner metadata: name: enable-binpacking spec: consolidation: enabled: true

對於可能無法中斷的工作負載,例如在沒有檢查點的情況下長時間執行的批次任務,請考慮使用 do-not-evict 註釋註釋 Pod。選擇不移出 Pod,表示您告知 Karpenter 不應自願移除包含此 Pod 的節點。不過,如果在節點耗盡時將 Pod do-not-evict 新增至節點,剩餘的 Pod 仍會移出,但該 Pod 會封鎖終止,直到移除為止。在任何一種情況下,都會封鎖節點,以防止在節點上排程其他工作。以下是示範如何設定註釋的範例:

apiVersion: v1 kind: Pod metadata: name: label-demo labels: environment: production annotations: + "karpenter.sh/do-not-evict": "true" spec: containers: * name: nginx image: nginx ports: ** containerPort: 80

調整 Cluster Autoscaler 參數以移除未充分利用的節點

節點使用率定義為請求的資源總和除以容量。預設為 scale-down-utilization-threshold 50%。此參數可以與 和 搭配使用scale-down-unneeded-time,這會決定節點在符合縮減規模資格之前應該不需要多久,預設值為 10 分鐘。在縮減規模的節點上執行的 Pod 將由 kube-scheduler 排程在其他節點上。調整這些設定有助於移除未充分利用的節點,但請務必先測試這些值,以免強制叢集過早縮減規模。

您可以透過確保昂貴的 Pod 受到 Cluster Autoscaler 辨識的標籤保護,來防止縮減規模。若要執行此作業,請確定 Pod 需要昂貴才能移出註釋 cluster-autoscaler.kubernetes.io/safe-to-evict=false。以下是設定註釋的範例 yaml:

apiVersion: v1 kind: Pod metadata: name: label-demo labels: environment: production annotations: + "cluster-autoscaler.kubernetes.io/safe-to-evict": "false" spec: containers: * name: nginx image: nginx ports: ** containerPort: 80

使用 Cluster Autoscaler 和 Karpenter 標記節點

AWS 資源標籤可用來組織您的資源,並在詳細的層級追蹤您的 AWS 成本。它們與成本追蹤的 Kubernetes 標籤沒有直接關聯。建議從 Kubernetes 資源標籤開始,並使用 Kubecost 等工具,根據 Pod 上的 Kubernetes 標籤、命名空間等取得基礎設施成本報告。

工作者節點需要有標籤,才能在 AWS Cost Explorer 中顯示帳單資訊。使用 Cluster Autoscaler,使用啟動範本標記受管節點群組中的工作者節點。對於自我管理節點群組,請使用 EC2 自動擴展群組標記您的執行個體。對於 Karpenter 佈建的執行個體,請使用節點範本中的 spec.tags 來標記它們。

多租戶叢集

在由不同團隊共用的叢集上工作時,您可能看不到在相同節點上執行的其他工作負載。雖然資源請求有助於隔離一些「雜訊鄰近」問題,例如 CPU 共用,但它們可能無法隔離所有資源邊界,例如磁碟 I/O 耗盡。不是每個工作負載的消耗性資源都可以隔離或限制。以高於其他工作負載的速率使用共用資源的工作負載,應透過節點污點和容錯進行隔離。這類工作負載的另一項進階技術是 CPU 鎖定,可確保容器的專屬 CPU 而非共用 CPU。

在節點層級隔離工作負載可能更昂貴,但使用預留執行個體Graviton 處理器Spot 可以排程 BestEffort 任務或利用額外的節省。

共用叢集也可能有叢集層級的資源限制,例如 IP 耗盡、Kubernetes 服務限制或 API 擴展請求。您應該檢閱可擴展性最佳實務指南,以確保您的叢集避免這些限制。

您可以在命名空間或 Karpenter 佈建器層級隔離資源。Resource Quotas 提供一種方法來設定對命名空間中資源工作負載可使用數量的限制。這可能是良好的初始護欄,但應該持續評估以確保它不會人為限制工作負載進行擴展。

Karpenter 佈建器可以對叢集中的某些消耗性資源 (例如 CPU、GPU) 設定限制,但您需要將租用戶應用程式設定為使用適當的佈建器。這可以防止單一佈建器在叢集中建立太多節點,但應該持續評估,以確保限制不會設定得太低,進而防止工作負載擴展。

排程的自動擴展

您可能需要在週末和下班時間縮減叢集。這對於您想要在不使用時縮減至零的測試和非生產叢集特別相關。叢集倒轉之類的解決方案可以根據 Cron 排程將複本縮減為零。您也可以使用 Karpenter 達成此目標,如下列 AWS 部落格所述。

最佳化運算容量類型

在最佳化叢集中的運算總容量並利用 bin 封裝後,您應該查看您在叢集中佈建的運算類型,以及如何支付這些資源的費用。AWS 具有運算節省計劃,可以降低運算成本,我們將將其分類為下列容量類型:

  • Spot

  • Savings Plans

  • On-Demand

  • Fargate

每種容量類型在管理開銷、可用性和長期承諾方面都有不同的權衡,您需要決定哪些適合您的環境。任何環境都不應依賴單一容量類型,而且您可以在單一叢集中混合多個執行類型,以最佳化特定工作負載需求和成本。

Spot

Spot 容量類型會從可用區域中的備用容量佈建 EC2 執行個體。Spot 提供最多 90% 的最大折扣,但這些執行個體可能會在其他地方需要時中斷。此外,佈建新的 Spot 執行個體可能不一定有容量,而且現有的 Spot 執行個體可以透過 2 分鐘的中斷通知回收。如果您的應用程式有很長的啟動或關閉程序,Spot 執行個體可能不是最佳選項。

Spot 運算應使用各種執行個體類型,以減少無法使用 Spot 容量的可能性。需要處理執行個體中斷,才能安全地關閉節點。使用 Karpenter 或受管節點群組的一部分佈建的節點會自動支援執行個體中斷通知。如果您使用的是自我管理節點,則需要分別執行節點終止處理常式,以正常關閉 Spot 執行個體。

您可以在單一叢集中平衡 Spot 執行個體和隨需執行個體。透過 Karpenter,您可以建立加權佈建器,以實現不同容量類型的平衡。使用 Cluster Autoscaler,您可以使用 spot 和隨需或預留執行個體建立混合節點群組

以下是使用 Karpenter 在隨需執行個體之前排定 Spot 執行個體優先順序的範例。建立佈建器時,您可以指定 Spot、隨需或兩者 (如下所示)。當您同時指定 時,如果 Pod 未明確指定是否需要使用 Spot 或隨需,則 Karpenter 會在佈建具有 price-capacity-optimization配置策略 的節點時優先考慮 Spot。

apiVersion: karpenter.sh/v1
kind: Provisioner
metadata:
  name: spot-prioritized
spec:
  requirements:
    - key: "karpenter.sh/capacity-type"
      operator: In
        values: ["spot", "on-demand"]

Savings Plans、預留執行個體和 AWS EDP

您可以使用運算節省計劃來減少運算支出。節省計劃提供 1 或 3 年運算用量承諾的折扣價格。用量可套用至 EKS 叢集中的 EC2 執行個體,但也適用於 Lambda 和 Fargate 等任何運算用量。透過節省計劃,您可以降低成本,並在承諾期間仍然選擇任何 EC2 執行個體類型。

運算節省計劃可將 EC2 成本降低高達 66%,而不需要對您想要使用的執行個體類型、系列或區域做出承諾。使用執行個體時,會自動套用節省成本。

EC2 Instance Savings Plans 提供高達 72% 的運算節省,並承諾在特定區域和 EC2 系列中使用,例如來自 C 系列的執行個體。您可以將用量轉移到區域內的任何 AZ、使用任何世代的執行個體系列,例如 c5 或 c6,以及使用系列中任何大小的執行個體。折扣將自動套用至您帳戶中符合節省計劃條件的任何執行個體。

預留執行個體類似於 EC2 執行個體Savings Plan,但也保證可用區域或區域中的容量,並透過隨需執行個體降低成本,最高可達 72%。計算需要多少預留容量後,您可以選擇要保留多久 (1 年或 3 年)。當您在帳戶中執行這些 EC2 執行個體時,系統會自動套用折扣。

客戶也可以選擇註冊與 AWS 簽訂的 Enterprise 協議。企業協議為客戶提供最符合其需求的專屬協議選項。客戶可以根據 AWS EDP (企業折扣計劃) 享有定價折扣。如需 Enterprise Agreements 的詳細資訊,請聯絡您的 AWS 銷售代表。

On-Demand

相較於 Spot,與節省計劃相比,隨需 EC2 執行個體具有無中斷和無長期承諾的可用性優勢。如果您想要降低叢集中的成本,您應該減少隨需 EC2 執行個體的使用量。

最佳化工作負載需求後,您應該能夠計算叢集的最小和最大容量。此數字可能會隨著時間而變更,但很少會下降。考慮將 Savings Plan 用於低於下限的所有項目,並找出不會影響應用程式可用性的容量。任何其他可能無法持續使用或可用性所需的項目都可以隨需使用。

如本節所述,降低用量的最佳方式是盡可能減少資源用量,並充分利用您佈建的資源。使用 Cluster Autoscaler,您可以使用 scale-down-utilization-threshold設定移除未充分利用的節點。使用 Karpenter,建議啟用整合。

若要手動識別可與工作負載搭配使用的 EC2 執行個體類型,您應該使用 ec2-instance-selector,它可以顯示每個區域中可用的執行個體,以及與 EKS 相容的執行個體。具有 x86 程序架構、4 Gb 記憶體、2 個 vCPUs 和 us-east-1 區域中可用的執行個體的範例用量。

ec2-instance-selector --memory 4 --vcpus 2 --cpu-architecture x86_64 \
  -r us-east-1 --service eks
c5.large
c5a.large
c5ad.large
c5d.large
c6a.large
c6i.large
t2.medium
t3.medium
t3a.medium

對於非生產環境,您可以在未使用的時段自動縮減叢集規模,例如夜間和週末。kubecost 專案叢集倒轉是控制器的範例,可根據設定的排程自動縮減叢集。

Fargate 運算

Fargate 運算是 EKS 叢集的全受管運算選項。它透過在 Kubernetes 叢集中為每個節點排程一個 Pod 來提供 Pod 隔離。它可讓您根據工作負載的 CPU 和 RAM 需求調整運算節點大小,以緊密控制叢集中的工作負載用量。

Fargate 可以將工作負載縮減為 0.5 GB 記憶體的 .25 vCPU,以及 120 GB 記憶體的 16 vCPU。可用的 Pod 大小變化數量有所限制,您需要了解工作負載最適合 Fargate 組態的方式。例如,如果您的工作負載需要 1 個 vCPU 搭配 0.5 GB 的記憶體,最小的 Fargate Pod 將是 1 個 vCPU 搭配 2 GB 的記憶體。

雖然 Fargate 有許多優點,例如沒有 EC2 執行個體或作業系統管理,但它可能需要比傳統 EC2 執行個體更多的運算容量,因為每個部署的 Pod 都會隔離為叢集中的個別節點。這需要更多重複項目,例如 Kubelet、記錄代理程式,以及您通常部署到節點的任何 DaemonSets。Fargate 不支援 DaemonSets,需要將其轉換為 Pod "`sidecars"`,並與應用程式一起執行。

Fargate 無法從 bin 封裝或 CPU 佈建中受益,因為工作負載的界限是無法爆量或在工作負載之間共用的節點。Fargate 將為您節省 EC2 執行個體管理時間,這本身就有成本,但 CPU 和記憶體成本可能比其他 EC2 容量類型更昂貴。Fargate Pod 可以利用運算節省計劃來降低隨需成本。

最佳化運算用量

在運算基礎設施上節省成本的另一種方法是為工作負載使用更有效率的運算。這可以來自效能更高的一般用途運算,例如 Graviton 處理器,比 x86 便宜 20% 且能源效率高 60%,或是 GPUs 和 FPGAs 等工作負載特定加速器。您需要建置可在手臂架構上執行的容器,並使用適合工作負載的加速器設定節點

EKS 能夠執行具有混合架構 (例如 amd64 和 arm64) 的叢集,如果您的容器是針對多個架構編譯的,您可以透過允許佈建器中的兩個架構來利用 Graviton 處理器。不過,若要保持一致的效能,建議您將每個工作負載保留在單一運算架構上,而且只有在沒有額外的容量可用時,才使用不同的架構。

佈建器可以設定多個架構,而工作負載也可以在其工作負載規格中請求特定架構。

apiVersion: karpenter.sh/v1 kind: Provisioner metadata: name: default spec: requirements: - key: "kubernetes.io/arch" operator: In values: ["arm64", "amd64"]

使用 Cluster Autoscaler,您將需要為 Graviton 執行個體建立節點群組,並在工作負載上設定節點公差,以利用新的容量。

GPUs 和 FPGAs可以大幅提高工作負載的效能,但工作負載需要最佳化才能使用加速器。許多機器學習和人工智慧的工作負載類型可以使用 GPUs 進行運算,而執行個體可以使用資源請求新增至叢集並掛載到工作負載。

spec: template: spec: - containers: ... resources: limits: nvidia.com/gpu: "1"

有些 GPU 硬體可以跨多個工作負載共用,因此可以佈建和使用單一 GPU。若要了解如何設定工作負載 GPU 共用,請參閱虛擬 GPU 裝置外掛程式以取得詳細資訊。您也可以參考下列部落格: