# Prometheus + Grafana + Node Exporter 监控部署方案

> 部署日期：2026-04-15
> 架构：Ubuntu2 (Prometheus + Grafana) + MacMini M4 (Node Exporter 原生安装)

---

## 整体架构

```
┌─────────────────────────────────────────────────────────────────┐
│                        本地网络 (LAN)                            │
│                                                                 │
│   ┌──────────────┐                      ┌──────────────────┐   │
│   │   MacMini    │                      │     Ubuntu2      │   │
│   │   M4 Chip   │◄───── 抓取 ───────► │   (Prometheus    │   │
│   │              │   192.168.3.189      │    + Grafana)    │   │
│   │  Node Exp.   │        :9100        │   192.168.3.45   │   │
│   │  (原生)      │                      │                  │   │
│   │              │                      │  :9090 Prometheus│   │
│   │              │                      │  :3000 Grafana   │   │
│   └──────────────┘                      └──────────────────┘   │
│                                                                 │
│                          └──► 浏览器访问 Dashboard ───►          │
└─────────────────────────────────────────────────────────────────┘
```

---

## 组件说明

| 组件 | 服务器 | IP | 端口 | 版本 |
|------|--------|-----|------|------|
| Prometheus | Ubuntu2 | 192.168.3.45 | 9090 | v2.51.0 |
| Grafana | Ubuntu2 | 192.168.3.45 | 3000 | 10.4.0 |
| node-exporter | MacMini | 192.168.3.189 | 9100 | 1.11.1 |

---

## 第一部分：Ubuntu2 部署 Prometheus + Grafana

### 1.1 创建目录结构

```bash
# 在 Ubuntu2 上执行
mkdir -p ~/docker/prometheus
mkdir -p ~/docker/grafana/provisioning/datasources
mkdir -p ~/docker/grafana/provisioning/dashboards
mkdir -p ~/docker/grafana/data
```

### 1.2 Prometheus 配置

**文件：~/docker/prometheus/docker-compose.yml**

```yaml
version: '3.8'

services:
  prometheus:
    image: prom/prometheus:v2.51.0
    container_name: prometheus
    restart: unless-stopped
    network_mode: host
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus-data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--web.console.libraries=/etc/prometheus/console_libraries'
      - '--web.console.templates=/etc/prometheus/consoles'
      - '--web.enable-lifecycle'
    extra_hosts:
      - "host.docker.internal:host-gateway"

volumes:
  prometheus-data:
```

**文件：~/docker/prometheus/prometheus.yml**

```yaml
global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  # Prometheus 自身监控
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  # MacMini node-exporter
  - job_name: 'macmini'
    static_configs:
      - targets: ['192.168.3.189:9100']
    scrape_interval: 30s
```

### 1.3 Grafana 配置

**文件：~/docker/grafana/docker-compose.yml**

```yaml
version: '3.8'

services:
  grafana:
    image: grafana/grafana:10.4.0
    container_name: grafana
    restart: unless-stopped
    ports:
      - "3000:3000"
    volumes:
      - ./provisioning/datasources:/etc/grafana/provisioning/datasources
      - ./provisioning/dashboards:/etc/grafana/provisioning/dashboards
      - ./data:/var/lib/grafana
    environment:
      - GF_SECURITY_ADMIN_USER=admin
      - GF_SECURITY_ADMIN_PASSWORD=admin123
      - GF_USERS_ALLOW_SIGN_UP=false
    extra_hosts:
      - "host.docker.internal:host-gateway"
```

**文件：~/docker/grafana/provisioning/datasources/datasource.yml**

```yaml
apiVersion: 1

datasources:
  - name: Prometheus
    type: prometheus
    access: proxy
    url: http://host.docker.internal:9090
    uid: prometheus
    isDefault: true
    editable: false
```

**文件：~/docker/grafana/provisioning/dashboards/dashboard.yml**

```yaml
apiVersion: 1

providers:
  - name: 'default'
    orgId: 1
    folder: ''
    type: file
    disableDeletion: false
    allowUiUpdates: true
    updateIntervalSeconds: 10
    options:
      path: /etc/grafana/provisioning/dashboards
```

### 1.4 启动服务

```bash
cd ~/docker/prometheus && docker compose up -d
cd ~/docker/grafana && docker compose up -d
```

### 1.5 验证状态

```bash
# 检查容器状态
docker ps

# 检查 Prometheus targets
curl http://localhost:9090/api/v1/targets

# 验证指标存在
curl -s http://localhost:9090/api/v1/query?query=up
```

---

## 第二部分：MacMini 部署 Node Exporter（原生安装）

### 2.1 重要说明

> **重要**：在 MacMini 上必须使用原生安装，不能用 Docker！
>
> **原因**：Docker Desktop for Mac 运行在 Linux VM 中，Docker 版的 node-exporter 只能看到 VM 的资源（约 8GB），无法看到真实的 Mac 硬件（16GB）。
>
> ```
> Mac Mini M4 (16GB)  ← 原生 node-exporter 才能看到真实硬件
>        ↓
> Linux VM (Docker)  ← Docker node-exporter 只能看到 VM 资源 (~8GB)
>        ↓
> Docker 容器        ← 只能看到 VM 的资源
> ```

### 2.2 安装 Node Exporter

```bash
# 使用 Homebrew 安装
/opt/homebrew/bin/brew install node_exporter

# 验证安装
node_exporter --version
```

### 2.3 创建启动脚本

**文件：~/Library/LaunchAgents/homebrew.node_exporter.plist**

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>homebrew.node_exporter</string>
    <key>ProgramArguments</key>
    <array>
        <string>/opt/homebrew/opt/node_exporter/bin/node_exporter</string>
        <string>--web.listen-address=:9100</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <true/>
</dict>
</plist>
```

### 2.4 启动服务

```bash
# 停止并移除旧的 Docker 版本（如果存在）
/Applications/Docker.app/Contents/Resources/bin/docker stop node-exporter
/Applications/Docker.app/Contents/Resources/bin/docker rm node-exporter

# 加载 launchd 服务
launchctl load ~/Library/LaunchAgents/homebrew.node_exporter.plist

# 启动服务
launchctl start homebrew.node_exporter
```

### 2.5 验证安装

```bash
# 检查服务状态
launchctl list | grep node

# 检查进程
ps aux | grep node_exporter | grep -v grep

# 检查端口
lsof -i :9100

# 验证指标（本地）
curl http://localhost:9100/metrics | head

# 验证总内存（应该显示 16GB）
curl -s http://localhost:9100/metrics | grep total_bytes
```

### 2.6 管理命令

```bash
# 查看状态
launchctl list | grep node

# 停止服务
launchctl unload ~/Library/LaunchAgents/homebrew.node_exporter.plist

# 重启服务
launchctl unload ~/Library/LaunchAgents/homebrew.node_exporter.plist
launchctl load ~/Library/LaunchAgents/homebrew.node_exporter.plist

# 查看日志
cat /var/log/system.log | grep node_exporter
```

---

## 第三部分：访问和使用

### 3.1 访问地址

| 服务 | 地址 | 用户名 | 密码 |
|------|------|--------|------|
| Prometheus | http://192.168.3.45:9090 | - | - |
| Grafana | http://192.168.3.45:3000 | admin | admin123 |

### 3.2 导入 Dashboard

**官方 Dashboard（推荐）**

1. 打开 Grafana: http://192.168.3.45:3000
2. 点击左侧菜单 Dashboards → + New → Import
3. 输入 Dashboard ID: 1860（Node Exporter Full）
4. 选择 Prometheus 数据源
5. 点击 Import

**变量设置（官方 Dashboard）**

官方 Dashboard 使用变量 $node 和 $job，需要在 Grafana 中设置：

1. 打开 Dashboard → 点击右上角 Dashboard settings（齿轮图标）
2. 选择 Variables
3. 添加/编辑变量：
   - node: label_values(node_memory_total_bytes, instance) 或手动输入 192.168.3.189:9100
   - job: label_values(node_memory_total_bytes, job) 或手动输入 macmini

---

## 第四部分：运维管理

### 4.1 重启服务

```bash
# Ubuntu2 - Prometheus
cd ~/docker/prometheus && docker compose restart

# Ubuntu2 - Grafana
cd ~/docker/grafana && docker compose restart

# MacMini - Node Exporter
launchctl unload ~/Library/LaunchAgents/homebrew.node_exporter.plist
launchctl load ~/Library/LaunchAgents/homebrew.node_exporter.plist
```

### 4.2 更新 Prometheus 配置后重载

```bash
# 热重载（无需重启 Prometheus）
curl -X POST http://localhost:9090/-/reload
```

### 4.3 常见问题排查

**问题：Grafana 显示 "Datasource not found"**
- 原因：Dashboard 中的 datasource UID 与实际不匹配
- 解决：检查 datasource.yml 中的 uid 是否与 Dashboard 中的匹配

**问题：Prometheus 无法抓取 MacMini 指标**
- 检查网络连通性：curl http://192.168.3.189:9100/metrics
- 检查 Prometheus targets：curl http://localhost:9090/api/v1/targets

**问题：Mac mini 内存显示 7.6GB 而不是 16GB**
- 原因：使用了 Docker 版 node-exporter
- 解决：改用原生安装（见第二部分）

---

## 第五部分：技术备注

### 5.1 macOS 与 Linux 指标差异

Node Exporter 在 macOS 上的指标名称与 Linux 略有不同：

| 描述 | Linux | macOS |
|------|-------|-------|
| 总内存 | node_memory_MemTotal_bytes | node_memory_total_bytes |
| 可用内存 | node_memory_MemAvailable_bytes | node_memory_free_bytes |
| CPU | node_cpu_seconds_total | node_cpu_seconds_total (相同) |
| 负载 | node_load1 | node_load1 (相同) |
| 磁盘 | node_disk_* | node_disk_* (相同) |
| 网络 | node_network_* | node_network_* (相同) |

### 5.2 Docker Desktop for Mac 网络说明

network_mode: host 在 Docker Desktop for Mac 上的行为：

| 环境 | host 模式绑定到 |
|------|----------------|
| Linux 宿主机 | 宿主机的网络接口 (正常) |
| Docker Desktop (Mac/Win) | Linux VM 的网络接口 (异常) |

因此在 MacMini 上使用 Docker 版会绑定到 VM 网络，导致外部无法访问。

### 5.3 指标数量对比

| 安装方式 | node_* 指标数 | 内存显示 |
|----------|--------------|----------|
| Docker 版 | ~1348 | ~7.6GB (VM) |
| 原生版 | ~1966 | 16GB (真实) |

### 5.4 监控数据流向

```
MacMini 原生 Node Exporter (:9100)
        ↓ HTTP (LAN)
Ubuntu2 Prometheus (:9090)
        ↓ 查询
Grafana (:3000) ← 浏览器访问
```

---

## 文件清单

### Ubuntu2 文件结构
```
~/docker/
├── prometheus/
│   ├── docker-compose.yml
│   └── prometheus.yml
└── grafana/
    ├── docker-compose.yml
    ├── data/
    └── provisioning/
        ├── datasources/
        │   └── datasource.yml
        └── dashboards/
            ├── dashboard.yml
            └── node-exporter.json (可选)
```

### MacMini 文件结构
```
~/Library/LaunchAgents/
└── homebrew.node_exporter.plist
```

---

## 相关链接

- Prometheus: https://prometheus.io/
- Grafana: https://grafana.com/
- Node Exporter: https://prometheus.io/docs/guides/node-exporter/
- 官方 Dashboard: https://grafana.com/grafana/dashboards/1860-node-exporter-full/

---

*最后更新：2026-04-15 by 云瀚 🌊*
