Ollama 生产环境监控:日志配置与 Prometheus 告警实战
凌晨三点十七分。手机在床头柜上震动了一下,然后是第二下、第三下。我迷迷糊糊地划开屏幕,Slack 上的红色告警消息刺得眼睛生疼:Ollama API timeout - service unavailable。
我的第一个念头是:完了。
当时我们刚把一个基于 Llama 3.1 的客服系统上线两周,用户量不大,每天几百次调用。部署的时候我其实有点心虚——只配了基本的日志记录,没有任何监控告警。想着”先跑起来再说”。结果就是,凌晨三点我被叫醒的时候,根本不知道问题出在哪。GPU 内存满了?进程挂了?还是网络问题?两眼一抹黑。
那次事故折腾到早上六点才恢复。事后复盘,我发现像我们这样的团队不在少数。
监控缺失是主要原因之一。
这篇文章,我想帮你避开我踩过的坑。我会把从日志配置到 Prometheus + Grafana 监控、再到 AlertManager 告警的完整方案分享出来——都是可以直接复制使用的配置文件。按照这个方案,你大概 30 分钟就能搭起一套生产级的监控体系。说实话,如果当时我有这套东西,那个凌晨至少能多睡三个小时。
生产环境监控的核心挑战
Ollama 和普通的 Web 服务不太一样。它是个”吃资源大户”。每个加载的模型,光是内存就要占 4 到 16 GB(数据来自 Markaicode 的实测)。而且模型冷启动——也就是从硬盘加载到内存——要 10 到 30 秒。这意味着如果你的服务挂了重启,用户得等半分钟才能收到响应。
我踩过的坑主要有这几个:
内存泄漏和 GPU 耗尽。长时间运行后,Ollama 有时候会”忘记”释放显存。我见过一台 24GB 显存的机器,跑了两天后只剩下 2GB 可用,新请求全被拒绝。问题在于我根本不知道发生了什么,直到用户投诉。
请求队列堆积。推理本身慢,一个请求可能要 5-20 秒。如果同时来几十个请求,队列会越积越长,最后超时。但你怎么知道队列是不是在堆积?只能靠猜。
模型加载延迟。多个模型切换的时候,加载时间是个黑箱。用户不知道为什么响应慢,你也不知道。
所以监控的目标就很清晰了:服务可用性(进程还在跑吗?)、性能指标(响应要多快?)、资源利用率(GPU 内存还剩多少?)、错误率(有多少请求失败了?)。这四个维度搞清楚了,心里才有底。
监控方案选型上,我试过几种组合。小团队用 Prometheus + Grafana 就够了;如果要追踪 LLM 的 Prompt 和响应,Langfuse 很好用;企业级环境可以考虑 SigNoz,它基于 OpenTelemetry,统一了日志、指标和追踪。接下来我重点讲 Prometheus 方案,因为这是最通用的基础。
日志配置与 systemd 服务优化
把 Ollama 跑起来容易,但要让它稳定跑下去,第一件事就是把日志搞对。我之前吃过亏——出问题了去翻日志,结果发现什么都没记,或者日志文件几十 GB 把磁盘撑爆了。
systemd 服务配置
如果你是直接用官方脚本安装的 Ollama,它已经帮你创建了 systemd 服务。但默认配置比较简单,生产环境需要加点料:
# /etc/systemd/system/ollama.service
[Unit]
Description=Ollama Service
After=network.target
[Service]
Type=simple
User=ollama
Group=ollama
# 工作目录
WorkingDirectory=/usr/share/ollama
# 环境变量
Environment="OLLAMA_HOST=0.0.0.0:11434"
Environment="OLLAMA_MODELS=/data/ollama/models"
Environment="OLLAMA_DEBUG=1"
Environment="OLLAMA_LOG_FORMAT=json"
# 资源限制(根据你的硬件调整)
LimitNOFILE=65535
LimitNPROC=4096
MemoryMax=32G
# 自动重启策略
Restart=always
RestartSec=10
# 启动命令
ExecStart=/usr/local/bin/ollama serve
# 标准输出和错误输出
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
几个关键点说说我的经验:
Restart=always 和 RestartSec=10:进程异常退出后自动重启,等 10 秒是给系统一点喘息时间。我有次遇到过内存耗尽导致的反复崩溃,没有这个间隔的话,它会疯狂重启,日志直接爆炸。
MemoryMax=32G:限制 Ollama 能用的最大内存。如果你的机器还有其他服务,这个很重要。我试过不加限制,结果 Ollama 把 64GB 内存吃满,连 SSH 都登不进去。
OLLAMA_DEBUG=1 和 OLLAMA_LOG_FORMAT=json:生产环境建议开 debug 模式,出问题才好排查。JSON 格式的日志方便后续用工具解析。
改完配置别忘了重载:
sudo systemctl daemon-reload
sudo systemctl restart ollama
sudo systemctl enable ollama # 开机自启
Docker 部署的日志配置
用 Docker 跑的话,日志管理更容易翻车。Docker 默认把日志写在 /var/lib/docker/containers/ 下,不加限制的话会无限增长。
我的 docker-compose 配置长这样:
# docker-compose.yml
version: '3.8'
services:
ollama:
image: ollama/ollama:latest
container_name: ollama
restart: always
ports:
- "11434:11434"
volumes:
- ./ollama_data:/root/.ollama
environment:
- OLLAMA_HOST=0.0.0.0:11434
- OLLAMA_DEBUG=1
deploy:
resources:
limits:
memory: 32G
logging:
driver: "json-file"
options:
max-size: "100m"
max-file: "5"
max-size: "100m" 表示单个日志文件最大 100MB,max-file: "5" 保留 5 个文件。算下来最多 500MB 日志,够用也不会撑爆磁盘。
日志级别说明
Ollama 支持的环境变量:
| 变量 | 说明 | 生产建议 |
|---|---|---|
OLLAMA_DEBUG | 设为 1 开启详细日志 | 建议开启 |
OLLAMA_LOG_LEVEL | 日志级别(INFO/DEBUG/WARN) | INFO 或 DEBUG |
OLLAMA_LOG_FORMAT | 日志格式(text/json) | JSON |
我一般都开着 DEBUG,硬盘不差这点空间,排查问题的时候能省好多时间。
journalctl 查日志实战
配置好后,查日志用 journalctl:
# 实时查看日志
sudo journalctl -u ollama -f
# 查最近 100 行
sudo journalctl -u ollama -n 100
# 查今天的日志
sudo journalctl -u ollama --since today
# 搜索特定关键词
sudo journalctl -u ollama | grep -i "error"
# 导出日志到文件
sudo journalctl -u ollama --since "2026-04-12 00:00:00" > ollama-debug.log
有个技巧:如果你开了 JSON 格式日志,可以用 jq 来解析:
sudo journalctl -u ollama -o json | jq 'select(.level=="error")'
这样就能只看错误级别的日志,不用在一堆 INFO 里翻。
Prometheus + Grafana 监控方案
日志算是事后复盘的工具,监控才是提前预警的眼睛。Prometheus + Grafana 这套组合,我自己用了两年多,虽然配置起来有点繁琐,但稳定可靠,社区资源也多。
ollama-exporter 部署
Ollama 本身不直接暴露 Prometheus 指标,需要用 exporter 来采集。我用的是 frcooper/ollama-exporter,虽然 Star 数不多(36 个),但功能够用。
部署方式有两种:直接跑二进制,或者用 Docker。我推荐 Docker:
# 在 docker-compose.yml 中添加 exporter 服务
services:
ollama-exporter:
image: frazco/ollama-exporter:latest
container_name: ollama-exporter
restart: always
ports:
- "9101:9101"
environment:
- OLLAMA_HOST=ollama:11434 # 指向 ollama 容器
depends_on:
- ollama
然后是 Prometheus 的配置:
# prometheus.yml
global:
scrape_interval: 30s # 采样间隔,Markaicode 建议用 30 秒
evaluation_interval: 30s
scrape_configs:
- job_name: 'ollama-exporter'
static_configs:
- targets: ['ollama-exporter:9101']
labels:
instance: 'ollama-prod'
# GPU 监控(如果用 NVIDIA)
- job_name: 'nvidia-gpu'
static_configs:
- targets: ['localhost:9835']
把 Prometheus 也加到 docker-compose 里:
services:
prometheus:
image: prom/prometheus:latest
container_name: prometheus
restart: always
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
volumes:
prometheus_data:
关键监控指标
ollama-exporter 会采集这些指标,我把重点的列出来:
| 指标名 | 说明 | 关注点 |
|---|---|---|
ollama_requests_total | 总请求数 | 错误率计算 |
ollama_requests_failed | 失败请求数 | 直接监控 |
ollama_model_load_duration_seconds | 模型加载耗时 | 冷启动性能 |
ollama_request_duration_seconds | 请求响应时间 | P95/P99 延迟 |
ollama_tokens_per_second | 推理速度 | throughput |
还有系统层面的指标(需要 node-exporter 配合):
- CPU 使用率:
node_cpu_seconds_total - 内存使用率:
node_memory_MemAvailable_bytes - 网络流量:
node_network_receive_bytes_total
GPU 监控配置
GPU 是 LLM 服务的心脏,监控必须到位。我用 nvidia_gpu_prometheus_exporter:
# 安装 NVIDIA GPU exporter
docker run -d \
--name nvidia-exporter \
--restart always \
-p 9835:9835 \
--gpus all \
nvidia/gpu-prometheus-exporter:latest
它会输出这些关键指标:
nvidia_gpu_utilization:GPU 利用率nvidia_gpu_memory_used_bytes:显存使用量nvidia_gpu_memory_free_bytes:剩余显存nvidia_gpu_temperature:GPU 温度
多卡环境的话,指标会带 gpu_id 标签,可以在 Grafana 里按显卡分别展示。
Grafana Dashboard 配置
Grafana 的 Dashboard 我直接给你一个可以导入的 JSON。把这个保存成文件,然后在 Grafana 里点 Import Dashboard 就能用:
{
"dashboard": {
"title": "Ollama Production Monitor",
"panels": [
{
"title": "Request Rate",
"type": "graph",
"targets": [
{
"expr": "rate(ollama_requests_total[5m])",
"legendFormat": "Requests/sec"
}
],
"gridPos": {"x": 0, "y": 0, "w": 12, "h": 6}
},
{
"title": "Error Rate",
"type": "gauge",
"targets": [
{
"expr": "rate(ollama_requests_failed[5m]) / rate(ollama_requests_total[5m]) * 100",
"legendFormat": "Error %"
}
],
"gridPos": {"x": 12, "y": 0, "w": 6, "h": 6}
},
{
"title": "GPU Memory Usage",
"type": "graph",
"targets": [
{
"expr": "nvidia_gpu_memory_used_bytes / nvidia_gpu_memory_total_bytes * 100",
"legendFormat": "GPU {{gpu_id}}"
}
],
"gridPos": {"x": 0, "y": 6, "w": 12, "h": 6}
},
{
"title": "Response Latency P95",
"type": "stat",
"targets": [
{
"expr": "histogram_quantile(0.95, rate(ollama_request_duration_seconds_bucket[5m]))",
"legendFormat": "P95 Latency"
}
],
"gridPos": {"x": 12, "y": 6, "w": 6, "h": 6}
}
]
},
"overwrite": true
}
实际效果差不多是这样:
- 左上:请求速率曲线,能看到峰值时段
- 右上:错误率仪表盘,超过 5% 会变红
- 左下:多卡 GPU 内存使用曲线
- 右下:P95 延迟数值
我还会加一个 Tokens/s 的面板,方便横向对比不同模型的推理速度。
Grafana 数据源配置
Grafana 容器启动后,需要手动配置 Prometheus 数据源:
- 登录 Grafana(默认 admin/admin)
- Configuration -> Data Sources -> Add data source
- 选 Prometheus,URL 填
http://prometheus:9090 - Save & Test
如果用 docker-compose 一起部署,网络互通直接用容器名就行。
告警规则与 AlertManager 配置
监控能看到问题,但告警才能让你知道”现在就要处理”。我之前犯过一个错:把所有告警都设成 critical,结果手机一天震动几十次,最后麻木了,真正出问题反而没反应。
告警分级策略
我把告警分成三级,这个逻辑是经过几次事故迭代出来的:
| 级别 | 触发条件 | 响应要求 |
|---|---|---|
| Critical | 服务宕机、GPU 内存超95%、错误率超20% | 立即处理(Slack + 手机推送) |
| Warning | 响应时间超60s、GPU 内存超80%、错误率超5% | 1 小时内查看(Slack only) |
| Info | 模型切换、新版本部署 | 仅记录(邮件汇总) |
关键原则:Critical 告警必须少,要让你一看到就紧张。
Prometheus 告警规则
在 prometheus.yml 里加上告警规则:
rule_files:
- 'ollama_alerts.yml'
然后单独写一个 ollama_alerts.yml:
# ollama_alerts.yml
groups:
- name: ollama_critical
rules:
# 服务宕机告警
- alert: OllamaServiceDown
expr: up{job="ollama-exporter"} == 0
for: 1m
labels:
severity: critical
annotations:
summary: "Ollama 服务宕机"
description: "Ollama exporter 无法连接,服务可能已停止"
# GPU 内存告警(>95%)
- alert: GPUMemoryCritical
expr: nvidia_gpu_memory_used_bytes / nvidia_gpu_memory_total_bytes > 0.95
for: 2m
labels:
severity: critical
annotations:
summary: "GPU 内存即将耗尽"
description: "GPU {{ gpu_id }} 内存使用率超过 95%,当前 {{ $value | humanizePercentage }}"
# 高错误率告警
- alert: HighErrorRate
expr: rate(ollama_requests_failed[5m]) / rate(ollama_requests_total[5m]) > 0.20
for: 3m
labels:
severity: critical
annotations:
summary: "请求错误率过高"
description: "过去 5 分钟错误率超过 20%,请检查日志"
- name: ollama_warning
rules:
# 响应时间告警
- alert: SlowResponseTime
expr: histogram_quantile(0.95, rate(ollama_request_duration_seconds_bucket[5m])) > 60
for: 5m
labels:
severity: warning
annotations:
summary: "P95 响应时间过慢"
description: "95% 请求响应时间超过 60 秒"
# GPU 内存预警
- alert: GPUMemoryWarning
expr: nvidia_gpu_memory_used_bytes / nvidia_gpu_memory_total_bytes > 0.80
for: 5m
labels:
severity: warning
annotations:
summary: "GPU 内存使用率较高"
description: "GPU {{ gpu_id }} 内存使用率超过 80%"
# 错误率预警
- alert: ErrorRateWarning
expr: rate(ollama_requests_failed[5m]) / rate(ollama_requests_total[5m]) > 0.05
for: 5m
labels:
severity: warning
annotations:
summary: "请求错误率上升"
description: "过去 5 分钟错误率超过 5%"
几个注意点:
for: Xm:持续 X 分钟才触发,避免瞬时波动误报- GPU 告警阈值 95%:实测下来,超过 95% 后基本马上就要出问题
- 错误率告警用了
rate():因为绝对数量没意义,要看趋势
AlertManager 配置
AlertManager 负责把告警发出去。配置文件 alertmanager.yml:
global:
resolve_timeout: 5m
# 路由配置
route:
group_by: ['severity', 'alertname']
group_wait: 30s # 等待 30 秒收集同组告警
group_interval: 5m # 同组告警间隔
repeat_interval: 3h # 未解决的告警重复发送间隔
routes:
- match:
severity: critical
receiver: 'critical-alerts'
continue: false
- match:
severity: warning
receiver: 'warning-alerts'
continue: false
- match:
severity: info
receiver: 'info-alerts'
# 接收器配置
receivers:
- name: 'critical-alerts'
slack_configs:
- api_url: 'https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK'
channel: '#ollama-critical'
send_resolved: true
title: '{{ .Status | toUpper }}: {{ .CommonAnnotations.summary }}'
text: '{{ .CommonAnnotations.description }}'
- name: 'warning-alerts'
slack_configs:
- api_url: 'https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK'
channel: '#ollama-monitor'
send_resolved: true
- name: 'info-alerts'
email_configs:
- to: 'your-email@example.com'
send_resolved: true
Slack Webhook 配置步骤
- 在 Slack 里创建一个 App(或者用 Incoming Webhooks)
- 添加 Webhook URL 到
api_url字段 - 建议分开 channel:critical 用专门的频道,warning 用普通频道
我还会加一个手机推送。如果你用 PagerDuty 或 OpsGenie,AlertManager 都有集成支持。不想花钱的话,可以用 Telegram Bot,配置也不复杂。
静默和抑制规则
有时候需要临时静默告警,比如维护期间。在 AlertManager UI 里可以直接操作:
# 访问 AlertManager UI
http://your-server:9093
# 点击 Silences -> New Silence
# 设置持续时间、匹配标签
也可以用 API:
curl -X POST http://localhost:9093/api/v1/silences \
-d '{
"matchers": [{"name": "alertname", "value": "OllamaServiceDown", "isRegex": false}],
"startsAt": "2026-04-12T10:00:00Z",
"endsAt": "2026-04-12T12:00:00Z",
"createdBy": "admin",
"comment": "Scheduled maintenance"
}'
LLM 专用监控工具进阶
Prometheus + Grafana 是通用方案,但 LLM 有一些特殊的监控需求:Prompt 追踪、Token 成本、响应质量评估。这些指标用传统监控工具不太好搞。
Langfuse:LLM 追踪和 Prompt 管理
Langfuse 是专门为 LLM 应用设计的监控平台,MIT 开源,支持自托管。它能做的事:
- 追踪每次对话:记录输入 Prompt、输出内容、Token 数量、耗时
- Prompt 版本管理:你的 Prompt 改了之后,能对比新旧版本的效果
- 质量评估:记录用户反馈、人工标注,追踪模型输出质量
集成方式很简单,Langfuse 官方有 Ollama 适配:
# Python 集成示例
from langfuse import Langfuse
import requests
langfuse = Langfuse(
public_key="pk-xxx",
secret_key="sk-xxx",
host="https://cloud.langfuse.com" # 或自托管地址
)
# 每次调用记录
trace = langfuse.trace(
name="ollama-chat",
input={"prompt": user_prompt},
metadata={"model": "llama3.1"}
)
response = requests.post(
"http://localhost:11434/api/generate",
json={"model": "llama3.1", "prompt": user_prompt}
)
trace.update(
output=response.json()["response"],
metadata={"tokens": response.json().get("eval_count", 0)}
)
部署 Langfuse 自托管版本可以用 Docker:
services:
langfuse-server:
image: langfuse/langfuse:latest
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgres://user:pass@db:5432/langfuse
- NEXTAUTH_SECRET=your-secret
如果你用 LangChain,集成更简单,Langfuse 有官方的 callback handler。
SigNoz:OpenTelemetry 统一监控
SigNoz 是一个基于 OpenTelemetry 的可观测性平台,把日志、指标、追踪统一在一块。好处是你不用分别维护 Prometheus、Jaeger、ELK 三套系统。
对于 LLM 应用,SigNoz 的追踪功能很实用:能看到一个请求从 API 入口到模型推理到数据库查询的完整链路。
部署 SigNoz 需要的资源比较多,建议至少 4GB 内存。官方有 Docker Compose 一键部署:
git clone https://github.com/SigNoz/signoz.git
cd signoz/deploy/docker
docker compose up -d
工具选型建议
我根据不同场景给个参考:
| 场景 | 推荐方案 | 原因 |
|---|---|---|
| 小团队(少于5人) | Prometheus + Grafana | 简单够用,社区资源丰富 |
| 需要 Prompt 追踪 | Prometheus + Langfuse | Langfuse 专注 LLM,互补 |
| 企业级多服务 | SigNoz + OpenTelemetry | 统一平台,运维成本更低 |
| 纯云原生 | 直接用托管服务 | 省运维精力 |
我自己目前用的是 Prometheus + Grafana + Langfuse 的组合。Prometheus 管基础设施指标,Langfuse 管 LLM 应用层,职责分开,心里清楚。
写在最后
说了这么多,其实就一句话:别等出事了再想监控。
我那次凌晨三点的教训,换来的是这套完整的监控方案。现在我的 Ollama 服务跑了一年多,中间遇到过几次 GPU 内存告警,但都在 Warning 级别就处理掉了,没再半夜被叫醒。
这套方案的搭建成本其实不高。我整理了所有配置文件,你可以直接下载使用:
- systemd 服务配置
- Docker Compose 完整部署(Ollama + Exporter + Prometheus + Grafana)
- Prometheus 告警规则
- AlertManager 配置模板
- Grafana Dashboard JSON
配套的 GitHub 仓库我放在文章最后了。按照这个配置,熟练的话 20 分钟就能跑起来,新手大概半小时。
下一步建议你:
- 先用最基础的 Prometheus + Grafana 把指标跑起来
- 观察 3-5 天,熟悉正常状态的数据范围
- 根据实际情况调整告警阈值
- 如果需要追踪 Prompt,再加 Langfuse
监控这件事,投入一次,收益是持续的。希望你不需要像我一样,用凌晨三点的教训来换这个经验。
配置文件仓库:github.com/yourname/ollama-monitoring-config(示例链接,实际部署请替换)
系列文章:
- Ollama 本地部署完全指南 — 系列第一篇
- Ollama 性能优化实战 — 下一篇预告
常见问题
Ollama 生产环境监控需要哪些核心指标?
Prometheus + Grafana 和 Langfuse 有什么区别?
告警阈值怎么设置才合理?
Docker 部署时日志文件无限增长怎么办?
GPU 多卡环境怎么分别监控每张显卡?
凌晨三点收到告警后怎么快速定位问题?
12 分钟阅读 · 发布于: 2026年4月12日 · 修改于: 2026年4月12日
相关文章
Ollama GPU 调度与资源管理:显存优化、多 GPU 负载均衡
Ollama GPU 调度与资源管理:显存优化、多 GPU 负载均衡
Ollama 性能优化实战:量化、批处理与内存调优完全指南
Ollama 性能优化实战:量化、批处理与内存调优完全指南
Ollama Embedding 实战:本地向量检索与 RAG 搭建

评论
使用 GitHub 账号登录后即可评论