Event-Driven Architecture with Ansible and Kafka

With an event-driven architecture, you can create a symbiosis between human actors and systems in the company and massively reduce the throughput time of your work in general. Modern businesses often use many different IT-Systems and Services – complexity therefore increases and you have to create and manage more and more API-Interfaces and interconnections – spaghetti infrastructure. So why not introduce a central event streaming service – a message bus / event-driven-architecture in order to enable easier integration of different systems and services into each other, allowing for a more flexible system that is easier to adapt to changing business needs.
opensight.ch – roman huesler

Today we will use our existing instance of apache kafka (a message bus), on which we will send an event / message that will be picked up by “Event Driven Ansible” in order to perform infrastructure automation tasks. Ansible can then run a playbook that would – as an example – provision a server or do any business task you can imagine…

Red Hat has developed Event-Driven Ansible technology to enhance and expand automation, increasing IT speed and agility while providing consistency and resilience. Today, we are offering a developer preview of this technology.

Event Driven Ansible

Ansible is an automation tool (open source) that combines functions such as software distribution, ad hoc command execution and configuration management. Normally, ansible follows a pushed-based model where playbook runs are initiated manually or by a schedule. With “Event Driven Ansible” you run actions according to hooks and predefined conditions. This could potentially eliminate a lot of manual tasks.

The Ansible system uses files in YAML format (playbooks) to describe the desired status of systems. The Ansible “master server” then connects to the “slave servers” (or WinRM in the case of Windows) via SSH in order to carry out the necessary configurations. There are numerous out-of-the-box “Ansible modules” with which you can carry out all sorts of system configurations.

Rulebooks, Rules, Conditions, Actions

So in Ansible you have your Playbooks, whereas in event driven ansible (EDA) you write a “rulebook”. In the rulebook, you can define some rules (documentation), hooks, alertmanagers, urls, files to listen to and then define rules to launch your playbooks accordingly. Also conditions can be defined.

Conditions (documentation) can be a triggered alert from the Alertmanager or an unreachable website, a newly created file or just a message that was received from the webook.

So here is our Example Rulebook that we use today. It hooks to events on the kafka topic (“kafka-test-topic”) and can also receive events over port 8080.

What happens when a condition is triggered is defined in an action (documentation). Most of the time “run_playbook” should fit your needs but you can check a list of other actions in the documentation. The message payload from the kafka message will be passed on to the playbook automatically (“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 for Event Driven Ansible

Installation

We will use:

  • Prereq – Apache Kafka (message bus) on Kubernetes
  • Prereq – Kafka UI on Kubernetes
  • Event Driven Ansible on Kubernetes
Image - Event Driven Ansible Setup with Kafka Message Bus

What Ansible AWX is for Ansible, the Event Driven Ansible Server is for the Ansible-Rulebook. We will use our Kubernetes Cluster to run an Event Driven Ansible (EDA) server and therefore generate a docker image. We already have a running kafka instance on our kubernetes. Also we have a running instance of “Kafka UI” so we are able to fire events with a GUI. We use the following dockerfile to generate the EDA-Image and then start it on the 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 to build event driven ansible server

Once the rule executes we start a 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

As of 2023-04-18 I have to use ansible_eda.event.message in the playbooks in order to access the message content

Check our GIT Repository (Link on the top) in order to have an overview of all the files.

Practice Test

We see the Event-Driven-Ansible Pod is now started and reeady on our kubernetes. It is hooked to the kafka message bus topic “kafka-test-topic”.

Image - Event Drive Ansible Server up and running

So lets send a message to the kafka message bus by using our Kafka UI container.

Image - Kafka Test Message to be picked up by Event Drive Ansible Server

Immediately the event driven ansible server picked up the event and executed the playbook.

Image - Event Driven Ansible Picking up Kafka Message and Executing Playbook

If you dont have a running kafka instance, you can also forward the port 8080 from the running pod on kubernetes to your local machine and then send a message to the webhook of EDA that we defined earlier:

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

Shell Command to be picked up by Event Driven Ansible Server