Event-Driven Architecture mit Ansible und Kafka

Event-Driven Architecture mit Ansible und Kafka
Foto von Jachan Devol / Unsplash
Handskizze: irgendein Event landet auf dem Kafka Event Bus, Event Driven Ansible bemerkt das neue Event und führt Ansible-Aktionen auf Ihrer Infrastruktur aus

Mit einer Event-Driven Architecture schaffen Sie eine Symbiose zwischen menschlichen Akteuren und Systemen im Unternehmen und verkürzen die Durchlaufzeit Ihrer Arbeit ganz allgemein massiv. Moderne Unternehmen nutzen oft viele verschiedene IT-Systeme und Services. Die Komplexität steigt, und Sie müssen immer mehr API-Schnittstellen und Verbindungen aufbauen und pflegen: eine Spaghetti-Infrastruktur. Warum also nicht einen zentralen Event-Streaming-Service einführen, einen Message Bus bzw. eine Event-Driven Architecture? Damit lassen sich unterschiedliche Systeme und Services einfacher miteinander integrieren, und es entsteht ein flexibleres System, das sich leichter an veränderte Geschäftsanforderungen anpassen lässt.
opensight.ch – roman huesler

Heute verwenden wir unsere bestehende Instanz von Apache Kafka (einem Message Bus), um darauf ein Event bzw. eine Message zu senden, die von «Event Driven Ansible» aufgegriffen wird, um Aufgaben der Infrastrukturautomatisierung auszuführen. Ansible kann dann ein Playbook ausführen, das zum Beispiel einen Server provisioniert oder jede andere Geschäftsaufgabe erledigt, die Sie sich vorstellen können…

Red Hat hat die Technologie Event-Driven Ansible entwickelt, um die Automatisierung zu erweitern und auszubauen: Sie erhöht Tempo und Agilität der IT und sorgt gleichzeitig für Konsistenz und Resilienz. Heute zeigen wir eine Developer Preview dieser Technologie.

Event Driven Ansible

Ansible ist ein (Open-Source-)Automatisierungswerkzeug, das Funktionen wie Softwareverteilung, Ad-hoc-Ausführung von Befehlen und Konfigurationsmanagement vereint. Normalerweise folgt Ansible einem Push-Modell: Playbook-Läufe werden manuell oder nach Zeitplan gestartet. Mit «Event Driven Ansible» führen Sie Aktionen anhand von Hooks und vordefinierten Bedingungen aus. Damit lassen sich potenziell viele manuelle Aufgaben eliminieren.

Ansible beschreibt den gewünschten Zustand von Systemen in Dateien im YAML-Format (Playbooks). Der Ansible-«Master-Server» verbindet sich dann per SSH (bzw. bei Windows per WinRM) mit den «Slave-Servern», um die nötigen Konfigurationen vorzunehmen. Es gibt zahlreiche «Ansible-Module» out of the box, mit denen Sie alle möglichen Systemkonfigurationen vornehmen können.

Rulebooks, Rules, Conditions, Actions

In Ansible haben Sie also Ihre Playbooks, in Event Driven Ansible (EDA) schreiben Sie dagegen ein «Rulebook». Im Rulebook definieren Sie, worauf gehört wird (Dokumentation): Hooks, Alertmanager, URLs oder Dateien. Dazu legen Sie Rules fest, die Ihre Playbooks entsprechend starten. Auch Conditions lassen sich definieren.

Conditions (Dokumentation) können ein ausgelöster Alert aus dem Alertmanager sein, eine nicht erreichbare Website, eine neu erstellte Datei oder einfach eine Message, die über den Webhook empfangen wurde.

Hier ist das Beispiel-Rulebook, das wir heute verwenden. Es hängt sich an die Events auf dem Kafka Topic («kafka-test-topic») und kann zusätzlich Events über Port 8080 empfangen.

Was passiert, wenn eine Condition zutrifft, wird in einer Action festgelegt (Dokumentation). Meistens dürfte «run_playbook» Ihre Anforderungen abdecken, eine Liste weiterer Actions finden Sie in der Dokumentation. Der Payload der Kafka Message wird automatisch an das Playbook übergeben («event.message»).

- name: Listen for events on kafka
  hosts: all

  sources:
    - ansible.eda.kafka:
        host: kafka-0.kafka-headless.kafka.svc.cluster.local
        port: 9092
        topic: kafka-test-topic
        group_id: ansible-eda
    - ansible.eda.webhook:
        host: 0.0.0.0
        port: 8080

  rules:
    - name: kafka
      condition: event.message != ""
      action:
        run_playbook:
          name: do-something.yml
    - name: webhook
      condition: event.payload.message != ""
      action:
        run_playbook:
          name: do-something.yml
          var_root: payload

Ansible Rulebook für Event Driven Ansible

Installation

Wir verwenden:

  • Voraussetzung – Apache Kafka (Message Bus) auf Kubernetes
  • Voraussetzung – Kafka UI auf Kubernetes
  • Event Driven Ansible auf Kubernetes
Aufbau in einem Kubernetes-Cluster: Kafka als Message Bus, daran angebunden die Container Kafka UI und Event Driven Ansible
Bild - Event-Driven-Ansible-Setup mit dem Kafka Message Bus

Was Ansible AWX für Ansible ist, ist der Event Driven Ansible Server für das Ansible Rulebook. Wir betreiben einen Event-Driven-Ansible-Server (EDA) auf unserem Kubernetes-Cluster und bauen dafür ein Docker Image. Auf unserem Kubernetes läuft bereits eine Kafka-Instanz. Ausserdem läuft eine Instanz von «Kafka UI», mit der wir Events über eine GUI auslösen können. Mit dem folgenden Dockerfile bauen wir das EDA-Image und starten es dann auf dem Kubernetes-Cluster.

FROM ubuntu:latest

RUN apt update && apt install -y build-essential maven openjdk-17-jdk python3-dev python3-pip
ENV JDK_HOME=/usr/lib/jvm/java-17-openjdk-amd64
ENV JAVA_HOME=$JDK_HOME
ENV PIP_NO_BINARY=jpy
ENV PATH=$PATH:~/.local/bin
RUN python3 -m pip install -U Jinja2
RUN python3 -m pip install aiokafka
RUN python3 -m pip install ansible ansible-rulebook ansible-runner wheel
RUN ansible-galaxy collection install community.general ansible.eda
RUN apt install vim curl -y

COPY *.yml ./
COPY webhook-rule.yml ./

EXPOSE 8080/tcp
CMD ["ansible-rulebook", "--rulebook", "webhook-rule.yml", "-i", "inventory.yml", "--verbose"]

Dockerfile für den Build des Event-Driven-Ansible-Servers

Sobald die Rule greift, starten wir das Playbook «do-something.yml»:

- hosts: all
  connection: local
  tasks:
    - debug:
        msg: "you have send the following message:"
    - debug:
        var: event.message

Ansible Playbook - do-something.yml

Stand 18.04.2023 muss ich in den Playbooks ansible_eda.event.message verwenden, um auf den Inhalt der Message zuzugreifen.

Im GIT-Repository (Link oben) finden Sie eine Übersicht über alle Dateien.

Praxistest

Der Event-Driven-Ansible-Pod ist jetzt auf unserem Kubernetes gestartet und bereit. Er hängt am Topic «kafka-test-topic» des Kafka Message Bus.

Pod ansible-eventdriven im Status Running, darunter das Log von ansible-rulebook, das sich auf kafka-test-topic einschreibt
Bild - der Event-Driven-Ansible-Server läuft

Senden wir also mit unserem Kafka-UI-Container eine Message an den Kafka Message Bus.

UI for Apache Kafka: Dialog Produce Message für kafka-test-topic mit dem Key test-message und dem Value message: hello from kafka
Bild - Kafka-Testnachricht, die der Event-Driven-Ansible-Server aufgreifen soll

Der Event-Driven-Ansible-Server hat das Event sofort aufgegriffen und das Playbook ausgeführt.

Pod-Log: ansible-rulebook aktiviert die Rule kafka, führt do-something.yml aus und gibt event.message: hello from kafka aus
Bild - Event Driven Ansible greift die Kafka Message auf und führt das Playbook aus

Falls Sie keine laufende Kafka-Instanz haben, können Sie auch Port 8080 des laufenden Pods auf Kubernetes an Ihren lokalen Rechner weiterleiten und dann eine Message an den Webhook von EDA senden, den wir vorhin definiert haben:

curl -H 'Content-Type: application/json' -d "{\"message\": \"hello from commandlinel\"}" http://127.0.0.1:8080/endpoint

Shell-Befehl, den der Event-Driven-Ansible-Server aufgreift