Graylog 集中日志平台实战:多台服务器日志统一收集、字段解析、看板与内容告警全流程

多台服务器日志散落各处,是站长最容易忽略的运维黑洞

一个人手上管几台服务器太正常了:一台跑主站,一台做数据库,一台当备份节点,可能还有一台测试机。平时相安无事,可一旦出问题,排查过程往往是这样:你发现网站变慢了,怀疑是数据库,于是 SSH 上数据库那台,tail -f 看 MySQL 日志,没看出问题;再想起 Nginx 那台的 access log 是不是有异常流量,又切过去翻;翻到一半,突然想起昨天那台备份机是不是跑崩了导致 IO 被打满……几台机器来回切,几分钟能定位的问题能耗掉你一小时。

这就是"日志分散"的代价。每一台机器都各自记日志,没有一个统一的地方能让你一眼看到整条链路发生了什么。今天要讲的 Graylog,就是专门解决这个问题的:把所有服务器的日志统一收集、集中存储、全文检索、并且能基于日志内容自动告警。它不是给大厂准备的重型武器——个人站跑一套单机 Graylog,资源占用完全可控,收益却非常明显。

先说一下它和同类工具的定位区别,免得你选错方向。rsyslog 是"采集和转发"工具,它能把日志汇到一起,但缺乏强大的检索和告警能力,适合做最基础的日志归集。Loki 是"轻量、只看标签不建全文索引"的方案,查询快、省资源,但全文搜索能力弱,复杂的条件过滤要靠 LogQL 硬写,而且默认不做内容索引。而 Graylog 走的是"全文索引"路线,底层用 Elasticsearch/OpenSearch 做索引,所以它的全文检索、字段聚合、看板和告警能力是最强的——代价是它比 Loki 吃资源,需要一套 JVM + 搜索引擎。个人站单机跑一套,配 4GB 内存左右是舒服的水位线。

Graylog 的三个组成部分

落地之前先把架构搞明白,否则配置会乱。

Graylog Server 是大脑,负责接收日志、解析字段、执行检索和告警。它本身用 Java 写,比较吃内存,默认 JVM 堆建议给 1–2GB。

Elasticsearch / OpenSearch 是索引和存储引擎。所有日志的结构化字段和全文内容都存在这里,检索也由它执行。Graylog 4.x 之后官方主推 OpenSearch,因为它许可更友好。这一块对内存和 vm.max_map_count 有硬性要求。

MongoDB 存的是 Graylog 自己的配置——流(Stream)、索引集(Index Set)、告警规则、用户、仪表盘等元数据。注意它不存日志本身,只存"配置",所以数据量很小,用默认配置即可。

数据流向是:服务器上的采集端(rsyslog / Filebeat / Graylog Sidecar)把日志通过 GELF、Syslog TCP/UDP、Beats 等协议发给 Graylog Server,Server 解析后写入 OpenSearch,检索和告警都基于 OpenSearch 里的索引。

部署:先解决 vm.max_map_count 这个硬门槛

用 Docker Compose 部署最省事,但有一个必须先做的系统参数配置,否则 OpenSearch 会启动失败、报 max virtual memory areas vm.max_map_count [65530] is too low。这个坑几乎每个人第一次都会踩:

# 临时生效
sysctl -w vm.max_map_count=262144

# 永久生效
echo "vm.max_map_count=262144" >> /etc/sysctl.conf
sysctl -p

注意,这个参数是改在宿主机上的,不是容器内。因为 OpenSearch 的 JVM 需要大量的内存映射文件,容器的 mmap 能力受限于宿主内核参数。改完再往下走。

然后是 compose 文件,把三个组件加一个供日志写入的密码:

version: "3.8"
services:
  mongodb:
    image: mongo:6
    restart: unless-stopped
    volumes:
      - ./mongo:/data/db

  opensearch:
    image: opensearchproject/opensearch:2
    restart: unless-stopped
    environment:
      - discovery.type=single-node
      - bootstrap.memory_lock=true
      - "OPENSEARCH_JAVA_OPTS=-Xms1g -Xmx1g"
      - DISABLE_SECURITY_PLUGIN=true
    ulimits:
      memlock: {soft: -1, hard: -1}
    volumes:
      - ./opensearch:/usr/share/opensearch/data
    ports:
      - "127.0.0.1:9200:9200"

  graylog:
    image: graylog/graylog:5.2
    restart: unless-stopped
    environment:
      - GRAYLOG_PASSWORD_SECRET=please_change_this_to_a_long_random_string
      - GRAYLOG_ROOT_PASSWORD_SHA2=1111111111111111111111111111111111111111111111111111111111111111
      - GRAYLOG_HTTP_EXTERNAL_URI=http://127.0.0.1:9000/
      - GRAYLOG_ELASTICSEARCH_HOSTS=http://opensearch:9200
      - GRAYLOG_MONGODB_URI=mongodb://mongodb:27017/graylog
    ports:
      - "127.0.0.1:9000:9000"
      - "127.0.0.1:12201:12201/udp"   # GELF UDP
      - "127.0.0.1:1514:1514"          # Syslog TCP
    depends_on:
      - mongodb
      - opensearch

这里 GRAYLOG_ROOT_PASSWORD_SHA2 是管理员密码的 SHA-256 哈希,123... 那个只是占位,必须换成你自己密码的哈希,用这条命令生成:

echo -n "你的密码" | sha256sum

DISABLE_SECURITY_PLUGIN=true 是关掉 OpenSearch 自带的 HTTPS 认证插件,因为它在内网里、由 Graylog 独占访问,个人站这么配足够。但同样,9200、9000、12201 全部只绑 127.0.0.1,绝不让它们直接暴露公网。

启动后等 OpenSearch 就绪(第一次要一两分钟),浏览器访问 http://127.0.0.1:9000,用用户名 admin 和你设的密码登录。要公网访问,走 Nginx 反代 + basic auth 或 IP 白名单,别偷懒。

配置输入(Input)和字段解析,让日志"活"起来

登录后第一件事是加输入。菜单 System → Inputs,选一个类型,最常见的两种:

GELF UDP 接收结构化日志,适合程序主动上报;Syslog TCP 接收传统 syslog,适合 rsyslog/系统日志转发。个人站建议两种都开。启动后 Graylog 会分配端口(GELF UDP 默认 12201,Syslog TCP 默认 1514)。

输入只负责"收",真正的价值在字段解析。日志一多,原始文本里什么信息都混在一起,你没法按状态码、按 IP、按耗时去筛选。Graylog 用 Extractors(提取器) 或 Pipeline 规则把文本里的关键信息抽成结构化字段。

比如 Nginx 的 access log,取这样一条原始行:

1.2.3.4 - - [12/Oct/2026:10:00:00 +0800] "GET /post/123.html HTTP/1.1" 200 5432 "-" "Mozilla/5.0"

可以建一个 Extractor,用正则按组提取:

^(\S+) \S+ \S+ \[([^\]]+)\] "(\S+) (\S+) [^"]*" (\d{3}) (\d+)

把 group 1 命名为 remote_ip,group 3 命名为 method,group 5 命名为 status,group 6 命名为 bytes。抽完之后,日志就从一坨文本变成了可以按字段筛选的记录。搜"过去一小时所有 5xx 请求"就是一行查询:

status:5* AND http_method:GET

这一步做没做,决定了你以后排查效率是一个量级的差距。字段解析是 Graylog 最值得投入时间的地方,别嫌麻烦。

用 Stream 分流,用 Dashboard 看整体

Stream(流)是 Graylog 里"给日志分类"的机制。你可以建几条规则,把不同来源的日志分到不同的流里,比如"全部 Nginx 日志进 nginx 流"、"只把 5xx 状态码进 error 流"、"数据库慢日志进 db 流"。分流之后,检索时可以只在某个流里搜,速度更快、结果更干净;配置告警时也能针对特定流做,避免被无关日志淹没。

分流规则用简单的条件表达式即可,比如 Nginx 流:

source:nginx-server-name

或者基于解析出的字段:

service:nginx AND level:error

Dashboard(仪表盘)把常用的检索结果固化成图表,一屏看全局。个人站至少值得建这三个面板:

  • 请求量与状态码分布:按小时统计总请求数,叠加 4xx/5xx 曲线,一眼看出异常时段。
  • Top 来源 IP:柱状图显示请求最多的 IP,CC 攻击或爬虫刷量时立刻现形。
  • 错误日志趋势:把所有 level:error 的数量按时间画出来,程序偷偷报错但没人看的情况就藏不住了。

Dashboard 建好之后,你每天花十秒扫一眼,比事后翻日志高效得多。

把告警接到手机,让日志自己"喊人"

Graylog 最强的一点是基于日志内容告警。你不需要盯着面板,配好规则后它自己会通知你。典型规则,比如"10 分钟内出现超过 50 次 500 错误":

status:5*    # 条件:字段匹配
# 触发条件:过去 10 分钟计数 > 50
# 阈值类型:Message Count

创建告警的入口在 Alerts → Event Definitions。写好条件后,配一个 Notification,把消息发到你想去的地方。个人站最实用的几种接收渠道:Email(SMTP)、Slack/Discord Webhook、钉钉或企业微信机器人 Webhook、Telegram Bot。以 Telegram 为例,只要一个 Bot Token 和 chat_id,Graylog 就能在你服务器出事时第一时间推消息到手机。

值得配的几条基础告警:500 错误激增、登录失败次数激增(可能是暴力破解)、某台主机完全没日志上报(可能宕机或网络断了)、磁盘相关的错误关键字出现。最后那条"心跳告警"尤其重要——"没有日志"本身就是一种需要告警的状态。

给要纳入的服务器配采集端

Graylog 本体搭好了,还得让每台服务器把日志送过来。有两种主流做法。

做法一:rsyslog 转发。在每台服务器上配置 rsyslog,把指定文件或全部日志通过 TCP 转发到 Graylog 的 Syslog 输入端口。改 /etc/rsyslog.d/60-graylog.conf:

*.* @@graylog.example.com:1514;RSYSLOG_SyslogProtocol23Format

两个 @ 表示 TCP(一个 @ 是 UDP,不推荐,会丢日志)。注意文件日志(比如 Nginx 的 access.log)默认不归 syslog 管,需要额外用 imfile 模块读取:

module(load="imfile")
input(type="imfile"
      File="/var/log/nginx/access.log"
      Tag="nginx-access"
      Severity="info")

做法二:Graylog Sidecar。官方提供一个叫 Sidecar 的轻量代理,装在每台机器上,由 Graylog Server 集中管理配置,你在网页上改采集规则,Sidecar 自动拉取生效。机器多的话这个体验最好,不用一台台上服务器改 rsyslog。

不管用哪种,配完都要回 Graylog 的 Search 页面搜一下,确认日志真的进来了、字段也解析对了。

五个必须知道的坑

第一,vm.max_map_count 没改。这是最大的拦路虎,OpenSearch 起不来八成是它,务必先改宿主机内核参数。

第二,把 9000/12201 暴露公网。Graylog 的输入端口如果裸奔在公网,等于让全世界往你磁盘里灌数据、把你的搜索引擎写爆。全部绑 127.0.0.1,对外走 Nginx。

第三,不注意磁盘生命周期。日志是无限增长的,OpenSearch 磁盘写满后整套服务全部卡死。一定要在 Index Set 里配好保留策略——按时间(比如只留 30 天)或按大小(比如超过 50GB 就删最旧的),让旧索引自动轮转删除。

第四,JVM 堆给太小。Graylog 和 OpenSearch 都是 Java 应用,堆给不够会频繁 GC 甚至 OOM。个人站给 Graylog 1–2GB、OpenSearch 1GB 起,是常见的舒服区间,别用 512MB 硬撑。

第五,上来就收集所有日志。把每台机器的全部日志一股脑塞进来,没用几天磁盘就爆,检索也慢。先想清楚"我要用它排查什么",只收有价值的日志(Web 访问、错误、认证、数据库慢查询),无关的 debug 日志先不收。

什么时候该用 Graylog,什么时候用 Loki

最后回到选型。如果你需要强全文检索、按字段聚合、复杂的告警规则、可视化看板,而且愿意为它付出多一点的资源开销,Graylog 是对的。如果你服务器内存吃紧、日志量不大、主要需求只是"日志能集中看、能按标签搜",那 Loki + Promtail 更轻、更省,前面提到的路径也没错。

但对个人站长而言,真正的门槛从来不是工具选哪个,而是你到底有没有把日志集中起来。哪怕是 Graylog 这种"重"方案,单机四五个 G 内存也跑得很稳,换来的是出问题时能在一分钟内定位到是哪台机器的哪个环节——这个正反馈,会让你以后再也回不去逐台 SSH 翻日志的日子。

Last modification:October 12th, 2026 at 08:25 pm

Leave a Comment