随着大模型应用的普及,Ollama 作为一个能够本地化运行大语言模型的工具,越来越受到开发者的青睐。然而,当我们将 Ollama 从单机测试环境迁移到生产环境时,如何确保它的稳定运行、如何感知 GPU 资源的消耗以及模型服务的响应延迟,就成了运维团队必须面对的核心问题。传统的查看日志方式已经无法满足实时性要求,我们需要一套自动化、可视化的监控方案。本文将详细介绍如何利用开源的监控利器 Prometheus 与 Grafana,构建一套完整的 Ollama 服务健康监控与告警体系,帮助你从被动救火转变为主动运维。

一、理解监控架构与核心指标

在动手搭建之前,我们需要先理清思路。Ollama 本身是一个提供模型推理服务的 API 服务器,它默认并不直接暴露 Prometheus 格式的监控指标。这意味着我们需要在 Ollama 和 Prometheus 之间搭建一座桥梁。这个桥梁通常被称为 Exporter,它的作用是定期查询 Ollama 的状态接口,并将返回的数据转换为 Prometheus 能够识别的格式。

监控 Ollama 主要关注三个维度的指标。首先是系统资源指标,包括 CPU 使用率、内存占用以及显存使用情况,因为大模型推理对显存的需求非常高,显存溢出是导致服务崩溃的常见原因。其次是服务性能指标,例如 API 请求的响应时间、QPS(每秒查询率)以及错误率,这能帮助我们判断服务是否因为负载过高而变慢。最后是模型状态指标,比如当前加载了哪些模型、模型的推理 token 生成速率等。

整个监控架构的数据流向是清晰的。Exporter 脚本运行在服务器后台,定时抓取 Ollama 的数据并将其格式化;Prometheus 服务按照配置的频率去拉取(Pull)这些格式化后的数据并存储在时序数据库中;Grafana 则连接到 Prometheus,通过图表将数据展示出来;Alertmanager 负责接收 Prometheus 发出的告警信号,并通过邮件或钉钉通知相关人员。

二、编写 Ollama 指标导出器

由于 Ollama 官方没有提供现成的 Prometheus Exporter,我们需要自己编写一个轻量级的脚本。这里我们选择使用 Python 语言,因为它拥有丰富的库支持,且易于阅读和修改。这个脚本的核心逻辑是调用 Ollama 的本地 API 获取状态信息,并使用 prometheus_client 库来注册指标。

以下是完整的导出器代码示例。请注意,这段代码需要安装 requestsprometheus_client 两个库才能运行。

(技术栈:Python 与 YAML)

#!/usr/bin/env python3
"""
Ollama 指标导出器
用于将 Ollama 服务状态转换为 Prometheus 格式
"""
import requests
from prometheus_client import start_http_server, Gauge, Counter, Info
import time

# 定义 Ollama 服务地址
OLLAMA_API = "http://localhost:11434"

# 初始化 Prometheus 指标
# 记录当前加载的模型信息
ollama_model_info = Info('ollama_model', 'Currently loaded model')
# 记录 CPU 使用率
ollama_cpu_usage = Gauge('ollama_cpu_usage_percent', 'CPU usage percentage')
# 记录内存使用率
ollama_memory_usage = Gauge('ollama_memory_usage_percent', 'Memory usage percentage')
# 记录 GPU 利用率
ollama_gpu_usage = Gauge('ollama_gpu_usage_percent', 'GPU usage percentage')
# 记录推理请求总数
ollama_requests_total = Counter('ollama_requests_total', 'Total requests served')

def fetch_ollama_metrics():
    try:
        # 获取模型状态
        response = requests.get(f"{OLLAMA_API}/api/tags", timeout=5)
        if response.status_code == 200:
            data = response.json()
            models = data.get('models', [])
            if models:
                ollama_model_info.info({'model': models[0]['name']})
            else:
                ollama_model_info.info({'model': 'none'})
        else:
            ollama_model_info.info({'model': 'error'})

        # 这里模拟系统指标获取,实际生产中可结合 psutil 库
        # 仅为演示格式,实际数值需根据服务器硬件读取
        ollama_cpu_usage.set(45.5)
        ollama_memory_usage.set(62.3)
        ollama_gpu_usage.set(88.1)
        ollama_requests_total.inc()
    except Exception as e:
        print(f"Error fetching metrics: {e}")

if __name__ == "__main__":
    # 启动 HTTP 服务,端口 8000,供 Prometheus 拉取
    start_http_server(8000)
    print("Exporter started on port 8000")
    
    # 持续循环获取指标
    while True:
        fetch_ollama_metrics()
        time.sleep(15) # 每 15 秒刷新一次数据

编写好脚本后,我们需要确保它在服务器启动时自动运行。可以通过 Systemd 服务或者简单的 Shell 后台命令来实现。在代码中,我们定义了多个 Gauge 类型指标,用于表示随时间变化的数值,如 CPU 和显存使用率。同时,使用 Counter 类型来累计请求次数,这有助于我们计算长期的流量趋势。注释部分详细说明了每个变量的用途,方便后续维护人员理解代码逻辑。

三、部署 Prometheus 采集服务

有了数据源之后,接下来需要部署 Prometheus 服务端来存储这些数据。Prometheus 通常以容器形式运行,这样可以保证环境的纯净和依赖的完整。我们需要编写一个配置文件,告诉 Prometheus 去哪里抓取刚才编写的导出器数据。

Prometheus 的配置文件采用 YAML 格式,结构清晰。我们需要配置 scrape_configs 部分,定义抓取的目标地址、抓取间隔以及基本的标签信息。

# prometheus.yml
# 全局配置
global:
  scrape_interval: 15s      # 每 15 秒抓取一次数据
  evaluation_interval: 15s  # 每 15 秒评估一次告警规则

# 规则文件配置
rule_files:
  - "alerts.yml"

# 抓取配置
scrape_configs:
  - job_name: 'ollama_exporter'
    # 指定抓取的目标地址,这里指向我们编写的 Python 脚本端口
    static_configs:
      - targets: ['localhost:8000']
        labels:
          service: 'ollama'
          environment: 'production'

在部署时,我们可以使用 Docker Compose 来简化操作,或者直接使用 Docker Run 命令。以下是启动 Prometheus 的 Bash 命令示例。我们需要将宿主机的配置文件挂载到容器内部,这样容器就能读取到我们刚才定义的规则。

# 启动 Prometheus 容器
# 映射 9090 端口用于访问 Prometheus Web 界面
# 将配置文件挂载到容器内
docker run -d \
  --name prometheus \
  -p 9090:9090 \
  -v /path/to/prometheus.yml:/etc/prometheus/prometheus.yml \
  prom/prometheus \
  --config.file=/etc/prometheus/prometheus.yml

执行上述命令后,Prometheus 就会开始工作。它会根据配置文件中定义的间隔,不断向 localhost:8000 发送 HTTP 请求,获取我们导出的指标数据。如果导出器运行正常,你可以在 Prometheus 的 Web 界面查看到 up 指标为 1,表示目标可达。这一步是整个监控体系的基础,确保数据能够被持续收集和存储。

四、搭建 Grafana 可视化看板

数据存储在 Prometheus 中只是一堆冷冰冰的数字,为了让这些数据变得直观易懂,我们需要引入 Grafana。Grafana 是一款强大的可视化平台,它支持与 Prometheus 无缝集成。我们可以通过在 Grafana 中添加 Prometheus 作为数据源,然后创建面板来展示指标。

Grafana 的查询语言是 PromQL,它允许我们从时间序列数据库中筛选和计算数据。例如,我们想要查看 Ollama 的 GPU 使用率趋势,可以编写如下查询语句。

# 查询过去 1 小时的 GPU 使用率平均值
avg(ollama_gpu_usage_percent) 

# 查询请求错误率,假设定义了 ollama_request_errors_total
# 计算错误请求数与总请求数的比率
rate(ollama_request_errors_total[5m]) / rate(ollama_requests_total[5m])

在 Grafana 中,我们可以创建一个仪表盘,包含多个面板。第一个面板使用折线图展示 GPU 使用率,帮助我们观察资源消耗的趋势,判断是否存在内存泄漏。第二个面板使用单值显示当前加载的模型名称,让我们一眼就能知道服务正在运行哪个模型。第三个面板使用热力图展示 API 的响应延迟分布,快速定位性能瓶颈。

配置 Grafana 数据源时,我们需要填写 Prometheus 的访问地址,通常是 http://prometheus:9090。配置完成后,点击保存并测试,确保 Grafana 能够成功连接到 Prometheus。随后,我们可以导入社区共享的 Prometheus 仪表盘模板,或者根据上述 PromQL 语句手动创建面板,打造出符合自己需求的监控视图。

五、配置告警规则

监控的最终目的是在问题发生前发现它,或者在故障发生时第一时间通知相关人员。Prometheus 的告警机制由两部分组成:Prometheus 服务端负责评估告警规则,而 Alertmanager 负责处理告警的分组、抑制和通知。

我们需要在 Prometheus 的配置中引入规则文件 alerts.yml。在这个文件中,我们定义具体的告警条件。例如,当 GPU 使用率持续 5 分钟超过 90% 时,我们应该发送告警。

# alerts.yml
groups:
  - name: ollama_alerts
    rules:
      # 规则 1:GPU 使用率过高
      - alert: HighGPUUsage
        expr: ollama_gpu_usage_percent > 90
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Ollama GPU 使用率过高"
          description: "当前 GPU 使用率为 {{ $value }}%,已超过 90% 阈值,持续 5 分钟。"

      # 规则 2:服务不可用
      - alert: OllamaDown
        expr: up{job="ollama_exporter"} == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "Ollama 导出器服务不可用"
          description: "Prometheus 无法连接到 Ollama 导出器,服务可能已宕机。"

在定义了规则后,还需要配置 Alertmanager 来接收这些告警。Alertmanager 支持多种通知渠道,包括邮件、钉钉、企业微信等。配置时,需要确保通知渠道的密钥和地址正确,否则告警将无法送达。通过这种分层设计,Prometheus 专注于计算,Alertmanager 专注于通知,使得告警系统更加灵活和稳定。

六、方案深度分析

在实施这套监控方案时,我们需要结合实际场景进行深入分析。

6.1 应用场景

这套方案非常适合中小型团队或者个人开发者在生产环境中部署 Ollama 服务。特别是当 Ollama 作为后端服务支撑聊天机器人、文档总结等应用时,稳定性至关重要。通过实时监控,可以防止因显存溢出导致的用户请求失败,提升用户体验。此外,对于需要进行模型压测的场景,监控数据也能提供宝贵的参考依据。

6.2 技术优缺点

优点方面,Prometheus 和 Grafana 都是成熟的开源方案,社区活跃,文档丰富,扩展性强。Prometheus 的 Pull 模式使得监控系统更加健壮,不依赖单个服务的心跳上报。Grafana 的可视化能力强大,能够灵活组合各种图表。缺点方面,Prometheus 默认是内存存储,长时间存储大量数据对内存消耗较大,需要配合 Thanos 或 Cortex 进行长期存储。另外,由于 Ollama 本身不支持原生指标,我们需要维护自定义的 Exporter 脚本,增加了少量的维护成本。

6.3 注意事项

在部署过程中,有几个关键点需要注意。首先是权限问题,Exporter 脚本需要有权限访问 Ollama 的 API 接口,通常需要在同一台机器运行或确保网络互通。其次是资源开销,Prometheus 和 Grafana 自身也会消耗一定的 CPU 和内存,建议将它们部署在独立的监控节点上,避免与业务服务争抢资源。最后是告警阈值设置,不要设置得过于敏感,以免产生告警风暴,干扰正常工作。建议根据历史数据逐步调整阈值。

七、总结

构建一套完善的 Ollama 监控体系,是保障大模型应用稳定运行的基石。通过本文介绍的方案,我们利用 Python 编写了自定义导出器,结合 Prometheus 的强大采集能力,以及 Grafana 的直观展示,实现了从数据采集、存储、可视化到告警通知的全链路监控。

虽然 Ollama 目前尚未原生支持 Prometheus 指标,但这并不妨碍我们利用现有的开源生态构建出高效的监控方案。随着大模型技术的不断发展,监控手段也需要不断迭代。希望本文提供的思路和方法,能够为你在生产环境中部署和管理 Ollama 服务提供有力的支持,让运维工作变得更加轻松和高效。通过持续优化监控策略,我们可以更好地利用硬件资源,提升模型的推理效率,最终为用户带来更优质的服务体验。