In Fortsetzung des vorherigen Artikels zu Bereitstellungstools in Kubernetes möchte ich Ihnen erläutern, wie Sie Jsonnet verwenden können, um die Beschreibung des Jobs in Ihrer Datei .gitlab-ci.yml zu vereinfachen

Gegeben
Es gibt eine Monorepa, in der:
- 10 Andockdateien
- 30 beschriebene Bereitstellungen
- 3 Umgebungen: Entwicklung , Inszenierung und Produktion
Herausforderung
Richten Sie eine Pipeline ein:
- Das Erstellen von Docker-Images sollte durch Hinzufügen eines Git-Tags mit einer Version erfolgen.
- Jeder Bereitstellungsvorgang sollte beim Senden an den Umgebungszweig und nur durch Ändern von Dateien in einem bestimmten Verzeichnis ausgeführt werden
- Jede Umgebung verfügt über einen eigenen Gitlab-Runner mit einem separaten Tag, der nur die Bereitstellung in der Umgebung durchführt.
- Nicht alle Anwendungen sollten in jeder der Umgebungen bereitgestellt werden, wir müssen die Pipeline beschreiben, um Ausnahmen vornehmen zu können.
- Einige Bereitstellungen verwenden das Git-Submodul und sollten mit der festgelegten Variablen
GIT_SUBMODULE_STRATEGY=normal
All dies zu beschreiben mag wie eine echte Hölle erscheinen, aber wir verzweifeln nicht und mit Jsonnet bewaffnet werden wir dies leicht und natürlich tun.
Lösung
gitlab-ci.yml verfügt über integrierte Funktionen zum Reduzieren der Beschreibung von wiederholten Jobs, die Sie beispielsweise erweitern oder einschließen können , bietet jedoch kein vollständiges Templating, sodass wir nicht die präzisesten und effizientesten beschreiben können.
Um dieses Problem zu lösen, empfehle ich die Verwendung von jsonnet, mit dem Sie die Code-Wiederholung bei der Beschreibung von Datenstrukturen fast vollständig beseitigen können.
Wenn Sie mit jsonnet arbeiten, empfehle ich dringend, ein Plugin für Ihren Editor zu installieren
Für vim gibt es beispielsweise ein vim-jsonnet-Plug-in , das die Syntaxhervorhebung aktiviert und bei jedem Speichern automatisch jsonnet fmt ausführt (dazu muss jsonnet installiert sein).
Schauen wir uns die Struktur unseres Repositorys an:
. ├── deploy │ ├── analyse │ ├── basin │ ├── brush │ ├── copper │ ├── dinner │ ├── dirty │ ├── drab │ ├── drunk │ ├── education │ ├── fanatical │ ├── faulty │ ├── guarantee │ ├── guitar │ ├── hall │ ├── harmonious │ ├── history │ ├── iron │ ├── maniacal │ ├── mist │ ├── nine │ ├── pleasant │ ├── polish │ ├── receipt │ ├── shop │ ├── smelly │ ├── solid │ ├── stroke │ ├── thunder │ ├── ultra │ └── yarn └── dockerfiles ├── dinner ├── drunk ├── fanatical ├── guarantee ├── guitar ├── harmonious ├── shop ├── smelly ├── thunder └── yarn
Docker-Images werden mit Kaniko erstellt
Die Bereitstellung von Anwendungen im Cluster erfolgt mit qbec . Jede Anwendung wird für drei verschiedene Umgebungen beschrieben. Um Änderungen am Cluster zu übernehmen, ist es ausreichend, Folgendes auszuführen:
qbec apply <environment> --root deploy/<app> --yes
wo:
<app>
- der Name unserer Anwendung<environment>
ist eine unserer Umgebungen: devel , stage oder prod .
Am Ende sollten unsere Jobs so aussehen:
Montage:
build:{{ image }}: stage: build tags: - build image: name: gcr.io/kaniko-project/executor:debug entrypoint: [""] script: - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/dockerfiles/{{ image }}/Dockerfile --destination $CI_REGISTRY_IMAGE/{{ image }}:$CI_COMMIT_TAG only: refs: - tags
Wobei anstelle von {{ image }}
der Verzeichnisname aus den Andockdateien ersetzt wird
Bereitstellen:
deploy:{{ environment }}:{{ app }}: stage: deploy tags: - {{ environment }} script: - qbec apply {{ environment }} --root deploy/{{ app }} --force:k8s-context __incluster__ --wait --yes only: changes: - deploy/{{ app }}/**/* refs: - {{ environment }}
Wobei anstelle von {{ app }}
der Verzeichnisname von deploy ersetzt wird,
und anstelle von {{ environment }}
- der Name der Umgebung, in der Sie implementieren möchten.
Beschreiben wir die Prototypen unserer Jobs als Objekte in einer separaten lib / jobs.jsonnet
{
Bitte beachten Sie, dass ich absichtlich keine refs
und tags
, um unsere Bibliothek flexibler zu gestalten und Ihnen die Funktionen von jsonnet vollständig zu demonstrieren. Wir werden sie später aus der Hauptdatei hinzufügen.
Nun werden wir unser .gitlab-ci.jsonnet beschreiben :
Beachten Sie die Funktionen ref , tag und submodule am Anfang der Datei, mit denen Sie ein überschreibendes Objekt erstellen können.
Eine kleine Erklärung: Wenn Sie " +:
" anstelle von " :
" zum Überschreiben von Objekten verwenden, können Sie einem vorhandenen Objekt oder einer vorhandenen Liste einen Wert hinzufügen.
Zum Beispiel " :
" für refs :
local job = { script: ['echo 123'], only: { refs: ['tags'] }, }; local ref(x) = { only+: { refs: [x] } }; job + ref('prod')
wird zurückkehren:
{ "only": { "refs": [ "prod" ] }, "script": [ "echo 123" ] }
Und hier ist das " +:
" für refs :
local job = { script: ['echo 123'], only: { refs: ['tags'] }, }; local ref(x) = { only+: { refs+: [x] } }; job + ref('prod')
wird zurückkehren:
{ "only": { "refs": [ "prod", "tags" ] }, "script": [ "echo 123" ] }
Wie Sie sehen, können Sie mit Jsonnet Ihre Objekte sehr effizient beschreiben und zusammenführen. Am Ausgang erhalten Sie immer fertiges JSON, das wir sofort in unsere Datei .gitlab-ci.yml schreiben können:
jsonnet .gitlab-ci.jsonnet > .gitlab-ci.yml
Überprüfen Sie die Anzahl der Zeilen:
Meiner Meinung nach ist es sehr gut!
Sie können weitere Beispiele sehen und Jsonnet direkt auf der offiziellen Website fühlen: jsonnet.org
Wenn Sie, wie ich, wie Jsonnet, dann schließen Sie sich unserer Gruppe im Telegramm t.me/jsonnet_ru an