主机温度

通过前面大家知道我有一台安装 PVE 系统的 N00 小主机。今天跟跟大家分享一下我使用 Telegraf 收集主机 CPU、固态硬盘、机械硬盘硬件温度数据,然后把数据存储在 InfluxDB 上,并在 Grafana 实时显示硬件数据的过程。

软件功能作用简介

  • Telegraf,数据采集工具,可以采集多种组件运行信息,而不需自己手写脚本定时采集,降低数据获取难度。
  • InfluxDB,数据存储工具,时间序列数据库,适合存储设备性能、日志、物联网传感器等带有时间戳的数据。
  • Grafana,数据可视化工具,帮助用户将数据源中的数据图形化的展示和实时监控,便于用户直观地理解数据。

打开 PVE 指标数据

将 Proxmox 指标收集重定向到 Telegraf 可以使用的本地 Socket。

# 修改 /etc/pve/status.cfg 文件添加如下内容
# root@pve:~# cat /etc/pve/status.cfg
influxdb: telegraf
        port 8089
        server localhost
# 启动 pvestatd 服务
systemctl restart pvestatd
# 检查 8089 监听状态
root@pve:~# netstat -lnptu | grep 8089
udp6       0      0 :::8089    :::*    2007/telegraf       

Telegraf

安装 Telegraf

官方文档 https://docs.influxdata.com/telegraf/v1/install/

curl -s https://repos.influxdata.com/influxdata-archive_compat.key > influxdata-archive_compat.key
echo '393e8779c89ac8d958f81f942f9ad7fb82a25e133faddaf92e15b16e6ac9ce4c influxdata-archive_compat.key' | sha256sum -c && cat influxdata-archive_compat.key | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/influxdata-archive_compat.gpg > /dev/null
echo 'deb [signed-by=/etc/apt/trusted.gpg.d/influxdata-archive_compat.gpg] https://repos.influxdata.com/debian stable main' | sudo tee /etc/apt/sources.list.d/influxdata.list
sudo apt-get update && sudo apt-get install telegraf

配置 Telegraf

# 配置文件
root@pve:~# cat /etc/telegraf/telegraf.conf
# 执行脚本
root@pve:~# cat /etc/telegraf/telegraf_temp.sh
# /etc/telegraf/telegraf.conf
[agent]
    interval = "10s"
    round_interval = true
    metric_batch_size = 1000
    metric_buffer_limit = 10000
    collection_jitter = "0s"
    flush_interval = "10s"
    flush_jitter = "0s"
    precision = ""
    hostname = ""
    omit_hostname = false

# Configuration for sending metrics to InfluxDB
[[outputs.influxdb_v2]]
    urls = ["http://192.168.0.114:8006"]
    token = "MNZJG8NzFPW6IXia9sE4VtUqWi5pMg3C54CVD9QUq5YZbxVRWcYVlZYQ9I-fXFVwjP2KibcW0yW3yPpvqKi7dQ=="
    organization = "z" # todo pve
    bucket = "mybucket"

[[inputs.socket_listener]]
    service_address = "udp://:8089"

[[inputs.smart]]
    path_smartctl = "/usr/sbin/smartctl"
    path_nvme = "/usr/sbin/nvme"
    use_sudo = true
    devices = [ 
        "/dev/disk/by-id/ata-WDC_WD40EJRX-89AKWY0_WD-WX62D40A9667 --all",
        "/dev/disk/by-id/ata-WDC_WD42EJRX-89BFNY0_WD-WX32DB174JFP --all",
        "/dev/nvme0 -d nvme"]

[[inputs.sensors]]
    remove_numbers = true
    timeout = "5s"    

[[inputs.exec]]
  commands = ["/etc/telegraf/telegraf_temp.sh"]
  timeout = "5s"
  data_format = "influx"

[[outputs.file]]
    files = ["stdout"]

温度获取

  • 使用 sensors -j 获取 CPU 和固态硬盘温度
  • 使用 smartctl -A /dev/sda 获取机械硬盘温度
  • 使用 curl <url> 访问接口,获取本地天气温度
#!/usr/bin/env bash
# /etc/telegraf/telegraf_temp.sh
sensor_data=$(sensors -j)
# 内核的温度
packageid0=$(echo "$sensor_data" | jq '.["coretemp-isa-0000"]["Package id 0"] | select(type == "object") | .temp1_input')
core0=$(echo "$sensor_data" | jq '.["coretemp-isa-0000"]["Core 0"] | select(type == "object") | .temp2_input')
core1=$(echo "$sensor_data" | jq '.["coretemp-isa-0000"]["Core 1"] | select(type == "object") | .temp3_input')
core2=$(echo "$sensor_data" | jq '.["coretemp-isa-0000"]["Core 2"] | select(type == "object") | .temp4_input')
core3=$(echo "$sensor_data" | jq '.["coretemp-isa-0000"]["Core 3"] | select(type == "object") | .temp5_input')
# CPU 插槽附近/上的温度传感器,该传感器可能不可靠
acpitzacpi0=$(echo "$sensor_data" | jq '.["acpitz-acpi-0"]["temp1"] | select(type == "object")  |  .temp1_input')
nvmepci0500=$(echo "$sensor_data" | jq '.["nvme-pci-0500"]["Composite"] | select(type == "object")  |  .temp1_input')
wd40ejrx89akwy0=$(smartctl -A /dev/sda | grep -i "temperature" | awk '{print $10}' | tr -d '\n\r')
wd40ejrx89akwy0=$(printf "%.1f" "$wd40ejrx89akwy0")
wd42ejrx89bfny0=$(smartctl -A /dev/sdb | grep -i "temperature" | awk '{print $10}' | tr -d '\n\r')
wd42ejrx89bfny0=$(printf "%.1f" "$wd42ejrx89bfny0")
sz=$(curl -s http://192.168.0.114:8035/api/weather/sz | jq '.data.qw')
sz=$(printf "%.1f" "$sz")
echo "n100_temp,device=cpu,chip=coretemp-isa-0000-packageid0 temp_input=$packageid0"
echo "n100_temp,device=cpu,chip=coretemp-isa-0000-core0 temp_input=$core0"
echo "n100_temp,device=cpu,chip=coretemp-isa-0000-core1 temp_input=$core1"
echo "n100_temp,device=cpu,chip=coretemp-isa-0000-core2 temp_input=$core2"
echo "n100_temp,device=cpu,chip=coretemp-isa-0000-core3 temp_input=$core3"
#echo "n100_temp,device=cpu,chip=acpitz-acpi-0 temp_input=$acpitzacpi0"
echo "n100_temp,device=cpu,chip=nvme-pci-0500 temp_input=$nvmepci0500"
echo "n100_temp,device=hdd,chip=wd40ejrx-89akwy0-wx62d40a9667 temp_input=$wd40ejrx89akwy0"
echo "n100_temp,device=hdd,chip=wd42ejrx-89bfny0-wx32db174jfp temp_input=$wd42ejrx89bfny0"
echo "n100_temp,device=weather,chip=sz temp_input=$sz"

Grafana

Grafana 的部署可以参考前面的【玩 docker】 监控平台 Prometheus + Grafana 的部署

在 Grafana 添加 InfluxDB 数据源,Query Language, InfluxDB 2.x 和 1.8+ 版本选择 Flux

添加数据源

然后创建 dashboards。

图表

图标的查询语句如下

from(bucket: "mybucket")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r["_measurement"] == "n100_temp")
  |> aggregateWindow(every: v.windowPeriod, fn: last, createEmpty: false)
  |> drop(columns: ["_field", "device", "host"])
  |> yield(name: "last")