

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

# 工作負載
<a name="scale-workloads"></a>

工作負載會影響叢集可以擴展的大小。使用 Kubernetes APIs工作負載會大幅限制您在單一叢集中可以擁有的工作負載總數，但您可以變更一些預設值，以協助減少負載。

Kubernetes 叢集中的工作負載可存取與 Kubernetes API 整合的功能 （例如 Secrets 和 ServiceAccounts)，但這些功能並非一律必要，如果未使用，則應停用。限制工作負載存取和對 Kubernetes 控制平面的依賴，將增加您可以在叢集中執行的工作負載數量，並透過移除不必要的工作負載存取並實作最低權限實務來提高叢集的安全性。如需詳細資訊，請參閱[安全最佳實務](https://docs.aws.amazon.com/eks/latest/best-practices/security.html)。

## 使用 IPv6 進行 Pod 聯網
<a name="_use_ipv6_for_pod_networking"></a>

您無法將 VPC 從 IPv4 轉換為 IPv6，因此在佈建叢集之前啟用 IPv6 非常重要。如果您在 VPC 中啟用 IPv6，並不表示您必須使用它，而且如果您的 Pod 和服務使用 IPv6，您仍然可以路由往返 IPv4 地址的流量。如需詳細資訊，請參閱 [EKS 聯網最佳實務](https://docs.aws.amazon.com/eks/latest/best-practices/networking.html)。

在[叢集中使用 IPv6 ](https://docs.aws.amazon.com/eks/latest/userguide/cni-ipv6.html) 可避免一些最常見的叢集和工作負載擴展限制。IPv6 可避免因沒有可用的 IP 地址而無法建立 Pod 和節點的 IP 地址耗盡。它也改善了每個節點的效能，因為 Pod 透過減少每個節點的 ENI 附件數量，更快地接收 IP 地址。您可以在 [VPC CNI 中使用 IPv4 字首模式](https://docs.aws.amazon.com/eks/latest/best-practices/prefix-mode-linux.html)來實現類似的節點效能，但您仍然需要確保 VPC 中有足夠的 IP 地址可用。

## 限制每個命名空間的服務數量
<a name="_limit_number_of_services_per_namespace"></a>

[命名空間中的服務數量上限為 5，000，叢集中的服務數量上限為 10，000](https://github.com/kubernetes/community/blob/master/sig-scalability/configs-and-limits/thresholds.md)。為了協助組織工作負載和服務、提高效能，並避免命名空間範圍資源的層疊影響，我們建議將每個命名空間的服務數量限制為 500。

使用 kube-proxy 為每個節點建立的 IP 資料表規則數量會隨著叢集中的服務總數而增加。產生數千個 IP 資料表規則並透過這些規則路由封包會對節點產生效能影響，並新增網路延遲。

建立包含單一應用程式環境的 Kubernetes 命名空間，只要每個命名空間的服務數量低於 500。這將使服務探索夠小，以避免服務探索限制，也可以協助您避免服務命名衝突。應用程式環境 （例如 dev、test、prod) 應該使用單獨的 EKS 叢集，而不是命名空間。

## 了解 Elastic Load Balancer 配額
<a name="_understand_elastic_load_balancer_quotas"></a>

建立服務時，請考慮您將使用的負載平衡類型 （例如 Network Load Balancer (NLB) 或 Application Load Balancer (ALB))。每個負載平衡器類型都提供不同的功能，並具有[不同的配額](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-limits.html)。某些預設配額可以調整，但有一些配額上限無法變更。若要檢視您的帳戶配額和用量，請在 AWS 主控台中檢視 [Service Quotas 儀表板](https://console.aws.amazon.com/servicequotas)。

例如，預設的 ALB 目標為 1000。如果您有超過 1000 個端點的服務，則需要增加配額或將服務分割到多個 ALBs 或使用 Kubernetes Ingress。預設 NLB 目標為 3000，但每個 AZ 限制為 500 個目標。如果您的叢集為 NLB 服務執行超過 500 個 Pod，您將需要使用多個 AZs 或請求提高配額限制。

使用與服務耦合的負載平衡器的替代方案是使用[輸入控制器](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/)。AWS Load Balancer 控制器可以為輸入資源建立 ALBs，但您可以考慮在叢集中執行專用控制器。叢集內輸入控制器可讓您在叢集內執行反向代理，從單一負載平衡器公開多個 Kubernetes 服務。控制器具有不同的功能，例如對 [Gateway API](https://gateway-api.sigs.k8s.io/) 的支援，視工作負載的數量和大小而定，可能會有好處。

## 使用 Route 53、Global Accelerator 或 CloudFront
<a name="_use_route_53_global_accelerator_or_cloudfront"></a>

若要使用多個負載平衡器做為單一端點提供服務，您需要使用 [Amazon CloudFront](https://aws.amazon.com/cloudfront/)、[AWS Global Accelerator](https://aws.amazon.com/global-accelerator/) 或 [Amazon Route 53](https://aws.amazon.com/route53/)，將所有負載平衡器公開為單一、面向客戶的端點。每個選項都有不同的優點，可以根據您的需求單獨或一起使用。

Route 53 可以使用通用名稱公開多個負載平衡器，並根據指派的權重將流量傳送至每個負載平衡器。您可以在[文件中閱讀更多關於 DNS 權重](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resource-record-sets-values-weighted.html#rrsets-values-weighted-weight)的資訊，也可以在 [AWS Load Balancer 控制器文件中](https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.4/guide/integrations/external_dns/#usage)閱讀如何使用 [Kubernetes 外部 DNS 控制器](https://github.com/kubernetes-sigs/external-dns)實作它們。

Global Accelerator 可以根據請求 IP 地址，將工作負載路由到最近的區域。這對於部署到多個區域的工作負載可能很有用，但無法改善單一區域中單一叢集的路由。如果無法使用 AZ，則使用 Route 53 搭配 Global Accelerator 具有其他優點，例如運作狀態檢查和自動容錯移轉。您可以在[此部落格文章](https://aws.amazon.com/blogs/containers/operating-a-multi-regional-stateless-application-using-amazon-eks/)中查看將 Global Accelerator 與 Route 53 搭配使用的範例。

CloudFront 可與 Route 53 和 Global Accelerator 搭配使用，也可以單獨使用，將流量路由到多個目的地。CloudFront 會快取從原始來源提供的資產，這可能會減少頻寬需求，視您提供的服務而定。

## 使用 EndpointSlices 而非 Endpoints
<a name="_use_endpointslices_instead_of_endpoints"></a>

探索符合服務標籤的 Pod 時，您應該使用 [EndpointSlices](https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/) 而非 Endpoints。端點是公開小規模服務的一種簡單方法，但自動擴展或進行更新的大型服務會導致 Kubernetes 控制平面上的大量流量。EndpointSlices 具有自動分組功能，可啟用拓撲感知提示等物件。

根據預設，並非所有控制器都會使用 EndpointSlices。您應該驗證控制器設定，並視需要啟用它。對於 [AWS Load Balancer 控制器](https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.4/deploy/configurations/#controller-command-line-flags)，您應該啟用`--enable-endpoint-slices`選用旗標以使用 EndpointSlices。

## 如果可能，請使用不可變和外部秘密
<a name="_use_immutable_and_external_secrets_if_possible"></a>

kubelet 會針對用於該節點上 Pod 磁碟區中的秘密，保留目前金鑰和值的快取。kubelet 會在 Secrets 上設定監看，以偵測變更。隨著叢集的擴展，越來越多的手錶可能會對 API 伺服器效能產生負面影響。

有兩種策略可以減少 Secrets 上的手錶數量：
+ 對於不需要存取 Kubernetes 資源的應用程式，您可以透過設定 automountServiceAccountToken 來停用自動掛載服務帳戶秘密：false
+ 如果您應用程式的秘密是靜態的，且未來不會修改，請將[秘密標記為不可變](https://kubernetes.io/docs/concepts/configuration/secret/#secret-immutable)。kubelet 不會維護不可變秘密的 API 監視。

若要停用自動將服務帳戶掛載到 Pod，您可以在工作負載中使用下列設定。如果特定工作負載需要服務帳戶，您可以覆寫這些設定。

```
apiVersion: v1
kind: ServiceAccount
metadata:
  name: app
automountServiceAccountToken: true
```

在超過 10，000 個限制之前，監控叢集中的秘密數量。您可以使用下列命令查看叢集中的秘密總數。您應該透過叢集監控工具來監控此限制。

```
kubectl get secrets -A | wc -l
```

您應該設定監控，在達到此限制之前提醒叢集管理員。考慮使用外部秘密管理選項，例如 [AWS Key Management Service (AWS KMS)](https://aws.amazon.com/kms/) 或 [Hashicorp Vault](https://www.vaultproject.io/) 搭配 [Secrets Store CSI 驅動程式](https://secrets-store-csi-driver.sigs.k8s.io/)。

## 限制部署歷史記錄
<a name="_limit_deployment_history"></a>

建立、更新或刪除 Pod 時可能會很慢，因為叢集中仍會追蹤舊物件。您可以減少[部署](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#clean-up-policy)`revisionHistoryLimit`的 以清除較舊的 ReplicaSets，這會降低到 Kubernetes Controller Manager 追蹤的物件總數。部署的預設歷史記錄限制為 10。

如果您的叢集透過 CronJobs 或其他機制建立許多任務物件，您應該使用 [`ttlSecondsAfterFinished`設定](https://kubernetes.io/docs/concepts/workloads/controllers/ttlafterfinished/)自動清除叢集中的舊 Pod。這會在指定的時間長度之後，從任務歷史記錄中移除成功執行的任務。

## 預設停用 enableServiceLinks
<a name="_disable_enableservicelinks_by_default"></a>

當 Pod 在節點上執行時， kubelet 會為每個作用中的服務新增一組環境變數。Linux 程序具有其環境的大小上限，如果您的命名空間中有太多服務，就可以達到此上限。每個命名空間的服務數量不應超過 5，000 個。之後，服務環境變數的數量會超出殼層限制，導致 Pod 在啟動時當機。

還有其他原因會導致 Pod 不應使用服務環境變數進行服務探索。環境變數名稱衝突、洩漏的服務名稱和總環境大小是幾個。您應該使用 CoreDNS 來探索服務端點。

## 限制每個資源的動態許可 Webhook
<a name="_limit_dynamic_admission_webhooks_per_resource"></a>

 [動態許可 Webhook ](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/)包括許可 Webhook 和變動 Webhook。它們是 API 端點，不是 Kubernetes 控制平面的一部分，當資源傳送到 Kubernetes API 時，會依序呼叫。每個 Webhook 預設逾時為 10 秒，如果您有多個 Webhook 或任何一個逾時，可能會增加 API 請求所需的時間。

確保您的 Webhook 高度可用，特別是在 AZ 事件期間，且 [failurePolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#failure-policy) 已正確設定為拒絕資源或忽略失敗。不需要時，請勿允許 --dry-run kubectl 命令繞過 Webhook 來呼叫 Webhook。

```
apiVersion: admission.k8s.io/v1
kind: AdmissionReview
request:
  dryRun: False
```

變更 Webhook 可以頻繁的連續修改資源。如果您有 5 個變動的 Webhook 並部署 50 個資源等，將存放每個資源的所有版本，直到壓縮執行為止，每 5 分鐘一次，以移除舊版本的修改後資源。在此案例中，當 etcd 移除取代的資源時，將會從 etcd 移除 200 個資源版本，並且根據資源的大小，可能會在 etcd 主機上使用相當大的空間，直到每 15 分鐘執行重組為止。

此重組可能會導致在 等化中暫停，這可能會對 Kubernetes API 和控制器造成其他影響。您應該避免頻繁修改大型資源，或快速連續修改數百個資源。

## 比較跨多個叢集的工作負載
<a name="_compare_workloads_across_multiple_clusters"></a>

如果您有兩個叢集應該有類似的效能，但沒有，請嘗試比較指標來識別原因。

例如，比較叢集延遲是常見的問題。這通常是由 API 請求量的差異所造成。您可以執行下列 CloudWatch LogInsight 查詢，以了解其差異。

```
filter @logStream like "kube-apiserver-audit"
| stats count(*) as cnt by objectRef.apiGroup, objectRef.apiVersion, objectRef.resource, userAgent, verb, responseStatus.code
| sort cnt desc
| limit 1000
```

您可以新增其他篩選條件來縮小範圍，例如專注於來自 的所有清單請求。 `foo`

```
filter @logStream like "kube-apiserver-audit"
| filter verb = "list"
| filter user.username like "foo"
| stats count(*) as cnt by objectRef.apiGroup, objectRef.apiVersion, objectRef.resource, responseStatus.code
| sort cnt desc
| limit 1000
```