Oct 15, 2021
9 min de lectura
Carlos M.
Cloudprober es un software que se utiliza para monitorear la disponibilidad y el rendimiento de varios componentes del sistema. Aquí en Hostinger, lo usamos para monitorear el tiempo de carga de los sitios web de nuestros clientes. Inicialmente, comenzó como la aplicación gratuita de código abierto de Google, que se inició para ayudar a los clientes a monitorear sus proyectos o infraestructuras.
La tarea principal de Cloudprober es ejecutar sondeos, que están destinados a sondear protocolos como HTTP, Ping, UDP, DNS para verificar que los sistemas funcionen como se espera desde el punto de vista de los clientes. Incluso es posible tener una sonda personalizada específica (por ejemplo, Redis o MySQL) a través de una API de sonda externa. Hostinger se centra en la sonda HTTP.
Cada sonda se define como la combinación de estos ajustes particulares:
Los Surfacers son mecanismos integrados diseñados para exportar datos a múltiples sistemas de monitoreo. Se pueden configurar varios Surfacers al mismo tiempo. Cloudprober tiene como objetivo principal ejecutar sondeos y crear métricas utilizables estándar basadas en los resultados de esos sondeos. Por lo tanto, proporciona una interfaz fácil de usar que hace que los datos de la sonda estén disponibles para los sistemas que ofrecen formas de consumir datos de monitoreo.
Actualmente, Cloudprober admite los siguientes tipos de aparejos: Stackdriver (Google Cloud Monitoring), Prometheus, Cloudwatch (AWS Cloud Monitoring), Google Pub / Sub, File y Postgres.
Los validadores de Cloudprober permiten ejecutar comprobaciones en las salidas de la solicitud de la sonda, si las hay. Se puede configurar más de un validador, pero todos deben tener éxito para que la sonda se marque como exitosa.
El validador Regex es el más común y funciona para la mayoría de los tipos de sonda. Cuando carga el sitio y espera que haya una cadena dentro, el Validador de expresiones regulares lo ayuda a hacerlo dinámico.
El validador HTTP, que solo es aplicable para un tipo de sonda HTTP, ayuda a verificar el encabezado (éxito/error) y el código de estado (éxito/error).
Por último, el validador de integridad de datos se utiliza principalmente para UDP o PINGS cuando esperamos datos en algún patrón repetitivo (por ejemplo, 1,2,3,1,2,3,1,2,3 en la carga útil).
Como es un software basado en la nube, Cloudprober tiene soporte para el descubrimiento automático de objetivos. Se considera una de las características más críticas en los entornos dinámicos de hoy, ya que con ella, Cloudprober puede tocar datos de Kubernetes, Google Cloud Engine, AWS EC2, descubrimiento de archivos y más. Si eso no es suficiente, también tiene un servicio de descubrimiento interno, para que puedas integrar otros descubrimientos en tu infraestructura.
La idea central detrás del descubrimiento de objetivos de Clouprober es utilizar una fuente independiente para aclarar los objetivos que se supone deben ser monitoreados. Puede encontrar más información sobre las características destacadas del descubrimiento de objetivos de Cloudprober aquí.
En octubre de 2020, Hostinger estaba buscando un sistema de monitoreo externo para recopilar estadísticas de tiempo de actividad y velocidad de todos los sitios web de los usuarios. Consul (sitio web Blackbox cónsul) fue considerado como una de las principales alternativas para monitorear sitios. Sin embargo, Cloudprober parecía una opción liviana y prometedora que se integraba con Stackdriver, lo que le permitía almacenar registros fácilmente, no tenía restricciones de rendimiento y el equipo de datos podía acceder a ella sin requisitos adicionales.
Se han distinguido numerosos factores que explican por qué hemos elegido Cloudprober como alternativa preferida:
Las pruebas de Cloudprober fueron un proceso continuo en Hostinger. Para decidir si Cloudprober se ajusta a nuestras necesidades, verificamos la fidelidad de la métrica y los posibles escenarios de instalación/configuración para nuestra escala.
Intentamos cambiar el código de Cloudprober para agregar un control de concurrencia básico. Se intentaron diferentes patrones para mantener una carga moderada durante la medición de latencia: una concurrencia de 5+5 (HTTP + HTTPS). En servidores muy cargados, tomó aproximadamente 30 minutos rastrear alrededor de 3900 sitios HTTPS y aproximadamente 70 minutos para hacer lo mismo con alrededor de 7100 sitios HTTP.
El principal desafío que reconocimos fue la extensión de la sonda: Cloudprober espera un intervalo de verificación configurado e inicia todas las sondas al mismo tiempo. No lo vimos como un gran problema para Cloudprober en sí, ya que Consul, Prometheus y Blackbox Exporter comparten la misma función, pero esto puede tener un impacto en todo el servidor de hosting.
Más tarde, Cloudprober se lanzó en aproximadamente 1,8 millones de sitios, y descubrimos que una instancia de GCP con 8 núcleos y 32GiB o RAM puede manejarlo bien (60% de CPU inactiva).
Aquí en Hostinger, las métricas HTTP se envían a PostgreSQL (técnicamente, CloudSQL en GCP). Se utiliza el filtrado de métricas y las métricas internas de Cloudprober se exportan al aparejo de Prometheus. Para verificar si los sitios están realmente alojados con nosotros, enviamos un encabezado específico a cada sitio y esperamos otra respuesta de encabezado.
Inicialmente, pensamos que usaríamos un aparejo Prometheus. Sin embargo, toda la métrica recopilada tenía un tamaño de alrededor de 1 GB. Esto fue demasiado para nuestro sistema Prometheus + M3DB. Si bien es posible hacerlo funcionar, no vale la pena. Por lo tanto, decidimos seguir adelante con PostgreSQL. También evaluamos Stackdriver, pero PostgreSQL se ajustaba mejor a nuestras herramientas y propósitos.
De forma predeterminada, el aparejador de Cloudprober PostgreSQL espera este tipo de tabla:
CREATE TABLE metrics (
time TIMESTAMP WITH TIME ZONE,
metric_name text NOT NULL,
value DOUBLE PRECISION,
labels jsonb,
PRIMARY KEY (time, metric_name, labels)
);
Hay algunos inconvenientes con este tipo de almacenamiento:
Al principio, destrozamos todos los insertos en una tabla. PostgreSQL (y muchos otros RDMS) presenta una técnica poderosa: triggers. Otra técnica notable se llama enumeraciones y permite almacenar datos «tipo cadena» de forma compacta (4 bytes por elemento). Al combinar estos dos con particiones, resolvimos todos los inconvenientes mencionados anteriormente.
Creamos dos tipos de datos personalizados:
CREATE TYPE http_scheme AS ENUM (
'http',
'https'
);
CREATE TYPE metric_names AS ENUM (
'success',
'timeouts',
'latency',
'resp-code',
'total',
'validation_failure',
'external_ip',
'goroutines',
'hostname',
'uptime_msec',
'cpu_usage_msec',
'instance',
'instance_id',
'gc_time_msec',
'mem_stats_sys_bytes',
'instance_template',
'mallocs',
'frees',
'internal_ip',
'nic_0_ip',
'project',
'project_id',
'region',
'start_timestamp',
'version',
'machine_type',
'zone'
);
Creamos la función de inserción de datos para el trigger:
CREATE OR REPLACE FUNCTION insert_fnc()
RETURNS trigger AS
$$
BEGIN
IF new.labels->>'dst' IS NULL THEN
RETURN NULL;
END IF;
new.scheme = new.labels->>'scheme';
new.vhost = rtrim(new.labels->>'dst', '.');
new.server = new.labels->>'server';
IF new.labels ? 'code' THEN
new.code = new.labels->>'code';
END IF;
new.labels = NULL;
RETURN new;
END;
$$
LANGUAGE 'plpgsql';
Y la mesa principal:
CREATE TABLE metrics (
time TIMESTAMP WITH TIME ZONE,
metric_name metric_names NOT NULL,
scheme http_scheme NOT NULL,
vhost text NOT NULL,
server text NOT NULL,
value DOUBLE PRECISION,
labels jsonb,
code smallint
) PARTITION BY RANGE (time);
Para la creación de particiones, podemos usar el siguiente script (crea particiones para los próximos 28 días y adjunta el disparador):
DO $$ DECLARE f record; i interval := '1 day'; BEGIN FOR f IN SELECT t as int_start, t+i as int_end, to_char(t, '"y"YYYY"m"MM"d"DD') as table_name FROM generate_series (date_trunc('day', now() - interval '0 days'), now() + interval '28 days' , i) t LOOP RAISE notice 'table: % (from % to % [interval: %])', f.table_name, f.int_start, f.int_end, i; EXECUTE 'CREATE TABLE IF NOT EXISTS m_' || f.table_name || ' PARTITION OF m FOR VALUES FROM (''' || f.int_start || ''') TO (''' || f.int_end || ''')'; EXECUTE 'CREATE TRIGGER m_' || f.table_name || '_ins BEFORE INSERT ON m_' || f.table_name || ' FOR EACH ROW EXECUTE FUNCTION insert_fnc()'; END LOOP; END; $$ LANGUAGE 'plpgsql';
Actualmente estamos en el proceso de realizar un monitoreo de host automáticamente tomando todos los hosts y la información del sitio web del Cónsul y usando la plantilla de cónsul para generar la configuración dinámica.
Particionamos los datos por día para la gestión de motivos y las operaciones sin bloqueo. También usamos desencadenadores y enumeraciones de PostgreSQL para filtrar, reescribir y eliminar jsonb filas para ahorrar espacio de almacenamiento (ahorros de hasta 10 veces) y acelerar las cosas. El equipo de datos importa esos datos de PostgreSQL a BigQuery y utiliza la manipulación o modificación de datos para satisfacer nuestras necesidades.
¿Cómo se vería la configuración real? Los datos dinámicos de la plantilla de cónsul se ven en la ruta del archivo, y Cloudprober volverá a leer este archivo en 600 segundos, por lo que se filtrará un archivo con todos los objetivos que tienen etiquetas para la sonda. Además, usamos «allow_metrics_with_label» para exponer diferentes tipos de métricas a diferentes superficies. Prometheus para el propio Cloudprober y PostgreSQL para sondeos. Para ahorrar ancho de banda de la red, usamos el método HTTP HEAD. No todos nuestros clientes tienen certificados TLS actualizados, por lo que debemos omitir las verificaciones de validez para ellos.
disable_jitter: true
probe {
name: "server1.hostinger.com-HTTP"
type: HTTP
targets {
rds_targets {
resource_path: "file:///tmp/targets.textpb"
filter {
key: "labels.probe",
value: "server1.hostinger.com-HTTP"
}
}
}
http_probe {
protocol: HTTP
port: 80
resolve_first: false
relative_url: "/"
method: HEAD
interval_between_targets_msec: 1000
tls_config {
disable_cert_validation: true
}
headers: {
name: "x-some-request-header"
value: "request-value"
}
}
additional_label {
key: "server"
value: "server1.hostinger.com"
}
additional_label {
key: "scheme"
value: "http"
}
interval_msec: 57600000
timeout_msec: 10000
validator {
name: "challenge-is-valid"
http_validator {
success_header: {
name: "x-some-response-header"
value: "header-value"
}
}
}
}
surfacer {
type: PROMETHEUS
prometheus_surfacer {
metrics_buffer_size: 100000
metrics_prefix: "cloudprober_"
}
allow_metrics_with_label {
key: "ptype",
value: "sysvars",
}
}
surfacer {
type: POSTGRES
postgres_surfacer {
connection_string: "postgresql://example:password@localhost/cloudprober?sslmode=disable"
metrics_table_name: "metrics"
metrics_buffer_size: 120000
}
allow_metrics_with_label {
key: "ptype",
value: "http",
}
}
rds_server {
provider {
file_config {
file_path: "/tmp/targets.textpb"
re_eval_sec: 600
}
}
}
resource {
name: "hostinger.com."
labels {
key: "probe"
value: "server1.hostinger.com-HTTP"
}
}
Solo tenemos una solicitud pendiente para satisfacer nuestras necesidades de usar Cloudprober correctamente, y Cloudprober se ejecuta en una sola instancia de 8x 2.20GHz y 32 GiB de RAM.
Fuentes de mayor interés
¿Te interesa probarlo y explorar las posibilidades de Cloudprober? Recomendamos consultar los siguientes sitios:
Más
Deja una respuesta