OpenStack Monasca’s Webhook-Integration

2016-03-25

OpenStack Monasca’s Webhook-Integration

Machine-translated — the English original is authoritative.

### Grahams zweisecündige Geschichte von Webhooks [nicht technisch]

Nun, ich bin sicher, Sie alle wissen, was Webhooks sind, aber ich habe es erst letzten Monat erfahren, in Vorbereitung auf eine andere Helion OpenStack-Integration.

Hier ist mein vereinfachtes Verständnis davon – sie sind „Push-Benachrichtigungen“.

Mit dem Aufkommen des Internets wurden wir sehr schnell sehr clever und begannen, all diese verrückten UDP- und TCP-Protokolle für M2M-Kommunikation zu verwenden. Da die Bandbreite nie ein Problem war (ich scherze), war Effizienz nie die erste Anforderung.

Viele Überwachungslösungen entschieden sich für HTTP als das Protokoll der Wahl und pollten einfach die Ressourcen, an denen sie interessiert waren, und warteten auf eine Antwort. Monasca bietet Ihnen eine RESTful-API an, wenn Sie diesen Ansatz verwenden möchten.

Dennoch bringt die Cloud Herausforderungen im Hinblick auf die Skalierung mit sich. Und wenn Sie versuchen, Hunderttausende von Diensten in Sekunden zu pollten, sind Effizienzen sehr wichtig. Da kommen Webhooks ins Spiel, um den Tag zu retten.

Im Gegensatz zum „altmodischen“ und ineffizienten Polling, das ein HTTP GET gefolgt von einem HTTP POST erfordert, selbst wenn es nichts zu melden gibt, erfordern Webhooks ein einzelnes HTTP POST und sie werden nur ausgelöst, wenn es etwas Wertvolles gibt, über das man POSTen kann!!!

Zusammengefasst also – häufige HTTP GET/POSTs versus seltene HTTP POSTs. Es gibt einen städtischen Mythos im Netz, dass Github die Last auf ihren Servern durch die Einführung von Webhooks um das 66-fache reduzierte, als Benutzer nach neuen Code-Änderungen suchten. [Ich habe keine Fakten dazu]

Wie richten wir sie ein – simples, besonders wenn Sie meinen vorherigen Blog-Beitrag über die SMTP-Integration gelesen haben. Lassen Sie uns zuerst das GUI-Stück machen – das alles könnte auch über die CLI gemacht werden, aber das würde erfordern, dass ich mehr lese.

Hinweis: Die Operations Console GUI ist spezifisch für die Helion OpenStack-Verteilung. Wenn Sie nicht Helion verwenden, müssen Sie die Monasca CLI verwenden.

Webhook-Konfiguration in HOS Monasca

  1. Melden Sie sich als Cloud-Admin-Benutzer bei der Helion Ops Console an
    Operations Portal

  2. Wählen Sie die Option „Notification Methods“ aus dem „Hamburger“-Menü in der oberen linken Ecke des Bildschirms.
    menu

  3. Erstellen Sie eine neue Benachrichtigungsmethode, wählen Sie Webhook und geben Sie die Details der URL ein, an die Sie Benachrichtigungen per HTTP POST senden möchten.
    createNewNotif

Und das ist alles, was es mit Webhooks auf sich hat. Aber warten Sie, „wie testen und verifizieren wir das“, höre ich Sie denken… nun, lesen Sie weiter.

Erstellen Sie einen Test-Alarm

Zurück zu unserem „Hamburger“-Menü und wählen Sie diesmal „Alarm Creation“ und erstellen Sie einen neuen Alarm wie folgt – wir wollen hier falsche Alarme – also verwende ich cpu.idle als Metrik und setze alberne Werte –
TestAlarm
Neue Alarmdefinition erstellen

Anfangs können 2 Unbekannte Alarme erscheinen, da dies das erste Mal ist, dass dieser Alarm ausgeführt wird und er keinen vorherigen Zustand hat. Seien Sie jedoch geduldig, in ein paar weiteren Minuten sollten Sie sehen, wie sich das Dashboard wie unten gezeigt aufleuchtet.
Alarm dashboard
Warten Sie ein paar Minuten (5)

Sie können nun die Alarme für mehr Details auswählen.
Alarm List
Schauen Sie sich die Alarme an
Alarm detail
Alarmdetails anzeigen

Und natürlich, worauf wir alle gewartet haben – Webhook-Alarme!!!

Doh! Wie testen wir Webhook-Alarme…

Viele unternehmensgrade Überwachungslösungen unterstützen heute noch keine Webhooks – diese Leute verstehen einfach nicht, was agil ist, und wundern sich, warum die kleineren Fische sie überholen.

Auch hier empfehle ich nicht, irgendetwas von dem, was Sie gleich sehen werden, auf Produktionssystemen durchzuführen – dies dient ausschließlich dem Testen und Verifizieren von Webhooks. Bitte beachten Sie auch, dass ich einen Port in der HOS Control-Plane-Firewall geöffnet habe, um meinen Deployer-Knoten als Webhook-Server, der auf Port 3001 läuft, verwenden zu können. [Siehen Sie sich den vorherigen SMTP-Beitrag an, wenn Sie dies IN IHREM LABOR testen möchten]

Hinweis: An alle Programmierer da draußen, ich entschuldige mich jetzt für alle Regeln, die ich breche, schlechten Code usw. Seien Sie sanft, ich habe diese Beispiele dank all Ihrer Veröffentlichungen zusammengehackt 🙂

Ich habe unten zwei Beispiel-Skripte bereitgestellt, eines für NodeJS und eines für Python. Python, weil viele OpenStack-Benutzer damit vertraut sein werden. NodeJS, weil ich einen Vorwand brauchte, damit zu spielen – es ist nett! Ich decke hier nicht ab, wie Sie Ihre Python- oder Node-Umgebungen einrichten, es gibt viele Blogs zu diesen Themen. Virtual Environment (virtualenv) ist Ihr Freund, wenn Sie Python verwenden – nutzen Sie es.

Python-Beispiel

Kopieren Sie das folgende Python-Skript in eine Datei und speichern Sie es als webhook.py. Dieses Skript wartet auf Webhook-Benachrichtigungen und schreibt sie, wenn es sie empfängt, in eine Protokolldatei. Dies könnte von Legacy-Überwachungslösungen verwendet werden, um die Alarme zu analysieren – es ist jedoch nicht unternehmensgrad – nur ein Beispiel.

webhook.py

# Author: Graham Joseph Land
# Blog: allthingscloud.eu
# Twitter: @allthingsclowd
# Email: graham@ the above domain
# Date: 24/03/2016
# 
# Name: webhook.py
# Version: 0.1
# Purpose: This script listens for webhook notifications and then writes them to a logfile
#
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
import json
import logging
import logging.handlers

# log file for this script
log_file = '/home/stack/monitoring/venv/webhook/webhook.log'

log_max_size = 25165824         # 24 MB
log_level = logging.INFO
#log_level = logging.DEBUG      # DEBUG is quite verbose

log = logging.getLogger('log')
log.setLevel(log_level)
log_handler = logging.handlers.RotatingFileHandler(log_file,
                                                   maxBytes=log_max_size,
                                                   backupCount=4)
f = logging.Formatter("%(asctime)s %(filename)s %(levelname)s %(message)s",
                      "%B %d %H:%M:%S")
log_handler.setFormatter(f)
log.addHandler(log_handler)

class webhookReceiver(BaseHTTPRequestHandler):

    def do_POST(self):
        """
            receives post, handles it
        """
        log.info('<<<<<<<<< Alert Start >>>>>>>>')
        message = 'OK'
        self.rfile._sock.settimeout(5)
        data_string = self.rfile.read(int(self.headers['Content-Length']))
        self.send_response(200)
        self.send_header("Content-type", "text")
        self.send_header("Content-length", str(len(message)))
        self.end_headers()
        self.wfile.write(message)

        # parse data
        text = json.loads(data_string)
        text = json.dumps(text, indent=2)
        log.info(text)
        log.info('<<<<<<<<< Alert End >>>>>>>>')

    def log_message(self, formate, *args):
        """
            disable printing to stdout/stderr for every post
        """
        return

def main():
    """
        the main event.
    """
    try:
        server = HTTPServer(('', 3001), webhookReceiver)
        log.info('started web server...')
        server.serve_forever()
    except KeyboardInterrupt:
        log.info('ctrl-c pressed, shutting down.')
        server.socket.close()

if __name__ == '__main__':

Führen Sie das Skript aus und tailen Sie die Protokolldatei – gehen Sie nun zurück und generieren Sie die Alarme erneut und sehen Sie, was passiert..
Webhook Alarm

Und da haben Sie es – Webhooks – „simples“!

Um Monasca-Probleme auszuschließen, könnten Sie dieses Skript auch mit einer curl-Anweisung wie folgt testen:

curl -H "Content-Type: application/json" -X POST -d '{"alarm_id": "1234","alarm_definition_id": "freddef","alarm_name": "fire alarm","alarm_description": "alarmDescription","alarm_timestamp": "timestamp","state": "Critical","old_state": "oldState","message": "this is the message","tenant_id": "tenant1234","metrics": "1234"}' --trace-ascii debugdump.txt http://172.16.60.9:3000/openstack/alerts

NodeJS-Beispiel

Beachten Sie, dass ich einen anderen Webhook-Endpunkt verwende als in dem Python-Beispiel.
nodejswebhook

Für die NodeJS-Beispielanwendung ist eine etwas komplexere Dateistruktur erforderlich.

Wir verwenden die Haupt-app server.js, die dann auf die „Route“-App webhook.js verweist, die den Webhook beim Empfang verarbeitet.

(venv)stack@helion-cp1-c0-m1-mgmt:~/monitoring/nodejs$ tree -I node_modules
.
|-- routers
|   `-- webhook.js
`-- server.js

Kopieren Sie die beiden unten stehenden Apps in passende Dateien, die unter Verwendung der oben gezeigten Verzeichnisstruktur benannt sind.

server.js

var bodyParser  = require( 'body-parser' ),
    express     = require( 'express' ),
    app         = express();

var webhook        = require( './routers/webhook' );

app.use( bodyParser.json() );
app.use( bodyParser.urlencoded({
  extended: true
}) );

app.get( '/', function ( req, res, next ) {
    res.send( 'Hooks listener running' );
});
app.use( '/openstack/alerts', webhook );

app.listen( 3001 );

und im Unterverzeichnis routers

webhook.js

var express = require( 'express' ),
    bodyParser = require('body-parser'),
    router  = express.Router();

router.use(bodyParser.json());

router.post( '/', function ( req, res, next ) {
    console.log(req.body);

    res.status(200).json({message: 'Monasca Hook received!'})
});

module.exports  = router;

Starten Sie die App und testen Sie zuerst mit curl –

stack@helion-cp1-c0-m1-mgmt:~$ curl -H "Content-Type: application/json" -X POST -d '{"alarm_id": "1234","alarm_definition_id": "freddef","alarm_name": "fire alarm","alarm_description": "alarmDescription","alarm_timestamp": "timestamp","state": "Critical","old_state": "oldState","message": "this is the message","tenant_id": "tenant1234","metrics": "1234"}' --trace-ascii debugdump.txt http://172.16.60.9:3001/openstack/alerts
{"message":"Monasca Hook received!"}stack@helion-cp1-c0-m1-mgmt:~$

Das Ergebnis sollte so aussehen

(venv)stack@helion-cp1-c0-m1-mgmt:~/monitoring/nodejs$ nodejs server.js
{ alarm_id: '1234',
  alarm_definition_id: 'freddef',
  alarm_name: 'fire alarm',
  alarm_description: 'alarmDescription',
  alarm_timestamp: 'timestamp',
  state: 'Critical',
  old_state: 'oldState',
  message: 'this is the message',
  tenant_id: 'tenant1234',
  metrics: '1234' }

Und schließlich senden Sie einen Alarm von Monasca, wie zuvor beschrieben, um zu sehen, wie die Webhook-Benachrichtigungen eintreffen und von der App verarbeitet werden.
NodeAlerts


[Hinweise: Fehlerbehebung bei der Benachrichtigungszustellung]

cd ~/scratch/ansible/next/hos/ansible
ansible-playbook -i hosts/verb_hosts monasca-reconfigure.yml

Originally published on allthingscloud.eu (2016-03-25).

← All posts