Skip to content

NFS 高可用存储监控告警方案

方案概述

基于 Prometheus + Grafana + Alertmanager 构建 NFS 高可用存储监控体系,覆盖:

  • 节点层面:CPU、内存、磁盘、网络
  • GlusterFS 层面:卷状态、brick 状态、容量、自愈
  • NFS-Ganesha 层面:服务存活、导出可用性
  • Keepalived 层面:VIP 漂移、VRRP 状态
  • 告警通道:邮件 / 钉钉 / 企业微信 / Slack

监控架构

                    ┌─────────────────┐
                    │    Grafana      │
                    │   (可视化)       │
                    └────────┬────────┘

                    ┌────────▼────────┐
                    │   Prometheus    │
                    │   (时序数据库)   │
                    └────────┬────────┘

        ┌────────────────────┼────────────────────┐
        │                    │                    │
┌───────▼───────┐   ┌────────▼────────┐   ┌──────▼──────┐
│  Node Exporter │   │ Gluster Exporter │   │ Ganesha     │
│  (节点指标)    │   │ (卷/brick 指标)  │   │ Exporter    │
└───────────────┘   └─────────────────┘   └─────────────┘
        │                    │                    │
        └────────────────────┼────────────────────┘

                  ┌──────────▼──────────┐
                  │    Alertmanager     │
                  │    (告警通知)        │
                  └─────────────────────┘

环境规划

组件部署节点端口
Prometheus独立监控节点(或 node1)9090
Grafana独立监控节点(或 node1)3000
Alertmanager独立监控节点(或 node1)9093
Node Exporter所有存储节点9100
Gluster Exporter所有存储节点9189
Ganesha Exporter所有存储节点9580

为简化,以下假设监控组件部署在 monitor 节点(IP: 10.0.0.20),存储节点为 node1/2/3


1. 部署 Prometheus

在监控节点执行:

bash
useradd --no-create-home --shell /bin/false prometheus
mkdir -p /etc/prometheus /var/lib/prometheus
cd /tmp
wget https://github.com/prometheus/prometheus/releases/download/v2.53.0/prometheus-2.53.0.linux-amd64.tar.gz
tar xvf prometheus-2.53.0.linux-amd64.tar.gz
cd prometheus-2.53.0.linux-amd64

cp prometheus promtool /usr/local/bin/
cp -r consoles/ console_libraries/ /etc/prometheus/
chown -R prometheus:prometheus /var/lib/prometheus /etc/prometheus

创建 /etc/prometheus/prometheus.yml

yaml
global:
  scrape_interval: 15s
  evaluation_interval: 15s

alerting:
  alertmanagers:
    - static_configs:
        - targets: ['localhost:9093']

rule_files:
  - /etc/prometheus/rules/*.yml

scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  - job_name: 'node-exporter'
    static_configs:
      - targets:
        - 'node1:9100'
        - 'node2:9100'
        - 'node3:9100'

  - job_name: 'gluster-exporter'
    static_configs:
      - targets:
        - 'node1:9189'
        - 'node2:9189'
        - 'node3:9189'

  - job_name: 'ganesha-exporter'
    static_configs:
      - targets:
        - 'node1:9580'
        - 'node2:9580'
        - 'node3:9580'

创建 systemd 服务 /etc/systemd/system/prometheus.service

ini
[Unit]
Description=Prometheus Monitoring System
After=network.target

[Service]
User=prometheus
Group=prometheus
Type=simple
ExecStart=/usr/local/bin/prometheus \
  --config.file=/etc/prometheus/prometheus.yml \
  --storage.tsdb.path=/var/lib/prometheus/ \
  --web.console.templates=/etc/prometheus/consoles \
  --web.console.libraries=/etc/prometheus/console_libraries
Restart=always

[Install]
WantedBy=multi-user.target

启动:

bash
systemctl daemon-reload
systemctl enable --now prometheus

2. 部署 Node Exporter(所有存储节点)

bash
cd /tmp
wget https://github.com/prometheus/node_exporter/releases/download/v1.8.1/node_exporter-1.8.1.linux-amd64.tar.gz
tar xvf node_exporter-1.8.1.linux-amd64.tar.gz
cp node_exporter-1.8.1.linux-amd64/node_exporter /usr/local/bin/

创建 systemd 服务 /etc/systemd/system/node_exporter.service

ini
[Unit]
Description=Node Exporter
After=network.target

[Service]
User=root
Type=simple
ExecStart=/usr/local/bin/node_exporter \
  --collector.filesystem.mount-points-exclude='^/(sys|proc|dev|run|var/lib/docker/.+|var/lib/containers/storage/.+)($|/)'
Restart=always

[Install]
WantedBy=multi-user.target

启动:

bash
systemctl daemon-reload
systemctl enable --now node_exporter

3. 部署 Gluster Exporter(所有存储节点)

使用社区版 gluster_exporter

bash
cd /tmp
wget https://github.com/ofesseler/gluster_exporter/releases/download/v0.2.7/gluster_exporter-0.2.7-linux-amd64.tar.gz
tar xvf gluster_exporter-0.2.7-linux-amd64.tar.gz
cp gluster_exporter /usr/local/bin/

创建 systemd 服务 /etc/systemd/system/gluster_exporter.service

ini
[Unit]
Description=GlusterFS Prometheus Exporter
After=network.target

[Service]
User=root
Type=simple
ExecStart=/usr/local/bin/gluster_exporter \
  --web.listen-address=:9189 \
  --web.telemetry-path=/metrics
Restart=always

[Install]
WantedBy=multi-user.target

启动:

bash
systemctl daemon-reload
systemctl enable --now gluster_exporter

验证指标:

bash
curl http://localhost:9189/metrics | head

4. 部署 Ganesha Exporter(所有存储节点)

NFS-Ganesha 原生通过 D-Bus 暴露统计信息,但没有成熟 exporter。这里使用一个轻量自定义 Python exporter。

4.1 安装依赖

bash
# Ubuntu
apt install -y python3-pip
pip3 install prometheus-client dbus-python --break-system-packages

# RHEL/Rocky
dnf install -y python3-pip python3-dbus
pip3 install prometheus-client

4.2 创建 exporter 脚本

写入 /usr/local/bin/ganesha_exporter.py

python
#!/usr/bin/env python3
import dbus
import sys
from prometheus_client import start_http_server, Gauge, Info
import time

EXPORTS_TOTAL = Gauge('ganesha_exports_total', 'Total NFS exports')
GANESHA_UP = Gauge('ganesha_up', 'NFS-Ganesha service status')

def collect():
    try:
        bus = dbus.SystemBus()
        obj = bus.get_object('org.ganesha.nfsd', '/org/ganesha/nfsd/admin')
        iface = dbus.Interface(obj, 'org.ganesha.nfsd.admin')
        stats = iface.GetAllStats()
        EXPORTS_TOTAL.set(len(stats.get('exports', [])))
        GANESHA_UP.set(1)
    except Exception as e:
        print(f"Error: {e}", file=sys.stderr)
        EXPORTS_TOTAL.set(0)
        GANESHA_UP.set(0)

if __name__ == '__main__':
    start_http_server(9580)
    while True:
        collect()
        time.sleep(15)
bash
chmod +x /usr/local/bin/ganesha_exporter.py

4.3 创建 systemd 服务

写入 /etc/systemd/system/ganesha_exporter.service

ini
[Unit]
Description=NFS-Ganesha Prometheus Exporter
After=nfs-ganesha.service

[Service]
User=root
Type=simple
ExecStart=/usr/local/bin/ganesha_exporter.py
Restart=always

[Install]
WantedBy=multi-user.target

启动:

bash
systemctl daemon-reload
systemctl enable --now ganesha_exporter

验证:

bash
curl http://localhost:9580/metrics

5. 配置告警规则

创建目录并写入规则文件:

bash
mkdir -p /etc/prometheus/rules

/etc/prometheus/rules/nfs-ha-alerts.yml

yaml
groups:
  - name: node_alerts
    rules:
      - alert: NodeDown
        expr: up{job="node-exporter"} == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "节点 {{ $labels.instance }} 不可达"
          description: "Node Exporter 在 {{ $labels.instance }} 上已经 1 分钟无响应。"

      - alert: DiskSpaceLow
        expr: (node_filesystem_avail_bytes / node_filesystem_size_bytes) < 0.1
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "节点 {{ $labels.instance }} 磁盘空间不足"
          description: "挂载点 {{ $labels.mountpoint }} 可用空间低于 10%。"

      - alert: HighCPUUsage
        expr: 100 - (avg(irate(node_cpu_seconds_total{mode="idle"}[5m])) by (instance) * 100) > 85
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "节点 {{ $labels.instance }} CPU 使用率过高"
          description: "CPU 使用率超过 85%。"

  - name: gluster_alerts
    rules:
      - alert: GlusterVolumeDown
        expr: gluster_volume_status == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "GlusterFS 卷异常"
          description: "卷 {{ $labels.volume }} 状态异常。"

      - alert: GlusterBrickDown
        expr: gluster_brick_status == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "GlusterFS Brick 离线"
          description: "卷 {{ $labels.volume }} 的 brick {{ $labels.brick }} 离线。"

      - alert: GlusterVolumeUsageHigh
        expr: (gluster_volume_size_used_bytes / gluster_volume_size_total_bytes) > 0.85
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "GlusterFS 卷使用率过高"
          description: "卷 {{ $labels.volume }} 使用率超过 85%。"

      - alert: GlusterHealPending
        expr: gluster_heal_count > 0
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "GlusterFS 存在待修复条目"
          description: "卷 {{ $labels.volume }} 有 {{ $value }} 个待修复条目,超过 10 分钟。"

  - name: ganesha_alerts
    rules:
      - alert: GaneshaServiceDown
        expr: ganesha_up == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "NFS-Ganesha 服务异常"
          description: "节点 {{ $labels.instance }} 的 NFS-Ganesha 服务不可用。"

      - alert: GaneshaNoExports
        expr: ganesha_exports_total == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "NFS-Ganesha 无可用导出"
          description: "节点 {{ $labels.instance }} 没有活动的 NFS 导出。"

注:gluster_exporter 实际指标名可能与上述略有不同,部署后请访问 http://node1:9189/metrics 确认实际指标名,再调整规则。

重载 Prometheus:

bash
systemctl reload prometheus
# 或
curl -X POST http://localhost:9090/-/reload

6. 部署 Alertmanager

bash
cd /tmp
wget https://github.com/prometheus/alertmanager/releases/download/v0.27.0/alertmanager-0.27.0.linux-amd64.tar.gz
tar xvf alertmanager-0.27.0.linux-amd64.tar.gz
cp alertmanager-0.27.0.linux-amd64/alertmanager /usr/local/bin/
cp alertmanager-0.27.0.linux-amd64/amtool /usr/local/bin/
mkdir -p /etc/alertmanager /var/lib/alertmanager

6.1 邮件通知配置

创建 /etc/alertmanager/alertmanager.yml

yaml
global:
  smtp_smarthost: 'smtp.example.com:587'
  smtp_from: 'alert@example.com'
  smtp_auth_username: 'xxx'
  smtp_auth_password: 'xxx'

route:
  receiver: 'email-admin'
  group_by: ['alertname']
  group_wait: 10s
  group_interval: 10s
  repeat_interval: 1h

receivers:
  - name: 'email-admin'
    email_configs:
      - to: 'admin@example.com'
        send_resolved: true

6.2 钉钉通知配置(可选)

yaml
receivers:
  - name: 'dingtalk'
    webhook_configs:
      - url: 'http://localhost:8060/dingtalk/webhook1/send'
        send_resolved: true

需额外部署 prometheus-webhook-dingtalk

bash
docker run -d \
  -p 8060:8060 \
  -v /etc/prometheus-webhook-dingtalk/config.yml:/etc/prometheus-webhook-dingtalk/config.yml \
  --name dingtalk \
  timonwong/prometheus-webhook-dingtalk

6.3 启动 Alertmanager

创建 /etc/systemd/system/alertmanager.service

ini
[Unit]
Description=Alertmanager
After=network.target

[Service]
User=root
Type=simple
ExecStart=/usr/local/bin/alertmanager \
  --config.file=/etc/alertmanager/alertmanager.yml \
  --storage.path=/var/lib/alertmanager
Restart=always

[Install]
WantedBy=multi-user.target

启动:

bash
systemctl daemon-reload
systemctl enable --now alertmanager

7. 部署 Grafana

bash
# Ubuntu
apt install -y apt-transport-software-properties wget
wget -q -O /usr/share/keyrings/grafana.key https://apt.grafana.com/gpg.key
echo "deb [signed-by=/usr/share/keyrings/grafana.key] https://apt.grafana.com stable main" | tee /etc/apt/sources.list.d/grafana.list
apt update
apt install -y grafana

# RHEL/Rocky
cat > /etc/yum.repos.d/grafana.repo <<EOF
[grafana]
name=grafana
baseurl=https://rpm.grafana.com
repo_gpgcheck=1
enabled=1
gpgcheck=1
gpgkey=https://rpm.grafana.com/gpg.key
sslverify=1
sslcacert=/etc/pki/tls/certs/ca-bundle.crt
EOF
dnf install -y grafana

启动:

bash
systemctl enable --now grafana-server

默认访问:http://monitor-ip:3000,默认账号 admin/admin

7.1 添加 Prometheus 数据源

  1. 登录 Grafana
  2. Configuration → Data Sources → Add data source
  3. 选择 Prometheus
  4. URL 填 http://localhost:9090
  5. Save & Test

7.2 推荐仪表盘

用途导入 ID / 来源
Node Exporter 主机监控ID: 1860
GlusterFS 监控可基于本文指标自建或搜索社区模板
NFS-Ganesha 监控自建仪表盘

8. 关键监控指标速查

层级指标含义
节点node_cpu_seconds_totalCPU 使用
节点node_memory_MemAvailable_bytes可用内存
节点node_filesystem_avail_bytes磁盘可用空间
GlusterFSgluster_volume_status卷是否在线
GlusterFSgluster_brick_statusbrick 是否在线
GlusterFSgluster_volume_size_used_bytes卷已用容量
GlusterFSgluster_heal_count待修复条目数
Ganeshaganesha_up服务是否存活
Ganeshaganesha_exports_total导出数量

9. 验证告警

9.1 手动触发告警测试

停止 node1 的 Ganesha 服务:

bash
systemctl stop nfs-ganesha

预期:

  • Prometheus Alert 页面出现 GaneshaServiceDown
  • 1 分钟后 Alertmanager 发送告警通知

恢复后:

bash
systemctl start nfs-ganesha

9.2 查看告警状态

bash
# Prometheus 告警页面
http://monitor-ip:9090/alerts

# Alertmanager
http://monitor-ip:9093

10. 日常运维命令

bash
# 查看所有 targets 状态
curl -s http://localhost:9090/api/v1/targets | jq

# 手动测试告警规则
/usr/local/bin/promtool check rules /etc/prometheus/rules/*.yml

# 检查 Alertmanager 配置
/usr/local/bin/amtool check-config /etc/alertmanager/alertmanager.yml

# 查看 GlusterFS 指标
curl -s http://node1:9189/metrics | grep gluster

# 查看 Ganesha 指标
curl -s http://node1:9580/metrics

11. 注意事项

  1. 防火墙:确保监控节点能访问存储节点的 910091899580 端口。
  2. 时间同步:Prometheus 依赖时间戳,所有节点必须保持时间一致。
  3. ** retention**:生产环境建议配置 Prometheus 数据保留策略,如 --storage.tsdb.retention.time=30d
  4. 指标名差异:不同版本的 exporter 指标名可能不同,请以实际 /metrics 输出为准调整告警规则。
  5. 安全:生产环境建议为 Prometheus/Grafana 配置 HTTPS 和认证。

文档版本:v1.0
适用系统:Ubuntu 22.04 / RHEL 9 / Rocky Linux 9