Kubernetes 是一個生產級的容器編排引擎,但是 Kubernetes 仍然存在系統複雜、故障診斷成本高等問題。網易內部在基於 Kubernetes 落地輕舟雲原生體系時遇到了不少問題,主要包括以下幾個維度:
- 由 Kubernetes 以及 Docker 的 Bug 引起的故障。
- 內核 Bug 導致的故障。
- 基礎設施抖動產生的問題。
- 用戶在容器化以及使用 Kubernetes 過程中遇到的問題。
- 用戶在容器化後遇到的業務相關問題。
Kubernetes 故障診斷恢復平臺是基於 Kubernetes 雲原生基礎設施能力打造的框架,旨在解決雲原生體系中故障診斷、運維恢復的自動化問題,幫助用戶更加平滑地完成容器化落地。
目標
Kubernetes 故障診斷恢復平臺的設計目標包括:
- 通用性:平臺依賴通用技術實現,平臺組件可以在絕大部分的 Linux 系統下運行並且能夠對 Linux 下運行遇到的故障進行診斷和運維。
- 可擴展性:平臺組件之間的交互爲松耦合接口設計並且整個框架是可插拔式的。
- 可維護性:框架邏輯簡潔明瞭,維護成本與功能數量爲線性關係,不同故障的分析和恢復邏輯具有獨立性。
架構
故障診斷恢復平臺 Agent 組件可以監聽 APIServer 獲取 Abnormal CRD 資源,Abnormal CRD 資源是對故障狀態機的抽象。故障診斷恢復平臺 Agent 組件可以通過 Event、Prometheus 報警、系統日誌中的關鍵條目產生相對應的 Abnormal CRD 並送入故障診斷恢復的流水線。故障診斷恢復平臺 Agent 組件使用 DaemonSet 部署在集羣中:
---------------------
Watch (Event, CRD) | |
--------------------->| APIServer |
| | |
| |-------------------|
| | |
-------------- --------- | Etcd |
| | Monitor | | Monitor | |
| Prometheus |<----------------| Agent |---------------->|-------------------|
| | | | | |
-------------- --------- | ControllerManager |
| | |
| |-------------------|
| | |
| | Scheduler |
| | |
| ---------------------
\|/
---------------------
| |
| Kernel |
| Docker |
| Kubelet |
| Cgroup |
| ...... |
| |
---------------------
故障診斷恢復平臺 Agent 組件由下列部分組成:
- 故障事件源(AbnormalSource)
- 故障分析鏈(DiagnoserChain)
- 信息管理器(InformationManager)
- 故障恢復鏈(RecovererChain)
------------------ ---------------------- ------------------ ------------------
| | Abnormal | | Abnormal | | Abnormal | |
| AbnormalSource |------------>| InformationManager |------------>| DiagnoserChain |------------>| RecovererChain |
| | | | | | | |
------------------ ---------------------- ------------------ ------------------
| | |
| | |
| | |
\|/ \|/ \|/
-------------------------- --------------- ---------------
| | | | | |
| InformationCollector 1 | | Diagnoser 1 | | Recoverer 1 |
| | | | | |
-------------------------- --------------- ---------------
| | |
| | |
| | |
\|/ \|/ \|/
-------------------------- --------------- ---------------
| | | | | |
| InformationCollector 2 | | Diagnoser 2 | | Recoverer 2 |
| | | | | |
-------------------------- --------------- ---------------
| | |
| | |
| | |
\|/ \|/ \|/
....... ....... .......
功能
故障診斷恢復平臺 Agent 組件功能如下:
- 獲取 Event、Prometheus 報警、系統日誌作爲故障源。
- 監聽故障診斷 Abnormal CRD 資源並進行處理和狀態同步。
- 對本節點故障進行診斷和恢復。
- 通過 Abnormal CRD 以及 InformationCollector CRD 進行監控擴展和增強。
故障診斷恢復平臺中 Abnormal 的狀態遷移流程如下:
- 故障事件源監聽到 Event、Prometheus 報警、系統日誌等異常,故障診斷恢復平臺 Agent 或用戶自行創建 Abnormal CRD 資源。
- 將 Abnormal 發送至信息管理器,標記 Abnormal 的狀態爲 InformationCollecting 並採集故障診斷恢復的信息。
- 如果信息能夠被成功收集則記錄 InformationCollected 狀況並繼續。
- 將 Abnormal 發送至故障分析鏈,標記 Abnormal 的狀態爲 Diagnosing 並對故障進行分析。
- 如果故障能夠被成功識別則記錄 Identified 狀況並繼續。
- 如果故障無法被成功識別則將 Abnormal 的狀態標記爲 Failed 並終止故障診斷恢復流程。
- 將 Abnormal 發送至故障恢復鏈,標記 Abnormal 的狀態爲 Recovering 並對故障進行恢復。
- 如果故障能夠被成功恢復則記錄 Recovered 狀況並標記 Abnormal 的狀態爲 Succeeded。
- 如果故障無法被成功恢復則標記 Abnormal 的狀態爲 Failed 並終止故障診斷恢復流程。
故障診斷恢復平臺中 Abnormal 的狀態遷移圖如下:
----------
| |
----------------------------------------------------------->| Failed |
/|\ /|\ | |
| | ----------
Failed | Failed |
| |
----------- ------------------------- -------------- -------------- -------------
| | | | | | | | | |
| Created |------------------>| InformationCollecting |------------------>| Diagnosing |------------------>| Recovering |------------------>| Succeeded |
| | | | /|\ | | /|\ | | /|\ | |
----------- ------------------------- | -------------- | -------------- | -------------
| | | | | |
Successfully | | Successfully | | Successfully | |
| | | | | |
\|/ | \|/ | \|/ |
------------------------ | -------------- | ------------- |
| | | | | | | | |
| InformationCollected |--------- | Identified |--------- | Recovered |---------
| | | | | |
------------------------ -------------- -------------
Abnormal CRD
Abnormal 是故障診斷恢復平臺中故障事件源、故障分析鏈、故障恢復鏈之間通信的接口。故障事件的詳情記錄在 Spec 中,故障事件源、故障分析鏈和故障恢復鏈對 Abnormal 進行處理並通過變更 Status 字段進行通信。故障診斷恢復平臺通過 Abnormal 提供以下功能:
- 記錄故障現象和來源,故障事件源會在接收到故障事件後將現象和來源寫入 AbnormalSpec 中。
- 維護故障恢復的狀態機,故障事件源、故障分析鏈、故障恢復鏈會在對故障恢復後將結果更新到 AbnormalStatus 中。
- 在節點上或容器內執行探測指令,如運行命令或者發送 HTTP 請求,並將結果輸出到 AbnormalStatus 中。
- 故障分析鏈將 Abnormal 逐個發送至故障分析器,故障分析器分析後輸出 Abnormal,故障分析鏈對輸出的 Abnormal 進行驗證後決定下一步流程。如果 Abnormal 被成功識別則更新 AbnormalStatus 並將 Abnormal 發往故障恢復鏈。如果無法識別或者發生錯誤則更新 AbnormalStatus 並等待人工干預。
- 故障恢復鏈將 Abnormal 逐個發送至故障恢復器,故障恢復器恢復後輸出 Abnormal,故障恢復鏈對輸出的 Abnormal 進行驗證後決定下一步流程。如果 Abnormal 被成功恢復則更新 AbnormalStatus。如果無法恢復或者發生錯誤則更新 AbnormalStatus 並等待人工干預。
Abnormal
Abnormal 是故障診斷恢復平臺中故障事件源、故障分析鏈、故障恢復鏈之間通信的接口,用於描述故障。
Field | Description | Scheme | Required |
---|---|---|---|
metadata | API 資源元數據。 | metav1.ObjectMeta | false |
spec | 故障的來源和現象說明。支持用戶自定義字段。 | AbnormalSpec | true |
status | 故障當前的狀態。由故障事件源、故障分析鏈、故障恢復鏈維護,用戶無法自行修改。 | AbnormalStatus | true |
AbnormalSpec
Field | Description | Scheme | Required |
---|---|---|---|
source | 故障的來源。該字段支持 Log、KubernetesEvent、PrometheusAlert、Probe 和 Custom。 | string | true |
log | 表示故障的日誌詳細信息,對應 source 字段的 Log。 | Log | false |
kubernetesEvent | 表示故障的 Kubernetes Event 詳細信息,對應 source 字段的 KubernetesEvent。 | corev1.Event | false |
prometheusAlert | 表示故障的 Prometheus Alert 詳細信息,對應 source 字段的 PrometheusAlert。 | PrometheusAlert | false |
nodeProbe | 用戶自定義的節點故障探測 Probe,支持 Probe 類型故障。 | NodeProbe | false |
podProbe | 用戶自定義的容器故障探測 Probe,支持 Probe 類型故障。 | PodProbe | false |
skipDiagnosis | 跳過故障分析步驟。 | bool | false |
skipRecovery | 跳過故障恢復步驟。 | bool | false |
nodeName | Abnormal 所在節點名。 | string | false |
assignedDiagnosers | 指定進行診斷的故障診斷器列表。 | []NamespacedName | false |
assignedRecoverers | 指定進行恢復的故障恢復器列表。 | []NamespacedName | false |
assignedInformationCollectors | 指定進行信息採集的信息採集器列表。 | []NamespacedName | false |
context | 用於擴展的上下文信息,支持 Custom 類型故障。 | runtime.RawExtension | false |
Log
Field | Description | Scheme | Required |
---|---|---|---|
filePath | 日誌文件的絕對路徑。 | string | true |
logEntry | 日誌中表示故障的條目。 | string | true |
PrometheusAlert
Field | Description | Scheme | Required |
---|---|---|---|
labels | Alert 的標籤。 | labels.Labels | true |
annotations | Alert 的註解。 | labels.Labels | true |
startsAt | 告警的開始時間 | metav1.Time | false |
endsAt | 告警的結束時間 | metav1.Time | false |
generatorURL | 告警生成者的 URL | string | false |
NodeProbe
Field | Description | Scheme | Required |
---|---|---|---|
name | 執行 Probe 的 Node。 | string | true |
timeoutSeconds | Probe 執行超時時間。 | int32 | false |
exec | Exec 命令。 | corev1.ExecAction | false |
httpGet | HTTP 請求。 | corev1.HTTPGetAction | false |
tcpSocket | TCP 探活。 | corev1.TCPSocketAction | false |
PodProbe
Field | Description | Scheme | Required |
---|---|---|---|
namespace | 執行 Probe 的 Pod 命名空間。 | string | true |
name | 執行 Probe 的 Pod。 | string | true |
container | 執行 Probe 的容器。 | string | true |
timeoutSeconds | Probe 執行超時時間。 | int32 | false |
exec | Exec 命令。 | corev1.ExecAction | false |
httpGet | HTTP 請求。 | corev1.HTTPGetAction | false |
tcpSocket | TCP 探活。 | corev1.TCPSocketAction | false |
AbnormalStatus
Field | Description | Scheme | Required |
---|---|---|---|
identifiable | 表示該故障爲可以被故障分析器識別的故障。 | bool | true |
recoverable | 表示該故障爲可以被故障恢復器恢復的故障。 | bool | true |
conditions | 描述故障恢復流程中關鍵點的狀況。 | []AbnormalCondition | false |
phase | 故障的當前階段。該字段支持 InformationCollecting、Diagnosing、Recovering、Succeeded、Failed、Unknown。 | string | false |
message | 表示當前故障恢復階段的可讀信息。用於輸出故障原因、故障恢復建議等。 | string | false |
reason | 表示當前故障恢復階段的簡短信息。 | string | false |
output | Exec 命令、HTTP 請求、TCP 探活的輸出。 | string | false |
startTime | 表示當前故障開始被診斷的時間。 | metav1.Time | false |
diagnoser | 成功執行的故障診斷器。 | NamespacedName | false |
recoverer | 成功執行的故障恢復器。 | NamespacedName | false |
context | 用於擴展的上下文信息,支持 Custom 類型故障。 | runtime.RawExtension | false |
AbnormalCondition
Field | Description | Scheme | Required |
---|---|---|---|
type | 故障狀況的類型。 | string | true |
status | 故障狀況的狀態。該字段支持 True、False、Unknown。 | string | true |
lastTransitionTime | 上一次狀況的狀態變化時間。 | metav1.Time | false |
message | 表示當前狀況的狀態變化原因的可讀信息。 | string | false |
reason | 表示當前狀況的狀態變化原因的簡短信息。 | string | false |
NamespacedName
Field | Description | Scheme | Required |
---|---|---|---|
namespace | API 資源的命名空間。 | string | false |
name | API 資源的名稱。 | string | true |
故障事件源
故障事件源是獲取故障事件的接口,大致可分爲以下幾類,每一類都需要實現故障事件源接口:
- 日誌:日誌是獲悉集羣發生故障的重要手段,通過監聽內核、Kubernetes 以及 Docker 日誌中的異常字段可以在第一時間發現故障並進行處理。
- Prometheus:Prometheus 滿足雲原生體系中絕大部分組件的監控需求,大部分組件的內部異常可由 Prometheus 接口暴露。
- Event:Kubernetes 中的事件支持更細緻的故障上報機制。
- CRD:CRD 用於自定義故障,用戶可以自定義進行擴展。
故障事件源在消費日誌、Prometheus 報警和 Event 後會生成 Abnormal 故障事件併發往故障分析鏈。用戶也可以直接通過 CRD 來創建故障事件。
故障分析鏈
故障分析鏈是一個調用鏈框架,本身並不包含故障分析的邏輯,用戶需要實現故障分析的具體邏輯並註冊到故障分析鏈中。故障分析鏈從故障事件源接收故障事件並將故障事件逐一傳入被註冊的故障分析器中,當故障事件能夠被某個故障分析器識別則中止調用並交由該邏輯進行處理。如果故障無法被任何故障分析器識別則直接獲取相關排障信息並報警。故障分析器一般是一個 HTTP 服務器。用戶可以將自定義故障診斷分析的腳本放入特定路徑,故障分析鏈會動態的獲取自定義故障診斷分析文件。
故障分析器在無法識別 Abnormal 故障事件時返回錯誤,故障分析器在成功識別 Abnormal 故障事件後變更 Status 字段。故障分析鏈在某個故障分析器成功識別 Abnormal 故障事件後將 Abnormal 故障事件發往故障恢復鏈。故障分析器在執行診斷時可以通過調用信息採集器獲取更多信息。
信息管理器
當故障分析或恢復流程較複雜時,需要從其他接口獲取更多信息用於故障的診斷和確認。此時故障分析器或故障恢復器可以調用信息採集器獲取更多信息。常用的信息採集器包括 eBPF、Golang 剖析文件、Java 虛擬機工具等。信息採集器一般是一個 HTTP 服務器。故障分析器或故障恢復器需要保證能夠正確處理從信息採集器獲取的信息。信息管理器用於管理多個信息採集器,用戶通過請求信息管理器獲取額外信息,信息管理器在接收到請求後會轉發到相應的信息採集器中。
故障恢復鏈
和故障分析鏈相似,故障恢復鏈也是一個調用鏈框架,本身並不包含故障恢復的邏輯,用戶需要實現故障恢復的具體邏輯並註冊到故障恢復鏈中。故障恢復鏈從故障分析鏈接收故障事件並將故障事件逐一傳入被註冊的故障恢復器中,當故障能夠被某個故障恢復器識別則中止調用並交由該邏輯進行處理。如果故障無法被任何故障恢復器識別則報錯中止。故障恢復器一般是一個 HTTP 服務器。用戶可以將自定義故障恢復的腳本放入特定路徑,故障恢復鏈會動態的獲取自定義故障恢復文件。
典型用例
社區 Issue 3529 中記錄的 Bug 會導致 Docker 18.06 及以下版本因爲 Shim 的死鎖而無法正常終止容器。當該故障出現時可以通過以下步驟實現該故障的診斷恢復:
- 實現故障事件源:獲取當前 Terminating 狀態的 Pod,當該類 Pod 存在時創建表示該故障的 CRD,標記
.spec.nodeName
字段爲該 Pod 所處節點。 - 實現故障分析器:首先通過進程樹查找到該容器對應的 Shim 進程。然後向該 Shim 進程發送 SIGUSR1 信號獲取棧信息,在棧信息中查找
reaper.go
相關函數以確定問題原因。 - 實現故障恢復器:殺死該容器對應的 Shim 進程進行恢復。
作者簡介:
黃久遠,網易杭州研究院輕舟雲原生資深研發工程師。專注於雲原生以及分佈式系統等領域,作爲核心成員參與了網易集團內部容器化落地以及網易輕舟容器平臺產品化。目前主要負責網易輕舟雲原生故障自動診斷系統的設計、開發以及商業化產品輸出等工作。