本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
工作負載
工作負載會影響叢集可以擴展的大小。使用 Kubernetes APIs工作負載會大幅限制單一叢集中可擁有的工作負載總數,但您可以變更一些預設值,以協助減少負載。
Kubernetes 叢集中的工作負載可存取與 Kubernetes API 整合的功能 (例如 Secrets and ServiceAccounts),但這些功能並非一律必要,如果未使用,則應停用。限制工作負載存取和對 Kubernetes 控制平面的依賴,將增加您可以在叢集中執行的工作負載數量,並透過移除不必要的工作負載存取並實作最低權限實務來提高叢集的安全性。如需詳細資訊,請參閱安全最佳實務。
使用 IPv6 進行 Pod 聯網
您無法將 VPC 從 IPv4 轉換為 IPv6,因此在佈建叢集之前啟用 IPv6 非常重要。如果您在 VPC 中啟用 IPv6,並不表示您必須使用它,而且如果您的 Pod 和服務使用 IPv6,您仍然可以路由往返 IPv4 地址的流量。如需詳細資訊,請參閱 EKS 聯網最佳實務。
在叢集中使用 IPv6 可避免一些最常見的叢集和工作負載擴展限制。IPv6 可避免因沒有可用的 IP 地址而無法建立 Pod 和節點的 IP 地址耗盡。它也改善了每個節點的效能,因為 Pod 透過減少每個節點的 ENI 附件數量,更快地接收 IP 地址。您可以在 VPC CNI 中使用 IPv4 字首模式來實現類似的節點效能,但您仍然需要確保 VPC 中有足夠的 IP 地址可用。
限制每個命名空間的服務數量
命名空間中的服務數量上限為 5,000,叢集中的服務數量上限為 10,000
使用 kube-proxy 為每個節點建立的 IP 資料表規則數量會隨著叢集中的服務總數而增加。產生數千個 IP 資料表規則並透過這些規則路由封包會對節點產生效能影響,並新增網路延遲。
建立包含單一應用程式環境的 Kubernetes 命名空間,只要每個命名空間的服務數量低於 500。這將使服務探索夠小,以避免服務探索限制,也可以協助您避免服務命名衝突。應用程式環境 (例如 dev、test、prod) 應該使用單獨的 EKS 叢集,而不是命名空間。
了解 Elastic Load Balancer 配額
建立服務時,請考慮您將使用的負載平衡類型 (例如 Network Load Balancer (NLB) 或 Application Load Balancer (ALB))。每個負載平衡器類型都提供不同的功能,並具有不同的配額。某些預設配額可以調整,但有一些配額上限無法變更。若要檢視您的帳戶配額和用量,請在 AWS 主控台中檢視 Service Quotas 儀表板
例如,預設的 ALB 目標為 1000。如果您有超過 1000 個端點的服務,則需要增加配額或將服務分割到多個 ALBs 或使用 Kubernetes Ingress。預設 NLB 目標為 3000,但每個 AZ 限制為 500 個目標。如果您的叢集為 NLB 服務執行超過 500 個 Pod,您將需要使用多個 AZs 或請求提高配額限制。
使用與服務耦合的負載平衡器的替代方案是使用輸入控制器
使用 Route 53、Global Accelerator 或 CloudFront
若要使用多個負載平衡器做為單一端點提供服務,您需要使用 Amazon CloudFront
Route 53 可以使用通用名稱公開多個負載平衡器,並根據指派的權重將流量傳送至每個負載平衡器。您可以在文件中閱讀更多關於 DNS 權重的資訊,也可以在 AWS Load Balancer 控制器文件中
Global Accelerator 可以根據請求 IP 地址,將工作負載路由到最近的區域。這對於部署到多個區域的工作負載可能很有用,但無法改善單一區域中單一叢集的路由。如果無法使用 AZ,則使用 Route 53 搭配 Global Accelerator 具有其他好處,例如運作狀態檢查和自動容錯移轉。您可以在此部落格文章
CloudFront 可與 Route 53 和 Global Accelerator 搭配使用,也可以單獨使用,將流量路由到多個目的地。CloudFront 會快取從原始來源提供的資產,這可能會減少頻寬需求,視您服務的內容而定。
使用 EndpointSlices 而非 Endpoints
探索符合服務標籤的 Pod 時,您應該使用 EndpointSlices
根據預設,並非所有控制器都會使用 EndpointSlices。您應該驗證控制器設定,並視需要啟用它。對於 AWS Load Balancer 控制器--enable-endpoint-slices
選用旗標以使用 EndpointSlices。
如果可能,請使用不可變和外部秘密
kubelet 會針對用於節點上 Pod 磁碟區中的秘密,保留目前金鑰和值的快取。kubelet 會在 Secrets 上設定監看,以偵測變更。隨著叢集擴展,越來越多的手錶可能會對 API 伺服器效能產生負面影響。
有兩種策略可以減少 Secrets 上的手錶數量:
-
對於不需要存取 Kubernetes 資源的應用程式,您可以透過設定 automountServiceAccountToken 來停用自動掛載服務帳戶秘密:false
-
如果您應用程式的秘密是靜態的,且未來不會修改,請將秘密標記為不可變
。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)
限制部署歷史記錄
建立、更新或刪除 Pod 時可能會很慢,因為叢集中仍會追蹤舊物件。您可以減少部署revisionHistoryLimit
的 以清除較舊的 ReplicaSets,這會降低到 Kubernetes Controller Manager 追蹤的物件總數。部署的預設歷史記錄限制為 10。
如果您的叢集透過 CronJobs 或其他機制建立許多任務物件,您應該使用 ttlSecondsAfterFinished
設定
預設停用 enableServiceLinks
當 Pod 在節點上執行時, kubelet 會為每個作用中的服務新增一組環境變數。Linux 程序具有其環境的大小上限,如果您的命名空間中有太多服務,則可以達到此上限。每個命名空間的服務數量不應超過 5,000。之後,服務環境變數的數量會超出殼層限制,導致 Pod 在啟動時當機。
還有其他 Pod 不應使用服務環境變數進行服務探索的原因。環境變數名稱衝突、洩漏的服務名稱和總環境大小是幾個。您應該使用 CoreDNS 來探索服務端點。
限制每個資源的動態許可 Webhook
動態許可 Webhook
確保您的 Webhook 高度可用,特別是在 AZ 事件期間,且 failurePolicy
apiVersion: admission.k8s.io/v1 kind: AdmissionReview request: dryRun: False
變更 Webhook 可以頻繁的連續修改資源。如果您有 5 個變動的 Webhook 並部署 50 個資源等,將存放每個資源的所有版本,直到壓縮執行為止,每 5 分鐘一次,以移除舊版本的修改後資源。在此案例中,當 etcd 移除取代的資源時,將會從 etcd 移除 200 個資源版本,並且根據資源的大小,可能會在 etcd 主機上使用相當大的空間,直到每 15 分鐘執行重組為止。
此重組可能會導致在 等化中暫停,這可能會對 Kubernetes API 和控制器造成其他影響。您應該避免頻繁修改大型資源,或快速連續修改數百個資源。
比較跨多個叢集的工作負載
如果您有兩個叢集應該有類似的效能,但沒有,請嘗試比較指標來識別原因。
例如,比較叢集延遲是常見的問題。這通常是由 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