1. 为什么你需要一个像样的监控系统如果你管过服务器哪怕就一两台肯定有过这种经历半夜被电话吵醒说网站打不开了你迷迷糊糊爬起来连上服务器一通top、df -h、netstat猛如虎结果发现是磁盘满了或者内存爆了。这种“救火式”的运维不仅人累效率还低问题往往要等用户反馈了才知道。这就是监控系统的价值所在。它就像你系统的“仪表盘”和“预警雷达”7x24小时不间断地帮你盯着服务器的 CPU、内存、磁盘、网络甚至是你自己写的应用程序。一旦哪个指标不正常比如 CPU 使用率连续 5 分钟超过 80%它就能立刻发出警报让你在问题影响用户之前就把它解决掉。Prometheus普罗米修斯就是当下最火、最适合云原生和容器环境的开源监控解决方案没有之一。我最早接触 Prometheus 是在 2017 年那时候容器化还没现在这么普及但它的设计理念——特别是基于拉取Pull模型和多维度数据模型——就已经让我眼前一亮。这么多年用下来从几台服务器的小项目到上千个容器的微服务集群Prometheus 都稳稳地扛住了。它不是什么“银弹”但绝对是运维工具箱里最趁手的那把“瑞士军刀”。今天我就带你从零开始手把手部署一套生产可用的 Prometheus 监控系统并配上最常用的主机监控组件 node_exporter。我会把每一步的操作、每一个关键配置参数的含义以及我踩过的那些坑都掰开揉碎了讲给你听。2. 动手之前先搞懂 Prometheus 的“三板斧”在开始敲命令之前花几分钟理解 Prometheus 的核心工作原理能让你在后续的配置和排错时事半功倍。你可以把它想象成一个非常专注的“数据收集员”和“分析员”。第一板斧拉取模型Pull Model。这和很多传统监控系统比如 Zabbix 的 Agent 主动上报不一样。Prometheus 是主动去“抓取”数据的。它周期性地比如每15秒向配置好的目标Targets发起一个 HTTP 请求目标端点通常是/metrics返回一堆文本格式的监控数据。这样做的好处是什么控制权在服务端Prometheus Server。我想什么时候抓、抓多频繁都由我决定。目标服务被监控的机器或应用只需要提供一个简单的 HTTP 接口不用关心数据怎么发送、发给谁架构上更简单也更容易实现。第二板斧多维数据模型Multi-dimensional Data Model。这是 Prometheus 的灵魂。每一条监控数据时间序列不仅仅是一个数值还附带了一组描述性的标签Label。举个例子同样是http_requests_total这个指标我可以给它加上methodGET、endpoint/api/users、status200、jobweb-server这些标签。这样我不仅能知道总请求数还能轻松地查询“web-server这个任务下/api/users这个端点的GET请求返回200状态码的有多少”。这种灵活性是传统监控系统里把指标名写成http_requests_get_api_users_200_total这种冗长字符串无法比拟的。第三板斧强大的 PromQLPrometheus Query Language。光有数据不行还得能查、能算。PromQL 就是用来查询和聚合这些带标签的时间序列数据的语言。它有点像 SQL但专为监控场景设计。你可以用它计算 CPU 使用率的 5 分钟平均负载可以统计最近一小时内 5xx 错误的比例也可以做复杂的多指标关联分析。后面我们配置告警规则和用 Grafana 画图全都离不开 PromQL。理解了这三点再看 Prometheus 的架构图就清晰了核心是 Prometheus Server它负责抓取和存储数据各种 Exporter如 node_exporter作为“翻译官”把操作系统、数据库、中间件的状态转换成 Prometheus 能理解的格式Alertmanager 负责处理告警去重、分组然后通过邮件、钉钉等发送最后用 Grafana 这种可视化工具把数据漂亮地展示出来。我们今天先搞定 Server 和 node_exporter 的部署。3. 实战部署一步步搭建你的监控堡垒好了理论说再多不如动手。我们假设一个最简单的场景有两台 Linux 服务器。一台IP: 192.168.8.121作为监控服务器安装 Prometheus Server另一台IP: 192.168.8.120作为被监控的主机安装 node_exporter。这个模式可以轻松扩展到成百上千台机器。3.1 环境准备与软件下载首先确保你的服务器有网络并且能用wget或curl命令。Prometheus 是 Go 语言写的打包成了单个二进制文件所以安装出奇地简单不需要配一堆运行环境。第一步下载软件包。我习惯在/usr/local/src目录下操作这里一般是放源码或第三方软件的地方。# 在监控服务器192.168.8.121上操作下载 Prometheus Server cd /usr/local/src wget https://github.com/prometheus/prometheus/releases/download/v2.47.0/prometheus-2.47.0.linux-amd64.tar.gz # 在被监控主机192.168.8.120上操作下载 node_exporter cd /usr/local/src wget https://github.com/prometheus/node_exporter/releases/download/v1.6.1/node_exporter-1.6.1.linux-amd64.tar.gz这里有个小技巧去 GitHub Releases 页面下载时如果不确定最新版本号可以先不写具体版本打开页面看看最新的标签是什么。我写的是当前比较稳定的版本你可以直接使用。下载速度慢的话可以考虑替换成国内的镜像源。第二步解压并整理目录。解压后我习惯把目录名简化一下方便后续管理和写配置文件。# 在监控服务器上操作 tar xf prometheus-2.47.0.linux-amd64.tar.gz -C /usr/local/ cd /usr/local mv prometheus-2.47.0.linux-amd64 prometheus # 在被监控主机上操作 tar xf node_exporter-1.6.1.linux-amd64.tar.gz -C /usr/local/ cd /usr/local mv node_exporter-1.6.1.linux-amd64 node_exporter现在/usr/local/prometheus和/usr/local/node_exporter目录里就是我们的核心程序了。你可以用ls -lh看看主要就是一个可执行文件加一堆配置文件、Web 前端资源。3.2 配置与启动 Prometheus Server进入 Prometheus 目录你会看到一个核心配置文件prometheus.yml。我们先不急着改用默认配置启动一下看看是否正常。cd /usr/local/prometheus ./prometheus --config.fileprometheus.yml如果看到控制台输出一堆日志最后有Server is ready to receive web requests.并且没有报错退出那就说明 Prometheus 本身运行起来了。这时按CtrlC停止它。我们接下来要配置成系统服务让它能在后台稳定运行。现在打开prometheus.yml文件我们来仔细看看里面的门道。这个文件是 YAML 格式的缩进非常关键。# 我的配置文件示例/usr/local/prometheus/prometheus.yml global: scrape_interval: 15s # 全局抓取间隔默认15秒一次。生产环境如果机器多可以适当调大到30s或60s减轻压力。 evaluation_interval: 15s # 告警规则评估间隔也是15秒检查一次规则。 # scrape_timeout: 10s # 每次抓取的超时时间一般不用改。 # 告警管理器配置我们还没装 Alertmanager先注释掉。 #alerting: # alertmanagers: # - static_configs: # - targets: # # - alertmanager:9093 # 告警规则文件路径可以在这里指定包含具体告警条件的 .rules 文件。 #rule_files: # - first_rules.yml # - second_rules.yml # 这是最重要的部分抓取配置。定义你要监控谁。 scrape_configs: # 第一个任务监控 Prometheus 自己。它自己也会暴露 metrics 接口。 - job_name: prometheus static_configs: - targets: [localhost:9090] # 它自己的web端口 labels: group: prometheus-servers # 可以给这组目标加个自定义标签方便管理 # 第二个任务监控所有 Linux 主机。我们通过 node_exporter 来抓。 - job_name: linux-nodes # 如果有很多台机器一个个写 targets 太麻烦后面会讲服务发现。 static_configs: - targets: [192.168.8.120:9100] # node_exporter 默认端口是9100 labels: instance: web-server-01 # 给这台机器起个别名告警时更容易识别 group: production-servers配置文件改好后强烈建议用 Prometheus 自带的工具校验一下语法这是个好习惯能避免因为缩进或格式错误导致服务起不来。./promtool check config prometheus.yml看到SUCCESS就说明配置没问题。接下来我们创建 systemd 服务文件让 Prometheus 以守护进程方式运行。cat /etc/systemd/system/prometheus.service EOF [Unit] DescriptionPrometheus Server Documentationhttps://prometheus.io/docs/introduction/overview/ Afternetwork.target [Service] Typesimple Userroot # 生产环境建议创建一个专门的用户如 prometheus Grouproot Restarton-failure ExecStart/usr/local/prometheus/prometheus \ --config.file/usr/local/prometheus/prometheus.yml \ --storage.tsdb.path/usr/local/prometheus/data \ --web.listen-address0.0.0.0:9090 \ --web.enable-lifecycle # 启用热重载配置的API端点后面会讲 ExecReload/bin/kill -HUP $MAINPID [Install] WantedBymulti-user.target EOF这里有几个关键启动参数我解释一下--config.file指定配置文件路径必须的。--storage.tsdb.path指定时间序列数据库的存储路径。数据量会随时间增长要确保这个目录有足够空间。--web.listen-address指定 Web 界面和 API 的监听地址。0.0.0.0:9090表示监听所有网卡的 9090 端口。--web.enable-lifecycle这个非常实用。它开启了一个 HTTP API (POST /-/reload)允许你在不重启 Prometheus 进程的情况下只重启加载配置文件。对于动态添加监控目标非常友好。现在启动并设置开机自启systemctl daemon-reload systemctl start prometheus systemctl enable prometheus systemctl status prometheus # 查看状态确保是 active (running)用ss -antlp | grep 9090或curl -I localhost:9090检查一下端口是否在监听。然后打开浏览器访问http://你的服务器IP:9090。你应该能看到 Prometheus 自带的 Web UI 了。在顶部导航栏点开 “Status” - “Targets”应该能看到一个名为prometheus的 job状态是UP。恭喜Server 端部署成功3.3 部署 node_exporter 监控主机node_exporter 是 Prometheus 生态里用于收集主机层面指标CPU、内存、磁盘、网络等的官方 Exporter。它同样是一个独立的二进制文件。在被监控主机192.168.8.120上我们已经解压了软件包。直接进入目录运行试试cd /usr/local/node_exporter ./node_exporter你会看到它开始输出日志并监听在9100端口。同样按CtrlC停止。node_exporter 的配置通常通过命令行参数进行它也有一个配置文件但监控主机的基础指标通常默认就够了。我们创建一个 systemd 服务来管理它cat /etc/systemd/system/node_exporter.service EOF [Unit] DescriptionNode Exporter Afternetwork.target [Service] Typesimple Userroot Grouproot Restarton-failure ExecStart/usr/local/node_exporter/node_exporter \ --web.listen-address:9100 \ --collector.systemd \ # 启用 systemd 收集器可以收集系统服务状态 --collector.systemd.unit-whitelist(docker|sshd|nginx|prometheus).service # 只收集指定服务的状态避免数据过多 --collector.filesystem.mount-points-exclude^/(sys|proc|dev|run)($|/) # 排除虚拟文件系统 [Install] WantedBymulti-user.target EOFnode_exporter 的参数也很有讲究--web.listen-address指定监听端口默认就是:9100。--collector.systemd这个收集器强烈建议开启它能告诉你每个系统服务的状态是 running 还是 failed。--collector.systemd.unit-whitelist配合上面参数使用用正则表达式指定只监控哪些服务。比如我这里关心 docker、sshd、nginx 和 prometheus 服务。如果不设置它会收集所有 systemd 单元的信息数据量会很大。--collector.filesystem.mount-points-exclude排除一些不需要监控的文件系统挂载点比如/sys、/proc这些。启动并启用服务systemctl daemon-reload systemctl start node_exporter systemctl enable node_exporter systemctl status node_exporter现在你可以在浏览器访问http://192.168.8.120:9100/metrics应该会看到一大串以node_开头的指标数据格式类似node_cpu_seconds_total{cpu0,modeidle} 123456.78。这说明 node_exporter 已经在正常工作暴露了主机的监控数据。3.4 让 Prometheus 发现并抓取 node_exporter现在数据源有了我们需要告诉 Prometheus Server 去抓取它。回到监控服务器192.168.8.121编辑prometheus.yml文件在scrape_configs部分我们之前已经添加了linux-nodes这个 job并指定了 target。确保配置正确。配置修改后因为启动时加了--web.enable-lifecycle参数我们可以用两种方式让配置生效热重载推荐curl -X POST http://localhost:9090/-/reload。注意Prometheus 默认要求启用--web.enable-lifecycle且请求的HOST头是localhost或127.0.0.1这是出于安全考虑。重启服务systemctl restart prometheus。热重载后再次打开 Prometheus 的 Web UI (http://192.168.8.121:9090/targets)。你应该能看到两个 Target一个是prometheus(UP)另一个是linux-nodes(UP)。如果linux-nodes的状态是UP并且Last Scrape时间在不断更新那就大功告成了Prometheus 已经开始周期性地从你的主机抓取监控数据了。4. 核心配置详解与高级玩法基础部署完成了但想用好 Prometheus还得深入理解它的配置。我们来把prometheus.yml里的几个核心部分拆开细说。4.1 全局配置global的权衡艺术scrape_interval和evaluation_interval是两个最重要的全局参数。scrape_interval: 15s抓取频率。频率越高数据越精细但 Prometheus 和网络的负担也越重存储空间消耗也越快。对于生产环境我通常根据监控对象的重要性来设置。核心业务应用可能设 15s而一些资源类监控如主机设 30s 或 60s 也完全可以接受。你甚至可以在后面的scrape_configs里为每个 job 单独覆盖这个全局设置。evaluation_interval: 15s告警规则评估频率。它决定了 Prometheus 多久计算一次你定义的告警规则比如CPU使用率 80%。这个值通常和scrape_interval保持一致或成倍数关系确保有最新的数据用于评估。4.2 抓取配置scrape_configs的多种姿势scrape_configs是配置的重头戏它定义了“监控谁”和“怎么监控”。静态配置static_configs就是我们刚才用的直接把目标的 IP 和端口写死在配置文件里。适合机器数量固定、变化不大的环境。- job_name: static-servers static_configs: - targets: [10.0.0.1:9100, 10.0.0.2:9100] labels: env: prod region: us-east文件服务发现file_sd_configs当机器数量较多或经常变动时手动改配置再重载很麻烦。你可以将目标列表写在一个单独的 JSON 或 YAML 文件里Prometheus 会定期读取这个文件。- job_name: file-sd-nodes file_sd_configs: - files: - /usr/local/prometheus/targets/nodes*.json # 可以匹配多个文件 refresh_interval: 5m # 5分钟刷新一次文件内容对应的nodes.json文件内容类似[ { targets: [ 192.168.1.10:9100 ], labels: { instance: app-01, job: node } }, { targets: [ 192.168.1.11:9100 ], labels: { instance: db-01, job: node } } ]这样你只需要更新这个 JSON 文件可以通过自动化脚本Prometheus 会自动发现新的监控目标。其他服务发现对于 Kubernetes、Consul、AWS EC2 等动态环境Prometheus 原生支持多种服务发现机制配置会更复杂一些但原理相通都是通过配置让 Prometheus 自动去这些平台拉取目标列表。4.3 告警规则rule_files初探虽然 Alertmanager 是另一个组件但告警规则是在 Prometheus Server 端定义的。规则文件通常以.rules或.yml为后缀。我们来写一个最简单的 CPU 告警规则。创建文件/usr/local/prometheus/rules/node_alerts.ymlgroups: - name: node_alerts rules: - alert: HostHighCpuUsage expr: 100 - (avg by (instance) (rate(node_cpu_seconds_total{modeidle}[5m])) * 100) 80 for: 5m # 持续5分钟满足条件才触发告警避免毛刺 labels: severity: warning team: ops annotations: summary: 高CPU使用率 (实例 {{ $labels.instance }}) description: {{ $labels.instance }} 的CPU使用率持续5分钟超过80%当前值为 {{ $value }}%。这个规则的意思是计算每个实例instance在过去5分钟内CPU空闲模式modeidle的时间比率然后用100减去它得到使用率。如果使用率大于80%并且持续了5分钟就触发一个名为HostHighCpuUsage的告警。然后在prometheus.yml中启用这个规则文件rule_files: - rules/node_alerts.yml重载配置后在 Prometheus Web UI 的 “Alerts” 标签页就能看到这条规则的状态Inactive,Pending,Firing。4.4 数据存储与保留策略Prometheus 默认将数据存储在本地路径由--storage.tsdb.path指定。它的存储引擎 TSDB 非常高效。但数据不能无限期保存默认是保留15天。你可以通过启动参数--storage.tsdb.retention.time来修改比如--storage.tsdb.retention.time90d表示保留90天。对于更长时间的数据存储和集群化方案通常会使用远程读写Remote Read/Write功能将数据备份到 InfluxDB、TiKV 或官方的 Prometheus TSDB 远程存储适配器中。这属于进阶话题当你的数据量达到 TB 级别或需要长期历史数据分析时就需要考虑了。5. 避坑指南与性能调优部署过程看似顺利但在生产环境大规模使用时肯定会遇到各种问题。这里分享几个我踩过的坑和对应的解决方案。坑一open too many files错误。当监控目标非常多比如上千个时Prometheus 需要同时维护大量的网络连接可能会突破系统的文件描述符限制。解决方法修改系统限制echo * soft nofile 65536 /etc/security/limits.conf并重启会话。调整 Prometheus 的--storage.tsdb.max-block-chunks-to-persist和--storage.tsdb.min-block-duration等参数优化内存和IO。但这些参数调优需要根据具体负载测试。坑二抓取超时Scrape Timeout。如果某个 Exporter 响应慢或者网络有波动可能导致抓取失败Target 状态在 UP 和 DOWN 之间跳动。可以在scrape_configs的 job 配置里单独设置scrape_timeout比如scrape_timeout: 30s比全局的10s更长。同时合理设置scrape_interval避免过于频繁的抓取给被监控端造成压力。坑三指标基数爆炸High Cardinality。这是 Prometheus 使用中最容易出问题的地方。指标基数指的是一个指标名下面由于标签Label值组合过多而产生的唯一时间序列的数量。比如你给 HTTP 请求指标加了一个user_id的标签每个用户访问都会产生一条新的时间序列用户量一大Prometheus 内存和存储就会爆掉。黄金法则避免将取值范围巨大或不可枚举的变量如用户ID、会话ID、订单号作为标签。标签应该是用于分组、筛选的维度如method、path、status_code、datacenter等。坑四PromQL 查询把服务器搞慢。在 Web UI 的 “Graph” 页面或 Grafana 里如果写了一个范围过大或计算过于复杂的 PromQL 查询比如rate(http_requests_total[1h])在数据量很大时可能会导致 Prometheus 查询引擎消耗大量 CPU 和内存甚至 OOM。对于 Grafana 面板尽量使用$__interval变量让查询步长自适应时间范围。对于告警规则避免使用过大的范围向量如[1h]通常[5m]或[15m]足够。性能调优小建议SSD 硬盘TSDB 有很多小文件随机写SSD 能极大提升性能。独立数据盘将--storage.tsdb.path指向一块独立的磁盘避免和系统盘或日志盘 IO 竞争。内存Prometheus 内存消耗和存储的数据量、活跃的序列数正相关。粗略估算每 100 万个时间序列大约需要 1-2GB 内存。确保服务器有足够的内存。分片Sharding 联邦Federation当单台 Prometheus 无法承受时可以按业务或地域部署多台 Prometheus然后用联邦Federation特性将一部分聚合数据汇总到全局的 Prometheus 中。走到这一步你的 Prometheus 监控系统已经具备了坚实的基础。它正在默默地收集着你服务器的健康数据。但这只是开始监控的价值在于“看见”和“预警”。接下来你需要用 Grafana 将数据变成直观的图表用 Alertmanager 设置告警渠道如邮件、钉钉、企业微信让监控真正活起来成为你运维工作中最可靠的伙伴。这些组件的部署和配置又是另一个精彩的故事了。记住监控体系的建设是迭代的先从核心指标开始稳定运行再逐步丰富和完善。