Skip to main content

Métricas

Temperatura en UI

La UI está hecha en JavaScript, con lo que es posible modificarla para añadir los datos de temperatura u otros.

perill

Las actualizaciones pueden cambiar la UI, así que esta configuración se pierde rápidamente y puede ser diferente en cada versión, con lo que no coincidirá en las líneas indicadas.

tip

Me he basado en este repositorio.

Instalar el sensor y comprobar qué utilizaremos. En mi caso utilizo el agrupador para la CPU y el sensor de disco duro.

apt-get install lm-sensors -y
sensors-detect
service kmod start
sensors

Añadir la lista de sensores a utilizar.

cp /usr/share/perl5/PVE/API2/Nodes.pm /usr/share/perl5/PVE/API2/Nodes.pm_BKP
vi /usr/share/perl5/PVE/API2/Nodes.pm

Tras el siguiente bloque (línea 498)

        $res->{rootfs} = {
total => $dinfo->{blocks},
avail => $dinfo->{bavail},
used => $dinfo->{used},
free => $dinfo->{blocks} - $dinfo->{used},
};

Añadir:

        my %sensors_config = (
cputemp => {
jsonpath => ['coretemp-isa-0000', 'Package id 0'],
valkey => 'temp1_input',
critkey => 'temp1_crit',
},
nvmetemp => {
jsonpath => ['nvme-pci-0100', 'Composite'],
valkey => 'temp1_input',
critkey => 'temp1_crit',
},
);
my $temp_default_val = 0;
my $temp_default_crit = 80;

my $sensors = eval { decode_json(`sensors -j`); };
if (defined($sensors)) {
keys %sensors_config;
while (my ($k, $v) = each %sensors_config) {
if (!defined($v->{jsonpath})) { next; }
my $currref = $sensors;
my $pathdefined = 1;
for my $pathseg (@{$v->{jsonpath}}) {
if (defined($currref->{$pathseg})) {
$currref = $currref->{$pathseg}
} else {
$pathdefined = 0;
last;
}
}
if (!$pathdefined) { next; }
$res->{$k} = {
used => defined($v->{valkey}) && defined($currref->{$v->{valkey}})
? $currref->{$v->{valkey}} : $temp_default_val,
total => defined($v->{critkey}) && defined($currref->{$v->{critkey}})
? $currref->{$v->{critkey}} : $temp_default_crit,
};
}
}

Añadir la función transformadora.

cp /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js_BKP
vi /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js

Sobre la línea 1097, añadir:

    render_node_temp: function(record) {
if (!record || !Ext.isNumeric(record.used) || !Ext.isNumeric(record.total)) {
return '-';
}
return record.used.toFixed(1) + '°C (crit: ' + record.total.toFixed(1) + '°C)';
},

Finalmente hay que añadir el bloque y ajustar las CSS.

cp /usr/share/pve-manager/js/pvemanagerlib.js /usr/share/pve-manager/js/pvemanagerlib.js_BKP
vi /usr/share/pve-manager/js/pvemanagerlib.js
/* Línea 45001 */
Ext.define('PVE.node.StatusView', {
extend: 'Proxmox.panel.StatusView',
alias: 'widget.pveNodeStatus',

height: 350, /* cambiar a 400 */

/* Tras línea 45087 */
{
xtype: 'box',
colspan: 2,
padding: '0 0 20 0',
},

/* Añadir */
{
itemId: 'cputemp',
iconCls: 'fa fa-fw fa-thermometer-half',
title: gettext('CPU temp'),
valueField: 'cputemp',
maxField: 'cputemp',
renderer: Proxmox.Utils.render_node_temp,
},
{
itemId: 'nvmetemp',
iconCls: 'fa fa-fw fa-thermometer-half',
title: gettext('NVMe temp'),
valueField: 'nvmetemp',
maxField: 'nvmetemp',
renderer: Proxmox.Utils.render_node_temp,
},
{
xtype: 'box',
colspan: 2,
padding: '0 0 20 0',
},

Al terminar todos los cambios, reiniciar y confirmar que se muestra correctamente en la UI.

systemctl restart pveproxy.service

La temperatura se muestra en la pantalla de Summary del nodo. img

Prometheus exporter

Por defecto, podemos exportar las metricas a Graphite o InfluxDB, pero no es posible utiliza Prometheus.

Debido a que Prometheus/Grafana suelen ser una unión bastante típica, existe un proyecto que incluso tiene un dashboard de Grafana preparado.

Usuario para métricas

Lo primero es crear un usuario que pueda acceder a Proxmox para obtener los datos, y un token que será utilizado por la aplicación.

pveum user add pve-exporter@pve
pveum acl modify / -user pve-exporter@pve -role PVEAuditor
pveum user token add pve-exporter@pve export --privsep=0

Ese mismo usuario se debe añadir a Linux para que pueda iniciar el proceso.

useradd -s /bin/false pve-exporter

Instalar el exportador

Instalamos las dependencias.

apt-get install python3-pip python3-venv -y

Y el exportador.

python3 -m venv /opt/prometheus-pve-exporter
/opt/prometheus-pve-exporter/bin/pip install prometheus-pve-exporter

Configuración

El exportador necesita un fichero que le indique el usuario y el token que hemos generado previamente.

mkdir -p /etc/prometheus
cat <<EOF > /etc/prometheus/pve.yml
default:
user: pve-exporter@pve
token_name: export
token_value: token_id
verify_ssl: false
EOF
warning

Cambiar el token_id según el token creado en la sección de usuario.

Creamos el fichero de inicialización y activamos el servicio.

cat <<EOF> /etc/systemd/system/prometheus-pve-exporter.service
[Unit]
Description=Prometheus exporter for Proxmox VE
Documentation=https://github.com/znerol/prometheus-pve-exporter

[Service]
Restart=always
User=pve-exporter
ExecStart=/opt/prometheus-pve-exporter/bin/pve_exporter --config.file /etc/prometheus/pve.yml

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable prometheus-pve-exporter
systemctl start prometheus-pve-exporter

Si todo ha funcionado, podremos acceder mediante el puerto 9221.

http://servername.domain.intranet:9221/pve

Prometheus

En este caso, Prometheus se configura a través de un Scrape Config indicándole el nombre del servidor, IP, y el contexto (/pve).

La configuración varía mucho dependiendo si tenemos Prometheus standalone, en Kubernetes con o sin operator, o Cloud.

Este es el ejemplo para configurarlo a través de Kubernetes de Operator el cuál acepta configuraciones a partir de la label release: kube-prom.

apiVersion: monitoring.coreos.com/v1alpha1
kind: ScrapeConfig
metadata:
name: proxmox
namespace: monitoring-system
labels:
release: kube-prom
spec:
staticConfigs:
- labels:
job: proxmox
targets:
- servername.domain.intranet:9221
metricsPath: /pve

Tras unos minutos, Prometheus leerá la configuración y mostrará los datos de Proxmox.

Grafana

Simplemente importar el [dashboard] oficial desde su web o desde su Id: 10347.

Métricas de temperatura

Tener la temperatura del sistema en la UI es práctico, pero no se almacena, lo que no nos permite tener un mejor control sobre ello. Debido a que Proxmox no tiene en consideración la temperatura, ninguno de los exportadores dispone de esta información.

Para ello hay 2 opciones:

  • Modificar el prometheus exporter para añadir este dato, con el peligro de perderlo a cada actualización.
  • Crear un exportador únicamente para ello.

En mi caso he optado por la segunda opción, creando un repositorio que dispone de todos los ficheros e instrucciones.

perill

Tal como se indica en el repositorio, el exportador está diseñado para reconocer los datos de temperatura de CPU y SSD en un formato y textos concretos. Ya que cada sensor es un mundo, este debe ser ajustado según los datos que nos indique.

Instalación

tip

Este exportador requiere las mismas dependencias utilizadas para la temperatura en UI y reutiliza el usuario en Linux creado para el Prometheus exporter.

Descargar el fichero y ajustar el método de extracción del sensor si es necesario. Este debe ser creado en:

/opt/temperature-metrics/metrics.py

Crear el fichero de arranque e iniciar el servicio.

cat <<EOF> /etc/systemd/system/temperature-metrics.service
[Unit]
Description=Temperature metrics for Proxmox VE
Documentation=https:/www.moon.cat

[Service]
Restart=always
User=pve-exporter
ExecStart=python3 /opt/temperature-metrics/metrics.py --node_name servername --port 9222

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable temperature-metrics
systemctl start temperature-metrics
warning

Cambiar el servername por el nombre del nodo para identificar quien es quien en caso de tener varios nodos. También he ajustado el puerto para utilizar el siguiente al de Prometheus Exporter.

Comprobar que los datos son correctos.

http://servername.domain.intranet:9222/metrics

Prometheus

Igual que en el Prometheus Exporter, la forma de configurarlo es mediante Scrape Config.

Este ejemplo sigue los mismos requisitos que el anterior, no siendo necesario indicar el contexto ya que Prometheus busca /metrics por defecto.

cat <<EOF | kubectl apply -f -
apiVersion: monitoring.coreos.com/v1alpha1
kind: ScrapeConfig
metadata:
name: proxmox-temperature
namespace: monitoring-system
labels:
release: kube-prom
spec:
staticConfigs:
- labels:
job: proxmox-temperature
targets:
- servername.domain.intranet:9222
EOF

Grafana

Similar a Prometheus, dependiendo del tipo de instalación de Grafana que tengamos, importar un dashboard es diferente.

Si Grafana funciona mediante operator y acepta aquellos con el label dashboards: "grafana", simplemente aplicar con el siguiente comando:

kubectl apply -f https://gitlab.com/ReiIzumi/proxmox-temperature-metrics/-/raw/main/grafana-dashboards-proxmox.yaml?ref_type=heads

En caso de tener un label diferente, ajustar el fichero e importar.

apiVersion: grafana.integreatly.org/v1beta1
kind: GrafanaDashboard
metadata:
name: proxmox-temperature
namespace: monitoring-system
spec:
folder: "General"
instanceSelector:
matchLabels:
dashboards: "grafana"
url: "https://gitlab.com/ReiIzumi/proxmox-temperature-metrics/-/raw/main/Proxmox-Temperature.json?ref_type=heads"
datasources:
- datasourceName: Prometheus
inputName: DS_PROMETHEUS

Grafana sin operator se configura en la instalación o se le asigna un volumen y se importa a través de la UI. Mi consejo es lanzar este tipo de instalación a la basura de donde no debería haber salido y cambiar al modo de Operator. Si aun así decides querer seguir sufriendo, puedes descargar el JSON y asignarlo a la configuración:

https://gitlab.com/ReiIzumi/proxmox-temperature-metrics/-/raw/main/Proxmox-Temperature.json?ref_type=heads
tip

No, en serio, si usas Grafana con volumen cambia ya al de operator.

Para Grafana standalone o Cloud, seguramente importar el JSON previamente indicado.