Graylog高可用部署实战:从集群搭建到Nginx负载均衡
1. 为什么我们需要一个高可用的日志平台?
想象一下,你负责维护一个核心的业务系统,半夜突然收到告警,服务挂了。你火急火燎地登录服务器,第一反应就是看日志,结果发现日志服务器自己也宕机了,一片漆黑,什么线索都没有。那种感觉,就像在黑夜里找掉在地上的钥匙,既无助又抓狂。
这就是单点故障的可怕之处。在今天的云原生和微服务架构下,系统组件繁多,日志就是我们的“黑匣子”,是排查问题的生命线。如果这个“黑匣子”本身不可靠,那整个系统的可观测性就无从谈起。所以,构建一个高可用的日志平台,不再是“锦上添花”,而是“雪中送炭”的必需品。
Graylog 作为一个优秀的开源日志管理平台,本身支持分布式架构,这为我们构建高可用方案提供了坚实的基础。一个完整的高可用 Graylog 集群,通常包含几个核心部分:首先是存储层,也就是 Elasticsearch 集群,它负责海量日志的索引和搜索,必须通过集群保证数据不丢失;其次是配置和元数据存储,我们用 MongoDB 副本集来承担,确保 Graylog 服务器的配置信息安全可靠;然后是 Graylog Server 节点本身,我们需要部署多个,让它们协同工作;最后,还需要一个统一的“大门”,也就是负载均衡器(比如 Nginx),把外部的日志摄入请求和用户的管理查询请求,合理地分发到后端的多个 Graylog Server 上。
这么一套组合拳下来,任何一个节点宕机,其他节点都能立刻顶上,服务不中断,数据不丢失。下面,我就结合自己多次搭建和运维的经验,带你从零开始,手把手构建这样一个坚如磐石的企业级 Graylog 高可用集群。我会把重点放在实战操作和那些容易踩坑的细节上,让你不仅能搭起来,更能理解为什么这么搭。
2. 基石:搭建 Elasticsearch 与 MongoDB 集群
高可用大厦的地基,就是后端存储集群。这一步没做稳,后面的 Graylog 配置得再花哨也是空中楼阁。
2.1 Elasticsearch 集群搭建:数据可靠性的保障
Elasticsearch (ES) 是 Graylog 的日志存储和搜索引擎。生产环境绝对不能用单节点。一个最基本的 ES 高可用集群至少需要 3 个节点,以防止“脑裂”问题。我习惯用 elasticsearch-7.x 版本,与 Graylog 的兼容性比较成熟稳定。
首先,在每台服务器上安装 ES。这里我直接用 yum 安装,比较省事。你需要先导入 Elastic 的 GPG 密钥和仓库配置。
# 导入 GPG 密钥
rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch
# 创建仓库文件
cat > /etc/yum.repos.d/elasticsearch.repo << EOF
[elasticsearch-7.x]
name=Elasticsearch repository for 7.x packages
baseurl=https://artifacts.elastic.co/packages/7.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=1
autorefresh=1
type=rpm-md
EOF
# 安装 Elasticsearch
yum install -y elasticsearch-7.17.9
安装完成后,关键来了——配置 elasticsearch.yml。下面是一个三节点集群的配置示例(以 node-1 为例):
# /etc/elasticsearch/elasticsearch.yml (node-1)
cluster.name: graylog-cluster # 集群名称,所有节点必须一致
node.name: es-node-1 # 节点名称,每个节点要唯一
path.data: /var/lib/elasticsearch # 数据目录,确保空间充足
path.logs: /var/log/elasticsearch
network.host: 0.0.0.0 # 绑定所有网络接口,生产环境建议绑定内网IP
http.port: 9200
discovery.seed_hosts: ["192.168.1.101", "192.168.1.102", "192.168.1.103"] # 所有节点IP
cluster.initial_master_nodes: ["es-node-1", "es-node-2", "es-node-3"] # 初始主节点候选者
bootstrap.memory_lock: true # 锁住内存,提高性能
discovery.seed_hosts 和 cluster.initial_master_nodes 这两个参数是集群组建的关键。前者让节点彼此发现,后者在集群首次启动时确定主节点。配置好后,依次启动三台机器的 ES 服务:systemctl start elasticsearch && systemctl enable elasticsearch。用 curl http://localhost:9200/_cluster/health?pretty 检查集群状态,看到 "status" : "green" 并且 "number_of_nodes" : 3,就说明集群健康运行了。
这里有个我踩过的坑:防火墙和 SELinux。务必确保所有 ES 节点之间的 9300(集群通信端口)和 9200(HTTP API端口)是互通的。可以用 firewall-cmd --permanent --add-port={9200,9300}/tcp 放行端口,或者直接在内网环境临时关闭防火墙进行测试。SELinux 也可能会阻止进程绑定端口,如果遇到启动失败,可以尝试 setenforce 0 设置为宽容模式排查问题。
2.2 MongoDB 副本集搭建:配置信息的安全屋
Graylog 的配置、用户数据、报警定义等都存在 MongoDB 里。我们用副本集(Replica Set)来保证这些元数据的高可用。同样,至少需要3个节点。
安装 MongoDB(以 4.4 版本为例):
# 配置 MongoDB yum 源
cat > /etc/yum.repos.d/mongodb-org-4.4.repo << EOF
[mongodb-org-4.4]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/\$releasever/mongodb-org/4.4/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-4.4.asc
EOF
yum install -y mongodb-org
配置副本集,每个节点的 /etc/mongod.conf 核心部分如下:
# /etc/mongod.conf
storage:
dbPath: /var/lib/mongo
journal:
enabled: true
systemLog:
destination: file
logAppend: true
path: /var/log/mongodb/mongod.log
net:
port: 27017
bindIp: 0.0.0.0 # 同样,生产环境建议绑定内网IP
replication:
replSetName: graylog-rs # 副本集名称,所有节点必须一致
启动所有节点的 MongoDB 服务后,连接到其中任意一个节点进行副本集初始化:
// 在 mongo shell 中执行
rs.initiate( {
_id : "graylog-rs",
members: [
{ _id: 0, host: "192.168.1.201:27017" },
{ _id: 1, host: "192.168.1.202:27017" },
{ _id: 2, host: "192.168.1.203:27017" }
]
})
执行 rs.status() 查看状态,确保其中一个节点显示为 "PRIMARY",其余为 "SECONDARY"。副本集就搭建完成了。这里有个小技巧,你可以在配置 Graylog 之前,先在 MongoDB 里创建一个专用的数据库和用户,这样更安全。不过 Graylog 也支持在连接字符串中自动创建,我们后面配置时会用到。
3. Graylog Server 集群:双机热备与配置详解
存储层搞定后,我们就可以部署 Graylog Server 本身了。高可用至少需要两个 Graylog Server 节点,一个主(Master),一个从(Slave),它们共享同一个 MongoDB 和 Elasticsearch 集群。
3.1 使用 Ansible 实现自动化部署
手动在一台台机器上安装配置效率太低,也容易出错。我强烈推荐使用 Ansible 进行剧本化部署。这不仅是一次性工作,更是为未来的运维、升级、扩容打下基础。下面我分享一个核心的 Playbook 示例。
假设我们有两台服务器:graylog-01(主)和 graylog-02(从)。首先,准备 Graylog 的 RPM 安装包。你可以从 Graylog 官网下载,我通常下载到本地,然后用 Ansible 的 copy 模块分发到目标机器。
# graylog_deploy.yml
- hosts: graylog_servers # 在 Ansible inventory 中定义的主机组
become: yes
vars:
graylog_version: "4.3.6"
master_node: "graylog-01"
tasks:
- name: 分发 Graylog Server RPM 包
copy:
src: "/local/path/graylog-server-{{ graylog_version }}.rpm"
dest: "/tmp/graylog-server.rpm"
- name: 安装 Graylog Server
yum:
name: "/tmp/graylog-server.rpm"
state: present
- name: 生成 password_secret (每个节点唯一)
shell: |
pwgen -N 1 -s 96
register: password_secret
delegate_to: localhost # 在控制机生成,然后传递给各个节点
run_once: yes
- name: 设置 root_password_sha2 (集群统一)
set_fact:
root_password_sha2: "{{ 'YourAdminPassword123!' | password_hash('sha256') }}"
这个 Playbook 做了几件事:分发安装包、安装软件、生成加密密钥。注意 password_secret 是每个 Graylog 节点用于加密通信和数据的密钥,必须唯一。而 root_password_sha2 是 Web 登录密码的 SHA256 哈希值,所有节点应该一致,这样你登录任何一个节点的 Web 界面密码都一样。
3.2 关键配置文件 server.conf 的差异化配置
安装完成后,最核心的就是 /etc/graylog/server/server.conf 文件。主节点和从节点的配置大部分相同,但有几处关键区别。我通过 Ansible 的模板功能来动态生成。
创建一个 Jinja2 模板文件 server.conf.j2:
# server.conf.j2 模板
is_master = {{ (inventory_hostname == master_node) | ternary('true', 'false') }}
node_id_file = /etc/graylog/server/node-id
password_secret = {{ password_secret.stdout }}
root_password_sha2 = {{ root_password_sha2 }}
root_username = admin
root_timezone = Asia/Shanghai
http_bind_address = {{ ansible_default_ipv4.address }}:9000
# 发布 URI,这是外部或负载均衡器访问本节点的地址
http_publish_uri = http://{{ ansible_default_ipv4.address }}:9000/
# Elasticsearch 集群连接
elasticsearch_hosts = http://192.168.1.101:9200,http://192.168.1.102:9200,http://192.168.1.103:9200
# MongoDB 副本集连接
mongodb_uri = mongodb://192.168.1.201:27017,192.168.1.202:27017,192.168.1.203:27017/graylog?replicaSet=graylog-rs
在 Playbook 中增加模板渲染任务:
- name: 配置 Graylog Server
template:
src: server.conf.j2
dest: /etc/graylog/server/server.conf
notify: restart graylog-server
看第一行 is_master,我用了 Ansible 的条件判断 (inventory_hostname == master_node)。只有当当前执行的主机名是我们在变量里定义的 master_node(即 graylog-01)时,这个值才是 true,对于 graylog-02 自动变为 false。这样就完美实现了主从节点的自动区分。
另外,http_bind_address 我绑定了服务器的内网 IP,而 http_publish_uri 也使用了这个 IP。这里有个非常重要的点:http_publish_uri 是 Graylog 节点向集群内外宣告自己的地址,负载均衡器(Nginx)和后端 Sidecar 采集器都会用这个地址来连接。所以它必须是一个能被其他组件访问到的地址,不能是 127.0.0.1。
3.3 启动与验证
配置完成后,启动服务并设置开机自启:
systemctl daemon-reload
systemctl start graylog-server
systemctl enable graylog-server
查看日志 journalctl -u graylog-server -f,确保没有报错。分别访问两个节点的 http://<节点IP>:9000,应该都能看到 Graylog 的 Web 登录界面。用 admin 和你设置的密码登录。
登录后,进入 System -> Nodes 页面,你应该能看到两个节点,其中一个的 Is Master 列显示为 Yes(主节点),另一个为 No(从节点)。这证明你的 Graylog Server 集群已经成功组建,它们共享着 MongoDB 里的配置,并共同向 Elasticsearch 集群写入和查询数据。
4. 接入层:Nginx 负载均衡与反向代理配置
现在我们有了一主一从两个 Graylog Server,但对外暴露两个入口显然不合适。我们需要一个统一的入口,这就是 Nginx 的作用。它主要干两件事:一是作为反向代理,将用户访问 Web 界面的请求负载均衡到后端 Graylog 节点;二是作为负载均衡器,接收来自各种采集器(如 Sidecar、Syslog)的日志数据流,并分发给后端节点。
4.1 配置 Upstream 与 Web 界面代理
首先,我们定义一个 upstream 块,把两个 Graylog Server 节点加进去。我通常使用 least_conn(最少连接)算法,这样可以将新的请求发给当前连接数最少的节点,负载更均衡。
# 在 nginx.conf 的 http 块内
upstream graylog_web_servers {
least_conn;
server 192.168.1.11:9000; # graylog-01
server 192.168.1.12:9000; # graylog-02
# 可以设置权重、健康检查等参数
# server 192.168.1.11:9000 weight=3;
# server 192.168.1.12:9000 max_fails=3 fail_timeout=30s;
}
然后,配置一个 server 块来代理 Web 请求:
server {
listen 80;
# 如果你有域名,可以配置 server_name,例如 graylog.yourcompany.com
server_name _;
location / {
proxy_pass http://graylog_web_servers;
# 以下几行 proxy_set_header 至关重要,它们将客户端的真实信息传递给 Graylog
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 设置较长的超时时间,因为日志查询可能耗时
proxy_read_timeout 300s;
proxy_connect_timeout 75s;
}
# 可选:静态资源缓存,提升访问速度
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
proxy_pass http://graylog_web_servers;
expires 30d;
add_header Cache-Control "public, immutable";
}
}
配置好后,执行 nginx -t 测试配置,然后 nginx -s reload 重载。现在,用户只需要访问 Nginx 的 IP 或域名,就可以无缝使用 Graylog Web 界面了。即使其中一个 Graylog 节点宕机,Nginx 会自动将请求转发到健康的节点,用户无感知。
4.2 配置 GELF/UDP/TCP 输入负载均衡
除了 Web 界面,Graylog 更重要的功能是接收日志。很多采集器(如 Sidecar 的 Filebeat、NXLog,或网络设备的 Syslog)会通过 GELF、UDP、TCP 等协议将日志发送到 Graylog。我们需要让 Nginx 也能对这些输入进行负载均衡。
但是请注意:Nginx 默认的 stream 模块(用于四层 TCP/UDP 代理)和 http 模块(七层代理)是分开的。对于 Graylog 的 GELF HTTP 输入(端口通常为 12201),我们可以用上面的 http 代理块类似处理,只需新增一个 location 或新的 upstream。
但对于 Syslog UDP/TCP 或 Raw/Plaintext TCP 输入,就需要用到 stream 模块。确保你的 Nginx 编译时包含了 --with-stream 模块。配置如下:
# 在 nginx.conf 的 main 层级,与 http 块并列
stream {
upstream graylog_syslog_udp {
server 192.168.1.11:1514; # Graylog 节点1的 Syslog UDP 输入端口
server 192.168.1.12:1514; # Graylog 节点2的 Syslog UDP 输入端口
}
server {
listen 514 udp; # Nginx 监听 UDP 514 端口(标准 Syslog 端口)
proxy_pass graylog_syslog_udp;
# UDP 代理需要指定缓冲区
proxy_buffer_size 16k;
proxy_responses 0; # 对于 UDP,通常设为 0,因为是无连接的
}
upstream graylog_gelf_tcp {
server 192.168.1.11:12201;
server 192.168.1.12:12201;
}
server {
listen 12201; # 默认监听 TCP
proxy_pass graylog_gelf_tcp;
proxy_connect_timeout 10s;
proxy_timeout 30m; # 长连接超时时间
}
}
这样配置后,所有采集器只需要将日志发送到 Nginx 服务器的对应端口(如 your-nginx-ip:514 或 your-nginx-ip:12201),Nginx 就会把日志流负载均衡到后端的 Graylog 集群。这极大地提高了日志摄入的吞吐量和可用性。
5. Graylog Sidecar 的自动化部署与管理
Graylog Sidecar 是一个轻量级的日志采集器管理器,它本身不采集日志,而是去管理你服务器上真正的采集器,比如 Filebeat、Winlogbeat 等。它通过 API 从 Graylog Server 获取采集配置,然后应用到对应的 Beats 上,实现了配置的集中管理和下发。
5.1 获取 API Token 与 Sidecar 安装
部署 Sidecar 前,必须先从 Graylog Web 界面获取一个 API Token。登录 Graylog,进入 System -> Sidecars,在 Configuration 选项卡里,点击 Create a new token,给它起个名字(比如 prod-sidecar-token)。这个 Token 是 Sidecar 与 Graylog Server 通信的凭证,务必妥善保存。
Sidecar 的安装也可以通过 Ansible 轻松完成。首先,从 GitHub 下载 Sidecar 的 RPM 包。然后在 Playbook 中增加针对 Sidecar 主机组的任务:
- hosts: sidecar_agents # 所有需要部署采集器的服务器
become: yes
vars:
graylog_server_url: "http://your-nginx-ip:80/api" # 注意是 Nginx 的地址和 API 路径
sidecar_api_token: "你的长串API Token"
tasks:
- name: 分发 Sidecar RPM 包
copy:
src: "/local/path/graylog-sidecar.rpm"
dest: "/tmp/graylog-sidecar.rpm"
- name: 安装 Sidecar
yum:
name: "/tmp/graylog-sidecar.rpm"
state: present
- name: 配置 Sidecar
template:
src: sidecar.yml.j2
dest: /etc/graylog/sidecar/sidecar.yml
notify: restart graylog-sidecar
sidecar.yml.j2 模板内容如下:
server_url: {{ graylog_server_url }}
server_api_token: {{ sidecar_api_token }}
node_name: {{ inventory_hostname }} # 使用 Ansible 主机名作为节点名
update_interval: 30
tls_skip_verify: true # 如果使用自签名证书,设为 true。生产环境建议配置正式证书。
tags: ["linux", "prod"] # 给这台 Sidecar 打上标签,方便在 Graylog 里分组管理
这里的关键是 server_url,它必须指向我们前面配置的 Nginx 的地址和 API 路径(/api)。这样,所有 Sidecar 都通过统一的负载均衡入口与 Graylog 集群通信,避免了单点故障。
5.2 配置管理与故障转移实践
Sidecar 启动并注册后,你会在 Graylog 的 System -> Sidecars 页面看到它。接下来,你可以在 Administration -> Sidecar Configuration 中创建配置。比如,创建一个 “Nginx Access Log” 配置,指定使用 Filebeat 来采集 /var/log/nginx/access.log,并将日志输出到 Graylog 的 GELF HTTP 输入。
将这个配置分配给带有 linux 和 prod 标签的 Sidecar 组。几分钟内,对应的服务器上的 Filebeat 就会自动被 Sidecar 配置好并启动,开始采集日志。
高可用在这里的体现是:如果某个 Graylog Server 节点宕机,Sidecar 通过 Nginx 访问 API 的请求会自动被导向另一个健康的节点,配置拉取和状态上报不会中断。同时,Sidecar 管理的 Filebeat 是将日志发送到 Nginx 的负载均衡端口,同样不受后端单个 Graylog 节点故障的影响。整个日志采集链路都是高可用的。
6. 故障转移与日常维护要点
集群搭起来只是第一步,更重要的是知道它怎么“活”的,以及出了问题怎么“治”。
6.1 理解故障转移流程
- Graylog Server 主节点宕机:当
is_master=true的节点宕机后,另一个is_master=false的节点不会自动切换为主节点。Graylog 的 Master 节点主要负责一些后台管理任务(如周期性的索引滚动、警报检查触发等)。Web 界面和日志摄入功能,两个节点都能独立处理。所以,即使主节点挂了,只要 Nginx 将请求代理到了从节点,基本功能不受影响。你可以手动修改从节点的server.conf,将is_master改为true并重启,来恢复完整的后台管理功能。 - Elasticsearch 节点宕机:只要集群中存活节点数大于等于2(对于3节点集群),ES 集群仍可读写。分片和副本机制会保证数据可用性。Graylog 会尝试重连,期间可能会有短暂的写入延迟或错误日志。
- MongoDB 副本集节点宕机:如果是从节点宕机,不影响使用。如果是主节点宕机,副本集会自动选举新的主节点,这个过程通常几秒钟。Graylog Server 配置了完整的副本集连接字符串,驱动会自动处理重连和主节点发现。
- Nginx 宕机:这是单点故障!所有日志摄入和 Web 访问都会中断。解决方案:对 Nginx 本身做高可用,例如使用 Keepalived 实现 VIP 漂移,或者使用云厂商的负载均衡器服务。
6.2 监控与日常检查清单
- Graylog 节点监控:定期查看
System -> Nodes页面,确认所有节点状态为Alive。关注Process buffer和Output buffer的使用率,持续过高可能意味着处理瓶颈。 - Elasticsearch 健康度:在 Graylog 的
System -> Elasticsearch页面查看集群状态,确保是Green。也可以直接调用 ES API:curl -XGET 'http://es-node:9200/_cluster/health?pretty'。 - MongoDB 副本集状态:定期连接 MongoDB Shell 执行
rs.status(),查看成员状态和选举信息。 - Sidecar 状态:在
System -> Sidecars页面,确保所有 Sidecar 状态为Running,最后汇报时间在几分钟内。 - 系统资源监控:监控 Graylog、ES、MongoDB 节点的 CPU、内存、磁盘 I/O 和磁盘空间。Elasticsearch 尤其吃内存和磁盘。
6.3 性能调优与扩容建议
- Elasticsearch 索引策略:Graylog 默认按天创建索引。对于日志量大的环境,可以调整为按小时,或者根据日志量设置
elasticsearch_max_docs_per_index(单索引最大文档数)和elasticsearch_max_number_of_indices(最大索引数),配合合理的 retention(保留)策略,防止磁盘被撑爆。 - JVM 堆内存:Graylog 和 Elasticsearch 都是 Java 应用,需要合理配置 JVM 堆内存。一般建议设置为系统物理内存的 50%,但不要超过 32GB(超过后 JVM 指针压缩失效,反而降低性能)。在
/etc/graylog/server/server.conf中配置-Xms4g -Xmx4g。 - 扩容:当处理能力不足时,水平扩容是最佳选择。可以轻松地增加 Graylog Server 节点,只需安装软件、配置
server.conf(指定正确的 ES 和 MongoDB 地址,并设置is_master=false),然后将其 IP 添加到 Nginx 的upstream中即可。Elasticsearch 和 MongoDB 集群也可以按需增加节点。
搭建和维护这样一个高可用的 Graylog 集群,初期确实需要一些投入,但一旦稳定运行,它带来的运维效率提升和故障排查能力是巨大的。你会发现自己再也不用担心日志服务器挂掉,可以从容地面对海量日志,快速定位线上问题。这套架构在我们生产环境已经平稳运行了两年多,期间经历了多次服务器硬件故障和业务流量洪峰,都很好地扛了下来,希望这份实战经验也能帮你构建出属于自己的可靠日志中枢。
更多推荐

所有评论(0)