Operator AIOps 实战

2025-11-08T14:11:02+08:00 | 3分钟阅读 | 更新于 2025-11-08T14:11:02+08:00

@

实战目标

在前一篇笔记中,我们学习了 Operator 的基本结构与 reconcile 机制。本篇将结合 LLM,构建一个简易的 AIOps Operator,使其能够:

  1. 接收用户声明的 AITask 自定义资源。
  2. 根据配置定期采集目标 Deployment 的状态和指标。
  3. 当触发阈值或异常状态时,调用 LLM 进行根因分析。
  4. 根据 LLM 的决策,自动执行修复动作(如重启 Pod、扩容)。

这种将 AI 推理能力嵌入 Kubernetes 控制平面的方式,是 AIOps 平台化的重要方向。

AIOps Operator 设计

CRD 定义

我们定义一个名为 AutoHeal 的 CRD:

apiVersion: aiops.example.com/v1
kind: AutoHeal
metadata:
  name: api-gateway-healer
  namespace: prod
spec:
  targetDeployment: api-gateway
  namespace: prod
  metricsSource: prometheus
  query: |
    histogram_quantile(0.99,
      rate(http_request_duration_seconds_bucket[5m]))    
  threshold: 0.5
  action: restart_pod
  llmEndpoint: http://llm-service:8000/v1/chat
status:
  phase: Monitoring
  lastDecision: ""
  lastExecutionTime: ""

控制器逻辑

控制器 reconcile 流程如下:

1. 读取 AutoHeal CR
2. 查询 Prometheus 获取当前指标
3. 若指标超过 threshold,构造 Prompt 调用 LLM
4. 解析 LLM 返回的 action
5. 执行 action(client-go 调用)
6. 更新 AutoHeal status
7. RequeueAfter 继续下一轮监控

核心代码示例

指标查询

func queryPrometheus(url, promql string) (float64, error) {
    resp, err := http.Get(fmt.Sprintf("%s/api/v1/query?query=%s", url, url.QueryEscape(promql)))
    if err != nil {
        return 0, err
    }
    defer resp.Body.Close()
    // 解析 JSON 提取 value
    return parsePrometheusValue(resp.Body)
}

LLM 调用与决策

func askLLM(endpoint, context string) (string, error) {
    prompt := fmt.Sprintf(`
你是一名 Kubernetes SRE。当前系统监控信息如下:
%s

请从以下动作中选择一个并直接返回动作名称:restart_pod / scale_up / noop
`, context)

    reqBody, _ := json.Marshal(map[string]interface{}{
        "model": "gpt-4",
        "messages": []map[string]string{
            {"role": "user", "content": prompt},
        },
    })

    resp, err := http.Post(endpoint, "application/json", bytes.NewBuffer(reqBody))
    if err != nil {
        return "", err
    }
    defer resp.Body.Close()

    // 解析 LLM 输出
    return parseLLMAction(resp.Body)
}

执行修复动作

func executeAction(ctx context.Context, c client.Client, action, namespace, deployment string) error {
    switch action {
    case "restart_pod":
        // 删除 Pod 触发重新调度
        pods := &corev1.PodList{}
        if err := c.List(ctx, pods, client.InNamespace(namespace), client.MatchingLabels{"app": deployment}); err != nil {
            return err
        }
        for _, pod := range pods.Items {
            if err := c.Delete(ctx, &pod); err != nil {
                return err
            }
        }
    case "scale_up":
        dep := &appsv1.Deployment{}
        if err := c.Get(ctx, types.NamespacedName{Namespace: namespace, Name: deployment}, dep); err != nil {
            return err
        }
        *dep.Spec.Replicas++
        return c.Update(ctx, dep)
    }
    return nil
}

Reconcile 主流程

func (r *AutoHealReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
    var ah aiopsv1.AutoHeal
    if err := r.Get(ctx, req.NamespacedName, &ah); err != nil {
        return ctrl.Result{}, client.IgnoreNotFound(err)
    }

    value, err := queryPrometheus(ah.Spec.MetricsSource, ah.Spec.Query)
    if err != nil {
        return ctrl.Result{}, err
    }

    if value > ah.Spec.Threshold {
        context := fmt.Sprintf("Deployment: %s/%s, P99 latency: %.2fs, threshold: %.2fs",
            ah.Spec.Namespace, ah.Spec.TargetDeployment, value, ah.Spec.Threshold)
        action, err := askLLM(ah.Spec.LLMEndpoint, context)
        if err != nil {
            return ctrl.Result{}, err
        }
        if err := executeAction(ctx, r.Client, action, ah.Spec.Namespace, ah.Spec.TargetDeployment); err != nil {
            return ctrl.Result{}, err
        }
        ah.Status.LastDecision = action
        ah.Status.LastExecutionTime = metav1.Now().Format(time.RFC3339)
        ah.Status.Phase = "Healed"
    } else {
        ah.Status.Phase = "Monitoring"
    }

    if err := r.Status().Update(ctx, &ah); err != nil {
        return ctrl.Result{}, err
    }

    return ctrl.Result{RequeueAfter: 60 * time.Second}, nil
}

部署与验证

  1. 使用 kubebuilder 生成 CRD 与 RBAC。
  2. 构建镜像并部署到集群。
  3. 创建 AutoHeal CR。
  4. 通过压测工具制造高延迟,观察 Operator 是否能自动触发修复。
kubectl apply -f config/crd/bases/aiops.example.com_autoheals.yaml
kubectl apply -f config/samples/aiops_v1_autoheal.yaml
kubectl logs -n aiops-system deployment/aiops-operator-controller-manager

设计要点与注意事项

  1. LLM 输出可靠性:LLM 可能产生不确定输出,建议将 action 限制在白名单内,并对输出进行校验。
  2. 安全控制:Operator 拥有较高权限,应通过 RBAC 最小化授权,并对危险操作增加审批机制。
  3. 可观测性:记录每次决策的上下文、指标、LLM 输出和执行结果,便于后续审计与模型优化。
  4. 回滚与限流:对自动修复操作设置冷却时间和最大执行次数,避免误操作扩大故障。

总结

通过将 LLM 决策能力封装到 Kubernetes Operator 中,我们实现了"声明式 AIOps":用户只需声明期望的修复策略,Operator 就能自主完成观测、推理和执行。这种模式为后续构建更复杂的 AIOps 平台奠定了坚实基础。

About Me

没什么想介绍的,一个很大众的码农…

喜欢代码,车,马,真的是 🐎

讨厌别人让我给自己的代码写注释 最厌烦别人的程序没有写注释

目标

学AI,加油!加油!