Upgrade des CES mit Blueprints
Ausprägungen des CES werden in einem sogenannten Blueprint (Englisch für Konstruktionszeichnung) festgehalten.
Ein Blueprint ist ein in JSON geschriebenes Dokument. Es beschreibt auf deklarative Weise den Zielzustand eines EcoSystems hinsichtlich:
- seiner installierten Dogus
- seiner weiteren Pakete, die zum Betrieb notwendig oder sinnvoll sind.
Aufbau eines Blueprints
In diesem Abschnitt werden Top-Level-Properties eines Blueprints erläutert.
Beispiel-Blueprint
Die Eigenschaften der hier aufgeführten Properties werden im folgenden Abschnitt "Aufbau eines Blueprints" erläutert.
{
"blueprintApi": "v1",
"blueprintId": "blueprint-id",
"cesappVersion": "4.2.3",
"dogus": [
{
"name": "official/redmine",
"version": "4.2.3-10",
"targetState": "present"
},
{
"name": "official/postfix",
"version": "3.2.4-1"
}
],
"packages": [
{
"name": "backup-watcher",
"version": "1.0.0"
}
],
"registryConfig": {
"nexus": {
"successfulInitialConfiguration": "true"
},
"_global": {
"domain": "ces.local"
}
},
"registryConfigEncrypted": {
"nexus": {
"admin_password": "nAtK3WSvdlYzeNmQhBkCeaTEGPMCHTcJimdtkncE...=="
}
}
}
Property blueprintApi
Diese Property definiert die Version des Blueprints. Je Version sind unterschiedliche, mögliche Implementierungen
denkbar, die den Funktionsumfang der cesapp
anzeigen, welche dieses Blueprint interpretiert. So lassen sich auch in
Zukunft mit Fortschritt der cesapp
noch vorherige Blueprints auswerten und anwenden.
Diese Property darf nicht leer sein.
Aktuell ist der Wert v1
erlaubt.
Property blueprintId
Diese Property dient zur eindeutigen Identifikation über unterschiedliche Blueprints hinweg, hat jedoch nur beschreibenden Charakter. Der Rahmen, in der die Eindeutigkeit ausreicht, wird durch die Organisation festgelegt, die diese Blueprints für sich einsetzt. Es bietet sich an, ein Versionierungsschema zu verwenden.
Da Blueprints darauf abzielen, Systemzustände nachzuvollziehen, sollten Blueprints nicht modifiziert werden, nachdem sie wenigstens einmal auf ein oder mehrere EcoSystem-Instanzen angewendet wurden. Stattdessen sollte ein Folge-Identifizierer für ein neues Blueprint gewählt werden.
Beispiel für aufeinander folgenden Blueprint-IDs für fünf unterschiedliche Blueprints:
"1.0.0 RC2"
"1.0.0"
"2.0.0 RC1"
"2.0.1 RC1"
"2.0.1"
Die blueprintId
darf nicht leer sein.
Property cesappVersion
Diese Property bezeichnet die genaue Version der cesapp
, also dem Tool, das das CES maßgeblich orchestriert. Weicht
diese Version von der bisher im CES installierten Version der cesapp
ab, dann wird die im Blueprint definiert Version
installiert und danach der Upgrade-Vorgang fortgesetzt.
Die Version der cesapp
kann unmittelbar mit Funktionalitäten oder Bugfixständen korrespondieren und muss mit ins
Gesamtbild der Dogus passen. Wie bei allen anderen Versionsangaben in einem Blueprint ist nur eine feste Versionsangabe
und keine Mindestversion oder Versionsintervalle möglich, um eine auditfähige Nachvollziehbarkeit zu gewährleisten.
Diese Property darf nicht leer sein.
Property dogus
Diese Property definiert eine Menge von Dogus, die installiert bzw. verändert werden sollen, sofern sie:
- noch nicht im EcoSystem vorhanden sind oder
- im EcoSystem vorhanden sind, aber nicht in der richtigen Version
Diese Property sowie deren Werte sind optional, die Reihenfolge der Einträge ist nicht relevant. Wenn ein Blueprint auf einem existierenden EcoSystem angewendet wird, in dem bereits bestimmte Dogus installiert sind, diese aber nicht genannt sind, dann wird die Behandlung dieser Dogus ignoriert und sie bleiben so bestehen, wie sie sind.
Dogu-Property innerhalb von dogus
Sofern vorhanden, müssen bzw. können einzelne Dogu-Einträge diese Properties enthalten:
-
name
- besteht aus Dogu-Namespace und Dogu-Name
- Beispiel:
"official/redmine"
- Pflichtangabe
-
version
- die Version des Dogus, die installiert werden soll (abhängig vom Dogu)
- Beispiel:
"3.15.2-2
- Bedingte Pflichtangabe, wenn mit
"targetState": "present"
dieses Teil installiert werden soll.
-
targetState
-
Kennzeichnet, ob das Dogu im Zielzustand vorhanden sein darf oder nicht
present
: Das Dogu muss in der angegebenen Version vorhanden sein, bzw. eine bestehende Version wird aktualisiertabsent
: Das Dogu darf nicht vorhanden sein, bzw. eine bestehende Version wird ersatzlos deinstalliert
- Optionale Angabe. Wenn Diese Property nicht vorhanden ist, dann wird standardmäßig
present
angenommen.
-
Dogus dürfen nicht mehrfach im Blueprint genannt werden. Auch nicht, wenn sie aus verschiedenen Namespaces stammen.
Property packages
Diese Property definiert eine Menge von Systempaketen, die installiert bzw. verändert werden sollen, sofern sie:
- noch nicht auf dem EcoSystem-Hostsystem vorhanden sind oder
- auf dem EcoSystem-Hostsystem installiert sind, aber nicht in der richtigen Version
Diese Property sowie deren Werte sind optional, die Reihenfolge der Einträge ist nicht relevant. Wenn ein Blueprint auf einem existieren EcoSystem angewendet wird, in dem bereits bestimmte Packages installiert sind, diese aber nicht genannt sind, dann wird die Behandlung dieser Pakete ignoriert und sie bleiben so bestehen, wie sie sind.
Package-Properties innerhalb von packages
Sofern vorhanden, müssen bzw. können einzelne Package-Einträge diese Properties enthalten:
-
name
- der Name des Pakets
- Beispiel:
"backup-watcher"
- Pflichtangabe
-
version
- die Version des Pakets, die installiert werden soll
- Beispiel:
"1.0.0
- Bedingte Pflichtangabe, wenn mit
"targetState": "present"
dieses Teil installiert werden soll.
-
targetState
-
Kennzeichnet, ob das Paket im Zielzustand vorhanden sein darf oder nicht
present
: Das Paket muss in der angegebenen Version vorhanden sein, bzw. eine bestehende Version wird aktualisiertabsent
: Das Paket darf nicht vorhanden sein, bzw. eine bestehende Version wird ersatzlos deinstalliert
- Optionale Angabe. Wenn Diese Property nicht vorhanden ist, dann wird standardmäßig
present
angenommen.
-
Wegen der besonderen Bedeutung, die der cesapp
im CES-Kontext zukommt, darf diese nicht im packages
-Bereich des
Blueprints definiert sein, sondern ausschließlich in der cesappVersion
-Property.
Verhalten des Wartungsmodus während eines Blueprint-Upgrades
Sobald ein Blueprint-Upgrade gestartet wird, wird der Wartungsmodus des CES aktiviert, um eine Nutzung der Dogus während des Vorgangs zu verhindern. Wenn der Vorgang abgeschlossen ist, wird der Wartungsmodus wieder deaktiviert und das CES kann wie gewohnt genutzt werden. Sollte der Wartungsmodus schon vor dem Start des Blueprint-Upgrades im CES aktiviert sein, wird er während des gesamten Vorgangs beibehalten und am Ende nicht deaktiviert.
Ausführung
Wird das oben beschriebene Blueprint mittels
cesapp upgrade blueprint Blueprint.json
angewendet, werden alle dort aufgelisteten Dogus in der angegebenen Version installiert. Downgrades werden generell nicht unterstützt, daher würde es zu Fehlern kommen, wenn die Dogus bereits in einer höheren Version installiert sind.
Registry-Keys setzen und entfernen
Setzen von etcd-Werten mittels Blueprint
Durch das Blueprint-Upgrade können Werte im etcd gesetzt werden. Der Aufbau des entsprechenden Bereiches
der blueprint.json
entspricht dabei dem Aufbau setup.json
.
Es können globale und dogu-spezifische etcd-Werte gesetzt werden. Verschlüsselte etcd-Werte müssen nach dem gleichen
Schema unter der Sektion registryConfigEncrypted
angelegt werden.
Das Setzen der Keys findet bei dem blueprint-Upgrade als letzter Schritt statt. Zuerst werden dabei alle globalen Werte und anschließend alle dogu-spezifischen etcd-Werte gesetzt.
Manche Dogus müssen gegebenenfalls neu gestartet werden, damit die Änderungen an der Registry bei ihnen wirksam werden. Darauf wird beim Ausführen des Blueprint-Upgrades hingewiesen.
Es ist nicht möglich, globale etcd-Werte verschlüsselt zu speichern. Dasselbe gilt für etcd-Werte eines Dogus, welches nicht installiert ist. Wird es dennoch versucht, so scheitert das blueprint-Upgrade.
Die verschlüsselten Werte werden verschlüsselt in der Blueprint-Historie abgespeichert.
Beispiel: blueprint.json
zum Setzen von etcd-Werten
{
"blueprintApi": "v1",
"blueprintId": "BP-ID",
"cesappVersion": "1.4.0",
"registryConfig": {
"doguName": {
"doguConfig" : "doguConfigValue",
"doguConfigGroup" : {
"doguConfig2" : "doguConfigValue",
"doguConfig3" : "doguConfigValue2"
}
},
"_global": {
"globalConfigKey": "globalConfigValue"
}
},
"registryConfigEncrypted": {
"backup": {
"key1" : "val1",
"key2" : {
"v1" : "val2",
"v2" : "val3"
}
}
},
"registryConfigAbsent": [
"_global/dir",
"_global/dir2/key1",
"_global/dir2/key2",
"cas/dir1/key1",
"cas/dir1/key2",
"cas/dir2",
"cas/key2"
]
}
Property registryConfig
Dieser Bereich entspricht der Struktur der Property registryConfig
der setup.json
. In geschachtelten JSON-Objekten
können die Werte und Struktur des Bereiches config
im etcd
bearbeitet werden. Dabei ist zu beachten, dass hier die
Werte im Klartext sowohl im Blueprint, als auch im etcd
abgelegt werden.
Property registryConfigEncrypted
Dieser Abschnitt entspricht dem bereits erläuterten Bereich registryConfig
. Der Unterschied jedoch liegt darin, dass
die Werte vor dem Ablegen im etcd
mittels der den Dogus zugehörigen Public Keys verschlüsselt werden. Vor der
Historisierung des Blueprints werden die Werte außerdem durch ihre verschlüsselten Pendants ersetzt.
Property registryConfigAbsent
Dieser Abschnitt erfüllt die Funktion zum Löschen von Registry-Keys. Die Angegebenen Keys werden vor dem Setzen neuer
Keys in der Registry gelöscht. Der Abschnitt unterscheidet sich von den Sektionen registryConfig
und registryConfigEncrypted
. Hier werden alle Keys oder alternativ auch Directories mit ihrem vollständigen Pfad
angegeben. Die Verschachtelung von Keys wird hier mit einem /
angegeben. Toplevel-Einträge können nicht gelöscht
werden. Also z.B. der Eintrag "_global" oder "cas" würde zu einem Fehler führen.
Beispiel:
Setzen von Keys:
{
"registryConfig": {
"cas": {
"keys": {
"key1": "value1",
"key2": "value2"
}
}
}
}
Löschen dieser Keys:
{
"registryConfigAbsent": [
"cas/keys/key1",
"cas/keys/key2"
]
}
Oder alternativ:
{
"registryConfigAbsent": [
"cas/keys"
]
}
Blueprint-Upgrade-Anpassungen via Blueprint Mask
Ein angepasstes Upgrade einer CES-Instanz mittels Blueprint und Blueprint Mask lässt sich via
cesapp upgrade blueprint --blueprint-mask blueprintmask.json blueprint.json
anstoßen, wobei die blueprint.json
die generellen Informationen enthält, welche durch die Informationen in der blueprintmask.json
angepasst werden.
Aufbau einer Blueprint Mask
Eine Blueprint Mask wird wie ein Blueprint als JSON-formatierte Textdatei angelegt. Darin werden verschiedene Properties beschrieben. Beispiel:
{
"blueprintMaskApi": "v1",
"blueprintMaskId": "BeispielMask",
"dogus": [
{
"name": "official/redmine",
"targetState": "absent"
},
{
"name": "postfix",
"targetState": "absent"
}
]
}
Property blueprintMaskApi
Diese Property definiert die Version der Blueprint Mask. Je Version sind unterschiedliche Implementierungen denkbar, die den Funktionsumfang der cesapp
anzeigen, welche diese Blueprint Mask interpretiert. So lassen sich auch in Zukunft mit Fortschritt der cesapp
noch vorherige Blueprint Masks auswerten und anwenden.
Diese Property darf nicht leer sein.
Aktuell ist der Wert v1
erlaubt.
Property blueprintMaskId
Diese Property dient zur eindeutigen Identifikation über unterschiedliche Blueprint Masks hinweg, hat jedoch nur beschreibenden Charakter. Der Rahmen, in der die Eindeutigkeit ausreicht, wird durch die Organisation festgelegt, die diese Blueprints für sich einsetzt. Es bietet sich an, ein Versionierungsschema zu verwenden.
Diese Property darf nicht fehlen oder leer sein.
Property dogus
Diese Property enthält ein JSON-Array, das aus Dogu-Objekten besteht. Diese Dogu-Objekte werden durch
ihren Namen (inklusive Namespace; bspw. "name": "official/scm"
) und den gewünschten Installationsstatus (present
oder absent
; bspw. "targetState": "present"
) beschrieben.
Es ist ebenfalls möglich, den Namen ohne Namespace anzugeben, da der Namespace in der blueprint.json
ohnehin verpflichtend ist.
Einschränkungen
Generell verändert eine Blueprint Mask nicht die Blueprint-JSON-Datei, sondern nur die Informationen, die beim Upgrade-Vorgang genutzt werden.
Mit der Blueprint Mask können nur Objekte verändert werden, die sich im Blueprint befinden, auf das die Mask angewendet wird. So lassen sich bspw. keine neuen Dogu-Objekte über die Mask hinzufügen.
Der targetState
einer Dogu-Definition in der Mask wird von der cesapp nicht inhaltlich validiert. Jeder targetState
, der nicht "absent"
ist, wird als "present"
interpretiert. Auch ein fehlender targetState
wird als "present"
interpretiert.
Namespace-Wechsel durch den Blueprint-Mechanismus
Durch den Blueprint-Mechanismus kann der Namespace eines Dogus gewechselt werden. Dabei kann auch gleichzeitig ein Upgrade stattfinden, indem einfach bei dem zu installierenden Dogu eine neuere Version angegeben wird.
Beispiel: Es ist official/meinDogu
in Version 1.0.0
installiert. In der auszuführenden blueprint.json
ist meinDogu in der
Version 1.0.1
und im Namespace premium
eingetragen. Ein Namespace-Wechsel (inklusive Upgrade) wird demnach beim Ausführen
der Blueprint durchgeführt.
Der Namespace-Wechsel muss explizit über den Blueprint-Befehl erlaubt werden.
Dies geschieht über den allow-namespace-switch
-Flag.
Beispiel: cesapp upgrade blueprint --allow-namespace-switch myBlueprint.json
.
Das Installieren einer älteren Version ist grundsätzlich nicht möglich.
Blueprint Historie
Die Informationen über alle durchgeführten Blueprint-Upgrades werden im etcd gespeichert. Dabei werden grundsätzlich die folgenden Werte historisiert:
- Der Zeitpunkt, an dem das letzte erfolgreiche Blueprint-Upgrade gestartet wurde (wird bei jedem Blueprint-Upgrade überschrieben).
- Der Zeitpunkt, an dem ein Blueprint-Upgrade abgeschlossen wurde.
- Die effektive
blueprint.json
. Sollte eine Blueprint-Maske verwendet worden sein, so sind die Auswirkungen dieser hier sichtbar.
Dazu werden, für den Fall, dass während eines Blueprint-Upgrades die Blueprint-Maske verwendet wurde, die folgenden Werte historisiert:
- Die
blueprintMask.json
- Die
blueprintOriginal.json
. Dies ist die Bueprint-Datei, ohne die Auswirkungen von der Blueprint-Maske.
Hinweis: Alle Timestamps sind im Format RFC3339
.
Aufbau etcd
Die oben aufgelisteten Werte sind unter diesen Keys im etcd zu finden:
/blueprint/current
/blueprint/<Startzeitpunkt>/endTime
/blueprint/<Startzeitpunkt>/blueprint.json
- ggf.
/blueprint/<Startzeitpunkt>/blueprintOriginal.json
- ggf.
/blueprint/<Startzeitpunkt>/blueprintMask.json
Ablauf
Zum Start des Blueprint-Upgrades wird die Zeit des Starts festgehalten. Nach Abschluss des Blueprint-Upgrades wird die blueprint.json
, sowie ggf. die blueprintMask.json
und die blueprintOriginal.json
inklusive Startzeitpunkt direkt im etcd gespeichert.
Wird das Blueprint-Upgrade erfolgreich durchlaufen, so wird anschließend im etcd der Endzeitpunkt sowie der Startzeitpunkt dieses Blueprint-Upgrades gespeichert.
Besonderheiten
Enthält eine blueprint.json
einen oder mehrere verschlüsselte Einträge, wird sie nicht in ihrer ursprünglichen Form in der Blueprint-Historie abgespeichert.
Die zu verschlüsselnden Werte werden mit den Public-Keys der entsprechenden Dogus verschlüsselt. In der blueprint.json
werden die zu verschlüsselnden Werte durch die verschlüsselten ersetzt und die veränderte Version wird in die Blueprint-Historie gespeichert.
Hierbei können gegebenenfalls Informationen (Formatierungen oder Werte, die von der cesapp
nicht erkannt werden) der blueprint.json
verloren gehen, da diese von der cesapp
auf die Klassenstruktur des Blueprints übertragen wird und daraus anschließend wieder eine .json
-Datei erstellt wird.
Beispiel: Abfrage der Werte im etcd
Um Informationen über das letzte durchgeführte Blueprint-Upgrade zu bekommen, muss zuerst der Startzeitpunkt des aktuellen Blueprint-Upgrades mit etcdctl get /blueprint/current
abgefragt werden.
Der Wert könnte wie folgt aussehen: 2019-09-27T09:14:42+02:00
Die blueprint.json
des letzten Blueprint-Upgrades wird durch den Befehl etcdctl get blueprint/2019-09-27T09:14:42+02:00/blueprint.json
aufgerufen.
Der Endzeitpunkt kann über die Abfrage etcdctl get blueprint/2019-09-27T09:14:42+02:00/endTime
ermittelt werden.
Die BlueprintId, des zuletzt erfolgreich ausgeführten Blueprint-Upgrades, kann über die Shell mithilfe des folgenden Befehls abgefragt werden:
etcdctl get /blueprint/$(etcdctl get /blueprint/current)/blueprint.json | jq -r ".blueprintId"