您的位置:  首页 > 技术杂谈 > 正文

KubeDiag 框架技术解析

2021-11-10 15:00 https://my.oschina.net/u/4565392/blog/5304265 网易数帆 次阅读 条评论

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。

  • 0
    感动
  • 0
    路过
  • 0
    高兴
  • 0
    难过
  • 0
    搞笑
  • 0
    无聊
  • 0
    愤怒
  • 0
    同情
热度排行
友情链接