分类:监控(monitoring) 标签: 监控、netdata、Prometheus、Grafana、Alertmanager、告警、Kubernetes 摘要: 一套完整监控体系怎么从零搭起来?本文从”为什么要监控”讲起,实操 netdata 快速上手、Prometheus + Grafana 全链路,再到 Prometheus 告警规则 + Alertmanager 邮箱通知的完整闭环。


一、先想清楚:监控到底监控什么?

我觉得,监控就回答三个问题:

  1. 机器还活着吗?(CPU / 内存 / 磁盘 / 网络)
  2. 服务还正常吗?(进程在不在、接口通不通、有没有报错)
  3. 出问题能提前知道吗?(指标异常 → 告警 → 通知处理)

围绕这三点,监控有两类做法:

  • 轻量级:netdata —— 开箱即用,看个实时状态。
  • 体系化:Prometheus + Grafana + Alertmanager —— 能存历史、能告警、能发通知,适合生产。

我做的时候先装 netdata 快速看全貌,再用 Prometheus 全家桶搭一套完整的含告警的体系,两套都实践了,对比看着才有体会。


二、第一套:netdata(一分钟上手的实时监控)

netdata 是我在阿里云服务器上通过 Docker 部署的,装完立刻能看机器实时状态。

部署

docker run -d --name netdata --network host \
  -v /proc:/host/proc:ro \
  -v /sys:/host/sys:ro \
  -v /var/run/docker.sock:/var/run/docker.sock:ro \
  netdata/netdata:latest

为什么用 Docker 部署 netdata?(而不是直接 apt install)

一句话:Docker 就是一个”集装箱”,好处是干净、好搬、好管理。

  • 直接 apt install netdata = 把东西直接堆在客厅地上:装了一堆依赖、配置散落在系统各处,哪天不要了卸载也卸不干净,还容易和系统里其他程序冲突。
  • 用 Docker 跑 = 把 netdata 装进一个独立的集装箱里:宿主机客厅干干净净,东西全在箱子里,不要了把箱子一扔就清空。

具体好处:

  1. 不污染宿主机:依赖和运行环境全在容器里,不影响系统其他程序。
  2. 开箱即用、零配置环境:镜像里该有的都配好了,docker run 一条命令就跑起来。
  3. 好管理、好统一:docker ps 一眼看到所有服务(netdata、jenkins、mysql… 一起管),统一的启停/升级/删除方式。
  4. 可移植:这台服务器上配好的,拿到别的机器一条命令就能复制。
  5. 升级/回滚方便:换镜像 tag 升级,出问题回退旧镜像。

但有个特例要解决:netdata 装在 Docker”集装箱”里,它还怎么监控宿主机?——这就是下面要讲的 --network host 和挂载卷的作用:虽然 netdata 住在箱子里,但我给它开了门,让它能探头看外面的宿主机。

这里有一个很关键的知识点:我用了 --network host(host 网络模式)。先看两种网络模式的差别:

  • bridge + -p:容器有自己的内网,要用 -p 19999:19999 把容器端口映射到宿主机。
  • host:容器直接复用宿主机网络,占用宿主机的 19999 端口,不需要 -p 映射。

① 为什么一定要给 netdata 用 host 模式?

netdata 要监控的不是容器自己,而是宿主机整台机器——CPU、内存、磁盘,尤其是网络流量。

  • 用 host:容器和宿主机共享同一个网络,netdata 能直接看到宿主机真实的网卡(eth0、lo 等)和它的流量、端口、连接,看到的数据才是宿主机“真实”的。
  • 用 bridge:容器用的是 Docker 虚拟出来的私有网卡,netdata 只能看到那个虚拟网卡的流量,看不到你服务器真实网卡的进出流量,监控就不准了。

所以 netdata 官方也是推荐 host 模式,原因就是它要完整监控宿主机。

② host 模式的代价(要用它就得知道)

  • 端口直接暴露在宿主机:19999 直接占了宿主机的端口,如果宿主机某个程序已占用 19999 就会冲突。
  • 隔离性差:容器和宿主机网络不隔离,不像 bridge 那样有独立内网。

③ 什么时候用哪个?(重要判断)

  • 要完整监控宿主机(如 netdata、node-exporter)→ 用 host。
  • 要隔离 + 端口映射、不想直接占宿主机端口(如你的 WordPress、MySQL)→ 用 bridge + -p。

外网访问要过两层防火墙(容易踩的坑)

一开始访问 http://IP:19999 超时,排查后是两层防火墙都要放行:

ufw allow 19999/tcp   # 第1层:系统 ufw

第2层:还要去云平台控制台(阿里云 → 轻量服务器 → 防火墙)放行 19999。

两层都通,外网才访问得到。这是云服务器新手最容易漏的一步。

netdata 上线后实时采集 4600+ 项指标,网页打开就能看 CPU、内存、网络、各容器实时曲线,零配置、纯看板。


三、第二套:Prometheus + Grafana(完整的监控链路)

netdata 只能看实时,存不了很久的历史、也做不了灵活告警。生产常用这条业界标准链路:

node-exporter(采集) → Prometheus(存储/抓取)→ Grafana(可视化)
  • node-exporter:给机器”量体温”,暴露指标接口(默认 9100)。
  • Prometheus:定期去抓指标存进数据库(默认 9090)。
  • Grafana:把数据画成图形(默认 3000)。

我在本地 ans 虚拟机(Ubuntu + k3s)上用 kubectl 把这条链部署进集群。

① node-exporter.yaml —— 采集本机指标

apiVersion: apps/v1
kind: Deployment
metadata:
  name: node-exporter
spec:
  replicas: 1
  selector: { matchLabels: { app: node-exporter } }
  template:
    metadata: { labels: { app: node-exporter } }
    spec:
      hostNetwork: true
      containers:
      - name: node-exporter
        image: prom/node-exporter
        ports: [ { containerPort: 9100 } ]

② prometheus.yaml —— 抓取并存储(配置主体)

这是纯监控的 Prometheus 配置,只负责抓取机器指标。

apiVersion: v1
kind: ConfigMap
metadata:
  name: prometheus-config
data:
  prometheus.yml: |
    global:
      scrape_interval: 15s
    scrape_configs:
      - job_name: 'node'
        static_configs:
          - targets: ['192.168.47.10:9100']
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: prometheus
spec:
  replicas: 1
  selector: { matchLabels: { app: prometheus } }
  template:
    metadata: { labels: { app: prometheus } }
    spec:
      containers:
      - name: prometheus
        image: prom/prometheus
        args: ["--config.file=/etc/prometheus/prometheus.yml"]
        ports: [ { containerPort: 9090 } ]
        volumeMounts:
        - name: config
          mountPath: /etc/prometheus/prometheus.yml
          subPath: prometheus.yml
      volumes:
      - name: config
        configMap: { name: prometheus-config }
---
apiVersion: v1
kind: Service
metadata: { name: prometheus }
spec:
  type: NodePort
  selector: { app: prometheus }
  ports: [ { port: 9090, targetPort: 9090, nodePort: 30090 } ]

③ grafana.yaml —— 可视化大盘

apiVersion: apps/v1
kind: Deployment
metadata: { name: grafana }
spec:
  replicas: 1
  selector: { matchLabels: { app: grafana } }
  template:
    metadata: { labels: { app: grafana } }
    spec:
      containers:
      - name: grafana
        image: grafana/grafana
        ports: [ { containerPort: 3000 } ]
---
apiVersion: v1
kind: Service
metadata: { name: grafana }
spec:
  type: NodePort
  selector: { app: grafana }
  ports: [ { port: 3000, targetPort: 3000, nodePort: 30000 } ]

部署 & 验证

kubectl apply -f node-exporter.yaml
kubectl apply -f prometheus.yaml
kubectl apply -f grafana.yaml
kubectl get pods
  • Prometheus /targets:node 目标 UP ✅
  • Grafana 加数据源 http://prometheus:9090 连接成功 ✅
  • CPU 曲线指标:100 - avg(rate(node_cpu_seconds_total{mode="idle"}[1m]))*100 ✅

四、告警与通知(完整闭环,亲测)

这是让监控”会主动找上门”的关键一环,也是我完整亲手验证过的一段。链路:

Prometheus 规则(CPU>90%)  →  Alertmanager  →  邮箱通知到手机

4.1 加告警规则

alerts.yml 的内容(CPU 使用率 持续超过 90%,for: 1m 维持 1 分钟 才触发 HighCPUUsage,避免短暂波动误报):

  alerts.yml: |
    groups:
      - name: node_alerts
        rules:
          - alert: HighCPUUsage
            expr: (100 - avg(rate(node_cpu_seconds_total{mode="idle"}[1m]))*100) > 90
            for: 1m
            labels:
              severity: warning
            annotations:
              summary: "CPU usage high: {{ $value }}%"

修改prometheus.yaml文件

apiVersion: v1
kind: ConfigMap
metadata:
  name: prometheus-config
data:
  prometheus.yml: |
    global:
      scrape_interval: 15s
    scrape_configs:
      - job_name: 'node'
        static_configs:
          - targets: ['192.168.47.10:9100']
  alerts.yml: |    #加在这里
    groups:
      - name: node_alerts
        rules:
          - alert: HighCPUUsage
            expr: (100 - avg(rate(node_cpu_seconds_total{mode="idle"}[1m]))*100) > 90
            for: 1m
            labels:
              severity: warning
            annotations:
              summary: "CPU usage high: {{ $value }}%"
---

要让这条规则生效,还要做 3 件事:

① 在 prometheus.yml 里加 rule_files,告诉它去哪加载规则:

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

修改prometheus.yaml文件

data:
  prometheus.yml: |
    global:
      scrape_interval: 15s
    rule_files:          # 加在这里,告警规则
      - /etc/prometheus/rules/*.yml    
    scrape_configs:
      - job_name: 'node'
        static_configs:
          - targets: ['192.168.47.10:9100']

② 在 Deployment 里用 subPath 把 alerts.yml 挂到那个规则目录:

        volumeMounts:
        - name: config
          mountPath: /etc/prometheus/prometheus.yml
          subPath: prometheus.yml
        - name: config
          mountPath: /etc/prometheus/rules/alerts.yml
          subPath: alerts.yml

③ 改 ConfigMap 不会自动重启,要重启加载:

kubectl apply -f prometheus.yaml
kubectl rollout restart deployment prometheus

最后浏览器打开 http://IP:30090/alerts,能看到 HighCPUUsage(状态 Inactive)就说明规则生效了。

4.2 部署 Alertmanager(负责把告警发出去)

新建 alertmanager.yaml,里面配了 QQ 邮箱 SMTP:

apiVersion: v1
kind: ConfigMap
metadata:
  name: alertmanager-config
data:
  alertmanager.yml: |
    global:
      smtp_smarthost: 'smtp.qq.com:465'
      smtp_from: 'xxx@qq.com'
      smtp_auth_username: 'xxx@qq.com'
      smtp_auth_password: '16位授权码'   # 不是登录密码
      smtp_require_tls: false
    route:
      group_by: ['alertname']
      group_wait: 10s
      repeat_interval: 1h
      receiver: 'email'
    receivers:
    - name: 'email'
      email_configs:
      - to: 'xxx@qq.com'
---
apiVersion: apps/v1
kind: Deployment
metadata: { name: alertmanager }
spec:
  replicas: 1
  selector: { matchLabels: { app: alertmanager } }
  template:
    metadata: { labels: { app: alertmanager } }
    spec:
      containers:
      - name: alertmanager
        image: prom/alertmanager
        args: ["--config.file=/etc/alertmanager/alertmanager.yml"]
        ports: [ { containerPort: 9093 } ]
        volumeMounts: [ { name: config, mountPath: /etc/alertmanager } ]
      volumes: [ { name: config, configMap: { name: alertmanager-config } } ]
---
apiVersion: v1
kind: Service
metadata: { name: alertmanager }
spec:
  type: NodePort
  selector: { app: alertmanager }
  ports: [ { port: 9093, targetPort: 9093, nodePort: 30093 } ]

⚠️ QQ 邮箱发信的关键:邮箱 → 登录 → 设置 → 账号 → 开启 “IMAP/SMTP服务”,会生成16 位授权码。Alertmanager 里填的是授权码,不是登录密码。 ⚠️ 常见坑:QQ 邮箱如果开了”免打扰”,邮件不会弹提醒,容易以为没发出来——其实看收件箱就有。

4.3 让 Prometheus 把告警推给 Alertmanager

这一步要在 prometheus.yml 里加”告警转发”配置(alerting 块):

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

修改prometheus.yaml文件

data:
  prometheus.yml: |
    global:
      scrape_interval: 15s
    rule_files:          # 告警规则
      - /etc/prometheus/rules/*.yml
    alerting:                                 # 加在这,告警发给 alertmanager
      alertmanagers:
        - static_configs:
            - targets: ['alertmanager:9093']
    scrape_configs:
      - job_name: 'node'
        static_configs:
          - targets: ['192.168.47.10:9100']
  • 验证:加完 kubectl apply -f prometheus.yaml 并 kubectl rollout restart deployment prometheus,然后访问 http://IP:30090/status → Alertmanagers 一栏显示 Up 即成功。

4.4 触发验证(亲眼看到闭环)

for i in 1 2 3 4 5; do yes > /dev/null & done   # 4核机器打满CPU

等 1 分多钟,会看到:

  1. http://IP:30090/alerts → HighCPUUsage 先 Pending,后 Firing(红)
  2. http://IP:30093(Alertmanager)→ 能查到这条告警,接收者 email
  3. QQ 邮箱收到告警邮件 📧

测完关闭负载:

pkill yes      # 告警随之回到 Inactive

我实际跑通了整个过程:CPU 打满 → Prometheus 判定 Firing → Alertmanager 收到并发送 → QQ 邮箱收到邮件。这就是完整的”采集 → 存储 → 展示 → 告警 → 通知”闭环。

4.5 更多通知方式(配置参考)

Alertmanager 不只是邮件,还能发到群机器人。以下是参考配置(我尚未亲手验证,实际接入时需按平台机器人规则微调):

钉钉群机器人

receivers:
- name: dingtalk
  webhook_configs:
  - url: 'https://oapi.dingtalk.com/robot/send?access_token=你的token'
    send_resolved: false

飞书群机器人

receivers:
- name: feishu
  webhook_configs:
  - url: 'https://open.feishu.cn/open-apis/bot/v2/hook/你的token'
    send_resolved: false

五、常见坑(快速查)

坑现象解决
外网访问不到浏览器超时ufw 和云平台安全组两层都要放行
改配置不生效加了规则/alerting 但没反应改 ConfigMap 后要 rollout restart deployment
采集目标 Down/targets 里 node 是 DOWN查 IP:port 对不对、目标服务起没起、IP 变没变(Pod 重建 IP 会变,优先用 Service 名)
只画图不告警 / 告警轰炸从没收到提醒,或整天响阈值和 for 时长要调好,别让瞬时波动误报
收不到邮件告警已 Firing 却收不到① 查 Alertmanager 日志 ② 检查 SMTP 授权码 ③ 看 QQ”免打扰”是否吞了提醒
时间不同步监控数据对不上、触发时机怪宿主机同步 NTP(timedatectl)
Grafana 拉镜像失败ContainerCreating/ImagePullBackOffk3s 配国内镜像加速或 ctr 手动 pull

分类: 监控