Erstellen flexibler Dienste für einen CoreOS-Cluster mit Flotteneinheitendateien

Einführung

CoreOS-Installationen nutzen eine Reihe von Tools, um die Verwaltung von Clustering- und Docker-Diensten zu vereinfachen. Während "+ etcd " für die Verknüpfung der einzelnen Knoten und die Bereitstellung eines Bereichs für globale Daten zuständig ist, besteht der größte Teil der eigentlichen Dienstverwaltungs- und Verwaltungsaufgaben darin, mit dem Daemon " fleet +" zu arbeiten.

In einem previous guide gingen wir auf die grundlegende Verwendung von Befehl + fleetctl + zum Manipulieren der Dienste und Cluster-Mitglieder. In diesem Handbuch haben wir kurz auf die Einheitendateien eingegangen, die die Flotte zur Definition von Diensten verwendet. Dies waren jedoch vereinfachte Beispiele für die Bereitstellung eines funktionierenden Dienstes zum Erlernen von + fleetctl +.

In diesem Handbuch werden wir uns eingehend mit den "+ Flotte +" - Einheitendateien befassen, um zu erfahren, wie sie erstellt werden, und um einige Techniken zu erlernen, mit denen Ihre Dienste in der Produktion robuster werden.

Voraussetzungen

Um dieses Tutorial abzuschließen, wird davon ausgegangen, dass Sie einen CoreOS-Cluster konfiguriert haben, wie in unserer https://www.digitalocean.com/community/tutorials/how-to-set-up-a-coreos-cluster-on beschrieben -digitalocean [Clustering-Anleitung]. So haben Sie drei Server mit dem Namen:

  • Coreos-1

  • Coreos-2

  • Coreos-3

Obwohl sich der größte Teil dieses Lernprogramms auf die Erstellung von Einheitendateien konzentriert, werden diese Computer später verwendet, um die Auswirkungen bestimmter Anweisungen auf die Zeitplanung zu veranschaulichen.

Wir gehen auch davon aus, dass Sie unseren Leitfaden unter how to use-your-coreos-clusters gelesen haben fleetctl. Sie sollten über gute Kenntnisse von "+ fleetctl +" verfügen, damit Sie diese Einheitendateien mit dem Cluster senden und verwenden können.

Wenn Sie diese Anforderungen erfüllt haben, fahren Sie mit dem Rest des Handbuchs fort.

Abschnitte und Typen von Unit-Dateien

Da der Service-Management-Aspekt von "+ fleet " hauptsächlich vom " systemd " init-System jedes lokalen Systems abhängt, werden " systemd +" Unit-Dateien zum Definieren von Services verwendet.

Während Services mit Abstand der gebräuchlichste mit CoreOS konfigurierte Einheitentyp sind, können tatsächlich andere Einheitentypen definiert werden. Dies ist eine Untergruppe derjenigen, die für konventionelle Unit-Dateien ("+ systemd ") verfügbar sind. Jeder dieser Typen wird durch den Typ identifiziert, der als Dateisuffix verwendet wird, wie z. B. " example.service +":

  • * service *: Dies ist der gebräuchlichste Typ von Gerätedateien. Es wird verwendet, um einen Dienst oder eine Anwendung zu definieren, die auf einem der Computer im Cluster ausgeführt werden können.

  • * socket *: Definiert Details zu einem Socket oder zu Socket-ähnlichen Dateien. Dazu gehören Netzwerksockets, IPC-Sockets und FIFO-Puffer. Diese werden verwendet, um Dienste aufzurufen, die gestartet werden, wenn Datenverkehr in der Datei angezeigt wird.

  • * device *: Definiert Informationen zu einem Gerät, die in der udev-Gerätestruktur verfügbar sind. Systemd erstellt diese nach Bedarf auf einzelnen Hosts für Kernel-Geräte basierend auf udev-Regeln. Diese werden in der Regel zum Bestellen von Problemen verwendet, um sicherzustellen, dass Geräte verfügbar sind, bevor Sie versuchen, diese bereitzustellen.

  • * mount *: Definiert Informationen zu einem Mount-Punkt für ein Gerät. Diese sind nach den Einhängepunkten benannt, auf die sie verweisen, wobei Schrägstriche durch Bindestriche ersetzt werden.

  • * automount *: Definiert einen Automount-Punkt. Sie folgen der gleichen Namenskonvention wie Mount-Einheiten und müssen von der zugehörigen Mount-Einheit begleitet werden. Diese dienen zur Beschreibung der On-Demand- und Parallelmontage.

  • * timer *: Definiert einen Timer, der einer anderen Einheit zugeordnet ist. Wenn der in dieser Datei festgelegte Zeitpunkt erreicht ist, wird die zugehörige Einheit gestartet.

  • * path *: Definiert einen Pfad, der auf pfadbasierte Aktivierung überwacht werden kann. Dies kann verwendet werden, um eine andere Einheit zu starten, wenn Änderungen an einem bestimmten Pfad vorgenommen werden.

Obwohl diese Optionen alle verfügbar sind, werden Serviceeinheiten am häufigsten verwendet. In diesem Handbuch werden nur die Konfigurationen der Wartungseinheiten erläutert.

Unit-Dateien sind einfache Textdateien, die mit einem Punkt und einem der oben genannten Suffixe enden. Im Inneren sind sie nach Abschnitten gegliedert. Für + Flotte + haben die meisten Einheitendateien das folgende allgemeine Format:

[Unit]



[Service]




[X-Fleet]

Die Abschnittsüberschriften und alles andere in einer Unit-Datei unterscheidet zwischen Groß- und Kleinschreibung. Der Abschnitt "+ [Einheit] +" wird verwendet, um allgemeine Informationen zu einer Einheit zu definieren. Optionen, die für alle Einheitentypen gelten, werden in der Regel hier platziert.

Der Abschnitt "+ [Service] +" wird verwendet, um Anweisungen festzulegen, die für Serviceeinheiten spezifisch sind. Die meisten (aber nicht alle) der oben genannten Einheitentypen verfügen über zugeordnete Abschnitte für spezifische Informationen zum Einheitentyp. Weitere Informationen finden Sie in der Manpage generic systemd unit file, die Links zu den verschiedenen Einheitentypen enthält.

Der Abschnitt "+ [X-Fleet] " wird verwendet, um die Planungsanforderungen für die Einheit zur Verwendung mit " Flotte +" festzulegen. In diesem Abschnitt können Sie festlegen, dass bestimmte Bedingungen erfüllt sein müssen, damit eine Einheit auf einem Host geplant werden kann.

Aufbau des Hauptdienstes

In diesem Abschnitt beginnen wir mit einer Variante der Unit-Datei, die in unserer https://www.digitalocean.com/community/tutorials/how-to-create-and-run-a-service-on-a-coreos beschrieben ist -cluster [grundlegende Anleitung zum Ausführen von Diensten unter CoreOS]. Die Datei heißt + apache.1.service + und sieht folgendermaßen aus:

[Unit]
Description=Apache web server service

# Requirements
Requires=etcd.service
Requires=docker.service
Requires=apache-discovery.1.service

# Dependency ordering
After=etcd.service
After=docker.service
Before=apache-discovery.1.service

[Service]
# Let processes take awhile to start up (for first run Docker containers)
TimeoutStartSec=0

# Change killmode from "control-group" to "none" to let Docker remove
# work correctly.
KillMode=none

# Get CoreOS environmental variables
EnvironmentFile=/etc/environment

# Pre-start and Start
## Directives with "=-" are allowed to fail without consequence
ExecStartPre=-/usr/bin/docker kill apache
ExecStartPre=-/usr/bin/docker rm apache
ExecStartPre=/usr/bin/docker pull /apache
ExecStart=/usr/bin/docker run --name apache -p ${COREOS_PUBLIC_IPV4}:80:80 \
/apache /usr/sbin/apache2ctl -D FOREGROUND

# Stop
ExecStop=/usr/bin/docker stop apache

[X-Fleet]
# Don't schedule on the same machine as other Apache instances
X-Conflicts=apache.*.service

Wir beginnen mit dem Abschnitt "+ [Unit] ". Hier besteht die Grundidee darin, die Einheit zu beschreiben und die Abhängigkeitsinformationen festzulegen. Wir beginnen mit einer Reihe von Anforderungen. Für dieses Beispiel haben wir harte Anforderungen verwendet. Wenn wir wollten, dass " fleet " versucht, zusätzliche Dienste zu starten, aber nicht bei einem Fehler beendet wird, hätten wir stattdessen die Direktive " Wants +" verwenden können.

Anschließend listen wir explizit die Reihenfolge der Anforderungen auf. Dies ist wichtig, damit die erforderlichen Dienste verfügbar sind, wenn sie benötigt werden. Es ist auch die Art und Weise, wie wir automatisch den Sidekick-Ankündigungsdienst starten, den wir bauen werden.

Für den Abschnitt "+ [Service] +" deaktivieren wir das Zeitlimit für den Start des Dienstes. Wenn ein Dienst zum ersten Mal auf einem Host ausgeführt wird, muss der Container aus der Docker-Registrierung abgerufen werden, was für das Startzeitlimit gilt. Die Standardeinstellung ist 90 Sekunden, was normalerweise ausreicht. Bei komplexeren Containern kann dies jedoch länger dauern.

Wir setzen dann den Killmode auf none. Dies wird verwendet, weil der normale Kill-Modus (Kontrollgruppe) manchmal dazu führt, dass Container-Entfernungsbefehle fehlschlagen (insbesondere, wenn die Docker-Option + - rm + versucht). Dies kann beim nächsten Neustart zu Problemen führen.

Wir ziehen die Umgebungsdatei ein, damit wir Zugriff auf die Umgebungsvariablen "+ COREOS_PUBLIC_IPV4 " und, falls das private Netzwerk während der Erstellung aktiviert war, auf die Umgebungsvariablen " COREOS_PRIVATE_IPV4 +" haben. Diese sind sehr nützlich, um Docker-Container so zu konfigurieren, dass sie die Informationen ihres jeweiligen Hosts verwenden.

Die Zeilen + ExecStartPre + werden verwendet, um Reste von vorherigen Läufen zu entfernen, um sicherzustellen, dass die Ausführungsumgebung sauber ist. Wir verwenden in den ersten beiden Fällen "+ = - ", um anzugeben, dass " systemd +" ignoriert und fortgesetzt werden soll, wenn diese Befehle fehlschlagen. Aus diesem Grund versucht Docker, frühere Container zu töten und zu entfernen, macht sich jedoch keine Sorgen, wenn keine gefunden werden. Der letzte Pre-Start wird verwendet, um sicherzustellen, dass die aktuellste Version des Containers ausgeführt wird.

Der eigentliche Startbefehl startet den Docker-Container und bindet ihn an die öffentliche IPv4-Schnittstelle des Host-Computers. Dadurch werden die Informationen in der Umgebungsdatei verwendet, und das Wechseln von Schnittstellen und Ports ist kein Problem. Der Prozess wird im Vordergrund ausgeführt, da der Container beendet wird, wenn der ausgeführte Prozess endet. Der Befehl stop versucht, den Container ordnungsgemäß zu stoppen.

Der Abschnitt "+ [X-Fleet] " enthält eine einfache Bedingung, die " fleet +" zwingt, den Dienst auf einer Maschine zu planen, auf der noch kein anderer Apache-Dienst ausgeführt wird. Auf diese Weise können Sie einen Dienst auf einfache Weise hoch verfügbar machen, indem Sie doppelte Dienste zwingen, auf separaten Computern zu starten.

Grundlegende Take-Aways für den Aufbau von Hauptdienstleistungen

Im obigen Beispiel haben wir eine ziemlich grundlegende Konfiguration durchgearbeitet. Es gibt jedoch viele Lehren, die wir daraus ziehen können, um uns bei der allgemeinen Gebäudetechnik zu unterstützen.

Einige zu beachtende Verhaltensweisen beim Aufbau eines Hauptdienstes:

  • * Separate Logik für Abhängigkeiten und Reihenfolge *: Legen Sie Ihre Abhängigkeiten mit den Direktiven "+ Requires = " oder " Wants = " fest, je nachdem, ob die Einheit, die Sie bauen, ausfallen soll, wenn die Abhängigkeit nicht erfüllt werden kann. Trennen Sie die Bestellung durch separate " After = " - und " Before = +" -Zeilen voneinander ab, damit Sie sie bei sich ändernden Anforderungen problemlos anpassen können. Das Trennen der Abhängigkeitsliste von der Bestellung kann Ihnen bei der Fehlersuche bei Abhängigkeitsproblemen helfen.

  • * Behandeln Sie die Dienstregistrierung mit einem separaten Prozess *: Ihr Dienst sollte bei "+ etcd +" registriert sein, um die Diensterkennung und die damit verbundenen dynamischen Konfigurationsfunktionen zu nutzen. Dies sollte jedoch von einem separaten "Sidekick" -Container gehandhabt werden, um die Logik getrennt zu halten. Auf diese Weise können Sie genauer über den Zustand des Dienstes berichten, wenn Sie ihn von außen betrachten. Dies ist auch für andere Komponenten erforderlich.

  • * Beachten Sie die Möglichkeit eines Timeouts für Ihren Dienst *: Überlegen Sie, die Direktive + TimeoutStartSec + anzupassen, um längere Startzeiten zu ermöglichen. Wenn Sie dies auf „0“ setzen, wird ein Startzeitlimit deaktiviert. Dies ist häufig erforderlich, da Docker manchmal ein Image abrufen muss (bei der ersten Ausführung oder wenn Updates gefunden werden), was die Initialisierung des Dienstes erheblich beschleunigen kann.

  • * Passen Sie den KillMode an, wenn Ihr Dienst nicht ordnungsgemäß beendet wird. *: Beachten Sie die Option "+ KillMode +", wenn Ihre Dienste oder Container scheinbar nicht ordnungsgemäß beendet werden. Wenn Sie diese Option auf "Keine" setzen, können Probleme behoben werden, bei denen Ihre Container nach dem Anhalten nicht entfernt werden. Dies ist besonders wichtig, wenn Sie Ihre Container benennen, da Docker fehlschlägt, wenn ein Container mit demselben Namen aus einer vorherigen Ausführung zurückgelassen wurde. Weitere Informationen finden Sie in der Dokumentation zu KillMode.

  • * Bereinigen Sie die Umgebung vor dem Start *: Stellen Sie im Zusammenhang mit dem obigen Punkt sicher, dass die vorherigen Docker-Container bei jedem Start bereinigt werden. Sie sollten nicht davon ausgehen, dass die vorherige Ausführung des Dienstes wie erwartet beendet wurde. Diese Bereinigungszeilen sollten den Bezeichner "+ = - " verwenden, damit sie unbemerkt fehlschlagen, wenn keine Bereinigung erforderlich ist. Während Sie Container normalerweise mit ` docker stop ` stoppen sollten, sollten Sie während der Bereinigung wahrscheinlich ` docker kill +` verwenden.

  • * Hostspezifische Informationen für die Portabilität von Diensten abrufen und verwenden *: Wenn Sie Ihren Dienst an eine bestimmte Netzwerkschnittstelle binden müssen, rufen Sie die Datei "+ / etc / environment " auf, um auf " COREOS_PUBLIC_IPV4 " zuzugreifen , ` COREOS_PRIVATE_IPV4 `. Wenn Sie den Hostnamen des Computers kennen müssen, auf dem Ihr Dienst ausgeführt wird, verwenden Sie den Systemd-Bezeichner `% H `. Weitere Informationen zu möglichen Spezifizierern finden Sie in den http://www.freedesktop.org/software/systemd/man/systemd.unit.html#Specifiers[systemd specifiers docs]. Im Abschnitt " [X-Fleet] " funktionieren nur die Bezeichner "% n ", "% N ", "% i " und "% p +".

Aufbau des Sidekick Announce Service

Jetzt, da wir eine gute Vorstellung davon haben, was beim Aufbau eines Hauptdienstes zu beachten ist, können wir anfangen, uns mit einem herkömmlichen "Sidekick" -Dienst zu befassen. Diese Sidekick-Dienste sind einem Hauptdienst zugeordnet und werden als externer Punkt zum Registrieren von Diensten bei "+ etcd +" verwendet.

Diese Datei, auf die in der Hauptgerätedatei verwiesen wurde, heißt "+ apache-discovery.1.service +" und sieht folgendermaßen aus:

[Unit]
Description=Apache web server etcd registration

# Requirements
Requires=etcd.service
Requires=apache.1.service

# Dependency ordering and binding
After=etcd.service
After=apache.1.service
BindsTo=apache.1.service

[Service]

# Get CoreOS environmental variables
EnvironmentFile=/etc/environment

# Start
## Test whether service is accessible and then register useful information
ExecStart=/bin/bash -c '\
 while true; do \
   curl -f ${COREOS_PUBLIC_IPV4}:80; \
   if [ $? -eq 0 ]; then \
     etcdctl set /services/apache/${COREOS_PUBLIC_IPV4} \'{"host": "%H", "ipv4_addr": ${COREOS_PUBLIC_IPV4}, "port": 80}\' --ttl 30; \
   else \
     etcdctl rm /services/apache/${COREOS_PUBLIC_IPV4}; \
   fi; \
   sleep 20; \
 done'

# Stop
ExecStop=/usr/bin/etcdctl rm /services/apache/${COREOS_PUBLIC_IPV4}

[X-Fleet]
# Schedule on the same machine as the associated Apache service
X-ConditionMachineOf=apache.1.service

Wir starten den Sidekick-Service auf die gleiche Weise wie den Hauptservice. Wir beschreiben den Zweck der Einheit, bevor wir zu den Abhängigkeitsinformationen und der Ordnungslogik übergehen.

Das erste neue Element hier ist die Direktive + BindsTo = +. Diese Anweisung veranlasst dieses Gerät, den an das aufgelistete Gerät gesendeten Befehlen zum Starten, Stoppen und Neustarten zu folgen. Grundsätzlich bedeutet dies, dass wir beide Einheiten verwalten können, indem wir die Haupteinheit manipulieren, sobald beide in "+ Flotte +" geladen sind. Dies ist ein Einwegmechanismus, sodass die Steuerung des Sidekicks keine Auswirkungen auf die Haupteinheit hat.

Für den Abschnitt "+ [Service] " beziehen wir wieder die Datei " / etc / environment ", da wir die darin enthaltenen Variablen benötigen. Die Direktive " ExecStart = " ist in diesem Fall im Grunde ein kurzes " bash +" - Skript. Es wird versucht, über die Schnittstelle und den Port, die verfügbar gemacht wurden, eine Verbindung zu den Hauptdiensten herzustellen.

Bei erfolgreicher Verbindung wird mit dem Befehl "+ etcdctl " ein Schlüssel für die öffentliche IP-Adresse des Host-Computers in " / services / apache " in " etcd " festgelegt. Der Wert dieses Objekts ist ein JSON-Objekt, das Informationen zum Service enthält. Der Schlüssel ist so eingestellt, dass er in 30 Sekunden abläuft. Wenn dieses Gerät unerwartet ausfällt, bleiben veraltete Serviceinformationen nicht in " etcd +" erhalten. Wenn die Verbindung fehlschlägt, wird der Schlüssel sofort entfernt, da nicht überprüft werden kann, ob der Dienst verfügbar ist.

Diese Schleife enthält einen 20-Sekunden-Schlafbefehl. Dies bedeutet, dass dieses Gerät alle 20 Sekunden (vor dem Timeout der Taste "+ etcd +" von 30 Sekunden) erneut prüft, ob die Haupteinheit verfügbar ist, und den Schlüssel zurücksetzt. Dies aktualisiert im Grunde die TTL auf dem Schlüssel, so dass sie für weitere 30 Sekunden als gültig angesehen wird.

Der Stoppbefehl führt in diesem Fall lediglich zu einem manuellen Entfernen des Schlüssels. Dadurch wird die Serviceregistrierung entfernt, wenn der Stoppbefehl des Hauptgeräts aufgrund der Direktive "+ BindsTo = +" auf dieses Gerät gespiegelt wird.

Für den Abschnitt "+ [X-Fleet] " müssen wir sicherstellen, dass dieses Gerät auf demselben Server wie das Hauptgerät gestartet wird. Dies ermöglicht es dem Gerät zwar nicht, die Verfügbarkeit des Dienstes für Remotecomputer zu melden, es ist jedoch wichtig, dass die Direktive ` BindsTo = +` korrekt funktioniert.

Grundlegende Take-Aways für den Aufbau von Sidekick Services

Beim Aufbau dieses Sidekicks können wir einige Dinge sehen, die wir als allgemeine Regel für diese Arten von Einheiten berücksichtigen sollten:

  • * Überprüfen Sie die tatsächliche Verfügbarkeit des Hauptgeräts *: Es ist wichtig, den tatsächlichen Status des Hauptgeräts zu überprüfen. Gehen Sie nicht davon aus, dass die Haupteinheit verfügbar ist, nur weil der Sidekick initialisiert wurde. Dies hängt vom Design und der Funktionalität des Hauptgeräts ab. Je aussagekräftiger Ihre Prüfung ist, desto glaubwürdiger wird Ihr Registrierungsstatus. Die Prüfung kann alles sein, was für die Einheit sinnvoll ist, von der Prüfung eines "+ / health" -Endpunkts bis zum Versuch, mit einem Client eine Verbindung zu einer Datenbank herzustellen.

  • * Führen Sie eine Schleife der Registrierungslogik durch, um eine regelmäßige Überprüfung durchzuführen. *: Es ist wichtig, die Verfügbarkeit des Dienstes beim Start zu überprüfen, es ist jedoch auch wichtig, dass Sie diese in regelmäßigen Abständen überprüfen. Dies kann zu unerwarteten Dienstfehlern führen, insbesondere wenn der Container dadurch nicht angehalten wird. Die Pause zwischen den Zyklen muss entsprechend Ihren Anforderungen angepasst werden, indem die Wichtigkeit einer schnellen Erkennung gegen die zusätzliche Belastung Ihres Hauptgeräts abgewogen wird.

  • * Verwenden Sie das TTL-Flag, wenn Sie sich bei etcd für die automatische Deregistrierung bei Fehlern registrieren. Um Konflikte zwischen dem registrierten und dem tatsächlichen Status Ihrer Dienste zu vermeiden, sollten Sie Ihre Schlüssel eine Zeitüberschreitung zulassen. Mit dem obigen Schleifenkonstrukt können Sie jeden Schlüssel vor dem Zeitlimitintervall aktualisieren, um sicherzustellen, dass der Schlüssel während der Ausführung des Sidekicks nie abläuft. Das Ruheintervall in Ihrer Schleife sollte etwas kürzer als das Timeout-Intervall sein, um sicherzustellen, dass dies ordnungsgemäß funktioniert.

  • * Registrieren Sie nützliche Informationen mit etcd, nicht nur eine Bestätigung. *: Während Ihrer ersten Iteration eines Sidekicks möchten Sie sich möglicherweise nur beim Starten des Geräts mit + etcd + genau registrieren. Dies ist jedoch eine verpasste Gelegenheit, viele nützliche Informationen für andere Dienste bereitzustellen. Obwohl Sie diese Informationen jetzt möglicherweise nicht benötigen, werden sie nützlicher, wenn Sie andere Komponenten mit der Fähigkeit zum Lesen von Werten aus "+ etcd " für ihre eigenen Konfigurationen erstellen. Der " etcd +" - Dienst ist ein globaler Schlüsselwertspeicher. Vergessen Sie also nicht, diesen Dienst zu nutzen, indem Sie Schlüsselinformationen bereitstellen. Das Speichern von Details in JSON-Objekten ist eine gute Möglichkeit, mehrere Informationen zu übergeben.

Wenn Sie diese Überlegungen berücksichtigen, können Sie damit beginnen, robuste Registrierungseinheiten zu erstellen, die auf intelligente Weise sicherstellen, dass "+ etcd +" die richtigen Informationen enthält.

Flottenspezifische Überlegungen

Während sich + fleet + Unit-Dateien größtenteils nicht von herkömmlichen + systemd + Unit-Dateien unterscheiden, gibt es einige zusätzliche Funktionen und Fallstricke.

Der offensichtlichste Unterschied ist die Hinzufügung eines Abschnitts mit dem Namen "+ [X-Fleet] ", der verwendet werden kann, um " Flotte +" zu steuern, wie Planungsentscheidungen getroffen werden sollen. Die verfügbaren Optionen sind:

  • * X-ConditionMachineID *: Hiermit kann eine genaue Maschine zum Laden der Einheit angegeben werden. Der angegebene Wert ist eine vollständige Rechner-ID. Dieser Wert kann von einem einzelnen Mitglied des Clusters abgerufen werden, indem die Datei "+ / etc / machine-id " oder " fleetctl " mit dem Befehl " list-machines -l +" überprüft wird. Die gesamte ID-Zeichenfolge ist erforderlich. Dies kann erforderlich sein, wenn Sie eine Datenbank ausführen, deren Datenverzeichnis auf einem bestimmten Computer gespeichert ist. Versuchen Sie, dies zu vermeiden, es sei denn, Sie haben einen bestimmten Grund dafür, da dies die Flexibilität des Geräts beeinträchtigt.

  • * X-ConditionMachineOf *: Mit dieser Anweisung kann dieses Gerät auf demselben Computer geplant werden, auf dem das angegebene Gerät geladen ist. Dies ist hilfreich für Sidekick-Einheiten oder für das Zusammenfassen zugeordneter Einheiten.

  • * X-Conflicts *: Dies ist das Gegenteil der obigen Deklaration, da hier Unit-Dateien angegeben werden, neben denen diese Unit nicht geplant werden kann. Dies ist nützlich, um auf einfache Weise die Hochverfügbarkeit zu konfigurieren, indem mehrere Versionen desselben Dienstes auf einem anderen Computer gestartet werden.

  • * X-ConditionMachineMetadata *: Hiermit werden Planungsanforderungen basierend auf den Metadaten der verfügbaren Computer festgelegt. In der Spalte "METADATA" der Ausgabe von "+ fleetctl list-machines +" sehen Sie die Metadaten, die für jeden Host festgelegt wurden. Um Metadaten festzulegen, übergeben Sie diese beim Initialisieren der Serverinstanz in Ihrer Cloud-Konfigurationsdatei.

  • * Global *: Dies ist eine spezielle Anweisung, die ein boolesches Argument verwendet, das angibt, ob dies auf allen Computern im Cluster geplant werden soll. Neben dieser Direktive können nur die Metadaten-Bedingungen verwendet werden.

Diese zusätzlichen Anweisungen geben einem Administrator mehr Flexibilität und Befugnis bei der Festlegung, wie Dienste auf den verfügbaren Computern ausgeführt werden sollen. Diese werden ausgewertet, bevor sie während der Phase "+ fleetctl load " an die Instanz " systemd +" einer bestimmten Maschine übergeben werden.

Dies bringt uns zum nächsten Punkt, auf den wir achten müssen, wenn wir mit verwandten Einheiten in + fleet + arbeiten. Das Dienstprogramm "+ fleetctl " bewertet keine Abhängigkeitsanforderungen außerhalb des Abschnitts " [X-Fleet] " der Einheitendatei. Dies führt zu interessanten Problemen bei der Arbeit mit Companion Units in ` fleet +`.

Dies bedeutet, dass das Tool "+ fleetctl +" zwar den erforderlichen Schritt unternimmt, um die Zieleinheit in den gewünschten Zustand zu versetzen, und den Vorgang des Übergebens, Ladens und Startens nach Bedarf basierend auf dem gegebenen Befehl durchläuft, dies jedoch nicht für die Abhängigkeiten der Einheit.

Wenn Sie also sowohl Ihre Haupt- als auch Ihre Sidekick-Einheit übermittelt, aber nicht geladen haben, geben Sie "+ fleetctl start main.service " ein und versuchen dann, die " main.service " - Einheit zu starten. Da jedoch die Einheit " sidekick.service " noch nicht geladen ist und " fleetctl " die Abhängigkeitsinformationen nicht auswertet, um die Abhängigkeitseinheiten durch den Lade- und Startvorgang zu bringen, schlägt die Einheit " main.service " fehl . Dies liegt daran, dass, sobald die Instanz " systemd " der Maschine die Einheit " main.service " verarbeitet, sie " sidekick.service " nicht finden kann, wenn _it_ die Abhängigkeiten auswertet. Die Einheit " sidekick.service +" wurde nie in die Maschine geladen.

Um diese Situation beim Umgang mit Companion Units zu vermeiden, können Sie die Dienste gleichzeitig manuell starten, ohne sich auf die Anweisung + BindsTo = + zu verlassen, die den Sidekick in einen aktiven Zustand versetzt:

fleetctl start main.service sidekick.service

Eine andere Möglichkeit besteht darin, sicherzustellen, dass die Sidekick-Einheit mindestens geladen ist, wenn die Haupteinheit ausgeführt wird. In der Ladephase wird eine Maschine ausgewählt und die Unit-Datei an die lokale Instanz "+ systemd " übergeben. Dies stellt sicher, dass die Abhängigkeiten erfüllt sind und dass die Direktive ` BindsTo = +` korrekt ausgeführt werden kann, um die zweite Unit aufzurufen:

fleetctl load main.service sidekick.service
fleetctl start main.service

Denken Sie daran, falls Ihre verbundenen Einheiten nicht korrekt auf Ihre Befehle + fleetctl + reagieren.

Instanzen und Vorlagen

Eines der leistungsstärksten Konzepte bei der Arbeit mit "+ fleet +" sind Einheitenvorlagen.

Einheitenvorlagen basieren auf einer Funktion von "+ systemd +", die "Instanzen" genannt wird. Hierbei handelt es sich um instanziierte Einheiten, die zur Laufzeit durch Verarbeitung einer Vorlageneinheitendatei erstellt werden. Die Vorlagendatei ist größtenteils einer normalen Unit-Datei sehr ähnlich, mit ein paar kleinen Änderungen. Diese sind jedoch bei richtiger Anwendung äußerst leistungsfähig.

Vorlagendateien können durch das "+ @ +" in ihrem Dateinamen identifiziert werden. Während ein herkömmlicher Dienst diese Form annimmt:

.service

Eine Vorlagendatei kann folgendermaßen aussehen:

@.service

Wenn eine Einheit aus einer Vorlage instanziiert wird, wird ihre Instanzkennung zwischen dem Suffix "+ @ " und " .service +" eingefügt. Diese ID ist eine eindeutige Zeichenfolge, die vom Administrator ausgewählt wird:

@.service

Auf den Namen der Basiseinheit kann in der Einheitendatei mit dem Bezeichner "% p +" zugegriffen werden. Ebenso kann mit `% i +` auf die angegebene Instanzkennung zugegriffen werden.

Hauptgerätedatei als Vorlage

Dies bedeutet, dass Sie anstelle der Erstellung Ihrer Hauptgerätedatei mit dem Namen "+ apache.1.service " mit den zuvor angezeigten Inhalten eine Vorlage mit dem Namen " apache @ .service +" erstellen können, die folgendermaßen aussieht:

[Unit]
Description=Apache web server service on port %i

# Requirements
Requires=etcd.service
Requires=docker.service
Requires=apache-discovery@%i.service

# Dependency ordering
After=etcd.service
After=docker.service
Before=apache-discovery@%i.service

[Service]
# Let processes take awhile to start up (for first run Docker containers)
TimeoutStartSec=0

# Change killmode from "control-group" to "none" to let Docker remove
# work correctly.
KillMode=none

# Get CoreOS environmental variables
EnvironmentFile=/etc/environment

# Pre-start and Start
## Directives with "=-" are allowed to fail without consequence
ExecStartPre=-/usr/bin/docker kill apache.%i
ExecStartPre=-/usr/bin/docker rm apache.%i
ExecStartPre=/usr/bin/docker pull /apache
ExecStart=/usr/bin/docker run --name apache.%i -p ${COREOS_PUBLIC_IPV4}:%i:80 \
/apache /usr/sbin/apache2ctl -D FOREGROUND

# Stop
ExecStop=/usr/bin/docker stop apache.%i

[X-Fleet]
# Don't schedule on the same machine as other Apache instances
X-Conflicts=apache@*.service

Wie Sie sehen, haben wir die Abhängigkeit von "+ apache-discovery.1.service " in " apache-discovery @% i.service " geändert. Dies bedeutet, dass wenn wir eine Instanz dieser Unit-Datei mit dem Namen " apache @ 8888.service " haben, dies einen Sidekick mit dem Namen " apache-discovery @ 8888.service " erfordert. Das `% i +` wurde durch die Instanzkennung ersetzt. In diesem Fall verwenden wir den Bezeichner, um dynamische Informationen über die Art und Weise zu speichern, in der unser Dienst ausgeführt wird, insbesondere den Port, auf dem der Apache-Server verfügbar sein wird.

Damit dies funktioniert, ändern wir den Parameter "+ docker run ", der die Ports des Containers für einen Port auf dem Host freigibt. In der statischen Unit-Datei haben wir den Parameter " $ {COREOS_PUBLIC_IPV4}: 80: 80 " verwendet, der den Port 80 des Containers dem Port 80 des Hosts auf der öffentlichen IPv4-Schnittstelle zuordnet. In dieser Vorlagendatei haben wir dies durch " $ {COREOS_PUBLIC_IPV4}:% i: 80 +" ersetzt, da wir die Instanzkennung verwenden, um uns mitzuteilen, welcher Port zu verwenden ist. Eine geschickte Wahl für die Instanzkennung kann eine größere Flexibilität in Ihrer Vorlagendatei bedeuten.

Der Docker-Name selbst wurde ebenfalls so geändert, dass er auch einen eindeutigen Containernamen verwendet, der auf der Instanz-ID basiert. Beachten Sie, dass Docker-Container das Symbol "+ @ +" nicht verwenden können. Wir hatten also einen anderen Namen als die Unit-Datei gewählt. Wir ändern alle Anweisungen, die für den Docker-Container gelten.

Im Abschnitt "+ [X-Fleet] +" haben wir auch die Planungsinformationen geändert, um diese instanziierten Einheiten anstelle der zuvor verwendeten statischen Einheiten zu erkennen.

Sidekick-Einheit als Vorlage

Wir können ein ähnliches Verfahren durchführen, um die Sidekick-Einheit für das Templating anzupassen.

Unsere neue Sidekick-Unit heißt "+ apache-discovery @ .service +" und sieht folgendermaßen aus:

[Unit]
Description=Apache web server on port %i etcd registration

# Requirements
Requires=etcd.service
Requires=apache@%i.service

# Dependency ordering and binding
After=etcd.service
After=apache@%i.service
BindsTo=apache@%i.service

[Service]

# Get CoreOS environmental variables
EnvironmentFile=/etc/environment

# Start
## Test whether service is accessible and then register useful information
ExecStart=/bin/bash -c '\
 while true; do \
   curl -f ${COREOS_PUBLIC_IPV4}:%i; \
   if [ $? -eq 0 ]; then \
     etcdctl set /services/apache/${COREOS_PUBLIC_IPV4} \'{"host": "%H", "ipv4_addr": ${COREOS_PUBLIC_IPV4}, "port": %i}\' --ttl 30; \
   else \
     etcdctl rm /services/apache/${COREOS_PUBLIC_IPV4}; \
   fi; \
   sleep 20; \
 done'

# Stop
ExecStop=/usr/bin/etcdctl rm /services/apache/${COREOS_PUBLIC_IPV4}

[X-Fleet]
# Schedule on the same machine as the associated Apache service
X-ConditionMachineOf=apache@%i.service

Wir haben dieselben Schritte durchlaufen, bei denen anstelle der statischen Version die instanziierte Version der Hauptprozesseinheit angefordert und an diese gebunden wurde. Dadurch wird die instanziierte Sidekick-Einheit mit der richtigen instanziierten Haupteinheit abgeglichen.

Während des Befehls "+ curl +", wenn wir die tatsächliche Verfügbarkeit des Dienstes überprüfen, ersetzen wir den statischen Port 80 durch die Instant-ID, damit die Verbindung zum richtigen Ort hergestellt wird. Dies ist erforderlich, da wir die Port-Exposure-Zuordnung im Docker-Befehl für unser Hauptgerät geändert haben.

Wir ändern auch den "Port", der in "+ etcd " protokolliert wird, so dass er dieselbe Instanz-ID verwendet. Mit dieser Änderung sind die in " etcd +" gesetzten JSON-Daten vollständig dynamisch. Der Hostname, die IP-Adresse und der Port, an dem der Dienst ausgeführt wird, werden abgerufen.

Schließlich ändern wir die Bedingung im Abschnitt "+ [X-Fleet] +" erneut. Wir müssen sicherstellen, dass dieser Prozess auf demselben Computer wie die Haupteinheitsinstanz gestartet wird.

Einheiten aus Vorlagen instanziieren

Um Einheiten aus einer Vorlagendatei zu instanziieren, haben Sie verschiedene Möglichkeiten.

Sowohl + fleet + als auch + systemd + können symbolische Links verarbeiten, wodurch wir die Möglichkeit haben, Links mit den vollständigen Instanz-IDs zu den Vorlagendateien wie folgt zu erstellen:

Dadurch werden zwei Links mit den Namen "+ apache @ 8888.service " und " apache-discovery @ 8888.service " erstellt. Jede dieser Einheiten verfügt über alle Informationen, die für die Ausführung dieser Einheiten durch " Flotte " und " Systemd +" erforderlich sind. Sie werden jedoch auf die Vorlagen zurückgeführt, damit wir alle erforderlichen Änderungen an einer einzigen Stelle vornehmen können.

Wir können diese Services dann mit + fleetctl + wie folgt einreichen, laden oder starten:

Wenn Sie keine symbolischen Links zum Definieren Ihrer Instanzen erstellen möchten, können Sie die Vorlagen auch selbst in + fleetctl + einreichen.

Sie können Einheiten aus diesen Vorlagen direkt in + fleetctl + instanziieren, indem Sie zur Laufzeit nur Instanz-IDs zuweisen. Beispielsweise könnten Sie den gleichen Dienst ausführen, indem Sie Folgendes eingeben:

Dies macht symbolische Verknüpfungen überflüssig. Einige Administratoren bevorzugen den Verknüpfungsmechanismus, da Sie die Instanzdateien jederzeit zur Verfügung haben. Sie können auch ein Verzeichnis an + fleetctl + übergeben, damit alles auf einmal gestartet wird.

Beispielsweise haben Sie in Ihrem Arbeitsverzeichnis möglicherweise ein Unterverzeichnis mit dem Namen "+ templates " für Ihre Vorlagendateien und ein Unterverzeichnis mit dem Namen " instance " für die instanziierten verknüpften Versionen. Sie könnten sogar ein " static +" für Einheiten ohne Vorlage haben. Das könnten Sie so machen:

mkdir templates instances static

Sie können dann Ihre statischen Dateien in "+ static" und Ihre Vorlagendateien in "+ templates" verschieben:

mv apache.1.service apache-discovery.1.service static
mv [email protected] [email protected] templates

Von hier aus können Sie die benötigten Instanzverknüpfungen erstellen. Lassen Sie uns unseren Service auf den Ports "+ 5555 ", " 6666 " und " 7777 +" ausführen:

Sie können dann alle Instanzen auf einmal starten, indem Sie Folgendes eingeben:

cd ..
fleetctl start instances/*

Dies kann sehr hilfreich sein, um Ihre Dienste schnell zu starten.

Fazit

Sie sollten zu diesem Zeitpunkt ein gutes Verständnis dafür haben, wie Unit-Dateien für "+ fleet " erstellt werden. Indem Sie einige der in Gerätedateien verfügbaren dynamischen Funktionen nutzen, können Sie sicherstellen, dass Ihre Dienste gleichmäßig verteilt sind, in der Nähe ihrer Abhängigkeiten und nützliche Informationen mit " etcd +" registrieren.

In einem later guide wird das Konfigurieren erläutert Ihre Container, um die Informationen zu verwenden, die Sie bei + etcd + registrieren. Dies kann Ihre Services dabei unterstützen, ein funktionierendes Wissen über Ihre tatsächliche Bereitstellungsumgebung aufzubauen, um Anforderungen an die entsprechenden Container im Backend weiterzuleiten.