InfluxDB + Telegraf 服务器监控实战:指标采集、Line Protocol 写入、Flux 查询与 Grafana 出图全流程

为什么个人站也需要一个正经的指标数据库

很多草根站长监控服务器的方式非常原始:写个 shell 脚本,每隔几分钟把 CPU、内存、磁盘占用打印到一个文本文件里,出问题的时候翻日志。这种方式在只有一台 VPS 的时候勉强够用,但只要站点起量、机器变成两三台,你就会发现文本日志根本没法回答一些最基本的问题:过去 30 天磁盘的增长斜率是多少?上周三下午网站变慢的那两个小时,到底是 CPU 打满还是磁盘 IO 打满?数据库连接数是不是每个月都在悄悄往上爬?

这些问题需要的不是一个「当前值」,而是「一段时间序列上的变化趋势」。这正是时序数据库(Time Series Database,TSDB)存在的理由。而 InfluxDB 就是这类数据库里最出名、生态最完整的一个。

本站之前写过 VictoriaMetrics(自建监控的另一个选择)和 TimescaleDB(基于 PostgreSQL 的时序扩展)。InfluxDB 和它们的定位有区别:VictoriaMetrics 更偏向「Prometheus 兼容的大规模指标存储」,TimescaleDB 是「让你不用换数据库就能做时序」,而 InfluxDB 是「从零为时序和监控场景设计的专用数据库」——它有自己的数据模型(measurement / tag / field)、自己的写入协议(line protocol)、自己的查询语言(Flux 以及 InfluxQL)。如果你想要一个专门给运维监控用的、开箱即用的指标库,InfluxDB 是最省心的选择。

本文会带你从零搭起一套「InfluxDB + Telegraf」的服务器指标采集系统:InfluxDB 负责存,Telegraf 负责采,Grafana 负责看。整套东西跑在一台 2GB 内存的 VPS 上毫无压力。

先想清楚:InfluxDB 的数据模型长什么样

InfluxDB 和关系型数据库最大的区别,是它没有「表」和「行」的概念。它的一个数据点(point)由三部分组成:

  • measurement(测量):相当于「表名」,比如 cpu、disk、nginx。它描述的是「这类数据是什么」。
  • tag(标签):带索引的键值对,用来描述数据点的「维度」,比如 host=web01、cpu=0、region=cn。tag 会被索引,所以用来做查询过滤条件。
  • field(字段):真正要存的数值,比如 usage_idle=98.5、bytes_recv=1024。field 不被索引,查询时靠时间范围 + tag 过滤来定位。

还有一个隐含的第四部分:timestamp(时间戳)。每一个 point 都必须带一个纳秒精度的时间戳,这是时序数据库的核心索引维度。

理解这个模型最重要的一个结论是:区分「tag」和「field」不是随手决定的,而是决定查询性能的关键。凡是你要拿来当 WHERE 条件的维度(主机名、cpu 核心号、磁盘挂载点、接口名),一律放 tag;凡是你要做聚合计算(AVG、SUM、MEAN)的数值,一律放 field。放错了,要么基数爆炸,要么查询全表扫。

还有一个血泪教训:tag 的基数是会爆炸的。所谓基数(cardinality),就是某个 measurement 下所有 tag 组合的数量。如果你把 request_id、user_ip 这种每次都不一样的东西当 tag,几百万个唯一的 tag 组合会瞬间把 InfluxDB 的内存吃光、写入性能崩掉。规则很简单:tag 只放取值有限且会重复出现的维度。

安装 InfluxDB:官方源 vs Docker

有两种装法。生产环境我推荐官方 apt 源,二进制直接运行,systemd 托管,升级方便。Docker 适合快速试用。

官方源安装(Debian / Ubuntu):

# 导入 GPG key
curl -s https://repos.influxdata.com/influxdata-archive.key | \
  gpg --dearmor | tee /usr/share/keyrings/influxdata-archive.gpg > /dev/null

# 添加源
echo "deb [signed-by=/usr/share/keyrings/influxdata-archive.gpg] \
  https://repos.influxdata.com/debian stable main" \
  | tee /etc/apt/sources.list.d/influxdata.list

apt update
apt install -y influxdb2

装完之后 InfluxDB 会自动启动,默认监听 8086 端口。这里有一个必须立刻处理的安全问题:InfluxDB 默认的 HTTP API 端口如果暴露在公网上,等于把整个指标库送人。哪怕是刚装好还没数据的实例,攻击者也能通过 API 创建 token、建组织。所以在初始化之前,先确认防火墙和监听地址。

# 看它到底监听了哪些地址
ss -tlnp | grep 8086
# 如果是 0.0.0.0:8086,用 ufw 挡掉外部访问,只留本机和 Grafana 所在机
ufw deny 8086/tcp
# 或者直接改配置只监听回环

编辑 /etc/influxdb/config.toml,把 HTTP 绑定改到回环,是最彻底的做法:

# /etc/influxdb/config.toml
http-bind-address = "127.0.0.1:8086"

改完 systemctl restart influxdb。之后如果需要从别的机器访问,走 SSH 隧道(ssh -L 8086:127.0.0.1:8086 user@server),不要为了图方便把它开到公网。

初始化与 Token 管理

InfluxDB 2.x 用 token 做认证,不再用用户名密码。首次初始化用 influx setup:

influx setup \
  --username admin \
  --password '一个足够长的强密码' \
  --org myorg \
  --bucket server_metrics \
  --retention 90d \
  --token '手工指定一个长随机串或让它自动生成' \
  --force

几个关键参数解释:--org 是组织(可以理解成命名空间),--bucket 是「桶」,相当于数据库实例,是数据实际存放的地方。--retention 90d 表示只保留 90 天数据,超过的自动删除——这个保留策略非常重要,否则一年下来磁盘会被悄悄吃满。90 天对大多数个人站够用,磁盘紧张就设 30d。

初始化完成后,token 会写在 /root/.influxdbv2/ 下(或 ~/.influxdbv2/configs)。这个 token 就是最高权限凭证,绝不能提交到 Git、绝不能出现在前端代码里。给 Telegraf 用的 token 应该单独创建一个只带「写权限、且只限某个 bucket」的 token,最小权限原则。

# 列出所有 token
influx auth list

# 创建只读 token(给 Grafana 用)
influx auth create --org myorg --read-bucket server_metrics --description "grafana-readonly"

# 创建只写 token(给 Telegraf 用)
influx auth create --org myorg --write-bucket server_metrics --description "telegraf-write"

Telegraf:把服务器指标采进 InfluxDB

Telegraf 是 InfluxData 官方的采集代理,单二进制、插件式,装一个就有几百种输入输出插件。它和 InfluxDB 是同一个厂商的,配合起来最顺。

apt install -y telegraf
# 或者用同一个 influxdata 源

Telegraf 的主配置文件在 /etc/telegraf/telegraf.conf。它分两大块:[[inputs.*]] 定义采什么,[[outputs.*]] 定义写去哪。一个最精简但实用的配置:

# /etc/telegraf/telegraf.conf

[global_tags]
  host = "web01"          # 给所有指标打上主机标签

[agent]
  interval = "15s"        # 采集间隔
  round_interval = true
  metric_batch_size = 1000
  metric_buffer_limit = 10000
  flush_interval = "15s"  # 写库间隔

# ---- 输入:CPU ----
[[inputs.cpu]]
  percpu = true           # 每个核心单独一条(tag: cpu=0,1,2...)
  totalcpu = true
  collect_cpu_time = false
  report_active = false

# ---- 输入:内存 ----
[[inputs.mem]]

# ---- 输入:磁盘空间 ----
[[inputs.disk]]
  ignore_fs = ["tmpfs", "devtmpfs", "overlay", "squashfs"]

# ---- 输入:磁盘 IO ----
[[inputs.diskio]]

# ---- 输入:网络 ----
[[inputs.net]]

# ---- 输入:系统负载 ----
[[inputs.system]]

# ---- 输入:进程数 / 连接数 ----
[[inputs.netstat]]

# ---- 输出:写入 InfluxDB 2.x ----
[[outputs.influxdb_v2]]
  urls = ["http://127.0.0.1:8086"]
  token = "$INFLUX_TOKEN"           # 从环境变量读,别硬编码
  organization = "myorg"
  bucket = "server_metrics"

注意 token 那一行——不要在配置文件里硬编码明文 token。正确做法是用 systemd 的 EnvironmentFile 把一个只含 INFLUX_TOKEN=... 的文件(权限 600)加载进来。Telegraf 支持在配置里用 $INFLUX_TOKEN 引用环境变量。

# /etc/default/telegraf  (chmod 600)
INFLUX_TOKEN=你创建的那个只写token

然后在 /etc/telegraf/telegraf.service.d/override.conf 里加上 EnvironmentFile=/etc/default/telegraf,systemctl daemon-reload && systemctl restart telegraf。

Telegraf 还有几个非常实用的插件值得开:

  • [[inputs.nginx]]:读 Nginx 的 stub_status,采集 active connections、requests、连接状态。前提是在 Nginx 里配一个只有本机能访问的 /nginx_status。
  • [[inputs.mysql]]:采集 MySQL 的连接数、QPS、慢查询、InnoDB 状态。只需要一个只读账号。
  • [[inputs.http_response]]:主动探测某个 URL 的响应时间和状态码,等于内置了一个轻量黑盒监控。
  • [[inputs.socket_listener]]:接收应用主动上报的自定义指标。

用 Line Protocol 手动写入自定义指标

除了 Telegraf 自动采,你经常需要从自己的脚本里上报业务指标——比如「今天发布了多少篇文章」「队列里积压了多少任务」。InfluxDB 的写入协议叫 line protocol,格式极其简单:

measurement,tag1=value1,tag2=value2 field1=value1,field2=value2 timestamp

举个例子,上报一次文章发布数量:

# 写入一条:站点今天发布了 3 篇文章
curl -s -XPOST "http://127.0.0.1:8086/api/v2/write?org=myorg&bucket=server_metrics&precision=s" \
  -H "Authorization: Token $INFLUX_TOKEN" \
  --data-binary 'site_stats,host=web01,published=3'

注意几个 line protocol 的坑:

  • measurement 和 tag 之间用逗号分隔,tag 和 field 之间用空格分隔,这个空格不能少。
  • 如果 field 的值是字符串,要加双引号(如 status="ok"),但如果永远只按字符串用,最好还是设计成 tag。
  • 时间戳默认是纳秒,用 &precision=s 可以让人直接用秒级 Unix 时间戳,省得算错位数。
  • 同一 measurement 下,field 的类型必须一致——这次写整数、下次写浮点,InfluxDB 会拒绝并报 field type conflict。这是新手最常见的报错,设计指标时就要定好类型。

查询:InfluxQL 与 Flux 怎么选

InfluxDB 2.x 同时支持两种查询语言。InfluxQL 是类 SQL 的老语言,上手快;Flux 是新的函数式管道语言,能力强但学习曲线陡。

一个 InfluxQL 查询,算最近一小时的 CPU 平均使用率:

SELECT mean("usage_idle") FROM "cpu" \
  WHERE time > now() - 1h AND "host"='web01' \
  GROUP BY time(5m), "cpu"

这行查询的含义是:取 cpu 这个 measurement 里,过去一小时的 usage_idle 字段,按 5 分钟一个窗口、按每个 CPU 核心分组求平均。注意 usage_idle 是空闲率,所以真实使用率是 100 - idle。

同样的查询用 Flux 写:

from(bucket: "server_metrics")
  |> range(start: -1h)
  |> filter(fn: (r) => r._measurement == "cpu" and r.host == "web01")
  |> filter(fn: (r) => r._field == "usage_idle")
  |> aggregateWindow(every: 5m, fn: mean)
  |> yield(name: "mean")

Flux 的 |> 是管道操作符,数据从上一个函数流向下一个。它比 InfluxQL 表达能力强得多(比如可以 join 不同 measurement、做复杂变换),代价是写起来啰嗦。我的建议是:简单查询用 InfluxQL 图省事,复杂分析用 Flux。另外要注意在 InfluxDB 2.x 里,InfluxQL 查询 bucket 需要在请求里带上 db + rp 参数映射,或者在 HTTP header 里指定 bucket,稍微绕一点。

接上 Grafana 出图

指标采进来了,最后一步是可视化。Grafana 连 InfluxDB 2.x:

apt install -y grafana
systemctl enable --now grafana-server

Grafana 的 3000 端口同样不要暴露公网,用 Nginx 反代 + 认证,或者干脆 ssh -L 3000:127.0.0.1:3000 本地看。在 Grafana 里添加数据源,类型选「InfluxDB」,配置:

  • Query Language:Flux(新版 Grafana 对 2.x 推荐 Flux)
  • URL:http://127.0.0.1:8086
  • Organization:myorg
  • Token:填那个只读 token(千万别用管理员 token)
  • Default Bucket:server_metrics

保存后就能在 Explore 里直接跑 Flux 查询了。做面板时,我建议至少做四张图:CPU 使用率(按核心)、内存使用率、磁盘使用率与增长趋势、网络进出流量。再加一张「磁盘可用空间」的单一数值面板,配上阈值变色,一眼就能看出哪台机器快满了。

保留策略与磁盘管理

时序数据库最大的运维风险就是磁盘被写满。InfluxDB 的数据是持续增长、只写不改的,如果不设保留策略,一年下来轻松吃掉几十 GB。除了在 bucket 上设 retention,还可以用「降采样」来长期保留趋势:把原始 15 秒精度的数据保留 30 天,然后把平均值按小时聚合后保留 1 年。

在 InfluxDB 2.x 里,降采样通过任务(Task)实现,用 Flux 写一个定时任务,把细粒度数据聚合后写入另一个长期 bucket:

option task = {name: "downsample_cpu", every: 1h}

from(bucket: "server_metrics")
  |> range(start: -task.every)
  |> filter(fn: (r) => r._measurement == "cpu")
  |> aggregateWindow(every: 1h, fn: mean)
  |> to(bucket: "server_metrics_1y")

同时监控 InfluxDB 自身的磁盘占用:du -sh /var/lib/influxdb2/。如果发现增长异常快,八成是某个 measurement 的 tag 基数爆炸了(比如误把 IP 当 tag),用 influx query 列出各 measurement 的 series 数量排查。

五个必踩的坑

  1. tag 基数爆炸:把 IP、request_id、URL 的完整路径当 tag,几百万序列瞬间吃掉内存。tag 只放能被反复复用的维度。
  2. 8086 暴露公网:InfluxDB 默认无鉴权也可访问部分端点,API 端口一旦公网可达就是裸奔。永远绑回环 + SSH 隧道。
  3. token 硬编码进 Git:配置文件、CI 脚本里写明文 token 是重灾区。用环境变量或 600 权限的 EnvironmentFile。
  4. field 类型冲突:同一个 measurement 的同一 field,一会儿写整数一会儿写浮点,InfluxDB 直接拒绝整批写入。设计时定好类型。
  5. 不设保留策略:磁盘慢慢被写满是最常见的翻车方式。bucket 一定要设 retention,长期趋势靠降采样任务保存。

小结

对于个人站长来说,InfluxDB + Telegraf + Grafana 是一套性价比极高的监控方案:全部开源免费,单台 2GB VPS 就能跑,装完之后你对服务器的了解会从「出事了才知道」变成「趋势一目了然」。关键在于把数据模型设计对——tag 放维度、field 放数值、基数要控制;把安全守住——绑回环、最小权限 token;把磁盘管住——设保留策略。

下一步可以做的事:给 Telegraf 加 http_response 插件做站点的黑盒可用性监控,或者写个小脚本把每天的访问量、收录数上报成自定义指标,长期跟踪 SEO 效果。

Last modification:October 12th, 2026 at 09:27 pm

Leave a Comment