Prometheus targets mit Ansible verwalten

Prometheus bietet eine Vielzahl von integrierten Mechanismen zum Verwalten von Targets. Neben der Kubernetes Service Discovery, welche auf unseren Container Platformen zum Einsatz kommt, verwenden wir in unserer VM Umgebung u.a. die file-based Service Discovery. In diesem Blogpost möchte ich aufzeigen, wie wir diese Konfiguration mit Ansible automatisiert verwalten.

Wie in unserem letzten Blogpost über Thanos bereits erwähnt, setzen wir bei Puzzle zur Überwachung unserer Infrastruktur Prometheus ein. Ein Teil dieser Infrastruktur bilden eine Vielzahl von virtuellen Maschinen (VMs), deren OS Metriken wir über den node_exporter scrapen. Die Provisionierung dieser VMs läuft automatisiert über Ansible ab. Unser Ziel war es, neu provisionierte VMs auch automatisiert in Prometheus als Target zu registrieren.

Service Discovery

Targets können in Prometheus grundsätzlich auf zwei verschiedene Arten konfiguriert werden:

Statische Konfiguration

Hierbei werden die Targets statisch in der Konfiguration von Prometheus hinterlegt. Eine Anpassung an den Targets erfordert dadurch eine Änderung an der Prometheus Konfigurationsdatei sowie einen Reload von Prometheus.

Beispiel einer statischen target config:

scrape_configs:
  - job_name: 'node' # this is a minimal example of a job definition containing the job_name and a target configuration
    static_configs:
    - targets:
      - server1:9100
      labels:
        labelname: 'labelvalue'

Dynamische Konfiguration

Im Gegensatz zur statischen Konfiguration werden bei der dynamischen Konfiguration nicht die Targets selbst in der Prometheus Konfiguration definiert, sondern lediglich Informationen dazu, wie Prometheus die Targets „entdecken“ kann. Dieses dynamische Entdecken von Targets wird bei Prometheus als Service Discovery (SD) bezeichnet. Es stehen verschiedene SD Mechanismen für unterschiedliche Einsatzzwecke (z.B. für verschiedene Cloud Provider oder Container Platformen etc.) zur Verfügung. Für die Konfiguration unserer VMs über Ansible verwenden wir die File-based Service Discovery (file_sd_config), bei welcher Prometheus die Targets aus einer YAML oder JSON Datei ausliest. Änderungen in diesen Dateien werden sofort (ohne Reload von Prometheus) angewendet.

Die Konfigurationsdateien mit den Targets haben das folgende Format:

---
# /etc/prometheus/file_sd/example.node.yml
- targets:
  - server1:9100
  labels:
    "labelname": "labelvalue"

Die file_sd_configKonfiguration in der Prometheus Konfigurationsdatei:

scrape_configs:
  - job_name: node
    file_sd_configs:
    - files:
      - /etc/prometheus/file_sd/*.node.yml

Der Pfad zu den YAML/JSON Dateien unterstützt Filename Patterns, womit im Dateiname max. ein * als Platzhalter verwendet werden kann. Im Beispiel oben werden alle Dateien mit der Endung .node.ymlim Ordner /etc/prometheus/file_sd/ durch den job node verwendet.
Der verwendete Pfad /etc/prometheus/file_sd ist lediglich ein Beispiel und kann grundsätzlich frei definiert werden.

Beispiel Ansible Task

Mit dem Template Modul von Ansible lassen sich YAML oder auch JSON Dateien erstellen, welche dann wiederum durch die file_sd_configsin Prometheus konfiguriert werden:

#jinja2:lstrip_blocks: True
---
{{ ansible_managed | comment }}
{% for host in groups['all'] | sort %}
- targets:
    - {{ hostvars[host].inventory_hostname -}}:9100
  labels:
  {% if hostvars[host].prometheus_labels is defined %}
  {% for key, value in hostvars[host].prometheus_labels.items() %}
    {{ key }}: {{ value }}
  {% endfor %}
  {% endif %}
{% endfor %}

Das obenstehende Template generiert eine YAML Datei mit allen Hosts im jeweiligen Inventory. Zusätzlich lassen sich die Labels für jeden Host individuell setzen (z.B. über die host_vars). Weitere Anpassungen wie z.B. individuelle Ports, lassen sich ebenfalls sehr einfach implementieren.

Ablauf

  1. Ein Mergerequest mit einem neuen Server im Ansible Inventory wird gemerged.
  2. Gitlab-CI führt den ansible-playbook Befehl aus.
  3. Ansible startet das Master Playbook, welches die Konfiguration der gesamten Infrastruktur vornimmt.
  4. In einem ersten Schritt wird der neue Server über die entsprechenden cloudscale.ch Ansible Module gestartet und zusätzliche Ressourcen (z.B. volumes, floating IPs oder anti-affinity groups) konfiguriert.
  5. Als nächstes wird der Server gemäss der entsprechenden Gruppe im Ansible Inventory konfiguriert. In diesem Schritt wird zusätzlich auch der node_exporter installiert
  6. Ansible aktualisiert über das Template im Beispiel oben die YAML Datei mit den zu überwachenden Hosts. Prometheus liest die aktualisierte Datei automatisch ein und fügt den neuen Server als Target hinzu.
Kommentare sind geschlossen.