KubeDiag 框架技術解析

語言: CN / TW / HK

KubeDiag 是基於 Kubernetes 雲原生基礎設施能力打造的開源框架,旨在解決雲原生體系中運維診斷的自動化問題,幫助使用者更加平滑地完成容器化落地。本文將為大家解讀 KubeDiag 整體框架設計。

Kubernetes 是一個生產級的容器編排引擎,但是 Kubernetes 仍然存在系統複雜、故障診斷成本高等問題。網易數帆近期開源的 KubeDiag,是基於 Kubernetes 雲原生基礎設施能力打造的框架,旨在解決雲原生體系中故障診斷、運維恢復的自動化問題。主要包括以下幾個維度:

  • 由 Kubernetes 以及 Docker 的 Bug 引起的故障。
  • 核心 Bug 導致的故障。
  • 基礎設施抖動產生的問題。
  • 使用者在容器化以及使用 Kubernetes 過程中遇到的問題。
  • 使用者在容器化後遇到的業務相關問題。

專案地址:https://github.com/kubediag/kubediag

設計目標

KubeDiag 的設計目標包括:

  • 可移植性:可以在部署 Kubernetes 的 Linux 標準環境下執行。
  • 可擴充套件性:使用者可以整合自定義的診斷功能。模組之間通過鬆耦合介面互動並且各功能模組均是可插拔式的。
  • 自動化:極大降低問題診斷的人力成本。使用者可以通過宣告式 API 定義診斷工作流並且在問題發生時自動執行。
  • 易用性:內建常見問題診斷邏輯以提供開箱即用的體驗。

架構設計

KubeDiag 由 Master 和 Agent 組成,並且從 APIServer 以及 Prometheus 等元件獲取資料。

架構設計

KubeDiag Master 設計

KubeDiag Master 負責管理 Operation、OperationSet、Trigger 和 Diagnosis 物件。當 OperationSet 建立後,KubeDiag Master 會進行合法性檢查並基於使用者定義生成有向無環圖,所有的診斷路徑被更新至 OperationSet 的元資料中。如果 OperationSet 中某個 Operation 的前置依賴診斷操作不存在,則該 OperationSet 會被標記為異常。

KubeDiag Master 會校驗 Diagnosis 的 PodReference 或 NodeName 是否存在,如果 Diagnosis 中只定義了 PodReference,則根據 PodReference 計算並更新 NodeName。KubeDiag Master 會查詢被 Diagnosis 引用的 OperationSet 狀態,如果被引用的 OperationSet 異常,則標記 Diagnosis 失敗。Diagnosis 可以由使用者直接手動建立,也可以通過配置 Prometheus 報警模板或 Kubernetes 事件模板自動建立。

KubeDiag Master 由下列部分組成:

  • 圖構建器(GraphBuilder)
  • Prometheus 報警管理器(Alertmanager)
  • Kafka 訊息管理器(KafkaConsumer)
  • 事件管理器(Eventer)

圖構建器

圖構建器基於 OperationSet 物件生成診斷執行流程圖。圖構建器根據 OperationSet 中包含的邊生成有向無環圖並計算出所有的診斷路徑。

Prometheus 報警管理器

Prometheus 報警管理器接收 Prometheus 報警並建立 Diagnosis 物件。Prometheus 報警管理器可以接收 Prometheus 報警並與 Trigger 中定義的模板進行匹配,如果匹配成功則根據 Trigger 的元資料建立 Diagnosis 物件。

Kafka 訊息管理器

Kafka 訊息管理器接收 Kafka 訊息並建立 Diagnosis 物件。Kafka 訊息的值必須是一個 JSON 物件並且包含建立 Diagnosis 所需的元資訊。

事件管理器

事件管理器接收 Kubernetes 事件並建立 Diagnosis 物件。事件管理器可以接收 Kubernetes 事件並與 Trigger 中定義的模板進行匹配,如果匹配成功則根據 Trigger 的元資料建立 Diagnosis 物件。

KubeDiag Agent 設計

KubeDiag Agent 負責實際診斷工作的執行並內建多個常用診斷操作。當 Diagnosis 建立後,KubeDiag Agent 會根據 Diagnosis 引用的 OperationSet 執行診斷工作流,診斷工作流是包括多個診斷操作的集合。

KubeDiag Agent 元件由下列部分組成:

  • 執行器(Executor)

執行器

執行器負責執行診斷工作流。Diagnosis 引用的 OperationSet 元資料中包含表示診斷工作流的有向無環圖和所有的診斷路徑。診斷路徑表示診斷過程中的排查路徑,通過執行某個診斷路徑中每個頂點的診斷操作可以對問題進行排查。如果某個診斷路徑的所有診斷操作均執行成功,則該次診斷被標記為成功。如果所有診斷路徑均執行失敗,則該次診斷被標記為失敗。

實現細節

KubeDiag 通過實現 Operation、OperationSet、Trigger 和 Diagnosis 自定義資源對一次運維診斷的過程進行抽象。

對於診斷的管理

KubeDiag 通過支援下列功能來滿足使用者管理診斷的需求:

  • 指定診斷的目標 Node 或 Pod。
  • 檢視當前診斷的階段。
  • 通過引數擴充套件診斷的狀態。
  • 診斷成功時檢視診斷的結果以及排查路徑。
  • 診斷失敗時檢視失敗的原因以及排查路徑。
  • 檢視診斷過程中某個階段的詳細資訊。

Diagnosis 物件

Diagnosis 物件的資料結構如下:

// DiagnosisSpec 定義了 Diagnosis 的目標狀態。
type DiagnosisSpec struct {
    // OperationSet 是待執行診斷流水線的 OperationSet 名。
    OperationSet string `json:"operationSet"`
    // 必須指定 NodeName 或 PodReference 其中的一個欄位。
    // NodeName 是診斷執行的節點。
    NodeName string `json:"nodeName,omitempty"`
    // PodReference 包含目標 Pod 的詳細資訊。
    PodReference *PodReference `json:"podReference,omitempty"`
    // Parameters 包含診斷過程中需要傳入的引數。
    // 通常該欄位的鍵為 OperationSet 中頂點的序號,值為執行該頂點診斷操作需要的引數。
    // Parameters 和 OperationResults 會被序列化為 JSON 物件並在執行診斷的過程中傳送給故障處理器。
    Parameters map[string]string `json:"parameters,omitempty"`
}

// PodReference 包含目標 Pod 的詳細資訊。
type PodReference struct {
    NamespacedName `json:",inline"`
    // Container 是目標容器名。
    Container string `json:"container,omitempty"`
}

// NamespacedName 表示 Kubernetes API 物件。
type NamespacedName struct {
    // Namespace 是 Kubernetes API 物件名稱空間。
    Namespace string `json:"namespace"`
    // Namespace 是 Kubernetes API 物件名。
    Name string `json:"name"`
}

// DiagnosisStatus 定義了 Diagnosis 的實際狀態。
type DiagnosisStatus struct {
    // Phase 是 Diagnosis 在其生命週期中所處位置的簡單巨集觀概述。狀況列表包含更多關於 Diagnosis 狀態的資訊。
    // 階段可能存在五種不同的值:
    //
    // Pending:Diagnosis 已被系統接受,但診斷執行前的準備工作還未完成。
    // Running:Diagnosis 已經繫結到了某個節點,至少有一個診斷操作正處於執行狀態。
    // Succeeded:診斷流水線中某個路徑中的所有診斷操作均執行成功。
    // Failed:診斷流水線中的所有路徑失敗。也就是說,所有路徑中最後一個執行的診斷操作返回碼非 200。
    // Unknown:因為某些原因無法取得 Diagnosis 的狀態。這種情況通常是因為與 Diagnosis 所在主機通訊失敗。
    Phase DiagnosisPhase `json:"phase,omitempty"`
    // Conditions 包含 Diagnosis 當前的服務狀態。
    Conditions []DiagnosisCondition `json:"conditions,omitempty"`
    // StartTime 是物件被系統接收的 RFC 3339 日期和時間。
    StartTime metav1.Time `json:"startTime,omitempty"`
    // FailedPaths 包含診斷流水線中所有執行失敗的路徑。路徑的最後一個頂點是操作執行失敗的頂點。
    FailedPaths []Path `json:"failedPath,omitempty"`
    // SucceededPath 是診斷流水線中執行成功的路徑。
    SucceededPath Path `json:"succeededPath,omitempty"`
    // OperationResults 包含診斷執行過程中操作的結果。
    // Parameters 和 OperationResults 會被序列化為 JSON 物件並在執行診斷的過程中傳送給故障處理器。
    OperationResults map[string]string `json:"operationResults,omitempty"`
    // Checkpoint 是恢復未完成診斷的檢查點。
    Checkpoint *Checkpoint `json:"checkpoint,omitempty"`
}

// DiagnosisCondition 包含 Diagnosis 當前的服務狀態。
type DiagnosisCondition struct {
    // Type 是狀況的型別。
    Type DiagnosisConditionType `json:"type"`
    // Status 是狀況的狀態。
    // 可以是 True、False、Unknown。
    Status corev1.ConditionStatus `json:"status"`
    // LastTransitionTime 描述了上一次從某個狀況遷移到另一個狀況的時間。
    LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"`
    // Reason 是對上一次狀況遷移的描述,該原因描述是唯一的、只包含單個詞語的、符合駝峰命名法的。
    Reason string `json:"reason,omitempty"`
    // Message 是描述上一次狀況遷移細節的資訊。
    Message string `json:"message,omitempty"`
}

// Checkpoint 是恢復未完成診斷的檢查點。
type Checkpoint struct {
    // PathIndex 是當前路徑在 OperationSet 狀態中的序號。
    PathIndex int `json:"pathIndex"`
    // NodeIndex 是當前頂點在路徑中的序號。
    NodeIndex int `json:"nodeIndex"`
}

// DiagnosisPhase 是描述當前 Diagnosis 狀況的標籤。
type DiagnosisPhase string

// DiagnosisConditionType 是 Diagnosis 狀況型別的合法值。
type DiagnosisConditionType string

// Diagnosis 的 API 物件。
type Diagnosis struct {
    metav1.TypeMeta   `json:",inline"`
    metav1.ObjectMeta `json:"metadata,omitempty"`

    Spec   DiagnosisSpec   `json:"spec,omitempty"`
    Status DiagnosisStatus `json:"status,omitempty"`
}

管理診斷狀態的遷移

診斷實際上是一個有狀態的任務,在診斷的生命週期中其狀態可能發生多次遷移,管理診斷狀態遷移的能力在很多場景中是必不可少的。

某個操作可能依賴特定格式的輸入。Diagnosis 中的 .spec.parameters 欄位用於指定診斷過程中需要傳入的引數。該欄位是一個鍵值對,鍵和值均必須為 String 型別。當執行的操作依賴特定格式的輸入時,使用者可以在該欄位中定義操作執行時需要輸入的引數,操作處理器在獲取引數後執行診斷操作。

某個操作可能依賴某個之前操作的輸出。Diagnosis 中的 .status.operationResults 欄位用於記錄診斷執行過程中操作的結果。該欄位是一個鍵值對,鍵和值均必須為 String 型別。當前操作執行的結果必須以 JSON 物件的形式返回,返回結果會被更新到該欄位中,如果後續操作的執行依賴當前操作的輸出,那麼後續操作處理器可以從 .status.operationResults 中獲取當前操作的結果。值得注意的是,如果在排查路徑中如果有兩個相同的操作對同一個鍵進行了更新,那麼後執行操作的結果會覆蓋先執行操作的結果。

使用者需要分析排查路徑中某個操作的結果並進行優化。Diagnosis 中的 .status.failedPath 欄位和 .status.succeededPath 欄位分別記錄了所有執行失敗的路徑和成功的路徑。每條路徑由一個數組表示,陣列的元素中包含頂點的序號和操作名。通過遍歷路徑可以還原操作執行的順序,每個操作結果的訪問資訊被記錄在 Operation 中的 .spec.storage 欄位。

Diagnosis 階段

Diagnosis 包含 .status.phase 欄位,該欄位是 Diagnosis 在其生命週期中所處位置的簡單巨集觀概述。該階段並不是對 Diagnosis 狀態的綜合彙總,也不是為了成為完整的狀態機。Diagnosis 階段的數量和含義是嚴格定義的。除了本文件中列舉的內容外,不應該再假定 Diagnosis 有其他的階段值。

下面是 .status.phase 可能的值:

  • Pending:Diagnosis 已被系統接受,但診斷執行前的準備工作還未完成。
  • Running:Diagnosis 已經繫結到了某個節點,至少有一個診斷操作正處於執行狀態。
  • Succeeded:診斷流水線中某個路徑中的所有診斷操作均執行成功。
  • Failed:診斷流水線中的所有路徑失敗。也就是說,所有路徑中最後一個執行的診斷操作返回碼非 200。
  • Unknown:因為某些原因無法取得 Diagnosis 的狀態。這種情況通常是因為與 Diagnosis 所在主機通訊失敗。

基於圖的診斷流水線

我們在設計基於圖的診斷流水線時主要考慮了以下假設條件:

  • 有限可終止:整個流水線不是無限執行的,在一定時間和空間複雜度內能夠終止執行。
  • 過程可追溯:診斷結束後可以檢視執行過程中某個頂點產生的結果。
  • 狀態機可擴充套件:支援增加新的處理頂點到流水線中。

KubeDiag 通過引入下列 API 物件實現了基於圖的診斷流水線:

  • Operation:描述如何在診斷流水線中加入處理頂點以及如何儲存該處理頂點產生的結果。
  • OperationSet:表示診斷過程狀態機的有向無環圖。
  • Trigger:描述如何通過 Prometheus 報警或 Kubernetes 事件觸發一次診斷。

Operation 物件

Operation 物件的資料結構如下:

// OperationSpec 定義了 Operation 的目標狀態。
type OperationSpec struct {
    // Processor 描述瞭如何在 KubeDiag 中註冊一個操作處理器。
    Processor Processor `json:"processor"`
    // Dependences 是所有被依賴且必須預先執行的診斷操作列表。
    Dependences []string `json:"dependences,omitempty"`
    // Storage 表示操作處理結果的儲存型別。
    // 如果該欄位為空,那麼操作處理結果不會被儲存。
    Storage *Storage `json:"storage,omitempty"`
}

// Processor 描述瞭如何在 KubeDiag 中註冊一個操作處理器。
type Processor struct {
    // ExternalAddress 是操作處理器的監聽地址。
    // 如果該欄位為空,那麼預設為 KubeDiag Agent 的地址。
    ExternalAddress *string `json:"externalAddress,omitempty"`
    // ExternalPort 是操作處理器的服務埠。
    // 如果該欄位為空,那麼預設為 KubeDiag Agent 的服務埠。
    ExternalPort *int32 `json:"externalPort,omitempty"`
    // Path 是操作處理器服務的 HTTP 路徑。
    Path *string `json:"path,omitempty"`
    // Scheme 是操作處理器服務的協議。
    Scheme *string `json:"scheme,omitempty"`
    // 操作處理器超時的秒數。
    // 預設為 30 秒。最小值為 1。
    TimeoutSeconds *int32 `json:"timeoutSeconds,omitempty"`
}

// Storage 表示操作結果的儲存型別。
type Storage struct {
    // HostPath 表示宿主機上的目錄。
    HostPath *HostPath `json:"hostPath,omitempty"`
}

// HostPath 表示宿主機上的目錄。
type HostPath struct {
    // 宿主機上目錄的路徑。
    // 如果該欄位為空,那麼預設為 KubeDiag Agent 的資料根目錄。
    Path string `json:"path"`
}

// Operation 的 API 物件。
type Operation struct {
    metav1.TypeMeta   `json:",inline"`
    metav1.ObjectMeta `json:"metadata,omitempty"`

    Spec OperationSpec `json:"spec,omitempty"`
}

OperationSet 物件

OperationSet 物件的資料結構如下:

// OperationSetSpec 定義了 OperationSet 的目標狀態。
type OperationSetSpec struct {
    // AdjacencyList 包含有向無環圖中所有表示診斷操作的頂點。
    // 陣列的第一個頂點表示診斷的開始而不是某個特定的診斷操作。
    AdjacencyList []Node `json:"adjacencyList"`
}

// Node 是有向無環圖中的一個頂點。它包含序號和操作名。
type Node struct {
    // ID 是該頂點的唯一識別符號。
    ID int `json:"id"`
    // To 是從該頂點能夠直接到達的頂點序號列表。
    To NodeSet `json:"to,omitempty"`
    // Operation 是在該頂點執行的操作名。
    Operation string `json:"operation"`
    // Dependences 是所有被依賴且必須預先執行的診斷操作 ID 列表。
    Dependences []int `json:"dependences,omitempty"`
}

// NodeSet 是一組頂點序號。
type NodeSet []int

// OperationSetStatus 定義了 OperationSet 的實際狀態。
type OperationSetStatus struct {
    // Paths 是有向無環圖中所有診斷路徑的集合。
    Paths []Path `json:"paths,omitempty"`
    // 表示定義中提供的頂點是否能生成合法的有向無環圖。
    Ready bool `json:"ready,omitempty"`
}

// Path 表示與所有邊方向一致的頂點線性順序。
type Path []Node

// OperationSet 的 API 物件。
type OperationSet struct {
    metav1.TypeMeta   `json:",inline"`
    metav1.ObjectMeta `json:"metadata,omitempty"`

    Spec OperationSetSpec `json:"spec,omitempty"`
    Status OperationSetStatus `json:"status,omitempty"`
}

Trigger 物件

Trigger 物件的資料結構如下:

// TriggerSpec 定義了 Trigger 的目標狀態。
type TriggerSpec struct {
    // OperationSet 是生成 Diagnosis 中引用的 OperationSet 名。
    OperationSet string `json:"operationSet"`
    // SourceTemplate 是用於生成 Diagnosis 的模板源。
    SourceTemplate SourceTemplate `json:"sourceTemplate"`
}

// SourceTemplate 描述用於生成 Diagnosis 的資訊。
type SourceTemplate struct {
    // 下列源中必須指定一個唯一的模板源。
    // PrometheusAlertTemplate 宣告基於 Prometheus 報警建立 Diagnosis 的模板。
    PrometheusAlertTemplate *PrometheusAlertTemplate `json:"prometheusAlertTemplate,omitempty"`
    // KubernetesEventTemplate 宣告基於 Event 建立 Diagnosis 的模板。
    KubernetesEventTemplate *KubernetesEventTemplate `json:"kubernetesEventTemplate,omitempty"`
}

// PrometheusAlertTemplate 宣告基於 Prometheus 報警建立 Diagnosis 的模板。
type PrometheusAlertTemplate struct {
    // Regexp 是用於匹配 Prometheus 報警模板的正則表示式。
    Regexp PrometheusAlertTemplateRegexp `json:"regexp"`
    // NodeNameReferenceLabel 指定用於設定 Diagnosis 的 ".spec.nodeName" 欄位的標籤鍵。
    NodeNameReferenceLabel model.LabelName `json:"nodeNameReferenceLabel"`
    // PodNamespaceReferenceLabel 指定用於設定 Diagnosis 的 ".spec.podReference.namespace" 欄位的標籤鍵。
    PodNamespaceReferenceLabel model.LabelName `json:"podNamespaceReferenceLabel,omitempty"`
    // PodNameReferenceLabel 指定用於設定 Diagnosis 的 ".spec.podReference.name" 欄位的標籤鍵。
    PodNameReferenceLabel model.LabelName `json:"podNameReferenceLabel,omitempty"`
    // ContainerReferenceLabel 指定用於設定 Diagnosis 的 ".spec.podReference.container" 欄位的標籤鍵。
    ContainerReferenceLabel model.LabelName `json:"containerReferenceLabel,omitempty"`
    // ParameterInjectionLabels 指定需要注入到 ".spec.parameters" 欄位的標籤鍵列表。
    ParameterInjectionLabels []model.LabelName `json:"parameterInjectionLabels,omitempty"`
}

// PrometheusAlertTemplateRegexp 是用於匹配 Prometheus 報警模板的正則表示式。
// 所有的正則表示式必須遵循 RE2 規範,詳情可參考 https://golang.org/s/re2syntax。
type PrometheusAlertTemplateRegexp struct {
    // AlertName 是用於匹配 Prometheus 報警的 AlertName 欄位的正則表示式。
    AlertName string `json:"alertName,omitempty"`
    // Labels 是用於匹配 Prometheus 報警的 Labels 欄位的正則表示式。
    // 只有標籤的值為正則表示式並且所有標籤均與 Prometheus 報警一致時才可以成功匹配。
    Labels model.LabelSet `json:"labels,omitempty"`
    // Annotations 是用於匹配 Prometheus 報警的 Annotations 欄位的正則表示式。
    // 只有註解的值為正則表示式並且所有註解均與 Prometheus 報警一致時才可以成功匹配。
    Annotations model.LabelSet `json:"annotations,omitempty"`
    // StartsAt 是用於匹配 Prometheus 報警的 StartsAt 欄位的正則表示式。
    StartsAt string `json:"startsAt,omitempty"`
    // EndsAt 是用於匹配 Prometheus 報警的 EndsAt 欄位的正則表示式。
    EndsAt string `json:"endsAt,omitempty"`
    // GeneratorURL 是用於匹配 Prometheus 報警的 GeneratorURL 欄位的正則表示式。
    GeneratorURL string `json:"generatorURL,omitempty"`
}

// KubernetesEventTemplate 宣告基於 Event 建立 Diagnosis 的模板。
type KubernetesEventTemplate struct {
    // Regexp 是用於匹配 Event 模板的正則表示式。
    Regexp KubernetesEventTemplateRegexp `json:"regexp"`
}

// KubernetesEventTemplateRegexp 是用於匹配 Event 模板的正則表示式。
// 所有的正則表示式必須遵循 RE2 規範,詳情可參考 https://golang.org/s/re2syntax。
type KubernetesEventTemplateRegexp struct {
    // Name 是用於匹配 Event 的 Name 欄位的正則表示式。
    Name string `json:"name,omitempty"`
    // Namespace 是用於匹配 Event 的 Namespace 欄位的正則表示式。
    Namespace string `json:"namespace,omitempty"`
    // Reason 是用於匹配 Event 的 Reason 欄位的正則表示式。
    Reason string `json:"reason,omitempty"`
    // Message 是用於匹配 Event 的 Message 欄位的正則表示式。
    Message string `json:"message,omitempty"`
    // Source 是用於匹配 Event 的 Source 欄位的正則表示式。
    // 所有 Source 中的欄位均為正則表示式。
    Source corev1.EventSource `json:"source,omitempty"`
}

// Trigger 的 API 物件。
type Trigger struct {
    metav1.TypeMeta   `json:",inline"`
    metav1.ObjectMeta `json:"metadata,omitempty"`

    Spec TriggerSpec `json:"spec,omitempty"`
}

註冊診斷操作

診斷操作表示在診斷流水線中執行的某個邏輯,是對診斷流水線管理的最小單元,例如獲取節點資訊、對日誌中的關鍵字進行匹配、對程序進行效能剖析等。通過建立 Operation 物件可以註冊診斷操作。診斷操作的後端是一個 HTTP 伺服器。註冊診斷操作時需要指定 HTTP 伺服器監聽的地址、路徑、診斷結果的儲存型別等。

註冊診斷流水線

診斷流水線是多個診斷操作的集合,通常一次診斷可能有多個排查路徑,所以一次診斷的狀態機通過有向無環圖進行抽象。通過建立 OperationSet 物件可以定義表示診斷狀態機的有向無環圖。診斷開始的狀態為有向無環圖的起點,有向無環圖中的路徑均為診斷過程中的排查路徑,當某條路徑可以成功執行到終點時則表示診斷執行成功。診斷流水線的生成邏輯如下:

  1. 使用者建立 OperationSet 資源並定義有向無環圖中所有的邊。
  2. 根據 OperationSet 的定義構建有向無環圖。
  3. 如果無法構建合法的有向無環圖,則將註冊失敗的狀態和失敗原因更新到 OperationSet 中。
  4. 列舉 OperationSet 中所有的診斷路徑並更新到 OperationSet 中。

表示診斷流水線的有向無環圖必須只包含一個源頂點(Source Node),該頂點用於表示診斷的開始狀態且不包含任何診斷操作。診斷路徑是任何從源頂點到任意阱頂點(Sink Node)的路徑。診斷路徑不包括表示診斷的開始狀態的源頂點。圖構建器通過搜尋出有向無環圖中所有的診斷路徑並更新至 OperationSet 的 .status.paths 欄位。

觸發診斷

Diagnosis 物件的元資料中包含了需要執行的 OperationSet。觸發診斷包括手動和自動兩種方式。通過手動建立 Diagnosis 物件可以直接觸發診斷。通過建立 Trigger 物件並配置 Prometheus 報警模板或 Event 模板可以基於 Prometheus 或 Event 自動生成 Diagnosis 以觸發診斷流水線。

執行診斷流水線

Diagnosis 物件的元資料中記錄了診斷流水線的執行狀態。診斷流水線的執行邏輯如下:

  1. 獲取被 Diagnosis 引用的 OperationSet 中所有的診斷路徑。
  2. 按照診斷執行路徑中 Operation 定義的診斷操作,將 Operation 執行的結果更新到 Diagnosis 中並持久化到 Operation 中相應的儲存型別。
  3. 如果路徑中定義的某個診斷操作執行失敗,則執行下一條診斷路徑。
  4. 如果路徑中定義的所有診斷操作均執行成功,則該次診斷成功。
  5. 如果所有路徑均無法成功,則該次診斷失敗。

診斷流水線

上列為一個表示診斷流水線的有向無環圖,每個節點代表一個 Operation,該圖的診斷路徑表示多個可執行的排查路徑:

  • 資料收集 1、資料分析 1、恢復 1
  • 資料收集 1、資料分析 1、恢復 2
  • 資料收集 2、資料分析 2、恢復 2
  • 資料收集 3、資料收集 4

典型用例

下列檔案定義了一個用於處理 Docker 問題的 OperationSet:

apiVersion: diagnosis.kubediag.org/v1
kind: OperationSet
metadata:
  name: docker-debugger
spec:
  adjacencyList:
  - id: 0 
    to:
    - 1
  - id: 1 
    operation: docker-info-collector
    to:
    - 2
  - id: 2 
    operation: dockerd-goroutine-collector
    to:
    - 3
  - id: 3 
    operation: containerd-goroutine-collector
    to:
    - 4
  - id: 4
    operation: node-cordon

一次通過 KubeletPlegDurationHigh 報警觸發 Docker 問題診斷的流程如下:

  • 使用者成功建立處理 Docker 問題的 OperationSet。
  • 使用者成功建立基於 KubeletPlegDurationHigh 報警觸發診斷的 Trigger
  • KubeletPlegDurationHigh 報警被髮送至 KubeDiag Master。
  • KubeDiag Master 根據報警中的資訊建立 Diagnosis。
  • Diagnosis 在觸發報警的節點上執行。
    • 採集 Docker 相關資訊。
    • 採集 Dockerd 的 Goroutine。
    • 採集 Containerd 的 Goroutine。
    • 將觸發報警的節點置為不可排程。
  • 診斷執行結束。

KubeletPlegDurationHigh 報警觸發診斷時序圖

歡迎加入社群

最後,KubeDiag 社群目前還在草創階段,歡迎大家踴躍加入 KubeDiag 社群,共同提升 Kubernetes 的自動化程度,解決後容器時代的使用難題,推動雲原生技術在全球落地應用。

KubeDiag 專案主頁:https://kubediag.org/

KubeDiag 專案地址:https://github.com/kubediag/kubediag

掃碼加入 KubeDiag 微信群:https://kubediag.nos-eastchina1.126.net/QR%20Code.jpeg

作者:黃久遠,網易數帆雲原生技術專家,KubeDiag Maintainer。