Docker Ambassador mit HAProxy und etcd

Keine Kommentare

In einem vorherigen Artikel habe ich über den allgemeinen Aufbau des Ambassador in einem gemeinsamen Projekt der LeanIX GmbH mit der codecentric AG geschrieben. In diesem Artikel werde ich weiter auf die technischen Details des Ambassador Containers eingehen.

Die Funktion des Ambassadors wird durch HAProxy realisiert. Auf Grund von Beschränkungen durch Docker und die Anforderung, die Konfiguration des HAProxy dynamisch und ohne Neustart des Containers ändern zu können, sind noch einige weitere Komponenten nötig:

supervisord

supervisord betreiben wir als root-Prozess im Ambassador Docker Container. Dies ist nötig, da der HAProxy für die Aktualisierung der Konfiguration neue Prozesse mit der neuen Konfiguration startet. Sollte der HAProxy als root-Prozess des Docker-Containers laufen, würde sich dieser beim Aktualisieren der Konfiguration beenden.

etcd

etcd ist ein verteilter Key Value Store. In unserem Fall speichern wir in etcd Parameter für die Konfiguration des HAProxy, genauer gesagt, welche Backends HAProxy für einen Dienst zur Verfügung stehen.

confd

confd dient dazu, Variablen aus einem Backend zu lesen und vorhandene Templates mit deren Werten zu füllen und ggf. Befehle auszuführen. In unserem Projekt überwacht confd bestimmte Einträge in etcd, überträgt diese in ein Template einer HAProxy-Konfigurationsdatei und gibt bei Änderungen dem HAProxy den Befehl seine Konfiguration neu zu laden.

Drei dieser vier Komponenten werden in einem Docker Container betrieben:

  • supervisord
  • confd
  • HAProxy

Diese Komponenten machen unseren Ambassador aus. Es gibt noch eine Diskussion darüber, ob wirklich mehrere Prozesse in einem Docker-Container laufen sollten. Eine Sichtweise dazu kommt aus dem Phusion-Projekt und wird in diesem Ambassador umgesetzt.

Der etcd ist nicht Teil des Ambassador Containers, sondern kann in beliebiger Form, auch als Docker-Container, an beliebiger Stelle laufen. Er muss lediglich über ein Netzwerk erreichbar sein.

Implementierung

Zuerst einmal das Grundgerüst für alles, das Dockerfile:

# Dockerfile for haproxy
# Version 1.0
FROM ubuntu:14.04
 
MAINTAINER Christian Zunker <christian.zunker@codecentric.de>
 
RUN apt-get update && apt-get install -y haproxy supervisor netcat
 
RUN mkdir -p /var/log/supervisor
COPY supervisord.conf /etc/supervisor/conf.d/ambassador.conf
 
ADD confd-0.7.1-linux-amd64 /usr/local/bin/confd
RUN chmod +x /usr/local/bin/confd
ADD haproxy.toml /etc/confd/conf.d/haproxy.toml
ADD haproxy.cfg.tmpl /etc/confd/templates/haproxy.cfg.tmpl
 
CMD ["/usr/bin/supervisord"]

Im Dockerfile ist festgelegt, dass supervisord gestartet werden soll. Dieser ist aber nur ein Mittel zum Zweck. Er startet die weiteren Dienste:

[supervisord]
nodaemon=true
 
[program:confd]
command=/usr/local/bin/confd -interval %(ENV_CONFD_INTERVAL)s -node %(ENV_ETCD_SERVER)s -config-file /etc/confd/conf.d/haproxy.toml
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
priority=18
 
[program:haproxy]
command=haproxy -f /etc/haproxy/haproxy.cfg -p /var/run/haproxy.pid
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
priority=19

Der supervisord startet unter anderem auch den confd. Dieser erhält über Umgebungsvariablen die Verbindungsdaten zum etcd und eine Konfigurationsdatei, in der sein Verhalten beschrieben wird:

[template]
src = "haproxy.cfg.tmpl"
dest = "/etc/haproxy/haproxy.cfg"
keys = [
  "/backends",
  "/vhosts"
]
reload_cmd = "haproxy -f /etc/haproxy/haproxy.cfg -p /var/run/haproxy.pid -sf $(cat /var/run/haproxy.pid)"

In der confd-Konfigurationsdatei wird auf das Template für die HAProxy-Konfiguration verwiesen und mit welchem Befehl der Reload des HAProxy durchzuführen ist. Die Informationen aus den Verzeichnissen /backends und /vhosts des etcd schreibt confd in die Template-Datei:

{{ $service_port := printf "%s" (getenv "SERVICE_PORT") }}
{{ $etcd_prefix := printf "%s" (getenv "ETCD_PREFIX") }}
{{ $service_type := printf "%s" (getenv "SERVICE_TYPE") }}
 
frontend {{ $service_type }}
    bind *:{{ $service_port }}
    mode tcp
    use_backend backend-{{ $service_type }} if TRUE
 
backend backend-{{ $service_type }}
    mode tcp
    balance roundrobin
    {{ $service_path := printf "%s/*" $etcd_prefix }}
    {{ range gets $service_path }}
    server {{base .Key}} {{.Value}} check
    {{ end }}

Damit man eine bessere Vorstellung davon bekommt, welche Daten confd in das Template schreibt, hier ein möglicher Aufbau der Daten in etcd:

/vhosts/leanix.acme.com/services/export/server1: 192.168.110.11:9100
/backends/solr/solr1: 192.168.110.11:8983
/backends/db/db1: 192.168.110.11:3306
/backends/mail/mail1: 192.168.110.11:25

Die Daten im etcd können während der Laufzeit geändert werden. confd prüft in regelmäßigen Abständen, ob es Änderungen gegeben hat. Ist das der Fall, passt confd die Konfiguration des HAProxy an und lässt diesen damit neu starten. So können im laufenden Betrieb neue Backends hinzugenommen oder auch wieder entfernt werden. Für den Docker-Container, der das Backend eigentlich nutzen möchte, sind die Änderungen transparent, da er seine Anfragen nur an den Ambassador stellt.

Die technischen Details dieser Umsetzung sind sicherlich projektspezifisch, können aber als Vorlage für andere Projekte verwendet werden um das Ambassador Pattern in angepasster Version umzusetzen.

Über die LeanIX GmbH:

LeanIX bietet eine innovative Lösung für das Enterprise Architecture Management (EAM) als Software-as-a-Service in der Public-Cloud oder im Rechenzentrum des Kunden. Die web-basierte Plattform besticht gegenüber traditionellen Ansätzen durch eine intuitive Benutzeroberfläche, ein flexibles Reporting und offene APIs. Dadurch lässt sich leanIX mit minimalem Trainingsaufwand schnell im Unternehmen einführen und nach kurzer Zeit Mehrwert generieren. Sowohl kleine bis mittlere als auch große Unternehmen aus verschiedenen Branchen vertrauen auf die Lösung, wie z.B. Axel Springer, Helvetia, RWE, Vaillant und Trusted Shops. Unabhängig von der Unternehmensgröße werden immer mehr Unternehmen als Kunden gewonnen, die bisher Berührungsängste mit dem Thema EAM hatten oder frustriert sind von schwerfälligen Tools. Gegründet wurde die LeanIX GmbH 2012 von Jörg G. Beyer und André Christ. Der Sitz der Gesellschaft befindet sich in Bonn, unterstützt von einem breiten Partnernetzwerk in Europa, Australien und Amerika.

Über die codecentric AG:

Als Experte für individuelle Software-Entwicklungen ist die codecentric AG der Vordenker für agile Software-Entwicklung und innovative Technologien in Deutschland. Rund 280 Mitarbeiter an dreizehn europäischen Standorten entwickeln Software-Lösungen der Zukunft. Dafür kombiniert codecentric das Know-how der besten IT-Architekten und Software-Entwickler mit dem Praxiswissen aus zahlreichen Projekten in den Bereichen Continuous Delivery, Big Data, Performance Solutions, Agile und Enterprise Development. Für optimale Java Performance, Skalierbarkeit und Stabilität haben codecentric-Kunden Zugriff auf umfassende Risiko-Management-, Troubleshooting-, Java-Optimierungs- und Performance-Management-Services nebst Werkzeugen.

Christian Zunker

Christian Zunker arbeitet als System Engineer im Bereich Hosting der codecentric AG. Dort beschäftigt er sich mit der Entwicklung und dem Betrieb von verteilten Systemen.

Share on FacebookGoogle+Share on LinkedInTweet about this on TwitterShare on RedditDigg thisShare on StumbleUpon

Kommentieren

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.