当Prometheus遇上大模型:时序异常检测与AI辅助根因分析实战

文章总体概览信息图

凌晨3点15分,手机震得我直接从床上弹起来。告警:支付网关P99延迟从80ms飙升到4.2s,订单超时率突破15%。打开Grafana一看——嚯,CPU正常、内存正常、连接数正常...所有基础指标都正常。

这种"指标都正常但服务就是慢"的故障,是运维最头疼的类型。传统监控的阈值告警只能告诉你"出事了",但说不出"为什么出事"。

好消息是,把时序异常检测和大模型结合起来,这套组合拳可以大幅缩短故障排查时间。

一、时序异常检测:从"设定阈值"到"自动发现"

传统阈值告警的局限性

我们之前的告警规则:

# PrometheusRule — 传统阈值告警
groups:
- name: latency_alerts
  rules:
  - alert: HighLatency
    expr: histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m])) > 1.0
    for: 5m
    labels:
      severity: critical
    annotations:
      summary: "P99延迟超过1秒"

这条规则的问题是:

  1. 静态阈值:业务高峰期的800ms也许正常,凌晨的500ms可能已经异常
  2. 发现滞后:只有持续超过阈值5分钟才告警,可能已经造成影响
  3. 无上下文:告警了也不知道为什么

基于统计学的时序异常检测

我们改用3-sigma和移动平均来做动态基线:

import numpy as np
import pandas as pd
from prometheus_api_client import PrometheusConnect

prom = PrometheusConnect(url='http://prometheus:9090', disable_ssl=True)

def detect_anomaly_3sigma(metric_name, window='30m'):
    """基于3-sigma的时序异常检测"""
    data = prom.custom_query(
        query=f'avg({metric_name}[1m])',
        params={'time': window}
    )
    
    values = [float(v[1]) for v in data[0]['values']]
    series = pd.Series(values)
    
    # 计算移动平均和标准差
    rolling_mean = series.rolling(window=5).mean()
    rolling_std = series.rolling(window=5).std()
    
    # 3-sigma检测
    upper_bound = rolling_mean + 3 * rolling_std
    lower_bound = rolling_mean - 3 * rolling_std
    
    # 标记异常点
    anomalies = series[(series > upper_bound) | (series < lower_bound)]
    
    return anomalies, upper_bound, lower_bound

# 批量检测多个指标
metrics_to_check = [
    'http_request_duration_seconds{quantile="0.99"}',
    'rate(http_requests_total[5m])',
    'container_cpu_usage_seconds_total{container="payment"}',
    'container_memory_working_set_bytes{container="payment"}'
]

anomaly_results = {}
for metric in metrics_to_check:
    anomalies, upper, lower = detect_anomaly_3sigma(metric)
    if not anomalies.empty:
        anomaly_results[metric] = {
            'anomaly_count': len(anomalies),
            'severity': 'high' if len(anomalies) > 3 else 'medium'
        }

二、大模型辅助根因分析:从"看数据"到"看结论"

异常检测告诉我们"什么指标异常了",但根因分析需要回答"为什么异常"。这里大模型可以扮演一个"资深SRE助手"的角色。

构建故障上下文

当异常检测触发后,我们自动聚合上下文信息:

def build_fault_context(anomaly_results, time_range='15m'):
    """构建故障上下文,供大模型分析"""
    context = {
        'event_time': datetime.now().isoformat(),
        'time_range': time_range,
        'anomalies': [],
        'changes': [],
        'topology': []
    }
    
    # 1. 异常指标上下文
    for metric, info in anomaly_results.items():
        context['anomalies'].append({
            'metric': metric,
            'anomaly_count': info['anomaly_count'],
            'severity': info['severity'],
            'current_value': info.get('current_value'),
            'baseline': info.get('baseline')
        })
    
    # 2. 最近的变更记录
    change_query = """
    SELECT * FROM deployment_events 
    WHERE deployed_at > NOW() - INTERVAL '1 hour'
    ORDER BY deployed_at DESC
    """
    context['changes'] = get_recent_changes(change_query)
    
    # 3. 服务拓扑依赖
    context['topology'] = get_service_topology('payment-service')
    
    return context

调用大模型分析

import requests
import json

def llm_root_cause_analysis(context):
    """调用大模型进行根因分析"""
    prompt = f"""你是一位资深的SRE工程师,以下是故障现场的监控数据和变更记录,请分析根因。

异常指标:{json.dumps(context['anomalies'], indent=2, ensure_ascii=False)}
最近变更:{json.dumps(context['changes'], indent=2, ensure_ascii=False)}
服务拓扑:{json.dumps(context['topology'], indent=2, ensure_ascii=False)}

请按以下格式输出:
1. 故障现象摘要
2. 可能根因(按可能性排序)
3. 推荐排查步骤
4. 建议修复措施
"""
    
    response = requests.post(
        'http://llm-service:8000/v1/chat/completions',
        json={
            'model': 'qwen2-72b',
            'messages': [
                {'role': 'system', 'content': '你是SRE专家,分析故障根因。'},
                {'role': 'user', 'content': prompt}
            ],
            'temperature': 0.1,
            'max_tokens': 2000
        }
    )
    return response.json()['choices'][0]['message']['content']

三、真实案例复盘

拿开头那个支付网关故障来说,这套系统的分析过程如下:

异常检测阶段(耗时15秒):

检测到 anomaly:
  - http_request_duration_seconds{quantile="0.99"}: 80ms → 4.2s
  - rate(http_requests_total[5m]) {instance="payment-03"}: 突降到0
  - container_cpu_usage_seconds_total{container="payment-03"}: 100% → 5%

大模型分析结果(耗时5秒):

故障现象摘要:支付网关P99延迟从80ms飙升至4.2s,
其中payment-03实例请求量降为0,疑似该实例已离线。

可能根因(按可能性排序):
1. payment-03实例OOM被K8s驱逐(概率80%)
2. 上游数据库连接池耗尽(概率15%)
3. 网络分区导致节点不可达(概率5%)

推荐排查步骤:
1. kubectl describe pod payment-03-xxx — 查看OOM状态
2. kubectl logs payment-03-xxx --previous — 查看崩溃前日志
3. 检查数据库连接池指标

建议修复措施:
1. 临时增加payment实例副本数
2. 调整JVM堆内存-Xms和-Xmx配置
3. 添加内存使用HPA自动扩缩容

实际排查结果:payment-03节点JVM堆内存配置过低,流量高峰触发了OOM Killer。按建议调整后故障恢复。

四、落地方案架构

完整的系统架构如下:

[时序指标] → Prometheus → 异常检测引擎 → 告警事件
                                         ↓
[变更记录] → CMDB     → 上下文聚合器  → LLM服务 → 根因报告
                                         ↓
[链路追踪] → Jaeger   → 拓扑分析器    → 钉钉/企微通知

关键点:异常检测要快(秒级),根因分析可以稍慢(分钟级)。两者解耦,各自独立迭代。

结语

时序异常检测解决了"发现问题"的效率问题,大模型解决了"排查问题"的效率问题。两者结合,让运维从"被动响应"转向"智能诊断"。

当然,大模型的分析结果不能直接当结论,它只是一个高效的辅助工具。最终的判断和操作,还是要靠工程师的经验和判断力。

本文作者:侯万里(万里侯),云原生运维工程师,专注于AI驱动运维智能化和可观测性体系建设

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐