Existe uma grande vítima de chutes e ajustes insanos de “thresholds” no mundo do monitoramento: o “load averages”, ou simplesmente “load”, para os mais íntimos. E os chutes em seus valores para “warning” e “critical” começam a aparecer exatamente pelo motivo menos desejado: a falta de entendimento sobre o que é e o que representam esses valores.
Os loads são apresentados em três valores distintos, porém correlatos: um representando a média do último minuto, outro a de cinco e outro a de quinze. E essa apresentação (em três valores) tem um motivo de ser: observar a tendência, algo normalmente ignorado no monitoramento.
A primeira confusão com os loads surge no entendimento empírico equivocado de que ele representa uso de recursos, mas não é bem assim. O load é calculado a partir do tempo que processos “seguram” a fila, algo que reflete o consumo. Loads altos costumam, sim, representar problemas… mas esses problemas são geralmente decorrentes de configurações equivocadas que impactam no aproveitamento inadequado dos recursos de hardware.
A falta de um entendimento adequado sobre o que os load averages representam acaba exigindo ajustes cegos de thresholds acompanhados do péssimo argumento “é assim mesmo” ou “esse servidor trabalha muito”. Tende-se a acreditar que um servidor com loads altos está trabalhando acima do esperado quando, na verdade, está trabalhando de forma inadequada, pois processos estão “segurando” a fila.
Monitorar load averages exige a observação do estado atual, da tendência (se está aumentando ou diminuindo) e picos. O estado atual e os picos podem ser diretamente observados no primeiro valor exibido, o da média do último minuto. Os outros demais valores (cinco e quinze minutos) permitem observar a tendência e devem ser considerados para comparação entre si e o último minuto. Julgar separadamente valores que representam a mesma coisa é, infelizmente, um erro muito comum.
Outro erro recorrente é o ajuste de thresholds “prevendo” uma normalidade operacional, removendo a objetividade desses indicadores e tornando-os cada vez mais subjetivos ao passo que os thresholds vão passando por novos ajustes ao longo do tempo sem qualquer lógica envolvida. Esses thresholds devem ser objetivos e estáticos, pois representam a situação do servidor e seus serviços, não uma normalidade operacional.
Idealmente, o load não deve ser superior a 1 (um) para cada núcleo de processamento disponível, mas deve-se considerar picos. E considerar picos envolve a alteração do “nível” do alarme. Se o load aumenta, o nível sobe. Mas se a tendência é a normalização (ou diminuição), o nível também deve seguir essa tendência.
Para ilustrar melhor, vamos seguir com exemplos. Supondo que um determinado servidor possua 4 núcleos, definimos o limite de OK para 4 (4,00, 4,00, 4,00). A partir disso, vamos trabalhar com multiplicadores, onde 1, 1.5 e 2 tendem a representar bem valores para um monitoramento “saudável”. Podemos, então, seguir com uma fórmula (onde X é o número de núcleos disponíveis e Y o valor representando o load):
- 1 minuto: WARNING para Y>X*1.5; CRITICAL para Y>X*2;
- 5 minutos: WARNING para Y>X; CRITICAL para Y>X*1.5;
- 15 minutos: WARNING para Y>X; CRITICAL para Y>X*1.5.
Observe que para 1 minuto consideramos multiplicadores maiores. Dessa forma consideramos picos e evitamos alarmes falsos, já que devemos, ainda, considerar a tendência comparando 1, 5 e 15 minutos.
Utilizando a fórmula acima, vamos analisar, então, algumas situações (considerando 4 núcleos):
- load: 4,00, 4,00, 4,00 — situação limite, até aqui o monitoramento deve retornar OK
- load: 7,00, 5,00, 4,00 — WARNING para 1 e 5 minutos com tendência a aumento
- load: 9,00, 5,50, 4,50 — CRITICAL para 1 e WARNING para 5 minutos com tendência a aumento
- load: 5,00, 7,00, 5,50 — WARNING para 1 e CRITICAL para 5 minutos com tendência a redução
- load: 4,00, 6,50, 8,00 — OK para 1, CRITICAL para 5 e CRITICAL para 15 minutos com tendência a redução
Veja que não faz sentido os dois últimos casos serem julgados críticos (CRITICAL) já que a tendência é a de queda do load. Nesses casos faz sentido a redução do nível do alarme para cada diminuição considerando a sequência 15, 5 e 1 minutos. O retorno, então, seria OK, já que a tendência é a de normalizar a situação.
Poderíamos, então (considerando representação por load_1, load_5 e load_15), dizer o seguinte:
- em CRITICAL: se load_5 < load_15, julga-se WARNING, e, se load_1 < load_5, julga-se OK
- em CRITICAL: se load_5 < load_15 e load_1 > load_5, continuamos a considerar WARNING
Considerando, então, que threshold de load não deve ser variável, mas que o nível do alarme deve ser, teremos maior sanidade no monitoramento, “forçaremos” equipes de infraestrutura e sistemas a adequarem as configurações, garantiremos o melhor uso possível dos recursos de hardware disponíveis, evitaremos falso-positivos e não perderemos alarmes que representam possíveis problemas.
Utilizando os conceitos acima expostos, então, podemos ter (em C, por exemplo) um check_load (para Nagios) mais são, conforme segue:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int main()
{
double load[3];
char *status=”OK”;
float warn[3], crit[3], ec=0;
int cores=sysconf(_SC_NPROCESSORS_ONLN);
getloadavg(load,3);
warn[0]=cores*1.5; crit[0]=cores*2; warn[1]=cores; crit[1]=cores*1.5; warn[2]=cores; crit[2]=cores*1.5;
if (load[0] > warn[0]) ec=1; if (load[1] > warn[1]) ec=1; if (load[2] > warn[2]) ec=1;
if (load[0] > crit[0]) ec=2; if (load[1] > crit[1]) ec=2; if (load[2] > crit[2]) ec=2;
if (ec != 0 && load[1] < load[2]) ec–; if (ec != 0 && load[0] < load[1]) ec–;
if (ec == 1) status=”WARNING”; if (ec == 2) status=”CRITICAL”;
printf(“%s – load average: %.2f, %.2f, %.2f|load1=%.3f;%.3f;%.3f;0; load5=%.3f;%.3f;%.3f;0; load15=%.3f;%.3f;%.3f;0;\n”, status, load[0], load[1], load[2], load[0], warn[0], crit[0], load[1], warn[1], crit[1], load[2], warn[2], crit[2]);
return ec;
}
Observe as três linhas em negrito. Na primeira coletamos a quantidade de processadores (núcleos, na verdade) online. Na segunda aplicamos os multiplicadores 1, 1.5 e 2, valores considerados razoáveis para nos mostrar “fugas” da normalidade. E na terceira fazemos a redução do nível de alarme conforme tendência de queda do load.
Se pudermos padronizar o check_load, eliminando variações de thresholds, e, mantivermos essa sanidade lógica, tenderemos a aproveitar melhor os recursos de hardware disponíveis, eliminando a necessidade de crescimento de infraestrutura pelo mau aproveitamento decorrente especialmente de falhas de configurações.