十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Windows主机监控实战:node_exporter+Prometheus+Grafana避坑指南

Windows主机监控实战:node_exporter+Prometheus+Grafana避坑指南 1. 为什么Windows主机监控值得单独折腾一套方案很多人第一次接触Prometheus生态都是在Linux服务器上完成的——node_exporter一个二进制文件丢上去systemd一挂齐活。等到需要监控Windows主机的时候习惯性地去搜node_exporter Windows发现确实有对应的exporter于是照猫画虎下载、解压、双击运行结果要么是服务起不来要么是Grafana面板上一片No data要么是采集到的磁盘、网络指标缺胳膊少腿。Windows的监控需求和Linux有本质区别。Linux下我们习惯看load average、看文件描述符、看inode使用率Windows下真正要盯的是CPU队列长度、内存的Committed Bytes、磁盘的Avg. Disk sec/Transfer、服务的运行状态、IIS的连接数、.NET的GC情况。这些指标在Windows的性能计数器Performance Counter体系里都有但node_exporter默认采集的Windows指标集和Linux并不完全一致很多Windows特有的计数器需要额外开启collector才能拿到。这套方案的核心链路是node_exporter负责在Windows主机上采集指标并暴露HTTP端点Prometheus负责定时拉取scrape并存储时序数据Grafana负责查询Prometheus并渲染成可视化面板。三者都是开源组件部署成本低社区生态成熟Grafana上有大量现成的Windows监控Dashboard可以直接导入使用。适合谁来参考这篇内容手里有Windows Server或者Windows 10/11工作站需要做长期监控的运维人员正在搭建混合架构监控体系LinuxWindows的SRE想用开源方案替代商业监控工具如Zabbix、SolarWinds但不确定Windows支持程度的工程师以及已经装了Prometheus和Grafana、但Windows节点一直没接进来的朋友。我前后在三套不同规模的环境里部署过这套组合踩过的坑包括但不限于Windows防火墙拦截9182端口、node_exporter以控制台方式运行导致关掉窗口就断采、Prometheus配置文件里target写错导致一直显示DOWN、Grafana面板时间范围和Prometheus数据保留期不匹配导致图表空白。下面把这些经验完整拆开讲。2. node_exporter在Windows上的安装与踩坑实录2.1 下载与目录规划别把exporter丢在桌面node_exporter的Windows版本在Prometheus官方GitHub Releases页面可以找到文件名类似node_exporter-1.8.2.windows-amd64.zip。下载后解压里面只有一个node_exporter.exe和一份LICENSE、NOTICE文件。我见过不少人在测试阶段直接把exe放在桌面或者Downloads文件夹里双击运行测试完觉得没问题结果正式上线时忘了迁移某次系统清理临时文件把exe删了监控直接断了一周才发现。所以从一开始就规划好目录结构C:\monitoring\ ├── node_exporter\ │ ├── node_exporter.exe │ └── logs\ │ └── node_exporter.log ├── prometheus\ │ ├── prometheus.exe │ ├── prometheus.yml │ └── data\ └── grafana\ └── (Grafana安装目录)把监控组件统一放在C:\monitoring下面好处是权限管理集中、备份路径明确、后续写脚本或做服务注册时路径引用不容易出错。如果Windows主机有多个盘符建议放在系统盘以外的数据盘避免系统盘空间告急时影响监控数据写入。2.2 命令行参数哪些collector必须开哪些最好关node_exporter在Windows上默认启用的collector和Linux版本有差异。直接双击运行的话它会监听0.0.0.0:9182注意Windows版默认端口是9182不是Linux的9100并启用一组默认collector。但默认集合并不能覆盖Windows运维最关心的几个维度。我通常会用以下参数启动node_exporter.exe --collectors.enabledcpu,cs,logical_disk,net,os,service,system,textfile,memory,process --web.listen-address:9182 --log.levelinfo逐个解释为什么这么选cpu采集CPU使用率、各核心的 idle/user/system 时间。Windows下这个collector依赖性能计数器如果发现CPU指标全是0大概率是性能计数器库损坏后面会讲修复方法。csComputer System采集系统层面的信息包括CPU队列长度、上下文切换次数、系统调用次数。CPU队列长度是判断Windows主机是否过载的关键指标比单纯的CPU使用率更有参考价值。logical_disk按逻辑盘符采集磁盘读写字节数、读写耗时、空闲空间。注意它采集的是逻辑盘C:、D:不是物理磁盘。net采集每个网络接口的收发字节数、错误包数、丢弃包数。os采集内存相关的指标包括可用内存、已提交内存Committed Bytes、分页文件使用情况。Windows的已提交内存超过物理内存分页文件总和时系统会变得极其卡顿这个指标必须盯。service采集Windows服务的运行状态。这个collector默认可能没开但非常有用——你可以通过Prometheus告警规则监控关键服务如SQL Server、IIS、自定义业务服务是否意外停止。system采集系统启动时间、进程数等基础信息。textfile允许你通过文本文件自定义指标。比如业务系统每小时导出一个.prom文件到指定目录node_exporter会自动读取并暴露。这个后面会展开讲。memory内存使用明细包括缓存、分页池、非分页池等。process进程级别的CPU和内存使用情况。注意这个collector在进程数很多的Windows主机上会消耗较多资源如果主机上跑了几百个进程建议谨慎开启或调大采集间隔。提示--collectors.enabled参数在不同版本的node_exporter中写法可能不同。1.16之后的版本推荐用--collector.name和--no-collector.name来精细控制比如--collector.service启用服务采集--no-collector.process禁用进程采集。建议先运行node_exporter.exe --help确认当前版本的参数格式。2.3 注册为Windows服务解决关掉窗口就断采的问题双击exe运行的方式只适合临时测试。正式环境必须注册为Windows服务否则远程桌面一断开、控制台窗口一关采集就停了。Windows下注册服务最稳妥的方式是用sc命令或者nssmNon-Sucking Service Manager。sc是系统自带的不需要额外下载但配置日志重定向比较麻烦nssm是第三方工具可以把任意exe包装成服务还能自动重启、重定向stdout/stderr到日志文件。用sc注册的命令如下sc create node_exporter binPath C:\monitoring\node_exporter\node_exporter.exe --collectors.enabledcpu,cs,logical_disk,net,os,service,system,textfile,memory --web.listen-address:9182 start auto sc description node_exporter Prometheus Node Exporter for Windows sc start node_exporter注意binPath和start后面的等号后面必须有一个空格这是sc命令的语法要求很多人第一次写会漏掉空格导致创建失败。用nssm的话更简单nssm install node_exporter C:\monitoring\node_exporter\node_exporter.exe nssm set node_exporter AppParameters --collectors.enabledcpu,cs,logical_disk,net,os,service,system,textfile,memory --web.listen-address:9182 nssm set node_exporter AppDirectory C:\monitoring\node_exporter nssm set node_exporter AppStdout C:\monitoring\node_exporter\logs\node_exporter.log nssm set node_exporter AppStderr C:\monitoring\node_exporter\logs\node_exporter.err.log nssm set node_exporter AppRestartDelay 5000 nssm start node_exporterAppRestartDelay 5000表示服务意外退出后5秒自动重启这个参数在实际运维中救过我好几次——某台Windows主机上node_exporter因为性能计数器偶发异常崩溃如果没有自动重启监控就断了。2.4 防火墙放行与端口验证服务起来之后第一件事是确认端口在监听netstat -ano | findstr 9182如果看到TCP 0.0.0.0:9182 LISTENING说明exporter正常。接下来在本机浏览器访问http://localhost:9182/metrics应该能看到一大段以# HELP和# TYPE开头的指标文本。但本机能访问不代表Prometheus能访问。Windows防火墙默认会拦截入站连接需要在防火墙里放行9182端口netsh advfirewall firewall add rule nameNode Exporter dirin actionallow protocolTCP localport9182如果公司安全策略不允许直接放行端口可以限制只允许Prometheus服务器的IP访问netsh advfirewall firewall add rule nameNode Exporter dirin actionallow protocolTCP localport9182 remoteip10.0.1.50注意有些环境里Windows主机加入了域域策略会覆盖本地防火墙规则。如果放行后仍然不通用netsh advfirewall firewall show rule nameall检查规则是否生效或者临时关闭域防火墙配置做对比测试。3. Prometheus端配置从target定义到指标重命名3.1 prometheus.yml的最小可用配置Prometheus的安装这里不展开假设你已经有一个运行中的Prometheus实例。核心是在prometheus.yml的scrape_configs下面增加一个jobscrape_configs: - job_name: windows scrape_interval: 30s scrape_timeout: 10s static_configs: - targets: - 10.0.1.101:9182 - 10.0.1.102:9182 labels: env: production os: windows几个关键点scrape_interval: 30sWindows主机的指标变化不像Linux那么频繁30秒采集一次足够。如果主机数量多超过50台可以放宽到60秒减轻Prometheus的存储和查询压力。scrape_timeout: 10s必须小于scrape_interval。Windows上node_exporter采集process和servicecollector时偶尔会慢10秒超时是经验值。labels给所有target打上统一标签后续在Grafana里可以用envproduction过滤也方便写告警规则时按环境区分。改完配置后用promtool check config prometheus.yml验证语法然后热加载curl -X POST http://localhost:9090/-/reload如果Prometheus没有开启--web.enable-lifecycle热加载会失败需要重启Prometheus进程。3.2 target状态排查UP、DOWN和unknown的区别配置生效后打开Prometheus Web UI的Status - Targets页面应该能看到windows job下面的target状态是UP。如果显示DOWN把鼠标悬停在错误信息上常见的有以下几种错误信息原因解决方式connection refusednode_exporter服务没起来或端口不对在Windows主机上netstat -ano | findstr 9182确认监听context deadline exceeded网络不通或防火墙拦截从Prometheus服务器telnet 10.0.1.101 9182测试连通性server returned HTTP status 500node_exporter内部collector报错查看node_exporter日志通常是性能计数器问题no such hosttarget主机名解析失败改用IP地址或在Prometheus服务器配置hosts还有一种情况是target显示UP但指标不全比如只有node_exporter_build_info这一条。这通常是因为--collectors.enabled参数没生效或者参数拼写错误导致所有collector都没启用。检查node_exporter启动日志里有没有msgEnabled collectors这一行后面会列出实际启用的collector列表。3.3 用metric_relabel_configs过滤和重命名指标Windows的node_exporter会暴露大量指标其中有些是你不关心的比如每个逻辑盘的详细读写延迟有些命名不符合你的告警规则习惯。这时候可以用metric_relabel_configs做二次处理。举个例子我想把所有Windows主机的node_logical_disk_free_bytes指标重命名为更直观的windows_disk_free_bytes同时只保留C盘和D盘的数据- job_name: windows scrape_interval: 30s static_configs: - targets: [10.0.1.101:9182] metric_relabel_configs: - source_labels: [__name__] regex: node_logical_disk_free_bytes target_label: __name__ replacement: windows_disk_free_bytes - source_labels: [volume] regex: C:|D: action: keepaction: keep表示只保留匹配的指标其他全部丢弃。这个操作在Prometheus存储层之前完成能有效减少存储量和查询开销。提示metric_relabel_configs是在scrape之后、写入存储之前执行的。如果你需要更复杂的转换比如计算磁盘使用率建议在Grafana的查询里用PromQL完成而不是在relabel阶段做因为relabel不支持算术运算。3.4 告警规则Windows主机最该盯的五个指标Prometheus本身只负责采集和存储告警需要配合Alertmanager。但告警规则是在Prometheus里定义的。以下是我在Windows环境里最常用的五条规则groups: - name: windows_alerts rules: - alert: WindowsHighCPU expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{modeidle}[5m])) * 100) 85 for: 10m labels: severity: warning annotations: summary: Windows主机 {{ $labels.instance }} CPU使用率超过85% - alert: WindowsLowMemory expr: (node_memory_Committed_Bytes - node_memory_Committed_Limit_Bytes) / node_memory_Committed_Limit_Bytes 0.9 for: 5m labels: severity: critical annotations: summary: Windows主机 {{ $labels.instance }} 已提交内存接近上限 - alert: WindowsDiskSpaceLow expr: node_logical_disk_free_bytes / node_logical_disk_size_bytes 0.15 for: 15m labels: severity: warning annotations: summary: Windows主机 {{ $labels.instance }} 磁盘 {{ $labels.volume }} 剩余空间不足15% - alert: WindowsServiceDown expr: node_service_state{staterunning} 0 for: 2m labels: severity: critical annotations: summary: Windows主机 {{ $labels.instance }} 服务 {{ $labels.service }} 未运行 - alert: WindowsExporterDown expr: up{jobwindows} 0 for: 3m labels: severity: critical annotations: summary: Windows主机 {{ $labels.instance }} 的node_exporter失联第一条CPU告警用的是100 - idle的方式比直接看node_cpu_seconds_total{modeuser}更准确因为Windows下system和interrupt时间也占用CPU。第二条内存告警用的是Committed Bytes和Committed Limit的比值这个指标比单纯的可用内存更能反映Windows内存压力——Windows会大量使用分页文件和缓存可用内存低不一定有问题但已提交内存接近上限一定会卡。第三条磁盘告警按卷过滤避免监控到光驱或恢复分区。第四条服务告警需要node_exporter启用了service collector并且node_service_state指标里包含你要监控的服务名。第五条是兜底规则exporter失联时触发。4. Grafana面板配置从导入到自定义4.1 添加Prometheus数据源Grafana启动后默认监听3000端口初始账号密码都是admin。登录后第一件事是添加数据源Configuration - Data Sources - Add data source - Prometheus。URL填Prometheus的地址比如http://10.0.1.50:9090。如果Grafana和Prometheus不在同一台机器确保网络互通。Access模式选Server (default)表示由Grafana后端去请求Prometheus而不是浏览器直接请求。保存后点击Save Test如果显示Data source is working说明连接正常。如果报错常见原因是Prometheus的--web.enable-cors没开跨域问题或者URL写成了https但Prometheus只监听http。4.2 导入Windows监控DashboardGrafana官方Dashboard库里有多个Windows监控面板最常用的是ID为10467的Windows Exporter Dashboard和ID为14694的Windows Node Exporter。导入方式Dashboards - Import - 输入ID - Load。导入后需要选择数据源选刚才添加的Prometheus然后面板就会显示数据。但直接导入的面板往往有几个问题变量instance默认显示所有target如果target多下拉框会很长。可以在Dashboard设置里给变量加过滤条件比如只显示envproduction的实例。部分面板的PromQL查询用的是Linux的指标名比如node_filesystem_avail_bytes在Windows上不存在会显示No data。需要手动改成Windows对应的指标node_logical_disk_free_bytes。时间范围默认是Last 6 hours如果Prometheus的数据保留期只有15天查更早的数据会空白。建议把Dashboard默认时间范围设为Last 24 hours。4.3 自定义面板以磁盘IO延迟为例导入的面板不一定覆盖你关心的所有指标。比如我想看每台Windows主机各逻辑盘的IO延迟Avg. Disk sec/Transfer这个指标在node_exporter里对应node_logical_disk_read_seconds_total和node_logical_disk_writes_total。新建一个Panel查询用rate(node_logical_disk_read_seconds_total[5m]) / rate(node_logical_disk_reads_total[5m])这个表达式的含义是过去5分钟内读操作总耗时除以读操作总次数得到平均每次读操作的耗时秒。Windows下这个值超过0.02秒20毫秒就说明磁盘IO有压力超过0.05秒基本可以确定是磁盘瓶颈。Panel的Visualization选Time seriesUnit选seconds (s)Legend填{{instance}} - {{volume}}这样图例上能直接看到是哪台机器的哪个盘。4.4 变量与模板化让一个面板适配所有Windows主机如果管理的主机超过10台每个面板都写死instance会很痛苦。Grafana的变量功能可以解决这个问题。在Dashboard设置里新建一个变量Name:instanceType:QueryData source: 选PrometheusQuery:label_values(up{jobwindows}, instance)Multi-value: 勾选Include All option: 勾选然后在Panel的查询里用$instance引用100 - (avg by(instance) (rate(node_cpu_seconds_total{modeidle, instance~$instance}[5m])) * 100)这样Dashboard顶部会出现一个下拉框可以选择查看哪些主机。instance~$instance里的~是正则匹配配合Multi-value可以实现多选。5. 那些让我加班到凌晨的常见问题5.1 node_exporter启动报错performance counter not found这是Windows上最典型的问题。node_exporter的cpu、logical_disk、net等collector依赖Windows性能计数器库。如果性能计数器损坏常见于系统更新后、或者被某些优化软件清理过node_exporter启动时会报错couldnt initialize performance counters: The specified object was not found on the computer修复方法是重建性能计数器库。以管理员身份打开命令提示符依次执行cd C:\Windows\System32 lodctr /R cd C:\Windows\SysWOW64 lodctr /R然后重启node_exporter服务。如果lodctr /R报错先执行lodctr /E:PerfOS和lodctr /E:PerfProc导出当前配置再执行lodctr /R重建。注意重建性能计数器后某些第三方监控软件如Zabbix Agent可能需要重新注册性能计数器否则会采集不到数据。如果主机上同时跑了其他监控agent操作前先确认影响范围。5.2 Grafana面板显示No data但Prometheus里有数据这个问题排查起来最耗时因为可能的原因很多。我的排查顺序是确认Prometheus里确实有数据在Prometheus Web UI的Graph页面直接执行PromQL比如node_cpu_seconds_total{instance10.0.1.101:9182}看有没有结果。检查Grafana的时间范围如果Prometheus里数据的时间戳是UTC而Grafana面板用的是浏览器本地时间可能因为时区差异导致查询范围偏移。在Grafana的Dashboard设置里把Timezone改成UTC试试。检查变量值如果Panel里用了$instance变量确认下拉框里选中的值是否和Prometheus里的label完全一致。比如Prometheus里instance是10.0.1.101:9182但变量查询返回的是10.0.1.101匹配不上就会No data。检查指标名Windows和Linux的node_exporter指标名有差异导入的Dashboard可能用的是Linux指标名。在Prometheus里执行{__name__~node_.*}看看实际有哪些指标。检查数据源确认Panel选的数据源是Prometheus而不是默认的-- Grafana --。5.3 采集间隔与数据保留期的平衡Prometheus默认的数据保留期是15天可以通过--storage.tsdb.retention.time30d延长。但保留期越长磁盘占用越大。一个粗略的估算公式磁盘占用 ≈ 每秒采集的样本数 × 每个样本的字节数 × 保留秒数每个样本在Prometheus的TSDB里大约占1.5到2字节压缩后。假设你有20台Windows主机每台暴露500个指标采集间隔30秒那么每秒采集的样本数约为20 × 500 / 30 ≈ 333 samples/s保留30天的磁盘占用约为333 × 2 × 30 × 86400 ≈ 1.7 GB这个量级对大多数环境都可以接受。但如果主机数量到200台或者指标数到2000个磁盘占用就会到几十GB。这时候要么缩短保留期要么用Prometheus的remote write把数据转发到长期存储如VictoriaMetrics、Thanos。5.4 Windows服务采集的特殊处理node_service_state指标默认只采集部分服务而且服务名是Windows内部名如MSSQLSERVER不是显示名如SQL Server (MSSQLSERVER)。如果你要监控自定义业务服务需要确认服务名sc query type service state all | findstr SERVICE_NAME然后在Prometheus告警规则里用内部名匹配。如果服务名包含空格或特殊字符在PromQL里需要用引号包裹。另外node_service_state的state标签有running、stopped、paused等值。我通常只监控running状态因为paused在Windows服务里很少见而且不同版本的node_exporter对paused的处理不一致。6. 让这套方案更稳的几个进阶操作6.1 用textfile collector暴露自定义业务指标node_exporter的textfile collector允许你把自定义指标写入.prom文件exporter会自动读取并合并到/metrics输出里。这在Windows上特别有用因为很多业务系统如IIS、SQL Server没有现成的exporter但可以通过PowerShell脚本定期采集。举个例子写一个PowerShell脚本每小时统计一次IIS的当前连接数写入C:\monitoring\node_exporter\textfile\iis_connections.prom$connections (Get-Counter \Web Service(_Total)\Current Connections).CounterSamples[0].CookedValue $content # HELP iis_current_connections Current connections to IIS # TYPE iis_current_connections gauge iis_current_connections $connections Set-Content -Path C:\monitoring\node_exporter\textfile\iis_connections.prom -Value $content然后在Windows任务计划程序里创建一个每小时执行一次的任务。node_exporter启动时需要加--collector.textfile.directoryC:\monitoring\node_exporter\textfile参数。提示textfile collector读取的是文件内容不是文件本身。如果脚本执行失败导致文件没更新exporter会继续暴露上一次的值。建议在脚本里加时间戳指标比如iis_connections_last_update_timestamp然后在Prometheus里告警这个时间戳超过2小时没更新。6.2 Prometheus的高可用与远程存储单点Prometheus在正式环境里是有风险的——Prometheus进程挂了监控就断了。简单的做法是用两台Prometheus同时采集相同的targetGrafana配置两个数据源查询时用Mixed模式。但这样查询结果会重复需要去重。更优雅的方案是用Prometheus的remote write把数据同时写到本地TSDB和远程存储如VictoriaMetrics。VictoriaMetrics兼容PromQL支持长期存储和水平扩展而且单节点版本部署很简单一个二进制文件就能跑。配置方式是在prometheus.yml里加remote_write: - url: http://10.0.1.60:8428/api/v1/write然后在Grafana里把数据源指向VictoriaMetrics的查询端点http://10.0.1.60:8428。这样即使本地Prometheus挂了历史数据还在VictoriaMetrics里新数据也可以由另一台Prometheus继续写入。6.3 监控数据的备份与恢复Prometheus的TSDB数据默认存在data目录下。备份最简单的方式是直接复制整个data目录但Prometheus运行中复制可能得到不一致的快照。推荐用Prometheus自带的snapshot APIcurl -X POST http://localhost:9090/api/v1/admin/tsdb/snapshot这个API需要在启动Prometheus时加--web.enable-admin-api。执行后会返回一个快照路径比如data/snapshots/20250101T120000Z-abc123把这个目录复制走即可。恢复时停止Prometheus把快照目录里的内容复制回data目录然后启动。注意快照只包含TSDB数据不包含prometheus.yml和告警规则文件这些需要单独备份。6.4 告警通知的降噪处理Alertmanager的告警分组和抑制规则能有效减少告警风暴。比如一台Windows主机失联时会同时触发WindowsExporterDown、WindowsHighCPU、WindowsLowMemory等多条告警。在Alertmanager里配置route: group_by: [alertname, instance] group_wait: 30s group_interval: 5m repeat_interval: 4h receiver: default inhibit_rules: - source_match: alertname: WindowsExporterDown target_match_re: alertname: Windows.* equal: [instance]inhibit_rules的含义是当WindowsExporterDown触发时抑制同一instance上所有其他Windows告警。这样运维人员只需要处理exporter失联这一条根因告警而不是被十几条衍生告警淹没。group_wait: 30s表示同一分组内的告警等待30秒再发送给Prometheus一点时间确认告警是否持续。repeat_interval: 4h表示同一告警如果一直没恢复每4小时重复通知一次避免频繁打扰。7. 关于这套组合的一些个人体会这套方案我从2021年开始在多个环境里使用最大的感受是Windows监控的难点不在Prometheus和Grafana而在node_exporter的collector配置和Windows本身的性能计数器稳定性。Linux下node_exporter几乎不需要额外配置就能拿到所有关键指标Windows下则需要根据实际需求精细选择collector还要处理性能计数器损坏、服务名不匹配、防火墙拦截等一系列平台特有的问题。另一个体会是Grafana面板不要追求大而全。我见过有人导入一个包含上百个Panel的Dashboard结果打开一次要加载十几秒真正关注的指标反而被淹没在图表海里。我的做法是每个环境只保留一个核心Dashboard包含CPU、内存、磁盘、网络、服务状态五类面板每个面板只展示最关键的几条曲线。需要深入排查时再去Prometheus的Graph页面写临时查询。最后说一个容易被忽略的点监控系统本身的资源消耗也要监控。Prometheus和Grafana跑在Windows上时它们的CPU和内存占用也应该被采集。可以在Prometheus的配置里加一个job用windows_exporter或者直接抓取Prometheus自身的/metrics端点。否则可能出现监控系统把被监控主机的资源吃满导致业务系统变慢的尴尬情况。
返回列表