Share via


針對 Azure Kubernetes Services 中的 API 伺服器和 Etcd 問題進行疑難解答

本指南旨在協助您識別及解決在大型 Microsoft Azure Kubernetes Services (AKS) 部署中的 API 伺服器內可能遇到的任何不可能的問題。

Microsoft 已測試 API 伺服器的可靠性和效能,規模為 5,000 個節點和 200,000 個 Pod。 包含 API 伺服器的叢集能夠自動向外延展,並將 Kubernetes 服務等級目標 (SLO) 。 如果您遇到高延遲或逾時,可能是因為分散式 etc 目錄上的資源外洩 (etcd) ,或違規的用戶端有過多的 API 呼叫。

必要條件

  • Azure CLI

  • Kubernetes kubectl 工具。 若要使用 Azure CLI 安裝 kubectl,請執行 az aks install-cli 命令。

  • AKS 診斷記錄特別 (啟用並傳送至 Log Analytics 工作區的 kube-audit 事件) 。 若要判斷是使用資源特定Azure 診斷模式來收集記錄,請檢查 Azure 入口網站 中的 [診斷設定] 刀鋒視窗。

  • AKS 叢集的標準層。 如果您使用免費層,則 API 伺服器和 etcd 包含有限的資源。 免費層中的 AKS 叢集不提供高可用性。 這通常是 API 伺服器和 Etcd 問題的根本原因。

  • kubectl-aks 外掛程式,可直接在 AKS 節點上執行命令,而不需使用 Kubernetes 控制平面。

徵狀

下表概述 API 伺服器失敗的常見徵兆:

徵兆 描述
來自 API 伺服器的逾時 AKS API 伺服器 SLA 中超出保證的頻繁逾時。 例如, kubectl 命令逾時。
高延遲 讓 Kubernetes SLO 失敗的高延遲。 例如,命令 kubectl 需要超過 30 秒的時間來列出 Pod。
處於狀態或面臨 Webhook 呼叫失敗的 API 伺服器 Pod CrashLoopbackOff 確認您沒有任何自定義許可 Webhook (,例如封鎖 API 伺服器呼叫的 Kyverno 原則引擎) 。

疑難解答檢查清單

如果您遇到高延遲時間,請遵循下列步驟來找出違規的用戶端,以及失敗的 API 呼叫類型。

步驟 1:依要求數目識別排名最高的使用者代理程式

若要識別哪些用戶端 (產生最多的要求,以及可能最大量的 API 伺服器載入) ,請執行類似下列程式代碼的查詢。 下列查詢會依傳送的 API 伺服器要求數目列出前 10 名使用者代理程式。

AKSAudit
| where TimeGenerated between(now(-1h)..now()) // When you experienced the problem
| summarize count() by UserAgent
| top 10 by count_
| project UserAgent, count_

注意事項

如果您的查詢未傳回任何結果,您可能已選取錯誤的數據表來查詢診斷記錄。 在資源特定模式中,數據會根據資源的類別寫入個別數據表。 診斷記錄會寫入數據 AKSAudit 表。 在 Azure 診斷模式中,所有數據都會寫入數據 AzureDiagnostics 表。 如需詳細資訊,請參閱 Azure 資源記錄

雖然瞭解哪些用戶端會產生最高的要求磁碟區很有説明,但單單是高要求量可能就不是問題的原因。 每個用戶端在 API 伺服器上產生之實際負載的更佳指標是它們所經歷的回應延遲。

步驟 2:識別並繪製每個使用者代理程式的 API 伺服器要求平均延遲圖表

若要識別每個使用者代理程式在時程圖表上繪製的 API 伺服器要求平均延遲,請執行下列查詢:

AKSAudit
| where TimeGenerated between(now(-1h)..now()) // When you experienced the problem
| extend start_time = RequestReceivedTime
| extend end_time = StageReceivedTime
| extend latency = datetime_diff('millisecond', end_time, start_time)
| summarize avg(latency) by UserAgent, bin(start_time, 5m)
| render timechart

此查詢是「依 要求數目識別熱門使用者代理程式」 一節中查詢的後續追蹤。 它可讓您深入瞭解每個使用者代理程序隨時間所產生的實際負載。

提示

藉由分析此數據,您可以識別可能指出 AKS 叢集或應用程式上問題的模式和異常狀況。 例如,您可能會注意到特定使用者遇到高延遲。 此案例可能表示造成 API 伺服器或等式負載過多的 API 呼叫類型。

步驟 3:識別給定使用者代理程式的不正確 API 呼叫

執行下列查詢,將第99個百分位數 (P99,) 指定用戶端不同資源類型的 API 呼叫延遲:

AKSAudit
| where TimeGenerated between(now(-1h)..now()) // When you experienced the problem
| extend HttpMethod = Verb
| extend Resource = tostring(ObjectRef.resource)
| where UserAgent == "DUMMYUSERAGENT" // Filter by name of the useragent you are interested in
| where Resource != ""
| extend start_time = RequestReceivedTime
| extend end_time = StageReceivedTime
| extend latency = datetime_diff('millisecond', end_time, start_time)
| summarize p99latency=percentile(latency, 99) by HttpMethod, Resource
| render table

此查詢的結果有助於識別對上游 Kubernetes SLO 失敗的 API 呼叫類型。 在大部分情況下,違規的用戶端可能會對一組太大的對象或對象進行太多 LIST 呼叫。 可惜的是,沒有硬性延展性限制可用來引導用戶瞭解 API 伺服器延展性。 API 伺服器或etcd延展性限制取決於 Kubernetes 延展性閾值中所述的各種因素。

原因 1:網路規則會封鎖從代理程式節點到 API 伺服器的流量

網路規則可以封鎖代理程序節點與 API 伺服器之間的流量。

若要確認設定錯誤的網路原則是否封鎖 API 伺服器與代理程式節點之間的通訊,請執行下列 kubectl-aks 命令:

kubectl aks config import \
    --subscription <mySubscriptionID> \
    --resource-group <myResourceGroup> \
    --cluster-name <myAKSCluster>

kubectl aks check-apiserver-connectivity --node <myNode>

config import 命令會擷取叢集中所有節點的虛擬機擴展集資訊。 然後, check-apiserver-connectivity 命令會使用此資訊來驗證 API 伺服器與指定節點之間的網路連線,特別是針對其基礎擴展集實例。

注意事項

如果命令的 check-apiserver-connectivity 輸出包含 Connectivity check: succeeded 訊息,則無法實作網路連線。

解決方案 1:修正網路原則以移除流量封鎖

如果命令輸出指出發生連線失敗,請重新設定網路原則,使其不會不必要地封鎖代理程序節點與 API 伺服器之間的流量。

原因 2:違規的用戶端洩漏 etcd 物件,並導致 etcd 變慢

常見的問題是持續建立物件,而不會刪除 etcd 資料庫中未使用的物件。 當 etcd 處理太多物件 (超過任何類型的 10,000) 時,這可能會導致效能問題。 這類物件的變更快速增加也可能導致預設超過 4 GB 的 etcd 資料庫大小 (4 GB) 。

若要檢查 etcd 資料庫使用量,請流覽至 [診斷] 和 [解決 Azure 入口網站 中的問題。 在搜尋方塊中搜尋 「etcd」,以執行 Etcd 可用性問題診斷工具。 診斷工具會顯示使用量明細和資料庫大小總計。

Azure 入口網站 螢幕快照,其中顯示 Azure Kubernetes Service (AKS) 的 Etcd 可用性診斷。

如果您只想要快速檢視以位元組為單位之 etcd 資料庫的目前大小,請執行下列命令:

kubectl get --raw /metrics | grep -E "etcd_db_total_size_in_bytes|apiserver_storage_size_bytes|apiserver_storage_db_total_size_in_bytes"

注意事項

針對不同的 Kubernetes 版本,上一個命令中的計量名稱不同。 針對 Kubernetes 1.25 和更早版本,請使用 etcd_db_total_size_in_bytes。 針對 Kubernetes 1.26 到 1.28,請使用 apiserver_storage_db_total_size_in_bytes

解決方案 2:定義物件建立、刪除物件或限制 etcd 中物件存留期的配額

若要防止 etcd 達到容量並導致叢集停機,您可以限制所建立的資源數目上限。 您也可以降低為資源實例產生的修訂數目。 若要限制可建立的物件數目,您可以 定義物件配額

如果您已識別出不再使用但正在佔用資源的物件,請考慮刪除它們。 例如,您可以刪除已完成的作業,以釋放空間:

kubectl delete jobs --field-selector status.successful=1

對於支援 自動清除的物件,您可以將 [存留時間] 設定 (TTL) 值來限制這些物件的存留期。 您也可以為物件加上標籤,以便使用標籤選取器大量刪除特定類型的所有物件。 如果您在對象之間建立 擁有者參考 ,則在刪除父對象之後,會自動刪除任何相依物件。

原因 3:違規客戶端進行過多的 LIST 或 PUT 呼叫

如果您判斷 etcd 未多載太多對象,違規的用戶端可能會對 API 伺服器進行太多 LISTPUT 呼叫。

解決方案 3a:調整您的 API 呼叫模式

請考慮調整用戶端的 API 呼叫模式,以降低控制平面上的壓力。

解決方案3b:節流控制平面無法控制的用戶端

如果您無法調整用戶端,您可以使用 Kubernetes 中的 優先順序和公平性 功能來節流用戶端。 這項功能有助於保留控制平面的健康情況,並防止其他應用程式失敗。

下列程式示範如何將違規用戶端的 LIST Pod API 設定為五個並行呼叫進行節流:

  1. Create 符合違規用戶端 API 呼叫模式的 FlowSchema

    apiVersion: flowcontrol.apiserver.k8s.io/v1beta2
    kind: FlowSchema
    metadata:
      name: restrict-bad-client
    spec:
      priorityLevelConfiguration:
        name: very-low-priority
      distinguisherMethod:
        type: ByUser
      rules:
      - resourceRules:
        - apiGroups: [""]
          namespaces: ["default"]
          resources: ["pods"]
          verbs: ["list"]
        subjects:
        - kind: ServiceAccount
          serviceAccount:
            name: bad-client-account
            namespace: default 
    
  2. Create 較低優先順序的設定來節流用戶端的不良 API 呼叫:

    apiVersion: flowcontrol.apiserver.k8s.io/v1beta2
    kind: PriorityLevelConfiguration
    metadata:
      name: very-low-priority
    spec:
      limited:
        assuredConcurrencyShares: 5
        limitResponse:
          type: Reject
      type: Limited
    
  3. 觀察 API 伺服器計量中的節流呼叫。

    kubectl get --raw /metrics | grep "restrict-bad-client"
    

原因 4:自定義 Webhook 可能會在 API 伺服器 Pod 中造成死結

Kyverno 之類的自定義 Webhook 可能會在 API 伺服器 Pod 內造成死結。

檢查與 API 伺服器相關的事件。 您可能會看到類似下列文字的事件訊息:

發生內部錯誤:呼叫 Webhook “mutate.kyverno.svc-fail” 失敗:無法呼叫 Webhook: Post“https://kyverno-system-kyverno-system-svc.kyverno-system.svc:443/mutate/fail?timeout=10s": write unix @->/tunnel-uds/proxysocket: write: broken pipe

在此範例中,驗證 Webhook 會封鎖某些 API 伺服器物件的建立。 由於此案例可能會在啟動程式期間發生,因此無法建立 API 伺服器和 Konnectivity Pod。 因此,Webhook 無法連線到這些 Pod。 此事件序列會造成死結和錯誤訊息。

解決方案 4:刪除 Webhook 設定

若要修正此問題,請刪除驗證和變更 Webhook 組態。 若要在 Kyverno 中刪除這些 Webhook 設定,請檢閱 Kyverno 疑難解答文章

協力廠商連絡資訊免責聲明

Microsoft 提供第三方連絡資訊,協助您尋找有關本主題的其他資訊。 此連絡資訊如有變更,恕不另行通知。 Microsoft 不保證第三方聯繫人信息的正確性。

協力廠商資訊免責聲明

本文提及的協力廠商產品是由與 Microsoft 無關的獨立廠商所製造。 Microsoft 不以默示或其他方式,提供與這些產品的效能或可靠性有關的擔保。

與我們連絡,以取得說明

如果您有問題或需要相關協助,請建立支援要求,或詢問 Azure community 支援。 您也可以將產品意見反應提交給 Azure 意應見反社群