共用方式為


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

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

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

必要條件

  • Azure CLI

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

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

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

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

基本健康情況檢查

  • 資源健康情況事件

    AKS 提供資源健康情況事件,讓重要元件停機。 在繼續之前,請確定 資源健康狀態 中沒有回報重大事件。

    顯示資源健康狀態事件的螢幕快照。

  • 診斷並解決問題

    AKS 提供叢集和控制平面可用性和效能的專用疑難解答類別

    顯示 [叢集和控制平面可用性與效能] 類別的螢幕快照。

徵兆

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

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

疑難排解檢查清單

如果您遇到高延遲時間,請遵循下列步驟來找出有問題的用戶端和失敗的 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 伺服器或 etcd 造成過多負載的 API 呼叫類型。

步驟 3:識別指定使用者代理程式的 API 呼叫錯誤

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

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>

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

注意

如果命令的 check-apiserver-connectivity 輸出包含 Connectivity check: succeeded 訊息,則網路聯機會不受阻礙。

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

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

原因 2:冒犯用戶端洩漏 etcd 物件,並導致 etcd 變慢

常見的問題是持續建立物件,而不刪除 etcd 資料庫中未使用的物件。 當 etcd 處理太多物件(超過 10,000 個)時,這可能會造成效能問題。 這類物件變更的快速增加,也可能導致超過 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. 建立 符合違規用戶端 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. 建立優先順序較低的組態,以節流用戶端的 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 中造成死結

自定義 Webhook,例如 Kyverno,可能會造成 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 意見反應社群提交產品意見反應。