

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

# 成本最佳化的最佳實務
<a name="cost-opt"></a>

成本最佳化是以最低的價格達成您的業務成果。遵循本指南中的文件，即可最佳化 Amazon EKS 工作負載。

## 一般準則
<a name="general-guidelines"></a>

在雲端中，有許多一般準則可協助您實現微服務的成本最佳化：
+ 確保在 Amazon EKS 上執行的工作負載獨立於執行容器的特定基礎設施類型，這將為在最便宜的基礎設施類型上執行它們提供了更大的靈活性。將 Amazon EKS 與 EC2 搭配使用時，由於工作負載的性質，當我們的工作負載需要特定類型的 EC2 執行個體時，可能會有例外狀況，例如[需要 GPU](https://docs.aws.amazon.com/eks/latest/userguide/gpu-ami.html) 或其他執行個體類型。
+ 選取描述最佳的容器執行個體：使用 [Amazon CloudWatch Container Insights for Amazon EKS ](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/deploy-container-insights-EKS.html)之類的服務，或 Kubernetes 生態系統中提供的第三方工具，來描述您的生產環境或生產前環境，並監控 CPU 和記憶體等關鍵指標。這將確保我們可以配置正確的資源量，並避免浪費資源。
+ 利用 AWS 中提供的不同購買選項，以搭配 EC2 執行 EKS，例如隨需、Spot 和 Savings Plan。

## EKS 成本最佳化最佳實務
<a name="eks-cost-optimization-best-practices"></a>

雲端的成本最佳化有三個一般最佳實務領域：
+ 經濟實惠的資源 (Auto Scaling、Down Scaling、政策和購買選項）
+ 支出意識 （使用 AWS 和第三方工具）
+ 隨著時間最佳化 （正確調整大小）

如同任何指引，存在權衡。請確定您與您的組織合作，以了解此工作負載的優先順序，以及哪些最佳實務最重要。

### 本指南的使用方式
<a name="how-to-use-this-guide"></a>

本指南適用於負責實作和管理 EKS 叢集及其支援的工作負載的開發團隊。本指南會組織成不同的最佳實務區域，以更輕鬆地使用。每個主題都有建議清單、要使用的工具，以及 EKS 叢集成本最佳化的最佳實務。主題不需要以特定順序讀取。

### AWS 服務和 Kubernetes 的主要功能
<a name="key-aws-services-and-kubernetes-features"></a>

下列 AWS 服務和功能支援成本最佳化：
+ EC2 執行個體類型、S Savings Plan （和預留執行個體） 和 Spot 執行個體，價格不同。
+ Auto Scaling 搭配 Kubernetes 原生 Auto Scaling 政策。針對可預測的工作負載，考慮 Savings Plan （先前預留的執行個體）。使用 EBS 和 EFS 等受管資料存放區，以取得應用程式資料的彈性和耐久性。
+ Billing and Cost Management 主控台儀表板以及 AWS Cost Explorer 提供 AWS 用量的概觀。使用 AWS Organizations 取得精細的帳單詳細資訊。已分享數個第三方工具的詳細資訊。
+ Amazon CloudWatch Container Metrics 提供 EKS 叢集資源用量的相關指標。除了 Kubernetes 儀表板之外，Kubernetes 生態系統中還有數種工具可用來減少浪費。

本指南包含一組建議，可用於改善 Amazon EKS 叢集的成本最佳化。

## 意見回饋
<a name="feedback"></a>

本指南將在 GitHub 上發佈，以便收集更廣泛的 EKS/Kubernetes 社群的直接意見回饋和建議。如果您有最佳實務，認為我們應該包含在指南中，請在 GitHub 儲存庫中提交問題或提交 PR。我們的目的是在服務中新增新功能時或新最佳實務演進時，定期更新指南。

# 成本最佳化架構
<a name="cost-opt-framework"></a>

AWS Cloud Economics 是一項紀律，透過採用 Amazon EKS 等現代運算技術，協助客戶提高效率並降低成本。紀律建議遵循名為「雲端財務管理 (CFM) 架構」的方法，其中包含 4 個支柱：

![\[CFM 架構\]](http://docs.aws.amazon.com/zh_tw/eks/latest/best-practices/images/cfm_framework.png)


## 請參閱支柱：衡量和責任
<a name="_the_see_pillar_measurement_and_accountability"></a>

See 支柱是一組基本的活動和技術，定義了如何測量、監控和建立雲端支出的責任。它通常稱為「可觀測性」、「檢測」或「遙測」。「可觀測性」基礎設施的功能和限制決定了可最佳化的項目。清楚了解您的成本是成本最佳化的關鍵第一步，因為您需要知道從何處開始。這種可見性也會引導您需要執行的活動類型，以進一步最佳化您的環境。

以下是我們 See pillar 最佳實務的簡短概觀：
+ 為您的工作負載定義和維護標記策略。
  + 使用[執行個體標記](https://docs.aws.amazon.com/eks/latest/userguide/eks-using-tags.html#tag-resources-for-billing)，標記 EKS 叢集可讓您查看個別叢集成本，並在成本和用量報告中配置這些成本。
+ 使用 [Kubecost](https://www.ibm.com/docs/en/kubecost/self-hosted/2.x?topic=installations-amazon-eks-integration) 等技術建立 EKS 用量的報告和監控。
  +  [啟用雲端智慧儀表板](https://wellarchitectedlabs.com/cost/200_labs/200_enterprise_dashboards/)，透過正確標記資源並使用視覺化，您可以測量和估計成本。
+ 將雲端成本分配給應用程式、業務單位 (LoBs) 和收入串流。
+ 與業務利益相關者定義、測量和流通效率/價值 KPIs。例如，建立測量每筆交易成本的「單位指標」 KPI，例如，乘車共享服務可能具有「每次乘車成本」的 KPI。

如需與此支柱相關的建議技術和活動詳細資訊，請參閱本指南[的成本最佳化 - 可觀測性](cost-opt-observability.md)一節。

## 儲存支柱：成本最佳化
<a name="_the_save_pillar_cost_optimization"></a>

此支柱是以「請參閱」支柱中開發的技術和功能為基礎。下列活動通常屬於此支柱：
+ 識別並消除環境中的浪費。
+ 符合成本效益的架構師和設計。
+ 選擇最佳購買選項，例如隨需執行個體與 Spot 執行個體。
+ 隨服務演進而調整：隨著 AWS 服務演進，有效使用這些服務的方式可能會改變。願意適應這些變更。

由於這些活動是可操作的，因此它們高度取決於您環境的特性。問問自己，成本的主要驅動因素是什麼？ 您的不同環境提供哪些商業價值？ 哪些購買選項和基礎設施選擇最適合每個環境，例如執行個體系列類型？

以下是 EKS 叢集最常見的成本驅動因素的優先順序清單：

1.  **運算成本：**結合多種執行個體系列、購買選項和平衡可擴展性與可用性需要仔細考慮。如需詳細資訊，請參閱本指南[的成本最佳化 - 運算](cost-opt-compute.md)一節中的建議。

1.  **網路成本：**將 3 AZs用於 EKS 叢集可能會增加可用區域間流量成本。如需如何平衡 HA 需求與降低網路流量成本的建議，請參閱本指南[的成本最佳化 - 網路](cost-opt-networking.md)一節。

1.  **儲存成本：**根據 EKS 叢集中工作負載的狀態/無狀態性質，以及如何使用不同的儲存類型，可以將儲存視為工作負載的一部分。如需 EKS 儲存成本的相關考量，請參閱本指南[的成本最佳化 - 儲存](cost-opt-storage.md)一節。

## 計畫支柱：規劃和預測
<a name="_the_plan_pillar_planning_and_forecasting"></a>

一旦實作了 See pillar 中的建議，叢集就會持續進行最佳化。隨著有效獲得操作叢集的經驗，規劃和預測活動可以專注於：
+ 動態預算和預測雲端成本。
+ 量化 EKS 容器服務交付的商業價值。
+ 整合 EKS 叢集成本管理與 IT 財務管理規劃。

## 執行支柱
<a name="_the_run_pillar"></a>

成本最佳化是一個持續的過程，涉及漸進式改進的飛輪：

![\[成本最佳化飛輪\]](http://docs.aws.amazon.com/zh_tw/eks/latest/best-practices/images/flywheel.png)


確保這些活動類型的執行贊助對於將 EKS 叢集最佳化整合到組織的「FinOps」工作至關重要。它透過共同了解 EKS 叢集成本、實作 EKS 叢集成本防護機制，以及確保工具、自動化和活動隨著組織需求而發展，來允許利益相關者保持一致。

## 參考
<a name="_references"></a>
+  [AWS 雲端經濟、雲端財務管理](https://aws.amazon.com/aws-cost-management/) 

# 支出意識
<a name="cost-opt-awareness"></a>

支出意識是了解 EKS 叢集中造成支出的人員、位置和原因。準確了解此資料將有助於提高對支出的意識，並重點介紹要修復的領域。

## 建議
<a name="_recommendations"></a>

### 使用 Cost Explorer
<a name="_use_cost_explorer"></a>

 [AWS Cost Explorer](https://aws.amazon.com/aws-cost-management/aws-cost-explorer/) easy-to-use界面，可讓您視覺化、了解和管理一段時間內的 AWS 成本和用量。您可以使用 Cost Explorer 中提供的篩選條件，在各種層級分析成本和用量資料。

#### EKS 控制平面和 EKS Fargate 成本
<a name="_eks_control_plane_and_eks_fargate_costs"></a>

使用篩選條件，我們可以查詢控制平面和 Fargate Pod 的 EKS 成本所產生的成本，如下圖所示：

![\[Cost Explorer - EKS 控制平面\]](http://docs.aws.amazon.com/zh_tw/eks/latest/best-practices/images/eks-controlplane-costexplorer.png)


使用篩選條件，我們可以查詢 EKS 中跨區域 Fargate Pod 產生的彙總成本，其中包括每個 CPU 的 vCPU 小時數和 GB 小時數，如下圖所示：

![\[Cost Explorer - EKS Fargate\]](http://docs.aws.amazon.com/zh_tw/eks/latest/best-practices/images/eks-fargate-costexplorer.png)


#### 資源的標記
<a name="_tagging_of_resources"></a>

Amazon EKS 支援將 [AWS 標籤新增至](https://docs.aws.amazon.com/eks/latest/userguide/eks-using-tags.html)您的 Amazon EKS 叢集。這可讓您輕鬆控制對 EKS API 的存取，以管理您的叢集。新增至 EKS 叢集的標籤專屬於 AWS EKS 叢集資源，不會傳播到叢集使用的其他 AWS 資源，例如 EC2 執行個體或負載平衡器。目前，所有新的和現有的 EKS 叢集都支援透過 AWS API、主控台和 SDKs叢集標記。

AWS Fargate 是一種技術，可為容器提供隨需、大小適中的運算容量。您必須定義至少一個 Fargate 描述檔，指定哪些 Pod 應在啟動時使用 Fargate，才能排程您叢集中 Fargate 上的 Pod。

將標籤新增至 EKS 叢集並列出標籤：

```
$ aws eks tag-resource --resource-arn arn:aws:eks:us-west-2:xxx:cluster/ekscluster1 --tags team=devops,env=staging,bu=cio,costcenter=1234
$ aws eks list-tags-for-resource --resource-arn arn:aws:eks:us-west-2:xxx:cluster/ekscluster1
{
    "tags": {
        "bu": "cio",
        "env": "staging",
        "costcenter": "1234",
        "team": "devops"
    }
}
```

在 [AWS Cost Explorer](https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/cost-alloc-tags.html) 中啟用成本分配標籤後，AWS 會使用成本分配標籤來整理成本分配報告中的資源成本，讓您更輕鬆地分類和追蹤 AWS 成本。

標籤對 Amazon EKS 來說不具有任何語意意義，並會嚴格解譯為字元字串。例如，您可以為 Amazon EKS 叢集定義一組標籤，協助您追蹤每個叢集的擁有者和堆疊層級。

### 使用 AWS Trusted Advisor
<a name="_use_aws_trusted_advisor"></a>

AWS Trusted Advisor 提供一套豐富的最佳實務檢查和五大類別的建議：成本最佳化、安全性、容錯能力、效能和服務限制。

對於成本最佳化，Trusted Advisor 有助於消除未使用的和閒置的資源，並建議承諾預留容量。協助 Amazon EKS 的關鍵動作項目將圍繞低使用率的 EC2 執行個體、未關聯的彈性 IP 地址、閒置負載平衡器、未充分利用的 EBS 磁碟區等。檢查的完整清單提供於 https：//https://aws.amazon.com/premiumsupport/technology/trusted-advisor/best-practice-checklist/。

Trusted Advisor 也為 EC2 執行個體和 Fargate 提供 Savings Plans 和預留執行個體建議，可讓您遞交一致的用量，以換取折扣費率。

**注意**  
Trusted Advisor 的建議是一般建議，而不是 EKS 特有的建議。

### 使用 Kubernetes 儀表板
<a name="_use_the_kubernetes_dashboard"></a>

 ** *Kubernetes 儀表板* ** 

Kubernetes Dashboard 是 Kubernetes 叢集的一般用途 Web 型 UI，可提供 Kubernetes 叢集的相關資訊，包括叢集、節點和 Pod 層級的資源使用量。在 Amazon EKS 叢集上部署 Kubernetes 儀表板的說明請參閱 [Amazon EKS 文件](https://docs.aws.amazon.com/eks/latest/userguide/dashboard-tutorial.html)。

Dashboard 提供每個節點和 Pod 的資源用量明細，以及有關 Pod、服務、部署和其他 Kubernetes 物件的詳細中繼資料。此合併資訊可讓您了解 Kubernetes 環境。

![\[Kubernetes 儀表板\]](http://docs.aws.amazon.com/zh_tw/eks/latest/best-practices/images/kubernetes-dashboard.png)


 ** *kubectl top 和描述命令* ** 

使用 kubectl top 和 kubectl 來檢視資源用量指標描述命令。kubectl top 會顯示叢集中 Pod 或節點，或特定 Pod 或節點的目前 CPU 和記憶體用量。kubectl describe 命令將提供特定節點或 Pod 的詳細資訊。

```
$ kubectl top pods
$ kubectl top nodes
$ kubectl top pod pod-name --namespace mynamespace --containers
```

使用頂端命令，輸出會顯示節點正在使用的 CPU （以核心為單位） 和記憶體 （以 MiB 為單位） 總量，以及這些數字代表的節點可配置容量百分比。然後，您可以透過新增 --*containers 旗標，在 Pod 內向下切入至下一個層級的容器*層級。

```
$ kubectl describe node <node>
$ kubectl describe pod <pod>
```

 *kubectl 描述*會傳回每個資源請求或限制所代表的總可用容量百分比。

kubectl top 和 描述、追蹤關鍵資源的使用率和可用性，例如 CPU、記憶體和跨 kubernetes Pod、節點和容器的儲存。此意識有助於了解資源用量，並協助控制成本。

### 使用 CloudWatch Container Insights
<a name="_use_cloudwatch_container_insights"></a>

使用 [CloudWatch Container Insights](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/deploy-container-insights-EKS.html) 從您的容器化應用程式和微服務收集、彙總和摘要指標和日誌。Container Insights 適用於 EC2 上的 Amazon Elastic Kubernetes Service 和 Amazon EC2 上的 Kubernetes 平台。指標包含 CPU、記憶體、磁碟和網路這類資源的使用率。

[文件中](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/deploy-container-insights-EKS.html)會提供洞見的安裝。

CloudWatch 會在叢集、節點、Pod、任務和服務層級建立彙總指標，做為 CloudWatch 指標。

 **下列查詢顯示節點清單，依平均節點 CPU 使用率排序** 

```
STATS avg(node_cpu_utilization) as avg_node_cpu_utilization by NodeName
| SORT avg_node_cpu_utilization DESC
```

 **依容器名稱的 CPU 用量** 

```
stats pct(container_cpu_usage_total, 50) as CPUPercMedian by kubernetes.container_name
| filter Type="Container"
```

 **依容器名稱劃分的磁碟用量** 

```
stats floor(avg(container_filesystem_usage/1024)) as container_filesystem_usage_avg_kb by InstanceId, kubernetes.container_name, device
| filter Type="ContainerFS"
| sort container_filesystem_usage_avg_kb desc
```

[Container Insights 文件中](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Container-Insights-view-metrics.html)會提供更多範例查詢 

此意識有助於了解資源用量，並協助控制成本。

### 使用 Kubecost 進行支出感知和指導
<a name="_using_kubecost_for_expenditure_awareness_and_guidance"></a>

也可以在 Amazon EKS 上部署 [kubecost](https://kubecost.com/) 等第三方工具，以掌握執行 Kubernetes 叢集的成本。如需使用 Kubecost 追蹤成本的資訊，請參閱此 [AWS 部落格](https://aws.amazon.com/blogs/containers/how-to-track-costs-in-multi-tenant-amazon-eks-clusters-using-kubecost/) 

使用 Helm 3 部署 kubecost：

```
$ curl -sSL https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash
$ helm version --short
v3.2.1+gfe51cd1
$ helm repo add stable https://kubernetes-charts.storage.googleapis.com/
$ helm repo add stable https://kubernetes-charts.storage.googleapis.com/c^C
$ kubectl create namespace kubecost
namespace/kubecost created
$ helm repo add kubecost https://kubecost.github.io/cost-analyzer/
"kubecost" has been added to your repositories

$ helm install kubecost kubecost/cost-analyzer --namespace kubecost --set kubecostToken="aGRoZEBqc2pzLmNvbQ==xm343yadf98"
NAME: kubecost
LAST DEPLOYED: Mon May 18 08:49:05 2020
NAMESPACE: kubecost
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
--------------------------------------------------Kubecost has been successfully installed. When pods are Ready, you can enable port-forwarding with the following command:

    kubectl port-forward --namespace kubecost deployment/kubecost-cost-analyzer 9090

Next, navigate to http://localhost:9090 in a web browser.
$ kubectl port-forward --namespace kubecost deployment/kubecost-cost-analyzer 9090

NOTE: If you are using Cloud 9 or have a need to forward it to a different port like 8080, issue the following command
$ kubectl port-forward --namespace kubecost deployment/kubecost-cost-analyzer 8080:9090
```

Kubecost 儀表板 - ![\[Kubernetes Cluster Auto Scaler logs\]](http://docs.aws.amazon.com/zh_tw/eks/latest/best-practices/images/kube-cost.png) 

### 使用 Kubernetes 成本分配和容量規劃分析工具
<a name="_use_kubernetes_cost_allocation_and_capacity_planning_analytics_tool"></a>

 [Kubernetes Opex Analytics](https://github.com/rchakode/kube-opex-analytics) 是一種工具，可協助組織追蹤 Kubernetes 叢集所使用的資源，以防止超額付款。為此，它會產生短期 (7 天）、中期 (14 天） 和長期 (12 個月） 用量報告，顯示每個專案隨著時間花費多少資源的相關洞見。

![\[Kubernetes Opex Analytics\]](http://docs.aws.amazon.com/zh_tw/eks/latest/best-practices/images/kube-opex-analytics.png)


### Yotascale
<a name="_yotascale"></a>

Yotascale 有助於準確分配 Kubernetes 成本。Yotascale Kubernetes 成本分配功能利用實際成本資料，其中包含預留執行個體折扣和 Spot 執行個體定價，而非一般市價估算，以通知 Kubernetes 總成本足跡

如需更多詳細資訊，請參閱[其網站](https://www.yotascale.com/)。

### Alcide Advisor
<a name="_alcide_advisor"></a>

Alcide 是 AWS 合作夥伴網路 (APN) 進階技術合作夥伴。Alcide Advisor 可協助確保您的 Amazon EKS 叢集、節點和 Pod 組態根據安全最佳實務和內部準則進行調校以執行。Alcide Advisor 是 Kubernetes 稽核和合規的無代理程式服務，其建置目的是在進入生產環境之前強化開發階段，以確保無摩擦且安全的 DevSecOps 流程。

您可以在此[部落格文章](https://aws.amazon.com/blogs/apn/driving-continuous-security-and-configuration-checks-for-amazon-eks-with-alcide-advisor/)中找到更多詳細資訊。

## 其他工具
<a name="_other_tools"></a>

### Kubernetes 垃圾收集
<a name="_kubernetes_garbage_collection"></a>

[Kubernetes 垃圾收集器](https://kubernetes.io/docs/concepts/workloads/controllers/garbage-collection/)的角色是刪除曾經擁有擁有者但不再擁有擁有者的特定物件。

### Fargate 計數
<a name="_fargate_count"></a>

 [Fargatecount](https://github.com/mreferre/fargatecount) 是一種有用的工具，可讓 AWS 客戶使用自訂 CloudWatch 指標，追蹤已部署在特定帳戶特定區域中 Fargate 上的 EKS Pod 總數。這有助於追蹤跨 EKS 叢集執行的所有 Fargate Pod。

### Popeye - Kubernetes 叢集清理程式
<a name="_popeye_a_kubernetes_cluster_sanitizer"></a>

 [Popeye - Kubernetes Cluster Sanitizer](https://github.com/derailed/popeye) 是一種公用程式，可掃描即時 Kubernetes 叢集，並報告已部署資源和組態的潛在問題。它會根據部署的內容而非磁碟上的內容來淨化您的叢集。透過掃描您的叢集，它可偵測組態錯誤，並協助您確保最佳實務已就緒

### Resources
<a name="_resources"></a>

請參閱下列資源，進一步了解成本最佳化的最佳實務。

#### 文件和部落格
<a name="_documentation_and_blogs"></a>
+  [Amazon EKS 支援標記](https://docs.aws.amazon.com/eks/latest/userguide/eks-using-tags.html) 

#### 工具
<a name="_tools"></a>
+  [什麼是 AWS Billing and Cost Management？](https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/cost-alloc-tags.html) 
+  [Amazon CloudWatch Container Insights](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/ContainerInsights.html) 
+  [如何使用 Kubecost 追蹤多租戶 Amazon EKS 叢集中的成本](https://aws.amazon.com/blogs/containers/how-to-track-costs-in-multi-tenant-amazon-eks-clusters-using-kubecost/) 
+  [Kubecost](https://kubecost.com/) 
+  [Kube Opsview](https://github.com/hjacobs/kube-ops-view) 
+  [Kubernetes Opex Analytics](https://github.com/rchakode/kube-opex-analytics) 

# 運算和自動擴展
<a name="cost-opt-compute"></a>

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

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

1. 適當大小的工作負載

1. 減少未使用的容量

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

## 適當調整工作負載大小
<a name="_right_size_your_workloads"></a>

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

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

利用[諸如 Goldilocks](https://www.youtube.com/watch?v=DfmQWYiwFDk)、[KRR](https://www.youtube.com/watch?v=uITOzpf82RY) 和 [Kubecost](https://aws.amazon.com/blogs/containers/aws-and-kubecost-collaborate-to-deliver-cost-monitoring-for-eks-customers/) 等工具來估計容器的資源請求和限制。根據應用程式的性質、效能/成本需求，以及評估哪些指標最適合擴展、應用程式效能下降的時間點 （飽和點），以及如何相應調整請求和限制的複雜性。如需本主題的進一步指引，請參閱[應用程式正確調整大小](https://docs.aws.amazon.com/eks/latest/best-practices/node_and_workload_efficiency.html)。

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

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

## 減少耗用量
<a name="_reduce_consumption"></a>

節省成本的最佳方法是佈建較少的資源。其中一種方法是根據工作負載的目前需求來調整工作負載。您應該從確保您的工作負載定義其需求並動態擴展開始任何成本最佳化工作。這將需要從您的應用程式取得指標和設定組態，例如 [https://kubernetes.io/docs/tasks/run-application/configure-pdb/](https://kubernetes.io/docs/tasks/run-application/configure-pdb/)和 [Pod 準備階段](https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.5/deploy/pod_readiness_gate/)，以確保您的應用程式可以安全地動態擴展和縮減。請務必考慮限制性 PodDisruptionBudgets 可防止 Cluster Autoscaler 和 Karpenter 縮減節點，因為 Cluster Autoscaler 和 Karpenter 都遵守 PodDisruptionBudgets。PodDisruptionBudget 中的 'minAvailable' 值應一律低於部署中的 Pod 數量，而且您應該在兩個之間保持良好的緩衝，例如，在 6 個 Pod 的部署中，您想要始終至少執行 4 個 Pod，請將 PodDisruptionBidget 中的 'minAvailable' 設定為 4。這將允許 Cluster Autoscaler 和 Karpenter 在節點縮減規模事件期間安全地從未充分利用的節點耗盡和移出 Pod。請參閱 [Cluster Autoscaler 常見問答集](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/FAQ.md#what-types-of-pods-can-prevent-ca-from-removing-a-node)文件。

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

Kubernetes Metrics Server 可針對 CPU 和記憶體用量等內建指標進行擴展，但如果您想要根據 Amazon CloudWatch 或 SQS 佇列深度等其他指標進行擴展，則應考慮事件驅動型自動擴展專案，例如 [KEDA](https://keda.sh/)。請參閱[此部落格文章](https://aws.amazon.com/blogs/mt/proactive-autoscaling-of-kubernetes-workloads-with-keda-using-metrics-ingested-into-amazon-cloudwatch/)，了解如何搭配 CloudWatch 指標使用 KEDA。如果您不確定要根據哪些指標進行監控和擴展，請查看[監控重要指標的最佳實務](https://aws-observability.github.io/observability-best-practices/guides/#monitor-what-matters)。

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

## 減少未使用的容量
<a name="_reduce_unused_capacity"></a>

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

### Karpenter 和 Cluster Autoscaler
<a name="_karpenter_and_cluster_autoscaler"></a>

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

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

如果您使用的是 Cluster Autoscaler，它會遵守每個 Auto Scaling 群組 (ASG) 的「最小值」和「最大值」，並且只調整「所需」值。設定基礎 ASG 的這些值時請務必注意，因為 Cluster Autoscaler 無法將 ASG 縮減到超過其「最小」計數。將「所需」計數設定為正常上班時間所需的節點數量，並將「最小」設定為非上班時間所需的節點數量。請參閱 [Cluster Autoscaler 常見問答集](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md#auto-discovery-setup)文件。

### Cluster Autoscaler Priority Expander
<a name="_cluster_autoscaler_priority_expander"></a>

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 的詳細資訊，請參閱[最佳實務一節](https://docs.aws.amazon.com/eks/latest/best-practices/cas.html)。

### 取消排程器
<a name="_descheduler"></a>

Cluster Autoscaler 可以根據需要排程的新 Pod 或節點使用率不足，從叢集新增和移除節點容量。在排程到節點之後，它不會接受 Pod 置放的冪冪檢視。如果您使用的是 Cluster Autoscaler，您也應該查看 [Kubernetes 取消排程器](https://github.com/kubernetes-sigs/descheduler)，以避免浪費叢集中的容量。

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

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

### Karpenter 合併
<a name="_karpenter_consolidation"></a>

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

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

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

```
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 參數以移除未充分利用的節點
<a name="_remove_under_utilized_nodes_by_adjusting_cluster_autoscaler_parameters"></a>

節點使用率定義為請求的資源總和除以容量。預設為 `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 標記節點
<a name="_tag_nodes_with_cluster_autoscaler_and_karpenter"></a>

AWS 資源[標籤](https://docs.aws.amazon.com/tag-editor/latest/userguide/tagging.html)可用來組織您的資源，並在詳細的層級追蹤您的 AWS 成本。它們與成本追蹤的 Kubernetes 標籤沒有直接關聯。建議從 Kubernetes 資源標籤開始，並使用 [Kubecost](https://aws.amazon.com/blogs/containers/aws-and-kubecost-collaborate-to-deliver-cost-monitoring-for-eks-customers/) 等工具，根據 Pod 上的 Kubernetes 標籤、命名空間等取得基礎設施成本報告。

工作者節點需要有標籤，才能在 AWS Cost Explorer 中顯示帳單資訊。使用 Cluster Autoscaler，使用[啟動範本](https://docs.aws.amazon.com/eks/latest/userguide/launch-templates.html)標記受管節點群組中的工作者節點。對於自我管理節點群組，請使用 [EC2 自動擴展群組](https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-tagging.html)標記您的執行個體。對於 Karpenter 佈建的執行個體，請使用[節點範本中的 spec.tags 來](https://karpenter.sh/docs/concepts/nodeclasses/#spectags)標記它們。

### 多租戶叢集
<a name="_multi_tenant_clusters"></a>

在由不同團隊共用的叢集上工作時，您可能看不到在相同節點上執行的其他工作負載。雖然資源請求有助於隔離一些「雜訊鄰近」問題，例如 CPU 共用，但它們可能無法隔離所有資源邊界，例如磁碟 I/O 耗盡。不是每個工作負載的消耗性資源都可以隔離或限制。以高於其他工作負載的速率使用共用資源的工作負載，應透過節點[污點和容錯](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/)進行隔離。這類工作負載的另一項進階技術是 [CPU 鎖定](https://kubernetes.io/docs/tasks/administer-cluster/cpu-management-policies/#static-policy)，可確保容器的專屬 CPU 而非共用 CPU。

在節點層級隔離工作負載可能更昂貴，但使用[預留執行個體](https://aws.amazon.com/ec2/pricing/reserved-instances/)、[Graviton 處理器](https://aws.amazon.com/ec2/graviton/)或 [Spot](https://aws.amazon.com/ec2/spot/) 可以排程 [BestEffort](https://kubernetes.io/docs/concepts/workloads/pods/pod-qos/#besteffort) 任務或利用額外的節省。

共用叢集也可能有叢集層級的資源限制，例如 IP 耗盡、Kubernetes 服務限制或 API 擴展請求。您應該檢閱[可擴展性最佳實務指南](https://docs.aws.amazon.com/eks/latest/best-practices/scale-control-plane.html)，以確保您的叢集避免這些限制。

您可以在命名空間或 Karpenter 佈建器層級隔離資源。[Resource Quotas](https://kubernetes.io/docs/concepts/policy/resource-quotas/) 提供一種方法來設定對命名空間中資源工作負載可使用數量的限制。這可能是良好的初始護欄，但應該持續評估以確保它不會人為限制工作負載進行擴展。

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

### 排程的自動擴展
<a name="_scheduled_autoscaling"></a>

您可能需要在週末和下班時間縮減叢集。這對於您想要在不使用時縮減至零的測試和非生產叢集特別相關。[叢集倒轉](https://github.com/kubecost/cluster-turndown)之類的解決方案可以根據 Cron 排程將複本縮減為零。您也可以使用 Karpenter 達成此目標，如下列 [AWS 部落格](https://aws.amazon.com/blogs/containers/manage-scale-to-zero-scenarios-with-karpenter-and-serverless/)所述。

## 最佳化運算容量類型
<a name="_optimize_compute_capacity_types"></a>

在最佳化叢集中的運算總容量並利用 bin 封裝後，您應該查看您在叢集中佈建的運算類型，以及如何支付這些資源的費用。AWS 具有[運算節省計劃](https://aws.amazon.com/savingsplans/compute-pricing/)，可以降低運算成本，我們將將其分類為下列容量類型：
+ Spot
+ Savings Plans
+ On-Demand
+ Fargate

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

### Spot
<a name="_spot"></a>

[Spot](https://aws.amazon.com/ec2/spot/) 容量類型會從可用區域中的備用容量佈建 EC2 執行個體。Spot 提供最多 90% 的最大折扣，但這些執行個體可能會在其他地方需要時中斷。此外，佈建新的 Spot 執行個體可能不一定有容量，而且現有的 Spot 執行個體可以透過 [2 分鐘的中斷通知](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-interruptions.html)回收。如果您的應用程式有很長的啟動或關閉程序，Spot 執行個體可能不是最佳選項。

Spot 運算應使用各種執行個體類型，以減少無法使用 Spot 容量的可能性。需要處理執行個體中斷，才能安全地關閉節點。使用 Karpenter 或受管節點群組的一部分佈建的節點會自動支援[執行個體中斷通知](https://docs.aws.amazon.com/eks/latest/best-practices/karpenter.html)。如果您使用的是自我管理節點，則需要分別執行[節點終止處理常式](https://github.com/aws/aws-node-termination-handler)，以正常關閉 Spot 執行個體。

您可以在單一叢集中平衡 Spot 執行個體和隨需執行個體。透過 Karpenter，您可以建立[加權佈建器](https://karpenter.sh/docs/concepts/scheduling/#on-demandspot-ratio-split)，以實現不同容量類型的平衡。使用 Cluster Autoscaler，您可以使用 [spot 和隨需或預留執行個體建立混合節點群組](https://aws.amazon.com/blogs/containers/amazon-eks-now-supports-provisioning-and-managing-ec2-spot-instances-in-managed-node-groups/)。

以下是使用 Karpenter 在隨需執行個體之前排定 Spot 執行個體優先順序的範例。建立佈建器時，您可以指定 Spot、隨需或兩者 （如下所示）。當您同時指定 時，如果 Pod 未明確指定是否需要使用 Spot 或隨需，則 Karpenter 會在佈建具有 [price-capacity-optimization配置策略](https://aws.amazon.com/blogs/compute/introducing-price-capacity-optimized-allocation-strategy-for-ec2-spot-instances/) 的節點時優先考慮 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
<a name="_savings_plans_reserved_instances_and_aws_edp"></a>

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

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

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

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

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

### On-Demand
<a name="_on_demand"></a>

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

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

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

若要手動識別可與工作負載搭配使用的 EC2 執行個體類型，您應該使用 [ec2-instance-selector](https://github.com/aws/amazon-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 專案[叢集倒轉](https://github.com/kubecost/cluster-turndown)是控制器的範例，可根據設定的排程自動縮減叢集。

### Fargate 運算
<a name="_fargate_compute"></a>

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

Fargate 可以將工作負載縮減為 0.5 GB 記憶體的 .25 vCPU，以及 120 GB 記憶體的 16 vCPU。可用的 [Pod 大小變化](https://docs.aws.amazon.com/eks/latest/userguide/fargate-pod-configuration.html)數量有所限制，您需要了解工作負載最適合 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 可以利用運算節省計劃來降低隨需成本。

## 最佳化運算用量
<a name="_optimize_compute_usage"></a>

在運算基礎設施上節省成本的另一種方法是為工作負載使用更有效率的運算。這可以來自效能更高的一般用途運算，例如 [Graviton 處理器](https://aws.amazon.com/ec2/graviton/)，比 x86 便宜 20% 且能源效率高 60%，或是 GPUs 和 [FPGAs](https://aws.amazon.com/ec2/instance-types/f1/) 等工作負載特定加速器。您需要建置可在[手臂架構上執行](https://aws.amazon.com/blogs/containers/how-to-build-your-containers-for-arm-and-save-with-graviton-and-spot-instances-on-amazon-ecs/)的容器，並使用[適合工作負載的加速器設定節點](https://aws.amazon.com/blogs/compute/running-gpu-accelerated-kubernetes-workloads-on-p3-and-p2-ec2-instances-with-amazon-eks/)。

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 執行個體建立節點群組，並在[工作負載上設定節點公差](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/)，以利用新的容量。

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

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

有些 GPU 硬體可以跨多個工作負載共用，因此可以佈建和使用單一 GPU。若要了解如何設定工作負載 GPU 共用，請參閱[虛擬 GPU 裝置外掛程式](https://aws.amazon.com/blogs/opensource/virtual-gpu-device-plugin-for-inference-workload-in-kubernetes/)以取得詳細資訊。您也可以參考下列部落格：
+  [在 Amazon EKS 上，使用 NVIDIA 時間分割和加速的 EC2 執行個體實現 GPU 共用](https://aws.amazon.com/blogs/containers/gpu-sharing-on-amazon-eks-with-nvidia-time-slicing-and-accelerated-ec2-instances/) 
+  [在 Amazon EKS 上，使用 NVIDIA 的多執行個體 GPU (MIG) 最大限度地提高 GPU 使用率：按 GPU 執行更多 Pod 以增強效能](https://aws.amazon.com/blogs/containers/maximizing-gpu-utilization-with-nvidias-multi-instance-gpu-mig-on-amazon-eks-running-more-pods-per-gpu-for-enhanced-performance/) 

# 成本最佳化 - 網路
<a name="cost-opt-networking"></a>

高可用性 (HA) 的架構系統是實現彈性和容錯能力的最佳實務。實際上，這表示將您的工作負載和基礎基礎設施分散到指定 AWS 區域中的多個可用區域 (AZs)。確保您的 Amazon EKS 環境具備這些特性，可增強系統的整體可靠性。除此之外，EKS 環境也可能由各種建構模組 （即 VPCs)、元件 （即 ELBs) 和整合 （即 ECR 和其他容器登錄檔） 組成。

高可用性系統與其他使用案例特定元件的組合，在資料傳輸和處理方式上扮演重要角色。這將對資料傳輸和處理所產生的成本產生影響。

以下詳述的實務將協助您設計和最佳化 EKS 環境，以達成不同網域和使用案例的成本效益。

## Pod 到 Pod 通訊
<a name="_pod_to_pod_communication"></a>

根據您的設定，Pod 之間的網路通訊和資料傳輸可能會對執行 Amazon EKS 工作負載的整體成本產生重大影響。本節將涵蓋不同的概念和方法，以緩解與 Pod 間通訊相關的成本，同時考慮高可用性 (HA) 架構、應用程式效能和彈性。

### 將流量限制為可用區域
<a name="_restricting_traffic_to_an_availability_zone"></a>

在 的早期，Kubernetes 專案開始開發拓撲感知建構，包括指派給節點的 kubernetes.io/hostname、topology.kubernetes.io/region 和 topology.kubernetes.io/zone 等標籤，以啟用功能，例如跨故障網域和拓撲感知磁碟區佈建器的工作負載分佈。在 Kubernetes 1.17 中畢業後，標籤也被利用來啟用 Pod 到 Pod 通訊的拓撲感知路由功能。

以下是一些策略，說明如何控制 EKS 叢集中 Pod 之間的跨可用區流量，以降低成本並盡可能減少延遲。

 *如果您想要精細了解叢集中 Pod 之間的跨可用區流量 （例如以位元組為單位傳輸的資料量），[請參閱此文章](https://aws.amazon.com/blogs/containers/getting-visibility-into-your-amazon-eks-cross-az-pod-to-pod-network-bytes/)。*

![\[拓撲感知路由\]](http://docs.aws.amazon.com/zh_tw/eks/latest/best-practices/images/topo_aware_routing.png)


如上圖所示，服務是穩定的網路抽象層，可接收目的地為 Pod 的流量。建立服務時，會建立多個 EndpointSlices。每個 EndpointSlice 都有端點清單，其中包含 Pod 地址的子集，以及它們正在執行的節點，以及任何其他拓撲資訊。使用在每個節點上執行的協助程式集 Amazon VPC CNI 時， kube-proxy 會維護網路規則，以啟用 Pod 通訊和服務探索 （替代的 eBPF 型 CNIs 可能不會使用 kube-proxy，但會提供同等行為）。它會履行內部路由的角色，但會根據其從建立的 EndpointSlices 消耗的內容來執行此操作。

在 EKS 上，kube-proxy 主要使用 iptables NAT 規則 （或 [IPVS](https://docs.aws.amazon.com/eks/latest/best-practices/ipvs.html)、[NFTables](https://kubernetes.io/blog/2025/02/28/nftables-kube-proxy/) 作為替代方案） 來分佈叢集中所有 Pod 的流量，無論其節點或 AZ 放置為何。此預設分佈可能會導致跨可用區流量路由，這可能會導致敏感應用程式延遲增加，並在大型部署中增加可用區間資料傳輸費用。

 **使用拓撲感知路由 （先前稱為拓撲感知提示）** 

在 Kubernetes 服務上啟用和實作[https://kubernetes.io/docs/concepts/services-networking/topology-aware-routing/](https://kubernetes.io/docs/concepts/services-networking/topology-aware-routing/)時，EndpointSlice 控制器會將端點按比例配置到叢集分散的不同區域。對於每個端點，EndpointSlice 控制器也會設定區域的*提示*。*提示*說明端點應該為哪個區域提供流量。 `kube-proxy`會根據套用*的提示*，將流量從區域路由到端點。

下圖顯示具有提示的 EndpointSlices 如何組織起來，以便根據其區域來源，`kube-proxy`知道應該前往哪個目的地。如果沒有提示，則不會有此類配置或組織，無論流量來自何處，都會代理到不同的區域目的地。

![\[端點配量\]](http://docs.aws.amazon.com/zh_tw/eks/latest/best-practices/images/endpoint_slice.png)


在某些情況下，EndpointSlice 控制器可能會套用不同區域的*提示*，這表示端點最終可能會為來自不同區域的流量提供服務。這樣做的原因是嘗試和維護不同區域中端點之間的流量均勻分佈。

以下是有關如何啟用服務*拓撲感知路由*的程式碼片段。

```
apiVersion: v1
kind: Service
metadata:
  name: orders-service
  namespace: ecommerce
  annotations:
    service.kubernetes.io/topology-mode: Auto
spec:
  selector:
    app: orders
  type: ClusterIP
  ports:

* protocol: TCP
port: 3003
targetPort: 3003
```

以下螢幕擷取畫面顯示 EndpointSlice 控制器的結果，已成功將提示套用至 AZ 中執行之 Pod 複本的端點`eu-west-1a`。

![\[配量殼層\]](http://docs.aws.amazon.com/zh_tw/eks/latest/best-practices/images/slice_shell.png)


**注意**  
請務必注意，拓撲感知路由仍在 Beta 版中。此功能在叢集拓撲中平均分佈的工作負載中執行更可預測，因為控制器會按比例分配跨區域的端點，但當區域中的節點資源過於不平衡以避免過載時，可能會略過提示指派。因此，強烈建議將其與排程限制一起使用，以提高應用程式的可用性，例如 [Pod 拓撲分散限制](https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/)。請注意，當容量跨區域波動時，例如使用 [Amazon EC2 Spot 執行個體](https://aws.amazon.com/ec2/spot/)時，可能不會指派提示，因為計算比例分佈時，無法即時偵測到中斷或替換。

 **使用流量分佈** 

[流量分佈](https://kubernetes.io/docs/reference/networking/virtual-ips/#traffic-distribution)在 Kubernetes 1.30 中推出，並在 1.33 中正式推出，為同一區域流量偏好設定提供了比拓撲感知路由更簡單的替代方案。雖然拓撲感知路由嘗試使用智慧方法來路由流量，以避免端點超載，但會導致無法預測的行為。流量分佈會改為優先考慮可預測性。PreferClose 選項會指示 kube-proxy 建立規則，先根據 EndpointSlice 控制器設定的區域*提示*，將流量路由到相同區域端點。當沒有相同區域端點可用時，它會回到將流量分散到服務的任何叢集端點。此功能專為接受最佳化鄰近性而非嘗試均勻分佈拓撲感知路由提供之負載的工作負載而設計。

以下是有關如何啟用服務*流量分佈*的程式碼片段。

```
apiVersion: v1
kind: Service
metadata:
  name: orders-service
  namespace: ecommerce
spec:
  trafficDistribution: PreferClose
  selector:
    app: orders
  type: ClusterIP
  ports:

* protocol: TCP
port: 3003
targetPort: 3003
```

啟用流量分佈時，會出現常見的挑戰：如果大多數流量來自相同區域，則單一可用區域內的端點可能會過載。此過載可能會造成重大問題：
+ 管理多可用區域部署的單一 Horizontal Pod Autoscaler (HPA) 可以透過跨不同AZs擴展 Pod 來回應。不過，此動作無法有效地解決受影響區域中增加的負載。
+ 在這種情況下，可能會導致資源效率低下。當類似 Karpenter 的叢集自動擴展器偵測到不同 AZs 的 Pod 橫向擴展時，可能會在不受影響的 AZs 中佈建其他節點，導致不必要的資源配置。

若要克服此挑戰：
+ 為每個區域建立單獨的部署，這些區域會有自己的 HPAs 來獨立擴展。
+ 利用拓撲分散限制來確保跨叢集的工作負載分佈，這有助於防止高流量區域中的端點過載。

 **使用自動擴展器：將節點佈建至特定 AZ** 

 *我們強烈建議*您在跨多個 AZs 的高可用性環境中執行工作負載。這可改善應用程式的可靠性，尤其是在 AZ 發生問題時。如果您願意為了降低網路相關成本而犧牲可靠性，您可以將節點限制為單一可用區域。

若要在相同可用區域中執行所有 Pod，請在相同可用區域中佈建工作者節點，或在相同可用區域中執行的工作者節點上排程 Pod。若要在單一 AZ 中佈建節點，請使用 [Cluster Autoscaler (CA)](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler) 定義子網路屬於相同 AZ 的節點群組。對於 [Karpenter，](https://karpenter.sh/)請使用 `topology.kubernetes.io/zone`並指定您要建立工作者節點的 AZ。例如，以下 Karpenter 佈建器程式碼片段會佈建 us-west-2a AZ 中的節點。

 **Karpenter** 

```
apiVersion: karpenter.sh/v1
kind: Provisioner
metadata:
name: single-az
spec:
  requirements:

* key: "topology.kubernetes.io/zone"`
operator: In
values: ["us-west-2a"]
```

 **Cluster Autoscaler (CA)** 

```
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
  name: my-ca-cluster
  region: us-east-1
  version: "1.21"
availabilityZones:

* us-east-1a
managedNodeGroups:
* name: managed-nodes
labels:
  role: managed-nodes
instanceType: t3.medium
minSize: 1
maxSize: 10
desiredCapacity: 1
...
```

 **使用 Pod 指派和節點親和性** 

或者，如果您的工作者節點在多個 AZs 中執行，則每個節點都會有標籤 * [topology.kubernetes.io/zone](http://topology.kubernetes.io/zone%E2%80%9D)*，其 AZ 值為 （例如 us-west-2a 或 us-west-2b)。您可以使用 `nodeSelector`或 `nodeAffinity` 將 Pod 排程到單一 AZ 中的節點。例如，下列資訊清單檔案會在 AZ us-west-2a 中執行的節點內排程 Pod。

```
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: test
spec:
  nodeSelector:
    topology.kubernetes.io/zone: us-west-2a
  containers:

* name: nginx
image: nginx
imagePullPolicy: IfNotPresent
```

### 限制節點的流量
<a name="_restricting_traffic_to_a_node"></a>

在某些情況下，限制區域層級的流量是不夠的。除了降低成本之外，您可能還需要減少某些經常相互通訊的應用程式之間的網路延遲。為了獲得最佳網路效能並降低成本，您需要一種方法來限制特定節點的流量。例如，微服務 A 應一律與節點 1 上的微服務 B 交談，即使在高可用性 (HA) 設定中也是如此。讓節點 1 上的微服務 A 與節點 2 上的微服務 B 交談可能會對此性質的應用程式所需的效能產生負面影響，特別是當節點 2 完全位於單獨的可用區域時。

 **使用服務內部流量政策** 

若要將 Pod 網路流量限制為節點，您可以使用*[服務內部流量政策](https://kubernetes.io/docs/concepts/services-networking/service-traffic-policy/) *。根據預設，傳送至工作負載的服務流量會隨機分散到不同的產生端點。因此，在 HA 架構中，這表示來自 Microservice A 的流量可以在不同 AZs 的任何指定節點上移至 Microservice B 的任何複本。不過，當服務的內部流量政策設為 時`Local`，流量將限制為流量來源節點上的端點。此政策指定節點本機端點的獨佔使用。透過隱含，該工作負載的網路流量相關成本將低於分佈的叢集範圍。此外，延遲會較低，讓您的應用程式效能更高。

**注意**  
請務必注意，此功能無法與 Kubernetes 中的拓撲感知路由結合使用。

![\[本機內部流量\]](http://docs.aws.amazon.com/zh_tw/eks/latest/best-practices/images/local_traffic.png)


以下是有關如何設定服務*內部流量政策*的程式碼片段。

```
apiVersion: v1
kind: Service
metadata:
  name: orders-service
  namespace: ecommerce
spec:
  selector:
    app: orders
  type: ClusterIP
  ports:

* protocol: TCP
port: 3003
targetPort: 3003
  internalTrafficPolicy: Local
```

為了避免因流量下降而導致應用程式的意外行為，您應該考慮以下方法：
+ 為每個通訊 Pod 執行足夠的複本
+ 使用[拓撲分散限制條件，讓 Pod 的分散](https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/)相對均勻 
+ 使用 [Pod 親和性規則](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity)來共同定位通訊 Pod

在此範例中，您有 2 個 Microservice A 複本和 3 個 Microservice B 複本。如果 Microservice A 的複本分散在節點 1 和 2 之間，且 Microservice B 在節點 3 上有全部 3 個複本，則由於`Local`內部流量政策，他們將無法通訊。如果沒有可用的節點本機端點，則會捨棄流量。

![\[node-local_no_peer\]](http://docs.aws.amazon.com/zh_tw/eks/latest/best-practices/images/no_node_local_1.png)


如果 Microservice B 在節點 1 和 2 上有其 3 個複本中的 2 個，則對等應用程式之間會進行通訊。但是，您仍然會有 Microservice B 的隔離複本，而沒有任何對等複本可與之通訊。

![\[node-local_with_peer\]](http://docs.aws.amazon.com/zh_tw/eks/latest/best-practices/images/no_node_local_2.png)


**注意**  
在某些情況下，如上圖中描述的隔離複本，如果仍有用途 （例如提供來自外部傳入流量的請求），則可能不是需要關注的原因。

 **將服務內部流量政策與拓撲分散限制搭配使用** 

搭配使用*內部流量政策*與*拓撲分散限制*，有助於確保您擁有適當數量的複本，以在不同節點上通訊微服務。

```
apiVersion: apps/v1
kind: Deployment
metadata:
  name: express-test
spec:
  replicas: 6
  selector:
    matchLabels:
      app: express-test
  template:
    metadata:
      labels:
        app: express-test
        tier: backend
    spec:
      topologySpreadConstraints:
      - maxSkew: 1
        topologyKey: "topology.kubernetes.io/zone"
        whenUnsatisfiable: ScheduleAnyway
        labelSelector:
          matchLabels:
            app: express-test
```

 **搭配 Pod 親和性規則使用服務內部流量政策** 

另一種方法是在使用服務內部流量政策時，使用 Pod 親和性規則。使用 Pod 親和性，您可以影響排程器來聯合定位某些 Pod，因為它們經常通訊。透過在特定 Pod 上套用嚴格的排程限制 (`requiredDuringSchedulingIgnoredDuringExecution`)，當排程器將 Pod 放置在節點上時，這將為您提供更好的 Pod 共置結果。

```
apiVersion: apps/v1
kind: Deployment
metadata:
  name: graphql
  namespace: ecommerce
  labels:
    app.kubernetes.io/version: "0.1.6"
    ...
    spec:
      serviceAccountName: graphql-service-account
      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - orders
            topologyKey: "kubernetes.io/hostname"
```

## Load Balancer與 Pod 通訊
<a name="_load_balancer_to_pod_communication"></a>

EKS 工作負載通常由負載平衡器前置，將流量分配到 EKS 叢集中的相關 Pod。您的架構可能包含內部和/或面向外部的負載平衡器。根據您的架構和網路流量組態，負載平衡器和 Pod 之間的通訊可能會產生大量的資料傳輸費用。

您可以使用 [AWS Load Balancer 控制器](https://kubernetes-sigs.github.io/aws-load-balancer-controller)自動管理 ELB 資源 (ALB 和 NLB) 的建立。您在此類設定中產生的資料傳輸費用將取決於網路流量採取的路徑。AWS Load Balancer 控制器支援兩種網路流量模式：*執行個體模式*和 *IP 模式*。

使用*執行個體模式*時，會在 EKS 叢集中的每個節點上開啟 NodePort。然後，負載平衡器會跨節點平均代理流量。如果節點上執行目的地 Pod，則不會產生資料傳輸費用。不過，如果目的地 Pod 位於另一個節點，且位於與接收流量的 NodePort 不同的 AZ 中，則會有從 kube-proxy 到目的地 Pod 的額外網路跳轉。在這種情況下，會產生跨可用區域資料傳輸費用。由於跨節點的流量均勻分佈，因此很可能會產生與跨區域網路流量跳躍相關的額外資料傳輸費用，從 kube-proxies 跳至相關目的地 Pod。

下圖說明從負載平衡器流向 NodePort，然後從 `kube-proxy`流向不同 AZ 中不同節點上目的地 Pod 之流量的網路路徑。這是*執行個體模式*設定的範例。

![\[LB 到 Pod\]](http://docs.aws.amazon.com/zh_tw/eks/latest/best-practices/images/lb_2_pod.png)


使用 *ip 模式*時，網路流量會從負載平衡器直接代理至目的地 Pod。因此，此方法*不會涉及任何資料傳輸費用*。

**注意**  
建議您將負載平衡器設定為 *IP 流量模式*，以減少資料傳輸費用。對於此設定，確保您的負載平衡器部署在 VPC 中的所有子網路中也很重要。

下圖說明網路 *IP 模式下*從負載平衡器流向 Pod 之流量的網路路徑。

![\[IP 模式\]](http://docs.aws.amazon.com/zh_tw/eks/latest/best-practices/images/ip_mode.png)


## 從容器登錄檔傳輸資料
<a name="_data_transfer_from_container_registry"></a>

### Amazon ECR
<a name="_amazon_ecr"></a>

將資料傳輸到 Amazon ECR 私有登錄檔是免費的。*區域內資料傳輸不會產生任何費用*，但傳輸至網際網路和跨區域的資料將按傳輸兩端的網際網路資料傳輸費率收費。

您應該使用 ECRs內建[映像複寫功能](https://docs.aws.amazon.com/AmazonECR/latest/userguide/replication.html)，將相關的容器映像複寫到與工作負載相同的區域。如此一來，複寫就會收取一次費用，而且所有相同的區域 （區域內） 映像提取都是免費的。

您可以使用*[介面 VPC 端點](https://docs.aws.amazon.com/whitepapers/latest/aws-privatelink/what-are-vpc-endpoints.html)連線至區域內 ECR 儲存庫，進一步降低從 ECR* 提取映像 （資料傳輸） 的相關資料傳輸成本。連線至 ECR 公有 AWS 端點 （透過 NAT Gateway 和網際網路閘道） 的替代方法會產生更高的資料處理和傳輸成本。下一節將詳細說明降低工作負載與 AWS Services 之間的資料傳輸成本。

如果您使用特別是大型映像執行工作負載，則可以使用預先快取的容器映像建置自己的自訂 Amazon Machine Image (AMIs)。這可以減少從容器登錄檔到 EKS 工作者節點的初始映像提取時間和潛在的資料傳輸成本。

## 資料傳輸至網際網路和 AWS 服務
<a name="_data_transfer_to_internet_aws_services"></a>

這是透過網際網路將 Kubernetes 工作負載與其他 AWS 服務或第三方工具和平台整合的常見做法。用於往返相關目的地流量的基礎網路基礎設施可能會影響資料傳輸過程中產生的成本。

### 使用 NAT 閘道
<a name="_using_nat_gateways"></a>

NAT Gateways 是執行網路位址轉譯 (NAT) 的網路元件。下圖說明 EKS 叢集中與其他 AWS 服務 (Amazon ECR、DynamoDB 和 S3) 和第三方平台通訊的 Pod。在此範例中，Pod 會在個別 AZs 的私有子網路中執行。若要從網際網路傳送和接收流量，NAT Gateway 會部署到一個可用區域的公有子網路，允許具有私有 IP 地址的任何資源共用單一公有 IP 地址以存取網際網路。此 NAT Gateway 會接著與網際網路閘道元件通訊，允許封包傳送到其最終目的地。

![\[NAT 閘道\]](http://docs.aws.amazon.com/zh_tw/eks/latest/best-practices/images/nat_gw.png)


針對這類使用案例使用 NAT Gateway 時，*您可以在每個 AZ 中部署 NAT Gateway，將資料傳輸成本降至最低*。如此一來，路由至網際網路的流量將通過相同可用區域中的 NAT Gateway，避免跨可用區域資料傳輸。不過，即使您將節省異地同步備份資料傳輸的成本，此設定的隱含性是您架構中其他 NAT Gateway 的成本。

此建議的方法如下圖所示。

![\[建議方法\]](http://docs.aws.amazon.com/zh_tw/eks/latest/best-practices/images/recommended_approach.png)


### 使用 VPC 端點
<a name="_using_vpc_endpoints"></a>

若要進一步降低此類架構的成本，*您應該使用 [VPC 端點](https://docs.aws.amazon.com/whitepapers/latest/aws-privatelink/what-are-vpc-endpoints.html)在工作負載和 AWS 服務之間建立連線*。VPC 端點可讓您從 VPC 內存取 AWS 服務，無需資料/網路封包周遊網際網路。所有流量都是內部的，並保留在 AWS 網路中。VPC 端點有兩種類型：界面 VPC 端點 ([許多 AWS 服務支援](https://docs.aws.amazon.com/vpc/latest/privatelink/aws-services-privatelink-support.html)) 和閘道 VPC 端點 （僅 S3 和 DynamoDB 支援）。

 **閘道 VPC 端點** 

 *閘道 VPC 端點沒有相關的每小時或資料傳輸成本*。使用閘道 VPC 端點時，請務必注意它們無法跨 VPC 邊界延伸。它們無法用於 VPC 對等互連、VPN 聯網或透過 Direct Connect 使用。

 **介面 VPC 端點** 

VPC 端點會[按小時計費](https://aws.amazon.com/privatelink/pricing/)，並透過基礎 ENI 支付與資料處理相關的額外費用。請注意，AZ 間資料傳輸[不會收費](https://aws.amazon.com/about-aws/whats-new/2022/04/aws-data-transfer-price-reduction-privatelink-transit-gateway-client-vpn-services/)。

下圖顯示透過 VPC 端點與 AWS 服務通訊的 Pod。

![\[VPC 端點\]](http://docs.aws.amazon.com/zh_tw/eks/latest/best-practices/images/vpc_endpoints.png)


## VPCs之間的資料傳輸
<a name="_data_transfer_between_vpcs"></a>

在某些情況下，您可能會在不同的 VPCs中 （在同一 AWS 區域內） 有工作負載，需要彼此通訊。這可以透過連接到個別 VPCs 的網際網路閘道，允許流量周遊公有網際網路來完成。這類通訊可以透過在公有子網路中部署基礎設施元件來啟用，例如 EC2 執行個體、NAT Gateway 或 NAT 執行個體。不過，包含這些元件的設定將產生處理/傳輸資料進出 VPCs的費用。如果往返個別 VPCs流量在 AZs 之間移動，則資料傳輸會產生額外費用。下圖說明使用 NAT Gateway 和網際網路閘道在不同 VPCs 中的工作負載之間建立通訊的設定。

![\[VPCs之間\]](http://docs.aws.amazon.com/zh_tw/eks/latest/best-practices/images/between_vpcs.png)


### VPC 互連連線
<a name="_vpc_peering_connections"></a>

若要降低此類使用案例的成本，您可以使用 [VPC 對等互連](https://docs.aws.amazon.com/vpc/latest/peering/what-is-vpc-peering.html)。使用 VPC 對等互連時，保留在相同可用區域內的網路流量無需支付資料傳輸費用。如果流量超過 AZs，會產生費用。不過，建議採用 VPC 對等互連方法來在相同 AWS 區域內不同 VPCs 中的工作負載之間進行符合成本效益的通訊。不過，請務必注意，VPC 對等互連主要對 1：1 VPC 連線有效，因為它不允許傳輸式聯網。

下圖是透過 VPC 互連連線進行工作負載通訊的高階表示。

![\[對等互連\]](http://docs.aws.amazon.com/zh_tw/eks/latest/best-practices/images/peering.png)


### 暫時性網路連線
<a name="_transitive_networking_connections"></a>

如上一節所述，VPC 對等連線不允許傳輸網路連線。如果您想要將 3 個以上的 VPCs 與傳輸性聯網需求連接，則應使用 [Transit Gateway](https://docs.aws.amazon.com/vpc/latest/tgw/what-is-transit-gateway.html) (TGW)。這可讓您克服 VPC 對等互連的限制，或與在多個 VPC 之間具有多個 VPC 對等互連相關聯的任何操作額外負荷 VPCs 。對於傳送至 TGW 的資料[，您需要按小時計費](https://aws.amazon.com/transit-gateway/pricing/)。*沒有與流經 TGW 的可用區域間流量相關聯的目的地成本。*

下圖顯示在不同 VPCs但在相同 AWS 區域內流經 TGW 的可用區域間流量。

![\[暫時性\]](http://docs.aws.amazon.com/zh_tw/eks/latest/best-practices/images/transititive.png)


## 使用服務網格
<a name="_using_a_service_mesh"></a>

服務網格提供強大的聯網功能，可用於降低 EKS 叢集環境中的網路相關成本。不過，如果您採用，您應該仔細考慮服務網格將對您的環境帶來的操作任務和複雜性。

### 將流量限制為可用區域
<a name="_restricting_traffic_to_availability_zones"></a>

 **使用 Istio 的區域權重分佈** 

Istio 可讓您在路由發生*後*將網路政策套用至流量。這是使用[目的地規則](https://istio.io/latest/docs/reference/config/networking/destination-rule/)來完成的，例如[地區性加權分佈](https://istio.io/latest/docs/tasks/traffic-management/locality-load-balancing/distribute/)。使用此功能，您可以控制流量的權重 （以百分比表示），而流量可根據其原始伺服器前往特定目的地。此流量的來源可以是來自外部 （或面向公有） 負載平衡器或叢集本身內的 Pod。當所有 Pod 端點都可用時，將根據加權循環配置負載平衡演算法選取地區性。如果某些端點運作狀態不佳或無法使用，[則會自動調整地區權重](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/load_balancing/locality_weight.html)，以反映可用端點中的此變更。

**注意**  
在實作地區性加權分佈之前，您應該先了解網路流量模式，以及目的地規則政策可能對應用程式行為造成的影響。因此，請務必使用 [AWS X-Ray](https://aws.amazon.com/xray/) 或 [Jaeger](https://www.jaegertracing.io/) 等工具建立分散式追蹤機制。

上述 Istio 目的地規則也可以套用，以管理從負載平衡器到 EKS 叢集中 Pod 的流量。地區加權分佈規則可以套用至從高可用性負載平衡器 （特別是輸入閘道） 接收流量的服務。這些規則可讓您根據區域原始伺服器 - 在這種情況下的負載平衡器，控制流向何處的流量。如果設定正確，相較於將流量平均或隨機分配到不同AZs Pod 複本的負載平衡器，產生的輸出跨區域流量較少。

以下是 Istio 中目的地規則資源的程式碼區塊範例。如下方所示，此資源會指定區域中 3 個不同AZs傳入流量的加權組態`eu-west-1`。這些組態宣告，來自指定 AZ 的大部分傳入流量 （在此案例中為 70%) 應代理至其來源相同 AZ 中的目的地。

```
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: express-test-dr
spec:
  host: express-test.default.svc.cluster.local
  trafficPolicy:
    loadBalancer:                      +
      localityLbSetting:
        distribute:
        - from: eu-west-1/eu-west-1a/  +
          to:
            "eu-west-1/eu-west-1a/_": 70
            "eu-west-1/eu-west-1b/_": 20
            "eu-west-1/eu-west-1c/_": 10
        - from: eu-west-1/eu-west-1b/_  +
          to:
            "eu-west-1/eu-west-1a/_": 20
            "eu-west-1/eu-west-1b/_": 70
            "eu-west-1/eu-west-1c/_": 10
        - from: eu-west-1/eu-west-1c/_  +
          to:
            "eu-west-1/eu-west-1a/_": 20
            "eu-west-1/eu-west-1b/_": 10
            "eu-west-1/eu-west-1c/*": 70**
    connectionPool:
      http:
        http2MaxRequests: 10
        maxRequestsPerConnection: 10
    outlierDetection:
      consecutiveGatewayErrors: 1
      interval: 1m
      baseEjectionTime: 30s
```

**注意**  
可分佈目的地的最小權重為 1%。這是因為在主要目的地中的端點運作狀態不佳或無法使用的情況下，維護容錯移轉區域和區域。

下圖說明 *eu-west-1* 區域中具有高度可用負載平衡器的情況，並套用地區權重分佈。此圖表的目的地規則政策設定為將 60% 來自 *eu-west-1a* 的流量傳送至相同 AZ 中的 Pod，而 40% 來自 *eu-west-1a* 的流量應傳送至 eu-west-1b 中的 Pod。

![\[停止流量控制\]](http://docs.aws.amazon.com/zh_tw/eks/latest/best-practices/images/istio-traffic-control.png)


### 將流量限制為可用區域和節點
<a name="_restricting_traffic_to_availability_zones_and_nodes"></a>

 **搭配 Istio 使用服務內部流量政策** 

若要降低與*外部*傳入流量和 Pod 之間的*內部*流量相關的網路成本，您可以結合 Istio 的目的地規則和 Kubernetes Service *內部流量政策*。將 Istio 目的地規則與服務內部流量政策結合的方式，主要取決於 3 件事：
+ 微服務的角色
+ 跨微服務的網路流量模式
+ 應如何跨 Kubernetes 叢集拓撲部署微服務

下圖顯示巢狀請求的網路流程會是什麼樣子，以及上述政策如何控制流量。

![\[外部和內部流量政策\]](http://docs.aws.amazon.com/zh_tw/eks/latest/best-practices/images/external-and-internal-traffic-policy.png)


1. 最終使用者向 **APP A 提出請求，**進而向 **APP C** 提出巢狀請求。 此請求會先傳送至高可用性負載平衡器，其在 AZ 1 和 AZ 2 中具有執行個體，如上圖所示。

1. 外部傳入請求接著會由 Istio Virtual Service 路由至正確的目的地。

1. 請求路由後，Istio 目的地規則會根據來源 (AZs 1 或 AZ 2) 控制流向個別 AZ 的流量。

1. 接著流量會移至 Service for **APP A**，然後代理至個別的 Pod 端點。如圖所示，80% 的傳入流量會傳送至 AZ 1 中的 Pod 端點，而 20% 的傳入流量會傳送至 AZ 2。

1.  然後，**APP A** 向 **APP C** 提出內部請求。 **APP C** 的服務已啟用內部流量政策 (`internalTrafficPolicy``：Local`)。

1. 由於 **APP C 可用的節點本機端點，從 APP A** (**NODE 1) **到 **APP C** 的內部請求成功。 ****

1. 從 **APP A** (**NODE 3) 到** **APP C** 的內部請求失敗，因為 **APP C** 沒有可用的*節點本機端點*。 如圖所示，APP C 在 NODE 3 上沒有複本。 **\$1**\$1

以下螢幕擷取畫面是從此方法的即時範例擷取。第一組螢幕擷取畫面示範對 的成功外部請求，`graphql`以及從 成功巢狀請求`graphql`到節點 上共置`orders`複本`ip-10-0-0-151.af-south-1.compute.internal`。

![\[Before\]](http://docs.aws.amazon.com/zh_tw/eks/latest/best-practices/images/before.png)


![\[結果之前\]](http://docs.aws.amazon.com/zh_tw/eks/latest/best-practices/images/before-results.png)


使用 Istio，您可以驗證和匯出代理知道的任何[上游叢集](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/intro/terminology)和端點的統計資料。這有助於提供網路流程的影像，以及工作負載服務之間的分佈共用。繼續使用相同的範例，可以使用下列命令來取得`graphql`代理知道的`orders`端點：

```
kubectl exec -it deploy/graphql -n ecommerce -c istio-proxy -- curl localhost:15000/clusters | grep orders
```

```
...
orders-service.ecommerce.svc.cluster.local::10.0.1.33:3003::**rq_error::0**
orders-service.ecommerce.svc.cluster.local::10.0.1.33:3003::**rq_success::119**
orders-service.ecommerce.svc.cluster.local::10.0.1.33:3003::**rq_timeout::0**
orders-service.ecommerce.svc.cluster.local::10.0.1.33:3003::**rq_total::119**
orders-service.ecommerce.svc.cluster.local::10.0.1.33:3003::**health_flags::healthy**
orders-service.ecommerce.svc.cluster.local::10.0.1.33:3003::**region::af-south-1**
orders-service.ecommerce.svc.cluster.local::10.0.1.33:3003::**zone::af-south-1b**
...
```

在此情況下，`graphql`代理只會知道其共用節點之複本的`orders`端點。如果您從訂單 Service 中移除`internalTrafficPolicy: Local`設定，並重新執行類似上述的命令，則結果會傳回分散在不同節點的複本的所有端點。此外，透過檢查個別端點`rq_total`的 ，您會注意到網路分佈中相對均勻的共用。因此，如果端點與在不同 AZs 中執行的上游服務相關聯，則跨區域的此網路分佈將產生更高的成本。

如上一節所述，您可以透過使用 Pod 親和性來共同定位經常通訊的 Pod。

```
...
spec:
...
  template:
    metadata:
      labels:
        app: graphql
        role: api
        workload: ecommerce
    spec:
      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - orders
            topologyKey: "kubernetes.io/hostname"
      nodeSelector:
        managedBy: karpenter
        billing-team: ecommerce
...
```

當 `graphql`和 `orders` 複本不存在於相同的節點 (`ip-10-0-0-151.af-south-1.compute.internal`) `200 response code`時， 的第一個請求`graphql`會成功，如下方 Postman 螢幕擷取畫面中的 所述，而來自 `graphql`的第二個巢狀請求會因 而`orders`失敗`503 response code`。

 ![\[After\]](http://docs.aws.amazon.com/zh_tw/eks/latest/best-practices/images/after.png) ![\[After results\]](http://docs.aws.amazon.com/zh_tw/eks/latest/best-practices/images/after-results.png) 

## 其他資源
<a name="_additional_resources"></a>
+  [使用 Istio 處理 EKS 上的延遲和資料傳輸成本](https://aws.amazon.com/blogs/containers/addressing-latency-and-data-transfer-costs-on-eks-using-istio/) 
+  [探索拓撲感知提示對 Amazon Elastic Kubernetes Service 網路流量的影響](https://aws.amazon.com/blogs/containers/exploring-the-effect-of-topology-aware-hints-on-network-traffic-in-amazon-elastic-kubernetes-service/) 
+  [取得 Amazon EKS 跨可用區域 Pod 到 Pod 網路位元組的可見性](https://aws.amazon.com/blogs/containers/getting-visibility-into-your-amazon-eks-cross-az-pod-to-pod-network-bytes/) 
+  [使用 Istio 最佳化 AZ 流量](https://youtu.be/EkpdKVm9kQY) 
+  [使用拓撲感知路由最佳化 AZ 流量](https://youtu.be/KFgE_lNVfz4) 
+  [使用服務內部流量政策最佳化 Kubernetes 成本和效能](https://youtu.be/-uiF_zixEro) 
+  [使用 Istio 和服務內部流量政策最佳化 Kubernetes 成本和效能](https://youtu.be/edSgEe7Rihc) 
+  [常見架構的資料傳輸成本概觀](https://aws.amazon.com/blogs/architecture/overview-of-data-transfer-costs-for-common-architectures/) 
+  [了解 AWS 容器服務的資料傳輸成本](https://aws.amazon.com/blogs/containers/understanding-data-transfer-costs-for-aws-container-services/) 

# 儲存
<a name="cost-opt-storage"></a>

## 概觀
<a name="_overview"></a>

在某些情況下，您可能想要執行需要短期或長期保留資料的應用程式。對於此類使用案例， Pod 可以定義和掛載磁碟區，以便其容器可以利用不同的儲存機制。Kubernetes 支援不同類型的磁碟[區](https://kubernetes.io/docs/concepts/storage/volumes/)，用於暫時性和持久性儲存。儲存體的選擇主要取決於應用程式需求。對於每種方法，都會有成本影響，以下詳述的實務將協助您在 EKS 環境中需要某種形式的儲存體的工作負載實現成本效益。

## 暫時性容積
<a name="_ephemeral_volumes"></a>

暫時性磁碟區適用於需要暫時性本機磁碟區，但不需要在重新啟動後保留資料的應用程式。此範例包括暫存空間、快取和唯讀輸入資料的需求，例如組態資料和秘密。您可以在[此處](https://kubernetes.io/docs/concepts/storage/ephemeral-volumes/)找到 Kubernetes 暫時性磁碟區的詳細資訊。大多數暫時性磁碟區 （例如 emptyDir、configMap、downwardAPI、秘密、hostpath) 都由本機連接的可寫入裝置 （通常是根磁碟） 或 RAM 提供支援，因此請務必選擇最具成本效益且效能最佳的主機磁碟區。

### 使用 EBS 磁碟區
<a name="_using_ebs_volumes"></a>

 *我們建議從 [gp3](https://aws.amazon.com/ebs/general-purpose/) 開始做為主機根磁碟區。*這是 Amazon EBS 提供的最新一般用途 SSD 磁碟區，相較於 gp2 磁碟區，它也提供較低的每 GB 價格 （最多 20%)。

### 使用 Amazon EC2 執行個體存放區
<a name="_using_amazon_ec2_instance_stores"></a>

 [Amazon EC2 執行個體存放](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/InstanceStorage.html)區為您的 EC2 執行個體提供暫時區塊層級儲存。EC2 執行個體存放區提供的儲存體可透過實體連接至主機的磁碟存取。與 Amazon EBS 不同，您只能在執行個體啟動時連接執行個體存放區磁碟區，而且這些磁碟區只在執行個體的生命週期內存在。它們無法分離並重新連接到其他執行個體。您可以[在這裡](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/InstanceStorage.html)進一步了解 Amazon EC2 執行個體存放區。*執行個體存放區磁碟區沒有相關的額外費用。*這使得它們 （執行個體存放區磁碟區） 比具有大型 EBS 磁碟區的一般 EC2 執行個體*更具成本效益*。

若要在 Kubernetes 中使用本機儲存磁碟區，您應該[使用 Amazon EC2 使用者資料](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-add-user-data.html)分割、設定和格式化磁碟區，以便在 Pod 規格中將磁碟區掛載為 [HostPath](https://kubernetes.io/docs/concepts/storage/volumes/#hostpath)。或者，您可以利用[本機持久性磁碟區靜態佈建器](https://github.com/kubernetes-sigs/sig-storage-local-static-provisioner)來簡化本機儲存管理。本機持久性磁碟區靜態佈建器可讓您透過標準 Kubernetes PersistentVolumeClaim (PVC) 界面存取本機執行個體存放區磁碟區。此外，它會佈建 PersistentVolumes (PVs)，其中包含節點親和性資訊，將 Pod 排程至正確的節點。雖然它使用 Kubernetes PersistentVolumes，但 EC2 執行個體存放區磁碟區本質上是暫時性的。寫入暫時性磁碟的資料只能在執行個體的生命週期內使用。當執行個體終止時，資料也是。如需詳細資訊，請參閱此[部落格](https://aws.amazon.com/blogs/containers/eks-persistent-volumes-for-instance-store/)。

請記住，使用 Amazon EC2 執行個體存放區磁碟區時，總 IOPS 限制會與主機共用，並將 Pod 繫結至特定主機。在採用 Amazon EC2 執行個體存放區磁碟區之前，您應該徹底檢閱工作負載需求。

## 持久性磁碟區
<a name="_persistent_volumes"></a>

Kubernetes 通常與執行中無狀態應用程式相關聯。不過，在某些情況下，您可能想要執行微服務，而這些微服務需要保留從一個請求到下一個請求的持久性資料或資訊。資料庫是這類使用案例的常見範例。不過，Pod 和其中的容器或程序本質上是暫時性的。若要將資料保留超過 Pod 的生命週期，您可以使用 PVs 定義在獨立於 Pod 的特定位置對儲存體的存取。*與 PVs 相關的成本高度取決於使用的儲存體類型，以及應用程式如何使用它。*

[這裡](https://docs.aws.amazon.com/eks/latest/userguide/storage.html)列出支援 Amazon EKS 上 Kubernetes PVs 的不同儲存選項類型。以下涵蓋的儲存選項包括 Amazon EBS、Amazon EFS、Amazon FSx for Lustre、Amazon FSx for NetApp ONTAP。

### Amazon Elastic Block Store (EBS) 磁碟區
<a name="_amazon_elastic_block_store_ebs_volumes"></a>

Amazon EBS 磁碟區可作為 Kubernetes PVs 使用，以提供區塊層級儲存磁碟區。這些非常適合依賴隨機讀取和寫入的資料庫，以及執行長時間連續讀取和寫入的輸送量密集型應用程式。[Amazon Elastic Block Store Container Storage Interface (CSI) 驅動程式](https://docs.aws.amazon.com/eks/latest/userguide/ebs-csi.html)可讓 Amazon EKS 叢集管理持久性磁碟區的 Amazon EBS 磁碟區的生命週期。容器儲存界面可啟用並促進 Kubernetes 與儲存系統之間的互動。當 CSI 驅動程式部署到您的 EKS 叢集時，您可以透過原生 Kubernetes 儲存資源存取其功能，例如持久性磁碟區 (PVs)、持久性磁碟區宣告 (PVCs) 和儲存類別 SCs)。[此連結](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/tree/master/examples/kubernetes)提供如何與 Amazon EBS CSI 驅動程式互動的實用範例。

#### 選擇正確的磁碟區
<a name="_choosing_the_right_volume"></a>

 *我們建議您使用最新一代的區塊儲存 (gp3)，因為它可在價格和效能之間取得適當的平衡*。它還可讓您獨立擴展磁碟區 IOPS 和輸送量，而不需要佈建額外的區塊儲存容量。如果您目前正在使用 gp2 磁碟區，強烈建議遷移至 gp3 磁碟區。部落格文章[將 Amazon EKS 叢集從 gp2 遷移至 gp3 EBS 磁碟區](https://aws.amazon.com/blogs/containers/migrating-amazon-eks-clusters-from-gp2-to-gp3-ebs-volumes/)，說明如何使用需要應用程式停機時間的 CSI [磁碟區快照](https://kubernetes.io/docs/concepts/storage/volume-snapshots/)功能，在 Amazon EKS 叢集**上使用備份和還原從 *gp3* 上的 gp2 遷移。

Amazon EBS 允許變更線上磁碟區大小、IOPS 和輸送量等磁碟區特性。利用此功能，即可使用此[部落格](https://aws.amazon.com/blogs/storage/simplifying-amazon-ebs-volume-migration-and-modification-using-the-ebs-csi-driver/)中所述的任一 PVC 註釋從 *gp3 上的 gp2* 遷移，而無需應用程式停機，這需要 EBS CSI 驅動程式 v1.19.0\$1，或從 Amazon EKS v1.31 和 EBS CSI 驅動程式 1.35 開始，方法是使用[此處](https://aws.amazon.com/blogs/containers/modify-amazon-ebs-volumes-on-kubernetes-with-volume-attributes-classes/)所述的 [VolumeAttributesClass API](https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/)。 **

當您的應用程式需要更高的效能，且所需的磁碟區大於單一 [gp3 磁碟區可支援的磁碟區](https://aws.amazon.com/ebs/general-purpose/)時，您應該考慮使用 [io2 區塊表達](https://aws.amazon.com/ebs/provisioned-iops/)式。這種類型的儲存體非常適合您最大、最密集的 I/O 和關鍵任務部署，例如 SAP HANA 或其他低延遲需求的大型資料庫。請記住，執行個體的 EBS 效能受到執行個體效能限制的限制，因此並非所有執行個體都支援 io2 區塊表達磁碟區。您可以在此[文件中](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/provisioned-iops.html)檢查支援的執行個體類型和其他考量事項。

 *單一 gp3 磁碟區最多可支援 16，000 個最大 IOPS、1，000 MiB/s 最大輸送量、16TiB。最新一代的佈建 IOPS SSD 磁碟區，可提供高達 256，000 IOPS、4，000 MiB/s、輸送量和 64TiB。*

在這些選項中，您應該根據應用程式的需求，量身打造最佳的儲存效能和成本。

#### 隨著時間的推移進行監控和最佳化
<a name="_monitor_and_optimize_over_time"></a>

請務必了解應用程式的基準效能，並針對選取的磁碟區進行監控，以檢查是否符合您的需求/期望，或是過度佈建 （例如，佈建 IOPS 未充分利用的情況）。

您可以在累積資料時逐漸增加磁碟區的大小，而不是從頭開始配置大型磁碟區。您可以使用 Amazon Elastic Block Store CSI 驅動程式 [(aws-ebs-csi-driver) 中的磁碟區調整大小](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/tree/master/examples/kubernetes/resizing)功能動態調整磁碟區大小。 aws-ebs-csi-driver *請記住，您只能增加 EBS 磁碟區大小。*

若要識別和移除任何懸置的 EBS 磁碟區，您可以使用 [AWS 信任顧問的成本最佳化類別](https://docs.aws.amazon.com/awssupport/latest/user/cost-optimization-checks.html)。此功能可協助您識別一段時間內寫入活動極低的未連接磁碟區或磁碟區。有一個雲端原生的開放原始碼唯讀工具，稱為 [Popeye](https://github.com/derailed/popeye)，可掃描即時 Kubernetes 叢集，並報告已部署資源和組態的潛在問題。例如，它可以掃描未使用的 PVs和 PVCs並檢查它們是否繫結，或是否有任何磁碟區掛載錯誤。

如需監控的詳細資訊，請參閱 [EKS 成本最佳化可觀測性指南](https://docs.aws.amazon.com/eks/latest/best-practices/cost-opt-observability.html)。

您可以考慮的另一個選項是 [AWS Compute Optimizer Amazon EBS 磁碟區建議](https://docs.aws.amazon.com/compute-optimizer/latest/ug/view-ebs-recommendations.html)。此工具會自動識別最佳磁碟區組態，以及所需的正確效能等級。例如，它可以根據過去 14 天內的最大使用率，用於與佈建 IOPS、磁碟區大小和 EBS 磁碟區類型相關的最佳設定。它也會量化從其建議衍生的潛在每月成本節省。您可以檢閱此[部落格](https://aws.amazon.com/blogs/storage/cost-optimizing-amazon-ebs-volumes-using-aws-compute-optimizer/)以取得更多詳細資訊。

#### 備份保留政策
<a name="_backup_retention_policy"></a>

您可以透過拍攝point-in-time快照來備份 Amazon EBS 磁碟區上的資料。Amazon EBS CSI 驅動程式支援磁碟區快照。您可以使用[此處](https://github.com/kubernetes-sigs/aws-ebs-csi-driver/blob/master/examples/kubernetes/snapshot/README.md)概述的步驟，了解如何建立快照和還原 EBS PV。

後續快照是增量備份，這表示只會儲存最近快照之後在裝置上變更的區塊。如此無須複製所有資料，可大幅減少建立快照所需的時間，並節省儲存成本。不過，在沒有適當保留政策的情況下增加舊 EBS 快照的數量，可能會導致大規模操作時產生非預期的成本。如果您透過 AWS API 直接備份 Amazon EBS 磁碟區，則可以利用 [Amazon Data Lifecycle Manager](https://aws.amazon.com/ebs/data-lifecycle-manager/) (DLM)，為 Amazon Elastic Block Store (EBS) 快照和 EBS 支援的 Amazon Machine Image (AMIs) 提供自動化的政策型生命週期管理解決方案。主控台可讓您更輕鬆地自動建立、保留和刪除 EBS 快照和 AMIs。

**注意**  
目前無法透過 Amazon EBS CSI 驅動程式使用 Amazon DLM。

在 Kubernetes 環境中，您可以利用名為 [Velero](https://velero.io/) 的開放原始碼工具來備份 EBS 持久性磁碟區。您可以在排程任務使備份過期時設定 TTL 旗標。以下是來自 Velero 的[指南](https://velero.io/docs/v1.12/how-velero-works/#set-a-backup-to-expire)範例。

### Amazon Elastic File System
<a name="_amazon_elastic_file_system_efs"></a>

 [Amazon Elastic File System (EFS)](https://aws.amazon.com/efs/) 是一種無伺服器、全彈性的檔案系統，可讓您使用標準檔案系統界面和檔案系統語意來共用檔案資料，以處理廣泛的工作負載和應用程式。工作負載和應用程式的範例包括 Wordpress 和 Drupal、JIRA 和 Git 等開發人員工具，以及 Jupyter 等共用筆記本系統以及主目錄。

Amazon EFS 的主要優點之一是，它可以由分散在多個節點和多個可用區域的多個容器掛載。另一個好處是您只需為所使用的儲存體付費。當您新增和移除不需要容量規劃的檔案時，EFS 檔案系統會自動成長和縮減。

若要在 Kubernetes 中使用 Amazon EFS，您需要使用 Amazon Elastic File System Container Storage Interface (CSI) Driver， [aws-efs-csi-driver](https://github.com/kubernetes-sigs/aws-efs-csi-driver)。目前，驅動程式可以動態建立[存取點](https://docs.aws.amazon.com/efs/latest/ug/efs-access-points.html)。不過，必須先佈建 Amazon EFS 檔案系統，並提供 做為 Kubernetes 儲存類別參數的輸入。

#### 選擇正確的 EFS 儲存類別
<a name="_choosing_the_right_efs_storage_class"></a>

Amazon EFS 提供[四個儲存類別](https://docs.aws.amazon.com/efs/latest/ug/storage-classes.html)。

兩個標準儲存類別：
+ Amazon EFS 標準
+  [Amazon EFS Standard-Infrequent Access](https://aws.amazon.com/blogs/aws/optimize-storage-cost-with-reduced-pricing-for-amazon-efs-infrequent-access/) (EFS Standard-IA)

兩個單區域儲存類別：
+  [Amazon EFS 單區域](https://aws.amazon.com/blogs/aws/new-lower-cost-one-zone-storage-classes-for-amazon-elastic-file-system/) 
+ Amazon EFS One Zone-Infrequent Access (EFS One Zone-IA)

不常存取 (IA) 儲存類別針對未每天存取的檔案進行成本最佳化。透過 Amazon EFS 生命週期管理，您可以將生命週期政策期間 (7、14、30、60 或 90 天） 未存取的檔案移至 IA 儲存類別*，相較於 EFS Standard 和 EFS One Zone 儲存類別，這些儲存類別分別可將儲存成本降低高達 92%*。

透過 EFS Intelligent-Tiering，生命週期管理會監控檔案系統的存取模式，並自動將檔案移至最佳的儲存類別。

**注意**  
aws-efs-csi-driver 目前無法控制變更儲存類別、生命週期管理或 Intelligent-Tiering。這些應該在 AWS 主控台或透過 EFS APIs 手動設定。

**注意**  
aws-efs-csi-driver 與以視窗為基礎的容器映像不相容。

**注意**  
由於 [DiskUsage](https://github.com/kubernetes/kubernetes/blob/ee265c92fec40cd69d1de010b477717e4c142492/pkg/volume/util/fs/fs.go#L66) 函數會耗用與檔案系統大小成比例的記憶體量，因此啟用 *vol-metrics-opt-in* （發射磁碟區指標） 時，存在已知的記憶體問題。*目前，我們建議在大型檔案系統上停用* *`--vol-metrics-opt-in` 選項，以避免耗用太多記憶體。以下是 github 問題[連結](https://github.com/kubernetes-sigs/aws-efs-csi-driver/issues/1104)，以取得更多詳細資訊。*

### Amazon FSx for Lustre
<a name="_amazon_fsx_for_lustre"></a>

Lustre 是一種高效能平行檔案系統，通常用於需要高達數百 GB/秒輸送量和每次操作延遲低於毫秒的工作負載。它用於機器學習訓練、財務建模、HPC 和影片處理等案例。[Amazon FSx for Lustre](https://aws.amazon.com/fsx/lustre/) 提供具有可擴展性和效能的全受管共用儲存體，與 Amazon S3 無縫整合。

您可以使用 FSx for Lustre 支援的 Kubernetes 持久性儲存磁碟區，使用 Amazon EKS 的 [FSx for Lustre CSI 驅動程式](https://github.com/kubernetes-sigs/aws-fsx-csi-driver)或 AWS 上的自我管理 Kubernetes 叢集。如需詳細資訊和範例，請參閱 [Amazon EKS 文件](https://docs.aws.amazon.com/eks/latest/userguide/fsx-csi.html)。

#### Amazon S3 的連結
<a name="_link_to_amazon_s3"></a>

建議將位於 Amazon S3 上的高耐用性長期資料儲存庫與您的 FSx for Lustre 檔案系統連結。一旦連結，大型資料集會視需要從 Amazon S3 延遲載入至 FSx for Lustre 檔案系統。您也可以執行分析並將結果傳回 S3，然後刪除 Lustre 檔案系統。

#### 選擇正確的部署和儲存選項
<a name="_choosing_the_right_deployment_and_storage_options"></a>

FSx for Lustre 提供不同的部署選項。第一個選項稱為*暫存*，不會複寫資料，而第二個選項稱為*持久*性，顧名思義，會保留資料。

第一個選項 *（速記*) 可用來*降低暫時性短期資料處理的成本。*持久性部署選項*是專為長期儲存而設計*，可自動複寫 AWS 可用區域內的資料。它還支援 SSD 和 HDD 儲存。

您可以在 FSx 中的參數下，為 lustre 檔案系統的 Kubernetes StorageClass 設定所需的部署類型。以下是提供範例範本[的連結](https://github.com/kubernetes-sigs/aws-fsx-csi-driver/tree/master/examples/kubernetes/dynamic_provisioning#edit-storageclass)。

**注意**  
對於對延遲敏感的工作負載或需要最高 IOPS/輸送量層級的工作負載，您應該選擇 SSD 儲存。對於不對延遲敏感的以輸送量為中心的工作負載，您應該選擇 HDD 儲存。

#### 啟用資料壓縮
<a name="_enable_data_compression"></a>

您也可以指定「LZ4」為資料壓縮類型，在檔案系統上啟用資料壓縮。啟用後，所有新寫入的檔案都會在 FSx for Lustre 上自動壓縮，再寫入磁碟，並在讀取時解壓縮。LZ4 資料壓縮演算法無失真，因此原始資料可以從壓縮資料完全重建。

您可以在 FSx 中 lustre 檔案系統的 Kubernetes StorageClass 的參數下，將資料壓縮類型設定為 LZ4。當值設定為 NONE 時，壓縮會停用，這是預設值。[此連結](https://github.com/kubernetes-sigs/aws-fsx-csi-driver/tree/master/examples/kubernetes/dynamic_provisioning#edit-storageclass)提供範例範本。

**注意**  
Amazon FSx for Lustre 與以視窗為基礎的容器映像不相容。

### Amazon FSx for NetApp ONTAP
<a name="_amazon_fsx_for_netapp_ontap"></a>

 [Amazon FSx for NetApp ONTAP](https://aws.amazon.com/fsx/netapp-ontap/) 是建置在 NetApp ONTAP 檔案系統的全受管共用儲存體。FSx for ONTAP 提供功能豐富、快速且靈活的共用檔案儲存，可從 AWS 或內部部署中執行的 Linux、Windows 和 macOS 運算執行個體廣泛存取。

Amazon FSx for NetApp ONTAP 支援兩個儲存層：*1/主要層*和 *2/容量集區層。*

*主要層*是佈建的高效能 SSD 型層，用於主動、延遲敏感的資料。全彈性*容量集區層*針對不常存取的資料進行成本最佳化、隨著資料分層而自動擴展，並提供幾乎無限制的 PB 容量。您可以在容量集區儲存上啟用資料壓縮和重複資料刪除，並進一步減少資料使用的儲存容量。NetApp 的原生政策型 FabricPool 功能會持續監控資料存取模式，並在儲存層之間自動雙向傳輸資料，以最佳化效能和成本。

NetApp 的 Astra Trident 使用 CSI 驅動程式提供動態儲存協同運作，可讓 Amazon EKS 叢集管理 Amazon FSx for NetApp ONTAP 檔案系統支援的持久性磁碟區 PVs 生命週期。若要開始使用，請參閱 Astra Trident 文件中的[使用 Astra Trident 與 Amazon FSx for NetApp ONTAP](https://docs.netapp.com/us-en/trident/trident-use/trident-fsx.html)。

## 其他考量
<a name="_other_considerations"></a>

### 最小化容器映像的大小
<a name="_minimize_the_size_of_container_image"></a>

部署容器後，容器映像會以多層的形式快取在主機上。透過減少映像的大小，可以減少主機上所需的儲存量。

透過從頭開始使用縮減的基礎映像，例如暫存映像或[無痕](https://github.com/GoogleContainerTools/distroless)容器映像 （僅包含您的應用程式及其執行時間相依性），*除了減少攻擊表面積和縮短映像提取時間等輔助優點之外，您還可以降低儲存成本。*

您也應該考慮使用開放原始碼工具，例如 [Slim.ai](https://www.slim.ai/docs/quickstart)，提供簡單、安全的方式來建立最少的映像。

多層套件、工具、應用程式相依性、程式庫可以輕鬆膨脹容器映像大小。透過使用多階段組建，您可以選擇性地將成品從一個階段複製到另一個階段，排除最終映像中不需要的所有項目。您可以在[此處](https://docs.docker.com/get-started/09_image_best/)查看更多映像建置最佳實務。

要考慮的另一件事是保留快取映像的時間。使用特定磁碟量時，您可能想要清除映像快取中的過時映像。這樣做有助於確保您有足夠的空間進行主機操作。根據預設， [kubelet](https://kubernetes.io/docs/reference/generated/kubelet) 每五分鐘對未使用的映像和每分鐘未使用的容器執行垃圾收集。

 *若要為未使用的容器和映像垃圾收集設定選項，請使用[組態檔案](https://kubernetes.io/docs/tasks/administer-cluster/kubelet-config-file/)調整 kubelet，並使用 [https://kubernetes.io/docs/reference/config-api/kubelet-config.v1beta1/](https://kubernetes.io/docs/reference/config-api/kubelet-config.v1beta1/) 資源類型變更與垃圾收集相關的參數。*

您可以在 Kubernetes [文件](https://kubernetes.io/docs/concepts/architecture/garbage-collection/#containers-images)中進一步了解。

# 可觀測性
<a name="cost-opt-observability"></a>

## 簡介
<a name="_introduction"></a>

可觀測性工具可協助您有效率地偵測、修復和調查工作負載。遙測資料的成本會隨著您使用 EKS 而自然增加。有時，平衡您的營運需求並衡量對業務重要的事項，以及控制可觀測性成本可能很困難。本指南著重於可觀測性的三個支柱的成本最佳化策略：日誌、指標和追蹤。這些最佳實務都可以獨立套用，以符合組織的最佳化目標。

## 日誌
<a name="_logging"></a>

記錄在監控和故障診斷叢集中的應用程式時扮演重要角色。有多種策略可用來最佳化記錄成本。下列最佳實務策略包括檢查您的日誌保留政策，以實作日誌資料保留的時間長度、根據重要性將日誌資料傳送至不同的儲存選項，以及使用日誌篩選來縮小儲存日誌訊息的類型。有效管理日誌遙測可為您的環境節省成本。

## EKS 控制平面
<a name="_eks_control_plane"></a>

### 最佳化您的控制平面日誌
<a name="_optimize_your_control_plane_logs"></a>

Kubernetes 控制平面是一組[管理叢集的元件](https://kubernetes.io/docs/concepts/overview/components/#control-plane-components)，這些元件會將不同類型的資訊做為日誌串流傳送至 [Amazon CloudWatch](https://aws.amazon.com/cloudwatch/) 中的日誌群組。雖然啟用所有控制平面日誌類型都有好處，但您應該了解每個日誌中的資訊，以及存放所有日誌遙測的相關費用。您需支付從叢集傳送至 Amazon [CloudWatch Logs 之日誌的標準 CloudWatch Logs 資料擷取和儲存成本](https://aws.amazon.com/cloudwatch/pricing/)。 Amazon CloudWatch 在啟用它們之前，請評估每個日誌串流是否必要。

例如，在非生產叢集中，選擇性地啟用特定日誌類型，例如 api 伺服器日誌，僅用於分析和之後停用。但是，對於生產叢集，您可能無法重現事件，並解決問題需要更多日誌資訊，則您可以啟用所有日誌類型。進一步的控制平面成本最佳化實作詳細資訊請參閱此[部落格](https://aws.amazon.com/blogs/containers/understanding-and-cost-optimizing-amazon-eks-control-plane-logs/)文章。

#### 將日誌串流至 S3
<a name="_stream_logs_to_s3"></a>

另一個成本最佳化最佳實務是透過 CloudWatch Logs 訂閱將控制平面日誌串流至 S3。利用 CloudWatch Logs [訂閱](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/Subscriptions.html)可讓您選擇性地將日誌轉送至 S3，相較於在 CloudWatch 中無限期保留日誌，它可提供更具成本效益的長期儲存。例如，對於生產叢集，您可以建立關鍵日誌群組，並在 15 天後利用訂閱將這些日誌串流到 S3。這將確保您能夠快速存取日誌以供分析，但也可以將日誌移至更具成本效益的儲存體，以節省成本。

**重要**  
自 9/5/2023 起，EKS 日誌在 Amazon CloudWatch Logs 中歸類為 Vended Logs。已終止的日誌是特定 AWS 服務日誌，由 AWS 服務代表客戶原生發佈，並可用於磁碟區折扣定價。請造訪 [Amazon CloudWatch 定價頁面](https://aws.amazon.com/cloudwatch/pricing/)，以進一步了解 Vended Logs 定價。

## EKS 資料平面
<a name="_eks_data_plane"></a>

### 日誌保留
<a name="_log_retention"></a>

Amazon CloudWatch 的預設保留政策是無限期保留日誌，永遠不會過期，因此產生適用於您 AWS 區域的儲存成本。為了降低儲存成本，您可以根據您的工作負載需求，為每個日誌群組自訂保留政策。

在開發環境中，可能不需要較長的保留期。但在生產環境中，您可以設定更長的保留政策，以滿足故障診斷、合規和容量規劃需求。例如，如果您在尖峰假日期間執行電子商務應用程式，系統負載會比較重，而且可能會出現可能無法立即注意到的問題，則建議您設定較長的日誌保留時間，以進行詳細的故障診斷和事件後分析。

您可以在 AWS CloudWatch 主控台或 [AWS API](https://docs.aws.amazon.com/cli/latest/reference/logs/put-retention-policy.html) 中[設定保留期間](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/Working-with-log-groups-and-streams.html#SettingLogRetention)，根據每個日誌群組，保留期間從 1 天到 10 年。擁有彈性的保留期間可以節省日誌儲存成本，同時維護關鍵日誌。

### 日誌儲存選項
<a name="_log_storage_options"></a>

儲存是可觀測性成本的一大驅動因素，因此最佳化日誌儲存策略至關重要。您的策略應與您的工作負載需求保持一致，同時維持效能和可擴展性。降低日誌儲存成本的一個策略是利用 AWS S3 儲存貯體及其不同的儲存層。

#### 將日誌直接轉送至 S3
<a name="_forward_logs_directly_to_s3"></a>

考慮將較不重要的日誌直接轉送至 S3，而非 Cloudwatch。這可能會對日誌儲存成本產生立即影響。其中一個選項是使用 Fluentbit 直接將日誌轉送至 S3。您可以在 `[OUTPUT]`區段中定義此項目，也就是 FluentBit 傳輸容器日誌以進行保留的目的地。[在此處](https://docs.fluentbit.io/manual/pipeline/outputs/s3#worker-support)檢閱其他組態參數。

```
[OUTPUT]
        Name eks_to_s3
        Match application.*
        bucket $S3_BUCKET name
        region us-east-2
        store_dir /var/log/fluentbit
        total_file_size 30M
        upload_timeout 3m
```

#### 僅將日誌轉送至 CloudWatch 進行短期分析
<a name="_forward_logs_to_cloudwatch_only_for_short_term_analysis"></a>

如需更關鍵的日誌，例如您可能需要立即對資料執行分析的生產環境，請考慮將日誌轉送至 CloudWatch。您可以在 `[OUTPUT]`區段中定義此項目，也就是 FluentBit 傳輸容器日誌以進行保留的目的地。[在此處](https://docs.fluentbit.io/manual/pipeline/outputs/cloudwatch)檢閱其他組態參數。

```
[OUTPUT]
        Name eks_to_cloudwatch_logs
        Match application.*
        region us-east-2
        log_group_name fluent-bit-cloudwatch
        log_stream_prefix from-fluent-bit-
        auto_create_group On
```

不過，這不會對您的成本節省造成立即影響。若要節省更多成本，您必須將這些日誌匯出至 Amazon S3。

#### 從 CloudWatch 匯出至 Amazon S3
<a name="_export_to_amazon_s3_from_cloudwatch"></a>

若要長期存放 Amazon CloudWatch logs，建議您將 Amazon EKS CloudWatch 日誌匯出至 Amazon Simple Storage Service (Amazon S3)。您可以透過[主控台](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/S3ExportTasksConsole.html)或 API 建立匯出任務，將日誌轉送至 Amazon S3 儲存貯體。完成後，Amazon S3 會呈現許多選項，以進一步降低成本。您可以定義自己的 [Amazon S3 生命週期規則](https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-lifecycle-mgmt.html)，將日誌移至符合您需求的儲存類別，或利用 [Amazon S3 Intelligent-Tiering](https://aws.amazon.com/s3/storage-classes/intelligent-tiering/) 儲存類別，讓 AWS 根據您的使用模式自動將資料移至長期儲存。如需詳細資訊，請參閱此[部落格](https://aws.amazon.com/blogs/containers/understanding-and-cost-optimizing-amazon-eks-control-plane-logs/)。例如，對於您的生產環境日誌， 會在 CloudWatch 中存放超過 30 天，然後匯出至 Amazon S3 儲存貯體。然後，如果您稍後需要參考日誌，您可以使用 Amazon Athena 查詢 Amazon S3 儲存貯體中的資料。

### 降低日誌層級
<a name="_reduce_log_levels"></a>

為您的應用程式練習選擇性記錄。根據預設，您的應用程式和節點都會輸出日誌。針對您的應用程式日誌，調整日誌層級以符合工作負載和環境的關鍵性。例如，以下 java 應用程式正在輸出`INFO`日誌，這是典型的預設應用程式組態，根據程式碼，可能會導致大量的日誌資料。

```
import org.apache.log4j.*;

public class LogClass {
   private static org.apache.log4j.Logger log = Logger.getLogger(LogClass.class);

public static void main(String[] args) {
      log.setLevel(Level.INFO);

   log.debug("This is a DEBUG message, check this out!");
   log.info("This is an INFO message, nothing to see here!");
   log.warn("This is a WARN message, investigate this!");
   log.error("This is an ERROR message, check this out!");
   log.fatal("This is a FATAL message, investigate this!");    } }
```

在開發環境中，將日誌層級變更為 `DEBUG`，因為這可協助您在問題進入生產環境之前進行偵錯或擷取潛在問題。

```
      log.setLevel(Level.DEBUG);
```

在生產環境中，請考慮將日誌層級修改為 `ERROR`或 `FATAL`。這只會在您的應用程式發生錯誤時輸出日誌、減少日誌輸出，並協助您專注於應用程式狀態的重要資料。

```
      log.setLevel(Level.ERROR);
```

您可以微調各種 Kubernetes 元件日誌層級。例如，如果您使用 [Bottlerocket](https://bottlerocket.dev/) 做為 EKS 節點作業系統，則有組態設定可讓您調整 kubelet 程序日誌層級。此組態設定的程式碼片段如下。請注意預設[日誌層級](https://github.com/bottlerocket-os/bottlerocket/blob/3f716bd68728f7fd825eb45621ada0972d0badbb/README.md?plain=1#L528) **2**，其會調整`kubelet`程序的記錄詳細程度。

```
[settings.kubernetes]
log-level = "2"
image-gc-high-threshold-percent = "85"
image-gc-low-threshold-percent = "80"
```

對於開發環境，您可以設定大於 **2** 的日誌層級，以檢視其他事件，這非常適合偵錯。對於生產環境，您可以將關卡設定為 **0**，以便僅檢視關鍵事件。

### 利用篩選條件
<a name="_leverage_filters"></a>

使用預設的 EKS Fluentbit 組態將容器日誌傳送至 Cloudwatch 時，FluentBit 會擷取並傳送充實 Kubernetes 中繼資料**的所有**應用程式容器日誌至 Cloudwatch，如以下`[INPUT]`組態區塊所示。

```
 [INPUT]
     Name                tail
     Tag                 application.*
     Exclude_Path        /var/log/containers/cloudwatch-agent*, /var/log/containers/fluent-bit*, /var/log/containers/aws-node*, /var/log/containers/kube-proxy*
     Path                /var/log/containers/*.log
     Docker_Mode         On
     Docker_Mode_Flush   5
     Docker_Mode_Parser  container_firstline
     Parser              docker
     DB                  /var/fluent-bit/state/flb_container.db
     Mem_Buf_Limit       50MB
     Skip_Long_Lines     On
     Refresh_Interval    10
     Rotate_Wait         30
     storage.type        filesystem
     Read_from_Head      ${READ_FROM_HEAD}
```

上述`[INPUT]`區段正在擷取所有容器日誌。這可能會產生可能不需要的大量資料。篩選此資料可減少傳送至 CloudWatch 的日誌資料量，因此可降低成本。您可以將篩選條件套用到日誌，然後再輸出到 CloudWatch。Fluentbit 會在 `[FILTER]`區段中定義此項目。例如，篩選掉 Kubernetes 中繼資料，使其無法附加到日誌事件，可能會降低您的日誌磁碟區。

```
    [FILTER]
        Name                nest
        Match               application.*
        Operation           lift
        Nested_under        kubernetes
        Add_prefix          Kube.

    [FILTER]
        Name                modify
        Match               application.*
        Remove              Kube.<Metadata_1>
        Remove              Kube.<Metadata_2>
        Remove              Kube.<Metadata_3>

    [FILTER]
        Name                nest
        Match               application.*
        Operation           nest
        Wildcard            Kube.*
        Nested_under        kubernetes
        Remove_prefix       Kube.
```

## 指標
<a name="_metrics"></a>

 [指標](https://aws-observability.github.io/observability-best-practices/signals/metrics/)提供有關系統效能的寶貴資訊。透過將所有與系統相關或可用的資源指標合併到集中位置，您可以獲得比較和分析效能資料的功能。這種集中式方法可讓您做出更明智的策略決策，例如擴展或縮減資源。此外，指標在評估資源的運作狀態方面扮演重要角色，可讓您在必要時採取主動措施。一般而言，可觀測性成本會隨著遙測資料收集和保留而擴展。您可以實作以下幾個策略來降低指標遙測的成本：僅收集重要的指標、降低遙測資料的基數，以及微調遙測資料收集的精細程度。

### 監控重要事項，並僅收集您需要的項目
<a name="_monitor_what_matters_and_collect_only_what_you_need"></a>

第一個降低成本策略是減少您正在收集的指標數量，進而降低保留成本。

1. 首先，從您和/或利益相關者的要求向後工作，以確定[最重要的指標](https://aws-observability.github.io/observability-best-practices/guides/#monitor-what-matters)。每個人的成功指標都不同！知道什麼是*好*東西，並對其進行測量。

1. 考慮深入探索您支援的工作負載，並識別其關鍵效能指標 (KPIs) a.k.a 'Golden Signals'。這些應符合業務和利益相關者要求。使用 Amazon CloudWatch 和指標數學計算 SLIs、SLOs 和 SLAs，對於管理服務可靠性至關重要。遵循[本指南](https://aws-observability.github.io/observability-best-practices/guides/operational/business/key-performance-indicators/#10-understanding-kpis-golden-signals)中概述的最佳實務，以有效監控和維護 EKS 環境的效能。

1. 然後，繼續瀏覽不同層級的基礎設施，以[連接 EKS 叢集、節點和其他基礎設施指標，並將其與工作負載 KPI 建立關聯](https://aws-observability.github.io/observability-best-practices/signals/metrics/#correlate-with-operational-metric-data)。 KPIs 將您的業務指標和操作指標存放在系統中，您可以將它們關聯在一起，並根據觀察到的對兩者的影響得出結論。

1. EKS 從控制平面、叢集 kube-state-metrics、Pod 和節點公開指標。所有這些指標的相關性取決於您的需求，但您可能不需要跨不同層的每個指標。您可以使用此 [EKS 基本指標](https://aws-observability.github.io/observability-best-practices/guides/containers/oss/eks/best-practices-metrics-collection/)指南做為基準，以監控 EKS 叢集和工作負載的整體運作狀態。

以下是 Prometheus 抓取組態的範例，其中我們使用 `relabel_config`來僅保留 kubelet 指標`metric_relabel_config`，並捨棄所有容器指標。

```
  kubernetes_sd_configs:
  - role: endpoints
    namespaces:
      names:
      - kube-system
  bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
  tls_config:
    insecure_skip_verify: true
  relabel_configs:
  - source_labels: [__meta_kubernetes_service_label_k8s_app]
    regex: kubelet
    action: keep

  metric_relabel_configs:
  - source_labels: [__name__]
    regex: container_(network_tcp_usage_total|network_udp_usage_total|tasks_state|cpu_load_average_10s)
    action: drop
```

### 如適用，減少基數
<a name="_reduce_cardinality_where_applicable"></a>

基數是指資料值的唯一性及其特定指標集的維度 （例如 Prometheus 標籤）。高基數指標有許多維度，每個維度指標組合都有更高的唯一性。較高的基數會導致較大的指標遙測資料大小和儲存需求，進而增加成本。

在下面的高基數範例中，我們看到 指標、延遲、 具有維度、RequestID、CustomerID 和 Service，而且每個維度都有許多唯一的值。Cardinality 是每個維度可能值的組合。在 Prometheus 中，每組唯一維度/標籤都視為新的指標，因此高基數表示更多的指標。

在每個指標具有許多指標和維度/標籤的 EKS 環境中 （叢集、命名空間、服務、Pod、容器等），基數通常會增加。為了最佳化成本，請仔細考慮您正在收集的指標基數。例如，如果您要彙總叢集層級視覺化的特定指標，則可以捨棄位於較低圖層的其他標籤，例如命名空間標籤。

為了識別 prometheus 中的高基數指標，您可以執行下列 PROMQL 查詢，以判斷哪些抓取目標具有最多指標 （基數）：

```
topk_max(5, max_over_time(scrape_samples_scraped[1h]))
```

和下列 PROMQL 查詢可協助您判斷哪些抓取目標具有最高的指標流失 （在指定的抓取中建立了多少個新指標系列） 率：

```
topk_max(5, max_over_time(scrape_series_added[1h]))
```

如果您使用的是 grafana，則可以使用 Grafana Lab 的 Mimirtool 來分析您的 grafana 儀表板和 prometheus 規則，以識別未使用的高基數指標。請遵循[本指南](https://grafana.com/docs/grafana-cloud/account-management/billing-and-usage/control-prometheus-metrics-usage/usage-analysis-mimirtool/?pg=blog&plcmt=body-txt#analyze-and-reduce-metrics-usage-with-grafana-mimirtool)，了解如何使用 `mimirtool analyze`和 `mimirtool analyze prometheus`命令來識別儀表板中未參考的作用中指標。

### 考慮指標精細度
<a name="_consider_metric_granularity"></a>

以更高的精細度收集指標，例如每秒與每分鐘，可能會對收集和存放多少遙測產生重大影響，進而增加成本。判斷合理的抓取或指標收集間隔，在足夠的精細程度之間取得平衡，以查看暫時性問題，並降低到足以符合成本效益的程度。減少用於容量規劃和較大時段分析的指標精細度。

以下是預設 AWS Distro for Opentelemetry (ADOT) EKS 附加元件收集器[組態](https://docs.aws.amazon.com/eks/latest/userguide/deploy-deployment.html)的程式碼片段。

**重要**  
全域 Prometheus 抓取間隔設定為 15 秒。此抓取間隔可能會增加，導致 Prometheus 中收集的指標資料量減少。

```
apiVersion: opentelemetry.io/v1alpha1
kind: OpenTelemetryCollector
metadata:
  name: my-collector-amp

...

config: |
    extensions:
      sigv4auth:
        region: "+++<YOUR_AWS_REGION>+++" service: "aps"+++</YOUR_AWS_REGION>+++

 receivers:
   #
   # Scrape configuration for the Prometheus Receiver
   # This is the same configuration used when Prometheus is installed using the community Helm chart
   #
   prometheus:
     config:
       global:   scrape_interval: 15s
         scrape_timeout: 10s
```

## 追蹤
<a name="_tracing"></a>

與追蹤相關的主要成本來自追蹤儲存產生。透過追蹤，目標是收集足夠的資料來診斷和了解效能層面。不過，由於 X-Ray 追蹤成本是以轉送至 X-Ray 的資料為基礎，因此在轉送之後清除追蹤不會降低您的成本。讓我們檢閱降低追蹤成本的方法，同時維護資料以執行適當的分析。

### 套用取樣規則
<a name="_apply_sampling_rules"></a>

根據預設，X-Ray 取樣率是保守的。定義抽樣規則，您可以在其中控制收集的資料量。這將提高效能效率，同時降低成本。透過[降低取樣率](https://docs.aws.amazon.com/xray/latest/devguide/xray-console-sampling.html#xray-console-custom)，您可以從請求中收集追蹤，只需工作負載所需的項目，同時維持較低的成本結構。

例如，您有 java 應用程式，您想要偵錯 1 個有問題路由之所有請求的追蹤。

 **透過 SDK 設定 ，從 JSON 文件載入抽樣規則** 

```
{
"version": 2,
  "rules": [
    {
"description": "debug-eks",
      "host": "*",
      "http_method": "PUT",
      "url_path": "/history/*",
      "fixed_target": 0,
      "rate": 1,
      "service_type": "debug-eks"
    }
  ],
  "default": {
"fixed_target": 1,
    "rate": 0.1
  }
}
```

 **透過主控台** 

### 使用 AWS Distro for OpenTelemetry (ADOT) 套用尾部取樣
<a name="_apply_tail_sampling_with_aws_distro_for_opentelemetry_adot"></a>

ADOT Tail Sampling 可讓您控制服務中擷取的追蹤量。不過， Tail Sampling 可讓您在請求中的所有範圍都完成後定義抽樣政策，而不是從頭開始。這進一步限制了傳輸到 CloudWatch 的原始資料量，進而降低成本。

例如，如果您要取樣 1% 的流量到登陸頁面，以及 10% 的請求到付款頁面，這可能會在 30 分鐘內讓您有 300 個追蹤。使用篩選特定錯誤的 ADOT Tail 取樣規則，您可以保留 200 個追蹤，以減少儲存的追蹤數量。

```
processors:
  groupbytrace:
    wait_duration: 10s
    num_traces: 300
    tail_sampling:
    decision_wait: 1s # This value should be smaller than wait_duration
    policies:
      - ..... # Applicable policies**
  batch/tracesampling:
    timeout: 0s # No need to wait more since this will happen in previous processors
    send_batch_max_size: 8196 # This will still allow us to limit the size of the batches sent to subsequent exporters

service:
  pipelines:
    traces/tailsampling:
      receivers: [otlp]
      processors: [groupbytrace, tail_sampling, batch/tracesampling]
      exporters: [awsxray]
```

### 利用 Amazon S3 Storage 選項
<a name="_leverage_amazon_s3_storage_options"></a>

您應該利用 AWS S3 儲存貯體及其不同的儲存類別來存放追蹤。在保留期間到期之前，將追蹤匯出至 S3。使用 Amazon S3 生命週期規則，將追蹤資料移至符合您需求的儲存類別。

例如，如果您有 90 天的追蹤，[Amazon S3 Intelligent-Tiering ](https://aws.amazon.com/s3/storage-classes/intelligent-tiering/)可以根據您的使用模式自動將資料移至長期儲存。如果您需要稍後再參考追蹤，您可以使用 [Amazon Athena](https://aws.amazon.com/athena/) 查詢 Amazon S3 中的資料。這可以進一步降低分散式追蹤的成本。

## 其他資源：
<a name="_additional_resources"></a>
+  [可觀測性最佳實務指南](https://aws-observability.github.io/observability-best-practices/guides/) 
+  [最佳實務指標集合](https://aws-observability.github.io/observability-best-practices/guides/containers/oss/eks/) 
+  [AWS re：Invent 2022 - Amazon (COP343) 的可觀測性最佳實務](https://www.youtube.com/watch?v=zZPzXEBW4P8) 
+  [AWS re：Invent 2022 - 可觀測性：現代應用程式的最佳實務 (COP344)](https://www.youtube.com/watch?v=YiegAlC_yyc) 