L’une de mes choses préférées à propos de QuestDB est la possibilité d’écrire des requêtes en SQL sur une base de données de séries chronologiques hautes performances. Depuis que j’utilise SQL comme langage de requête principal pendant pratiquement toute ma carrière professionnelle, il me semble naturel d’interagir avec des données en utilisant SQL au lieu d’autres langages de requête propriétaires plus récents. Combiné avec les extensions SQL personnalisées de QuestDB, son support SQL intégré facilite l’écriture de requêtes complexes.
Dans ma vie d’ingénieur cloud, je suis constamment confronté à des métriques de séries chronologiques. Malheureusement, de nombreuses bases de données de métriques populaires d’aujourd’hui ne prennent pas en charge le langage de requête SQL. Par conséquent, je suis devenu plus dépendant des tableaux de bord prédéfinis et il me faut plus de temps pour écrire mes propres requêtes avec des JOIN, des transformations et des agrégations temporelles.
QuestDB peut être un excellent choix pour ingérer des métriques d’application et d’infrastructure, il nécessite juste un peu plus de travail sur la configuration initiale que l’outil Kubernetes du jour. Malgré cet investissement de temps initial supplémentaire (qui est assez minime dans le grand schéma des choses), je pense que les avantages de l’utilisation de QuestDB pour les métriques d’infrastructure en valent la peine.
Dans cet article, je vais montrer comment nous utilisons QuestDB comme composant principal de cette nouvelle fonctionnalité. Cela devrait fournir suffisamment d’informations pour que vous puissiez également utiliser QuestDB pour ingérer, stocker et interroger les métriques d’infrastructure dans vos propres clusters.
Architecture
Prometheus est une base de données de séries chronologiques commune qui est déjà installée dans de nombreux clusters Kubernetes. Nous tirerons parti de sa fonctionnalité d’écriture à distance pour acheminer les données vers QuestDB à des fins d’interrogation et de stockage. Cependant, étant donné que l’écriture à distance Prometheus ne prend pas en charge le protocole de ligne InfluxDB (ILP) recommandé par QuestDB en tant que format de sérialisation, nous devons utiliser un proxy pour traduire les métriques au format Prometheus en messages ILP. Nous utiliserons Telegraf d’Influx Data comme composant de traduction.
Désormais, avec nos données dans QuestDB, nous pouvons utiliser SQL pour interroger nos métriques à l’aide de l’une des méthodes prises en charge : la console Web, le protocole filaire PostgreSQL ou l’API REST HTTP.
Voici un aperçu rapide de l’architecture :
Écriture à distance Prometheus
Bien que Prometheus fonctionne sur un modèle d’extraction basé sur des intervalles, il a également la capacité de transmettre des métriques à des sources distantes. Ceci est connu sous le nom de capacité « d’écriture à distance » et est facilement configurable dans un fichier YAML. Voici un exemple de configuration d’écriture à distance de base :
remoteWrite:
- url: http://default.telegraf.svc:9999/write
name: questdb-telegraf
remote_timeout: 10s
Ce YAML configurera Prometheus pour envoyer des échantillons à l’URL spécifiée avec un délai de 10 secondes. Dans ce cas, nous transmettrons nos métriques à Telegraf, avec un port et un point de terminaison personnalisés que nous pouvons spécifier dans la configuration de Telegraf (voir ci-dessous pour plus de détails). Il existe également une variété d’autres options d’écriture à distance, permettant aux utilisateurs de personnaliser les délais d’attente, les en-têtes, l’authentification et les configurations de relabing supplémentaires avant d’écrire dans le magasin de données distant. Toutes les options possibles sont disponibles sur le site Web de Prometheus.
QuestDB ILP et Telegraf
Maintenant que notre écriture à distance est configurée, nous devons configurer sa destination. L’installation de telegraf dans un cluster est simple, il suffit helm install
sa carte Helm.
Nous devons configurer telegraf pour lire à partir d’un socket Web (où Prometheus est configuré pour écrire) et l’envoyer à QuestDB pour un stockage à long terme. Dans un déploiement Kubernetes, ces options peuvent être définies dans la section config de la charte Telegraf Helm. values.yaml file
.
Configuration d’entrée
Étant donné que Telegraf recevra des métriques de Prometheus, nous devons ouvrir un port qui permet la communication entre les deux services. Telegraf dispose d’un plugin d’écoute HTTP qui lui permet d’écouter le trafic sur un port spécifié. Nous devons également configurer le chemin de l’écouteur pour qu’il corresponde à notre URL d’écriture à distance Prometheus.
L’écouteur HTTP (v2) prend en charge plusieurs formats de données à consommer via son architecture de plug-in. Une liste complète des options peut être trouvée dans la documentation Telegraf. Nous utiliserons le plugin Prometheus Remote Write Parser pour accepter nos messages Prometheus.
Voici à quoi ressemble cette configuration dans la configuration telegraf :
[[inputs.http_listener_v2]]
## Address and port to host HTTP listener on
service_address = ":9999"
## Paths to listen to.
paths = ["/write"]
## Data format to consume.
data_format = "prometheusremotewrite"
Lors de la transmission de ces valeurs au graphique Helm, vous pouvez utiliser cette yaml
spécification:
config:
inputs:
- http_listener_v2:
service_address: ":9999"
path: "/write"
data_format: prometheusremotewrite
Configuration de sortie
Nous vous recommandons d’utiliser le protocole de ligne InfluxDB (ILP) sur TCP pour insérer des données dans QuestDB. Heureusement, Telegraf inclut un plugin de sortie ILP. Mais malheureusement, ce n’est pas une solution plug-and-play. Par défaut, toutes les métriques seront écrites dans une seule mesure, prometheus_remote_write
, la clé de la métrique individuelle étant envoyée sur le réseau sous forme de champ. En pratique, cela signifie que toutes vos métriques seront écrites dans une seule table QuestDB, appelée prometheus_remote_write
. Il y aura alors une colonne supplémentaire pour chaque métrique et champ que vous capturez. Cela conduit à une grande table, avec potentiellement des milliers de colonnes, avec laquelle il est difficile de travailler et qui contient toutes les données éparses, ce qui pourrait avoir un impact négatif sur les performances.
Pour résoudre ce problème, Telegraf nous fournit un exemple de script starlark qui transforme chaque mesure de sorte que nous aurons une table par métrique dans QuestDB. Ce script s’exécutera pour chaque métrique reçue par telegraf, de sorte que la sortie sera formatée correctement.
Voici à quoi ressemble la configuration de sortie de Telegraf :
[[outputs.socket_writer]]
## Address and port to write to
address = "tcp://questdb.questdb.svc:9009"
[[processors.starlark]]
source=""'
def apply(metric):
if metric.name == "prometheus_remote_write":
for k, v in metric.fields.items():
metric.name = k
metric.fields["value"] = v
metric.fields.pop(k)
return metric
'''
Comme avantage supplémentaire de l’utilisation d’ILP avec QuestDB, nous n’avons même pas à nous soucier de l’ensemble de champs de chaque métrique. Sur ILP, QuestDB crée automatiquement des tables pour les nouvelles métriques. Il ajoute également de nouvelles colonnes pour les champs qu’il n’a jamais vus auparavant, et INSERT
s null
s pour tous les champs manquants.
Configuration de la barre
J’ai trouvé que le moyen le plus simple de configurer le values.yaml
consiste à monter le script starlark en tant que volume et à y ajouter une référence dans le fichier config. De cette façon, nous n’avons pas besoin de gérer les espaces ou d’indentation spéciale dans notre ConfigMap
spécification.
La configuration de sortie et de starlark Helm ressemblerait à ceci :
# continued from above
# config:
outputs:
- socket_writer:
address: tcp://questdb.questdb.svc:9009
processors:
- starlark:
script: /opt/telegraf/remotewrite.star
Nous devons également ajouter le volume et monter au niveau racine du values.yaml
:
volumes:
- name: starlark-script
configMap:
name: starlark-script
mountPoints:
- name: starlark-script
mountPath: /opt/telegraf
subpath: remotewrite.star
Ce volume fait référence à un ConfigMap
qui contient le script starlark de l’exemple ci-dessus :
---
apiVersion: v1
kind: ConfigMap
metadata:
name: starlark-script
data:
remotewrite.star: |
def apply(metric):
...
Interroger des métriques avec SQL
QuestDB possède de puissantes extensions SQL qui peuvent simplifier l’écriture de requêtes de séries chronologiques. Par exemple, étant donné l’ensemble standard de métriques collectées par une installation Prometheus typique, nous pouvons utiliser QuestDB non seulement pour trouver les pods avec la plus grande utilisation de mémoire dans un cluster (sur une période de 6 mois), mais également pour trouver la période spécifique lorsque l’utilisation de la mémoire a augmenté. Nous pouvons même accéder à des étiquettes personnalisées pour aider à identifier les pods avec un nom lisible par l’homme (au lieu du long nom alphanumérique attribué aux pods par les déploiements ou les ensembles avec état). Tout cela est effectué avec une syntaxe SQL simple utilisant des JOIN (améliorés par le mot-clé ASOF) et SAMPLE BY pour regrouper les données en jours avec une simple ligne de SQL :
SELECT l.label_app_kubernetes_io_custom_name, w.timestamp, max(w.value / r.value) as mem_usage
FROM container_memory_working_set_bytes AS w
ASOF JOIN kube_pod_labels AS l ON (w.pod = l.pod)
ASOF JOIN kube_pod_container_resource_limits AS r ON (
r.pod = w.pod AND
r.container = w.container
)
WHERE label_app_kubernetes_io_custom_name IS NOT NULL
AND r.resource="memory"
AND w.timestamp > '2022-06-01'
SAMPLE BY 1d
ALIGN TO CALENDAR TIME ZONE 'Europe/Berlin'
ORDER BY mem_usage DESC;
Voici un exemple de résultat de cette requête :
label_app_kubernetes_io_custom_name | horodatage | mem_usage |
---|---|---|
vif austin | 2022-07-04T16:18:00.000000Z | 0.999853875401 |
banzaï optimiste | 2022-07-12T16:18:00.000000Z | 0.9763028946 |
tassig compatissant | 2022-07-11T16:18:00.000000Z | 0.975367909527 |
grincheux qui fuit | 2022-07-11T16:18:00.000000Z | 0.974941994418 |
morse excentrique | 2022-07-05T16:18:00.00000Z | 0.95084235665 |
panini admiratif | 2022-06-21T16:18:00.000000Z | 0.925567626953 |
Ce n’est qu’une des nombreuses façons dont vous pouvez utiliser QuestDB pour écrire de puissantes requêtes de séries chronologiques que vous pouvez utiliser pour une enquête ponctuelle ou pour alimenter des tableaux de bord.
Rétention métrique
Étant donné que les bases de données stockant les métriques d’infrastructure peuvent atteindre des tailles extrêmes au fil du temps, il est important d’appliquer une période de rétention pour libérer de l’espace en supprimant les anciennes métriques. Même si QuestDB ne prend pas en charge le traditionnel DELETE
commande SQL, vous pouvez toujours implémenter la rétention des métriques à l’aide de la commande DROP PARTITION
…