Trick 42 mit dem Director – Jobs in Reihenfolge

Nachdem wir unseren Trick 17 mit dem Director veröffentlichten, schiebe ich Trick 42 direkt hinterher. Wie im Blogpost von Markus beschrieben, sind Schnittmengen aus mehreren Importquellen eine geniale Lösung um beispielsweise Hosts aus mehreren Quellen mit Informationen anzureichern. Konfiguriert man nun eine Vielzahl solcher Importquellen die für die Schnittmenge dienen sollen, bekommt man evtl. im Ablauf gewisse Probleme mit der Reihenfolge.

Zur genauen Erklärung unser Ausgangsszenario:

  • CMDB 1: Quelle für die Basisdaten des Hosts (Name, IP, FQDN, …)
  • CMDB 2: Quelle für den OS-Type (CentOS, OpenSuSE, Debian, …)
  • CMDB 3: Quelle für den Ansprechpartner (Hr. Müller, Hr. Maier, …)

Damit die Hosts aus CMDB 1 angereichert erstellt (Import + Sync) werden können müssen zuerst CMDB 2 und CMDB 3 abgearbeitet werden. Logisch – wenn der OS-Type und der Ansprechpartner des Hosts dem Director nicht bekannt sind wird es mit Hilfe von Trick 17 auch nicht möglich sein den Host aus CMDB 1 mit Daten anzureichern.

Hauptsächlich fällt dieses Problem beim initialen Import + Sync der Daten auf. Je nachdem wie oft sich eure Importquellen ändern kann dies “gar nicht schlimm” (Hr. Müller ist für den Server 3 Jahre zuständig) oder auch “sehr unglücklich” (Ihr importiert die Kontaktdaten einer ständig wechselnden Rufbereitschaft) sein.

Für den Fall das die Reihenfolge der Importquellen wichtig ist gibt es eine denkbar simple Lösung.

Ihr legt für jeden Import und Sync einen Job im Director an…

 

…und notiert euch jeweils die ID des Director Jobs (die Zahl an der letzten Stelle der URL).

Mit Hilfe dieser ID könnt ihr nun die im Director konfigurierten Jobs von der Kommandozeile aus ausführen. Der Job mit der ID 1 (Import Job für CMDB1) kann mit dem Kommando “icingacli director jobs run 1” gestartet werden.

Am Ende bauen wir uns dazu noch ein kleines Skript:

#!/bin/bash

# set paths and vars
ICINGA_CLI=`which icingacli`
JOB_CMD=${ICINGA_CLI}" director jobs run"

# execute jobs
echo "import and sync..."

echo -e "\tcmdb1"
${JOB_CMD} 1
${JOB_CMD} 2

echo -e "\tcmdb2";
${JOB_CMD} 3
${JOB_CMD} 4

echo -e "\tcmdb3";
${JOB_CMD} 5
${JOB_CMD} 6

Und voilà – wir haben die Imports und Syncs in einer Reihenfolge 🙂

Tobias Redel

Autor: Tobias Redel

Tobias hat nach seiner Ausbildung als Fachinformatiker bei der Deutschen Telekom bei T-Systems gearbeitet. Seit August 2008 ist er bei NETWAYS, wo er in der Consulting-Truppe unsere Kunden in Sachen Open Source, Monitoring und Systems Management unterstützt. Insgeheim führt er jedoch ein Doppelleben als Travel-Hacker, arbeitet an seiner dritten Millionen Euro (aus den ersten beiden ist nix geworden) und versucht die Weltherrschaft an sich zu reißen.

Benchmarking Graphite

Before using Graphite in production, you should be aware of how much load it can handle. There is nothing worse than finding out your carefully planned and build setup is not good enough. If you are already using Graphite, you might want to know the facts of your current setup. Knowing the limits of a setup helps you to react on future requirements. Benchmarking is essential if you really want to know how many metrics you can send and how many requests you can make. To find this out, there are some tools out there that help you to run benchmarks.

Requirements

The most important thing you need when starting to benchmark Graphite is time. A typical Graphite stack has 3 – 4 different components. You need plenty of time to properly find out how much load each of them can handle and even more to decide which settings you may want to tweak.

Haggar

Haggar is a tool to simulate plenty of agents that send generated metrics to the receiving endpoint of a Graphite stack (carbon-cache, carbon-relay, go-carbon, etc…). The amount of agents and metrics is configurable, as well as the intervals. Even though Haggar does not consume much resources, you should start it on a separate machine.

Haggar is written in go and installed with the go get command. Ensure that Go (>= v1.8) is installed and working before installing Haggar.

Installing Haggar

go get github.com/gorsuch/haggar

You’ll find the binary in your GOPATH that you have set during the installation of Go previously.

Running Haggar:

$GOPATH/bin/haggar -agents=100 -carbon=graphite-server.example.com:2003 -flush-interval=10s -metrics=1000

Each agent will send 1000 metrics every 10 seconds to graphite-server.example.com on port 2003. The metrics are prefixed with haggar. by default. The more agents and metrics you send, the more write operations your Graphite server will perform.

Example output of Haggar:

root@graphite-server:/opt/graphite# /root/go/bin/haggar -agents=100 -carbon=graphite-server.example.com:2003 -flush-interval=10s -metrics=1000
2017/09/21 09:33:30 master: pid 16253
2017/09/21 09:33:30 agent 0: launched
2017/09/21 09:33:42 agent 1: launched
2017/09/21 09:33:46 agent 2: launched
2017/09/21 09:34:00 agent 0: flushed 1000 metrics
2017/09/21 09:34:02 agent 1: flushed 1000 metrics
2017/09/21 09:34:06 agent 2: flushed 1000 metrics

Testing the write performance is a good starting point, but it’s not the whole truth. In a production environment data is not only written but also read. For example by users staring at dashboards all day long. So reading the data is as much important as writing it because it also produces load on a server. This is where JMeter comes into play.

JMeter

Apache JMeter usually is used to test the performance of web applications. It has many options to simulate requests against a web server. JMeter can also be used to simulate requests against Graphite-Web. You should do this simultaneously while Haggar is sending data, so you have the “complete” simulation.

The easiest way to configure JMeter is the graphical interface. Running test plans is recommended on the command line, though. Here’s an example how I set up JMeter to run requests against Graphite-Web:

  • Add a Thread Group to the Test Plan
    • Set the Number of Threads (eg. 5)
    • Set the loop count to Forever
  • Add a Random Variable to the Thread Group
    • Name the variable metric
    • Set the minimum to 1
    • Set the maximum to 1000
    • Set `Per Thread` to true
  • Add another Random Variable to the Thread Group
    • Name the variable agent
    • Set the minimum to 1
    • Set the maximum to 100
    • Set Per Thread to true

Haggar uses numbers to name it’s metrics. With these variables we can create dynamic requests.

  • Add a HTTP Request Defaults to the Thread Group
    • Set the server name or IP where your Graphite-Web is running (eg. graphite-server.example.com)
    • Add the path /render to access the rendering API of Graphite-Web
    • Add some parameters to the URL, examples:
      • width: 586
      • height: 308
      • from: -30min
      • format: png
      • target: haggar.agent.${agent}.metrics.${metric}

The most important part about the request defaults is the target parameter.

  • Add a HTTP Request to the Thread Group
    • Set the request method to GET
    • Set the request path to /render
  • Add a View Results in Table to the Thread Group

The results table shows details of each request. On the bottom there is an overview of the count of all samples, the average time and deviation. Optionally you can also add a Constant Throughput Timer to the Thread Group to limit the requests per minute.

If everything is working fine, you can now start the test plan and it should fire lots of requests against your Graphite-Web. For verification, you should also look into the access logs, just to make sure.

At this point your Graphite server is being hit by Haggar and JMeter at the same time. Change the settings to find out at which point your server goes down.

Interpretation

Obviously, killing your Graphite server is not the point of running benchmarks. What you actually want to know is, how each component behaves with certain amounts of load. The good thing is, every Graphite component writes metrics about itself. This way you get insights about how many queries are running, how the cache is behaving and many more.

I usually create separate dashboards to get the information. For general information, I use collectd to monitor the following data:

  • Load, CPU, Processes, I/O Bytes, Disk Time, I/O Operations, Pending I/O Operations, Memory

The other dashboards depend on the components I am using. For carbon-cache the following metrics are very interesting:

  • Metrics Received, Cache Queues, Cache Size, Update Operations, Points per Update, Average Update Time, Queries, Creates, Dropped Creates, CPU Usage, Memory Usage

For carbon-relay you need to monitor at least the following graphs:

  • Metrics Received, Metrics Send, Max Queue Length, Attempted Relays, CPU Usage, Memory Usage

All other Graphite alternatives like go-carbon or carbon-c-relay also write metrics about themselves. If you are using them instead of the default Graphite stack, you can create dashboards for them as well.

Observing the behaviour during a benchmark is the most crucial part of it. It is important to let the benchmark do its thing for a while before starting to draw conclusions. Most of the tests will peak at the start and then calm after a while. That’s why you need a lot of time when benchmarking Graphite, every test you make will take its own time.

Performance Tweaks

Most setups can be tuned to handle more metrics than usual. This performance gain usually comes with a loss of data integrity. To increase the number of handled metrics per minute the amount of I/Ops must be reduced.

This can be done by forcing the writer (eg. carbon-cache) to keep more metrics in the memory and write many data points per whisper update operation. With the default carbon-cache this can be achieved by setting MAX_UPDATES_PER_SECOND to a lower value than the possible I/Ops of the server. Another approach is to let the kernel handle caching and allow it to combine write operations. The following settings define the behaviour of the kernel regarding dirty memory ratio.

  • vm.dirty_ratio (eg. 80)
  • vm.dirty_background_ratio (eg. 50)
  • vm.diry_expire_centisecs (eg. 60000)

Increasing the default values will lead to more data points in the memory and multiple data points per write operation.

The downside of these techniques is that data will be lost on hardware failure. Also, stopping or restarting the daemon(s) will take much longer, since all the data needs to be flushed to disk first.

Blerim Sheqa

Autor: Blerim Sheqa

Blerim ist seit 2013 bei NETWAYS und seitdem schon viel in der Firma rum gekommen. Neben dem Support und diversen internen Projekten hat er auch im Team Infrastruktur tatkräftig mitgewirkt. Hin und wieder lässt er sich auch den ein oder anderen Consulting Termin nicht entgehen. Mittlerweile kümmert sich Blerim hauptsächlich im Icinga Umfeld um die technischen Partner und deren Integrationen in Verbindung mit Icinga 2.

Trick 17 mit dem Director

Möchte man die Schnittmenge aus mehreren Importquellen im Icinga Director vereinen, so gibt es dafür einen Lösungsweg der bislang vielen noch nicht bekannt ist.

Beispielhaft dienen folgende zwei SQL-Tabellen als Ausgangslage, testhost03 ist dabei nur in der Tabelle “hosts01” enthalten:

MariaDB [cmdb]> SELECT * FROM cmdb.hosts01;
+----+------------+----------+---------+
| id | hostname   | address  | os      |
+----+------------+----------+---------+
|  1 | testhost01 | 10.0.0.1 | Windows |
|  2 | testhost02 | 10.0.0.2 | Linux   |
|  3 | testhost03 | 10.0.0.3 | Windows |
+----+------------+----------+---------+

MariaDB [cmdb]> SELECT * FROM cmdb.hosts02;
+----+------------+----------+---------+
| id | hostname   | address  | os      |
+----+------------+----------+---------+
|  1 | testhost01 | 10.0.0.1 | Windows |
|  2 | testhost02 | 10.0.0.2 | Linux   |
+----+------------+----------+---------+

Um nun die Daten aus beiden Quellen abzugleichen ohne gleich Objekte im Director zu erzeugen, behilft man sich mit einer Datenliste als Zwischenschritt. Die ID der neu erstellten Datenliste wird später benötigt und kann über die Director-Datenbank herausgefunden werden:

MariaDB [director]> SELECT * FROM director.director_datalist WHERE list_name = "Hosts from 2nd import source";
+----+------------------------------+-------------+
| id | list_name                    | owner       |
+----+------------------------------+-------------+
|  2 | Hosts from 2nd import source | icingaadmin |
+----+------------------------------+-------------+

Wie dem Namen der Liste unschwer zu entnehmen ist sollen dort die Hosts aus der 2ten Importquelle, also von “hosts02”, zwischengespeichert werden.

Mit diesen Informationen kann die entsprechende Sync Rule für die Synchronisation der Hosts aus der 2ten Quelle in die Datenliste erstellt werden. Neben der ID als jeweilige “list_id” (hier “2”) werden die Felder “entry_name” und “entry_value” definiert:

Nach dem Syncvorgang erhält die Datenliste die entsprechenden Einträge. Im Beispiel sind das testhost01 und testhost02. In der Import Source für die erste Datenquelle werden deren Einträge nun anhand des “Map”-Modifiers mit den Einträgen aus der Datenliste abgeglichen:

Damit ergibt sich folgende Vorschau der Import Source:

In der darauf aufbauenden Sync Rule ist es wichtig eine entsprechende Filter expression zu setzen:

Ist sie negiert, wie im vorangegangenen Beispiel, werden die Hosts die in beiden Datenquellen vorkommen erzeugt. Im Beispiel wären das testhost01 und testhost02. Liegt keine Negierung vor (z.B. “map=”), so werden nur die Hosts erzeugt die in der zweiten Datenquelle nicht vorkommen. Also beispielhaft testhost03. Damit der Filter greift, muss der Bezeichner (hier “map”) allerdings auch als Eigenschaft der Sync Rule vorkommen.

Der Icinga Director hält noch wesentlich mehr Funktionen für verschiedenste Anwendungsbereiche bereit. Das vorangegangene Beispiel dient lediglich dazu die Fähigkeiten dieses mächtigen Tools etwas zu veranschaulichen. Bei weiteren Fragen rund um den Director oder auch Icinga 2 stehen wir bei NETWAYS natürlich gerne zur Verfügung.

Markus Waldmüller

Autor: Markus Waldmüller

Markus war bereits mehrere Jahre als Systemadministrator in Neumarkt i.d.OPf. und Regensburg tätig. Nach Technikerschule und Selbständigkeit ist er nun Anfang 2013 bei NETWAYS als Lead Senior Consultant gelandet. In seiner Freizeit ist der sportbegeisterte Neumarkter mit an Sicherheit grenzender Wahrscheinlichkeit auf dem Mountainbike oder am Baggersee zu finden.

Monthly Snap August > GitHub, Icinga 2, OSBConf, OSMC, Mac, Cloud Management, SSH, Braintower, Foreman

In August, Johannes Meyer began with an overview of some future Github topics and Lennart continued with part 6 of Icinga 2 Best Practice.
Julia said thank you to our OSBConf Sponsors, while Georg wrote not one, not two, but three articles on simplifying SSL certificates!
Then Alex shared his happiness to be a Mac user now and Dirk reviewed the Foreman Birthday Bash!
On events, Julia announced the program for the Open Source Monitoring Conference, continued with the second reason to join the OSBConf and started the OSMC blog series “Stay tuned!”.
Later in August, Isabel presented the ConiuGo Modem and showed the advantages of the Braintower SMS Gateway.
Towards the end of August, Enrico started a blog series on Cloud Management and Gunnar told us about SSH authentication with GnuPG and smart cards.

Julia Hackbarth

Autor: Julia Hackbarth

Julia hat 2017 ihre Ausbildung zum Office Manager bei NETWAYS absolviert und währenddessen das Events&Marketing Team kennen und lieben gelernt. Besondere Freude bereiten ihr bei NETWAYS die tolle Teamarbeit und vielseitige Herausforderungen. Privat nutzt Julia ihre freie Zeit, um so oft wie möglich über's Handballfeld zu flitzen und sich auszutoben. In ihrer neuen Rolle als Marketing Managerin freut sie sich auf spannende Aufgaben und hofft, dass ihr die Ideen für kreative Texte nicht so schnell ausgehen.

Versteckte Perlen in Icinga Web 2

In Icinga Web 2 gibt es ein paar versteckte Parameter, die leider noch nicht dokumentiert sind aber sicher hier und da hilfreich sein können.

Entwicklermodus für JavaScript und CSS

Icinga Web 2 liefert eigentlich JavaScript und CSS komprimiert an den Client aus. Als Entwickler oder zur Fehlersuche ist aber hilfreich, die Kandidaten in ihrer Originalform auszuliefern. Dazu hängt man den Parameter _dev=1 an die URL.

Listen und Detail-Informationen exportieren

Die Listen zur Ansicht der Hosts, Services und Gruppen und der jeweiligen Detail-Bereiche lassen sich nach JSON und CSV exportieren. Dazu hängt man den format Parameter mit entweder json oder csv als Wert an, also z.B. icingaweb2/monitoring/list/services?format=json.

Vollbildmodus

Um eine Sicht in Icinga Web 2 in den Vollbildmodus zu bringen, hängt man einfach die zwei Parameter showCompact=1 und showFullscreen=1 an die URL. showCompact blendet die Kontrollelemente wie den Filter-Editor und Paginator aus und showFullscreen das Menü und den Header. Das ganz sieht dann so aus:

Eric Lippmann

Autor: Eric Lippmann

Eric kam während seines ersten Lehrjahres zu NETWAYS und hat seine Ausbildung bereits 2011 sehr erfolgreich abgeschlossen. Seit Beginn arbeitet er in der Softwareentwicklung und dort an den unterschiedlichen NETWAYS Open Source Lösungen, insbesondere inGraph und im Icinga Team an Icinga Web. Darüber hinaus zeichnet er sich für viele Kundenentwicklungen in der Finanz- und Automobilbranche verantwortlich.

Icinga 2 – Monitoring automatisiert mit Puppet Teil 7: Objekte aus Hiera erzeugen

This entry is part 7 of 7 in the series Icinga 2 Monitoring automatisiert mit Puppet

Vor einiger Zeit trat der Wunsch auf mit dem aktuellen Icinga-2-Modul für Puppet beliebe Objekte aus Hiera heraus zu erzeugen. Zum Beispiel aus folgender Hiera-Datei sollen ein Host-Objekt und zwei Service-Objekte gebaut werden.

---
monitoring::object:
  'icinga2::object::host':
    centos7.localdomain:
      address: 127.0.0.1
      vars:
        os: Linux
  'icinga2::object::service':
    ping4:
      check_command: ping4
      apply: true
      assign: 
        - host.address
    ssh:
      check_command: ssh
      apply: true
      assign:
        - host.address && host.vars.os == Linux

In Puppet 4 lässt sich dies nun sehr einfach mit zwei Schleifen realisieren:

class { 'icinga2':
  manage_repo => true,
}

$default = lookup('monitoring::default')

lookup('monitoring::object').each |String $object_type, Hash $content| {
  $content.each |String $object_name, Hash $object_config| {
    ensure_resource(
      $object_type,
      $object_name,
      deep_merge($default[$type], $object_config))
  }
}

Hierbei sind sogar für jeden Objekt-Type auch noch Defaults in Hiera gesetzt, z.B. in einer Datei common.yaml, die immer gelesen wird.

---
monitoring::default:
  'icinga2::object::host':
    import:
      - generic-host
    target: /etc/icinga2/conf.d/hosts.conf
  'icinga2::object::service':
    import:
      - generic-service
    target: /etc/icinga2/conf.d/services.conf

Dieses Verfahren ist mit dem selben Code auf Objekte mit allen möglichen Objekt-Typen erweiterbar. Passt man den Funktionsaufruf von lookup entsprechend an, kann auch über die Hiera-Struktur gemerged werden.

Lennart Betz

Autor: Lennart Betz

Der diplomierte Mathematiker arbeitet bei NETWAYS im Bereich Consulting und bereichert seine Kunden mit seinem Wissen zu Icinga, Nagios und anderen Open Source Administrationstools. Im Büro erleuchtet Lennart seine Kollegen mit fundierten geschichtlichen Vorträgen die seinesgleichen suchen.