Kubernetes 上游 SLOs - Amazon EKS

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

Kubernetes 上游 SLOs

Amazon EKS 執行與上游 Kubernetes 版本相同的程式碼,並確保 EKS 叢集在 Kubernetes 社群定義的 SLOs 內運作。Kubernetes Scalability Special Interest Group (SIG) 定義可擴展性目標,並透過 SLIs 和 SLOs 調查效能的瓶頸。

SLIs 是我們測量系統的方式,例如可用來判斷系統執行狀況的指標或指標,例如請求延遲或計數。SLOs定義系統執行「良好」時預期的值,例如,請求延遲保持不到 3 秒。Kubernetes SLOs 和 SLIs 專注於 Kubernetes 元件的效能,並與專注於 EKS 叢集端點可用性的 Amazon EKS 服務 SLAs 完全獨立。

Kubernetes 有許多功能可讓使用者使用自訂附加元件或驅動程式來擴展系統,例如 CSI 驅動程式、許可 Webhook 和自動擴展器。這些擴充功能可能會以不同方式大幅影響 Kubernetes 叢集的效能,例如,如果 Webhook 目標無法使用,則使用 的許可 Webhook failurePolicy=Ignore可能會為 K8s API 請求增加延遲。Kubernetes 可擴展性 SIG 使用「您承諾,我們承諾」架構來定義可擴展性:

Kubernetes SLOs

Kubernetes SLOs 不會考慮可能影響叢集的所有外掛程式和外部限制,例如工作者節點擴展或許可 Webhook。這些 SLOs著重於 Kubernetes 元件,並確保 Kubernetes 動作和資源的運作符合預期。SLOs 可協助 Kubernetes 開發人員確保 Kubernetes 程式碼的變更不會降低整個系統的效能。

Kuberntes 可擴展性 SIG 定義了下列官方 SLO/SLIs。Amazon EKS 團隊會定期對這些 SLOs/SLIs 的 EKS 叢集執行可擴展性測試,以在進行變更並發佈新版本時監控效能降低。

目標 定義 SLO

API 請求延遲 (變動)

處理每個 (資源、動詞) 對之單一物件變動 API 呼叫的延遲,測量為過去 5 分鐘內的第 99 個百分位數

在預設 Kubernetes 安裝中,針對每個 (資源、動詞) 配對,不包括虛擬和彙總資源和自訂資源定義,每個叢集天的第 99 個百分位數 <= 1s

API 請求延遲 (唯讀)

處理每個 (資源、範圍) 對非串流唯讀 API 呼叫的延遲,測量為過去 5 分鐘內的第 99 個百分位數

在預設 Kubernetes 安裝中,針對每個 (資源、範圍) 配對,不包括虛擬和彙總資源和自訂資源定義,每個叢集天的第 99 個百分位數:(a) <= 1s,如果 scope=resource(b) <= 30s (如果 scope=namespacescope=cluster)

Pod 啟動延遲

可排程無狀態 Pod 的啟動延遲,不包括提取映像和執行初始化容器的時間,從 Pod 建立時間戳記開始測量,到透過監看報告其所有容器已啟動和觀察為止,測量為過去 5 分鐘內的第 99 個百分位數

在預設 Kubernetes 安裝中,每個叢集天的第 99 個百分位數 <= 5s

API 請求延遲

根據1m0s預設, kube-apiserver--request-timeout定義為 ,這表示請求在逾時和取消之前最多可以執行一分鐘 (60 秒)。為延遲定義的 SLOs 會依所提出的請求類型細分,可以是變動或唯讀:

變動

在 Kubernetes 中變更請求會變更資源,例如建立、刪除或更新。這些請求非常昂貴,因為在傳回更新後的物件之前,這些變更必須寫入至 等後端Etcd 是分散式金鑰值存放區,用於所有 Kubernetes 叢集資料。

對於 (資源、動詞) 對 Kubernetes 資源,此延遲測量為 5 分鐘內的第 99 個百分位數,例如,這將測量建立 Pod 請求和更新節點請求的延遲。請求延遲必須 <= 1 秒才能滿足 SLO。

唯讀

唯讀請求會擷取單一資源 (例如取得 Pod X) 或集合 (例如「從命名空間 X 取得所有 Pod」)。會kube-apiserver維護物件的快取,因此可能會從快取傳回請求的資源,或者可能需要先從 等項目擷取它們。這些延遲也會由 5 分鐘內的第 99 個百分位數測量,但唯讀請求可以有不同的範圍。SLO 定義了兩個不同的目標:

  • 對於對單一資源提出的請求 (即 kubectl get pod -n mynamespace my-controller-xxx ),請求延遲應保持 <= 1 秒。

  • 對於對命名空間或叢集中的多個資源提出的請求 (例如 kubectl get pods -A),延遲應保持 <= 30 秒

SLO 具有不同請求範圍的不同目標值,因為對 Kubernetes 資源清單提出的請求預期請求中所有物件的詳細資訊會在 SLO 中傳回。在大型叢集或大型資源集合上,這可能會導致大型回應大小,這可能需要一些時間才能傳回。例如,在執行數萬個 Pod 的叢集中,當以 JSON 編碼時,每個 Pod 大約為 1 KiB,傳回叢集中的所有 Pod 會包含 10MB 或更多。Kubernetes 用戶端可以使用 APIListChunking 來擷取大型資源集合,協助減少此回應大小。

Pod 啟動延遲

此 SLO 主要關注從建立 Pod 到該 Pod 中的容器實際開始執行所需的時間。為了測量此值與 Pod 上記錄的建立時間戳記的差異,以及當該 Pod 上的 WATCH 報告已開始計算容器時 (不包括容器映像提取和初始化容器執行的時間)。為了滿足 SLO,此 Pod 啟動延遲的每個叢集天的第 99 個百分位數必須保持 <=5 秒。

請注意,此 SLO 假設此叢集中已存在工作者節點處於就緒狀態,以便排程 Pod。此 SLO 不會考慮映像提取或初始化容器執行,也限制測試為「無狀態 Pod」,其不會利用持久性儲存外掛程式。

Kubernetes SLI 指標

Kubernetes 也正在改善 SLIs 的可觀測性,方法是將 Prometheus 指標新增至追蹤這些 SLIs 一段時間的 Kubernetes 元件。使用 Prometheus 查詢語言 (PromQL),我們可以建置在 Prometheus 或 Grafana 儀表板等工具中顯示 SLI 效能的查詢,以下是上述 SLOs的一些範例。

API 伺服器請求延遲

指標 定義

apiserver_request_sli_duration_seconds

每個動詞、群組、版本、資源、子資源、範圍和元件的回應延遲分佈 (未計算 Webhook 持續時間和優先順序和公平性佇列等待時間),以秒為單位。

apiserver_request_duration_seconds

每個動詞、試轉值、群組、版本、資源、子資源、範圍和元件的回應延遲分佈,以秒為單位。

注意:apiserver_request_sli_duration_seconds指標從 Kubernetes 1.27 開始可用。

您可以使用這些指標來調查 API Server 回應時間,以及 Kubernetes 元件或其他外掛程式/元件是否有瓶頸。以下查詢是以社群 SLO 儀表板為基礎。

API 請求延遲 SLI (變動) - 這次不包含 Webhook 執行或佇列中等待的時間。 histogram_quantile(0.99, sum(rate(apiserver_request_sli_duration_seconds_bucket{verb=~"CREATE|DELETE|PATCH|POST|PUT", subresource!~"proxy|attach|log|exec|portforward"}[5m])) by (resource, subresource, verb, scope, le)) > 0

API 請求延遲總計 (變動) - 這是請求在 API 伺服器上接受的總時間,這次可能比 SLI 時間長,因為它包括 Webhook 執行和 API 優先順序和公平性等待時間。 histogram_quantile(0.99, sum(rate(apiserver_request_duration_seconds_bucket{verb=~"CREATE|DELETE|PATCH|POST|PUT", subresource!~"proxy|attach|log|exec|portforward"}[5m])) by (resource, subresource, verb, scope, le)) > 0

在這些查詢中,我們會排除未立即傳回的串流 API 請求,例如 kubectl port-forwardkubectl exec請求 (subresource!~"proxy|attach|log|exec|portforward"),而且只會篩選修改物件 () 的 Kubernetes 動詞verb=~"CREATE|DELETE|PATCH|POST|PUT"。然後,我們將計算過去 5 分鐘內該延遲的第 99 個百分位數。

我們可以對唯讀 API 請求使用類似的查詢,只需修改我們正在篩選的動詞,以包含唯讀動作 LISTGET。根據請求的範圍,也有不同的 SLO 閾值,即取得單一資源或列出一些資源。

API 請求延遲 SLI (唯讀) - 這次不包含 Webhook 執行或佇列中等待的時間。對於單一資源 (scope=resource, threshold=1s) histogram_quantile(0.99, sum(rate(apiserver_request_sli_duration_seconds_bucket{verb=~"GET", scope=~"resource"}[5m])) by (resource, subresource, verb, scope, le))

對於相同命名空間中的資源集合 (scope=namespace, threshold=5s) histogram_quantile(0.99, sum(rate(apiserver_request_sli_duration_seconds_bucket{verb=~"LIST", scope=~"namespace"}[5m])) by (resource, subresource, verb, scope, le))

對於整個叢集的資源集合 (scope=cluster, threshold=30s) histogram_quantile(0.99, sum(rate(apiserver_request_sli_duration_seconds_bucket{verb=~"LIST", scope=~"cluster"}[5m])) by (resource, subresource, verb, scope, le))

API 請求延遲總計 (唯讀) - 這是請求在 API 伺服器上接受的總時間,這次可能比 SLI 時間更長,因為它包含 Webhook 執行和等待時間。對於單一資源 (scope=resource, threshold=1s) histogram_quantile(0.99, sum(rate(apiserver_request_duration_seconds_bucket{verb=~"GET", scope=~"resource"}[5m])) by (resource, subresource, verb, scope, le))

對於相同命名空間中的資源集合 (scope=namespace, threshold=5s) histogram_quantile(0.99, sum(rate(apiserver_request_duration_seconds_bucket{verb=~"LIST", scope=~"namespace"}[5m])) by (resource, subresource, verb, scope, le))

對於整個叢集的資源集合 (scope=cluster, threshold=30s) histogram_quantile(0.99, sum(rate(apiserver_request_duration_seconds_bucket{verb=~"LIST", scope=~"cluster"}[5m])) by (resource, subresource, verb, scope, le))

SLI 指標透過排除請求在 API Priority and Fairness 佇列中等待的時間、透過許可 Webhook 或其他 Kubernetes 延伸模組運作,來深入了解 Kubernetes 元件的效能。總指標提供更全面的檢視,因為它反映您的應用程式等待 API 伺服器回應的時間。比較這些指標可以深入了解請求處理發生延遲的位置。

Pod 啟動延遲

指標 定義

kubelet_pod_start_sli_duration_seconds

啟動 Pod 的持續時間,不包括提取影像和執行初始化容器的時間,從 Pod 建立時間戳記到透過監視報告其所有容器已啟動和觀察的時間

kubelet_pod_start_duration_seconds

從第一次看到 Pod 的 kubelet 到開始執行 Pod 的持續時間,以秒為單位。這不包括排程 Pod 或向外擴展工作者節點容量的時間。

注意:從 kubelet_pod_start_sli_duration_seconds Kubernetes 1.27 開始提供。

與上述查詢類似,您可以使用這些指標來深入了解與 Kubelet 動作相比,節點擴展、映像提取和初始化容器延遲 Pod 啟動的時間。

Pod 啟動延遲 SLI - 這是從建立 Pod 到應用程式容器回報為執行中的時間。這包括工作者節點容量可用和 Pod 排程所需的時間,但這不包括提取映像或初始化容器執行所需的時間。 histogram_quantile(0.99, sum(rate(kubelet_pod_start_sli_duration_seconds_bucket[5m])) by (le))

Pod 啟動延遲總計 - 這是第一次啟動 Pod 所需的時間。這是從 kubelet 透過 WATCH 接收 Pod 時開始測量,其中不包含工作者節點擴展或排程的時間。這包括提取映像和初始化容器以執行的時間。 histogram_quantile(0.99, sum(rate(kubelet_pod_start_duration_seconds_bucket[5m])) by (le))

叢集上的 SLOs

如果您要從 EKS 叢集中的 Kubernetes 資源收集 Prometheus 指標,您可以深入了解 Kubernetes 控制平面元件的效能。

效能測試儲存庫包含 Grafana 儀表板,可在測試期間顯示叢集的延遲和關鍵效能指標。效能測試組態利用 kube-prometheus-stack,這是設定為收集 Kubernetes 指標的開放原始碼專案,但您也可以使用 Amazon Managed Prometheus 和 Amazon Managed Grafana。

如果您使用的是 kube-prometheus-stack或類似的 Prometheus 解決方案,您可以安裝相同的儀表板,以即時觀察叢集上的 SLOs。

  1. 首先,您需要安裝在具有 的儀表板中使用的 Prometheus 規則kubectl apply -f prometheus-rules.yaml。您可以在這裡下載規則的副本:https://https://github.com/kubernetes/perf-tests/blob/master/clusterloader2/pkg/prometheus/manifests/prometheus-rules.yaml

    1. 請務必檢查 檔案中的命名空間是否符合您的環境

    2. 如果您使用 ,請確認標籤符合 prometheus.prometheusSpec.ruleSelector Helm 值 kube-prometheus-stack

  2. 然後,您可以在 Grafana 中安裝儀表板。此處提供用於產生它們的 json 儀表板和 python 指令碼:https://https://github.com/kubernetes/perf-tests/tree/master/clusterloader2/pkg/prometheus/manifests/dashboards

    1. slo.json 儀表板會顯示叢集與 Kubernetes SLOs 相關的效能

假設 SLOs專注於叢集中 Kubernetes 元件的效能,但您可以檢閱其他指標,為您的叢集提供不同的觀點或洞見。Kubernetes 社群專案,例如 Kube-state-metrics,可協助您快速分析叢集中的趨勢。Kubernetes 社群中最常見的外掛程式和驅動程式也會發出 Prometheus 指標,讓您調查自動擴展器或自訂排程器等項目。

可觀測性最佳實務指南提供其他 Kubernetes 指標的範例,您可以用來深入了解。