Live Previews mit Kubernetes, Helm und GitLab

Wenn ein Entwickler mit einer Aufgabe fertig ist, möchte er den geänderten Code in der Regel in den Master mergen. Bevor das geschieht, ist jedoch oft eine Rücksprache mit anderen Teammitgliedern notwendig. Insbesondere wenn dabei das Feedback von UX-Designern, Mitarbeitern der Qualitätskontrolle oder etwa Product Ownern benötigt wird. Wenn diese den Code erst selbst ausführen müssen, vergeht meist wertvolle Zeit.
Mit Review-Apps lässt sich dieser Prozess beschleunigen, indem automatisiert eine Live-Preview für jeden neuen Merge/Pull-Request direkt in der Cloud erstellt wird. Da solche Review-Apps in einer Art Staging-Umgebung ausgeführt werden, sind sie dem Produktivsystem extrem ähnlich und bieten somit eine sehr realistische Vorschau aller Änderungen. Da Theorie und Praxis in der Informatik Hand in Hand gehen sollten, zeigen wir in diesem Artikel, wie man Container-Technologien in Verbindung mit DevOps-Methoden nutzen kann, um automatische Review-Apps direkt in der Cloud erstellen zu lassen.
Möchte man Review-Apps nutzen, eignen sich Container hervorragend dafür, denn mit ihnen bleiben Anwendungen leichtgewichtig und werden dennoch sehr portabel. Container-Technologien erlauben somit schlanke Build-Prozesse und beschleunigen das Deployment der Review-Apps. Zum Ausführen von Containern benötigt man eine Container Runtime wie beispielsweise Docker [1] oder rkt [2]. Da ein manuelles Verwalten der laufenden Container bei steigender Anzahl an Review-Apps kaum möglich ist, benötigt man zusätzlich einen Container-Orchestrator wie Kubernetes [3] oder Marathon [4].
Diese Technologien steuern beispielsweise, auf welcher Maschine innerhalb der Cloud eine Review-App gestartet wird, teilen entsprechende Rechenressourcen zu und kümmern sich um das Netzwerk-Routing innerhalb der Cloud. In diesem Artikel arbeiten wir exemplarisch mit Docker und Kubernetes, da beide zu den populärsten Lösungen zählen. Als Code-Repository nutzen wir in diesem Praxis-Beispiel GitLab [5], da hier bereits eine Continuous Integration-Lösung mit an Bord ist (GitLab CI). Ähnliches kann man beispielsweise aber auch mit einem GitHub- [6] oder Bitbucket-Repository [7] in Verbindung mit einem Jenkins-Server [8] erzielen.
Voraussetzungen
Um verschiedene Review-Apps für jeden git Commit erzeugen zu können, muss eine Basis-Domain (oder Subdomain) verfügbar sein, bei der ein Wildcard DNS Record gesetzt werden kann. Eine beispielhafte DNS-Konfiguration für die Basis-Domain reviews.covexo.de könnte wie folgt aussehen:
reviews.covexo.com. IN A 192.168.0.1 *.reviews.covexo.com. IN CNAME reviews.covexo.de
Integration von GitLab, GitLab Runner und Kubernetes
GitLab ist eine Open Source-Alternative zu GitHub und kann sowohl selbst gehostet [9] als auch "as a Service" über gitlab.com verwendet werden. Neben der Möglichkeit, bereits bestehende Kubernetes Cluster mit GitLab zu verbinden, lassen sich seit Version 10.1 sogar voll funktionsfähige Kubernetes Cluster mit wenigen Klicks erstellen [10]. Dazu gibt man GitLab durch einen Klick auf Sign in with Google Zugriff auf das Google-Nutzer-Konto. Im Hintergrund erhält GitLab dabei über das oAuth-Protokoll [11] eine Berechtigung für das Abrufen und Verwalten von Diensten der Google Cloud.
Anschließend lassen sich direkt aus GitLab Kubernetes Cluster erstellen, die dann bereits mit GitLab verbunden sind. Diese Option gibt es sowohl in der selbst gehosteten Version als auch auf gitlab.com. Im Hintergrund erhält GitLab dabei die URL der Kubernetes-API, die auf den Master Nodes innerhalb des Clusters läuft. Zudem erhält GitLab einen Kubernetes Service Account Token [12], der zur Authentifizierung bei jedem API-Request mitgeschickt wird und mit dem GitLab für bestimmte API-Requests autorisiert ist. Weitergehende Informationen zur Verwaltung solcher Berechtigungen lassen sich der Dokumentation zum Thema Role-Based Access Control in Kubernetes entnehmen [13].
Neben der Integration von Kubernetes und GitLab wird außerdem noch der GitLab Runner benötigt. Dieser ist dafür zuständig, CI Jobs auszuführen. Welche Jobs ausstehen und wo sie ausgeführt werden sollen, fragt der GitLab Runner in einem festgelegten Intervall über die REST-API von GitLab ab. Der dafür notwendige Access Token kann in der GitLab UI über Settings > CI/CD > Runners Settings erstellt werden und muss entsprechend in der Konfigurationsdatei des Runners hinterlegt werden. Neben dem API Access Token wird in der Runner-Konfiguration außerdem festgelegt, wie viele CI-Jobs maximal parallel ausgeführt werden dürfen (concurrent), über welche URL die GitLab-API erreichbar ist und mit welchem Executor (Shell, Docker, Docker Machine, Parallels, VirtualBox, SSH, Kubernetes) die CI-Jobs ausgeführt werden sollen.
Auch wenn unsere Review-Apps später in einem Kubernetes Cluster laufen sollen, können die CI-Jobs, die unsere Review-Apps deployen, mit einem anderen Executor als Kubernetes betrieben werden. Eine gängige Option wäre hier jedoch, ebenfalls den Kubernetes Executor zu verwenden, aber ggf. ein separates Kubernetes Cluster nur für die Ausführung der CI-Jobs zu verwenden. Eine entsprechende Runner-Konfiguration könnte wie folgt aussehen:
concurrent = 4 [[runners]] name = "My GitLab CI Runner" url = "https://gitlab.com/ci" token = "...." executor = "kubernetes" [runners.kubernetes] namespace = "ci-jobs"
Demo-Projekt mit Dockerfile
Bevor wir uns Kubernetes und GitLab widmen, benötigen wir eine Beispiel-Anwendung. Dazu nutzen wir eine Node.js-Anwendung, die lediglich aus der Datei src/main.js besteht und wie folgt aussieht:
const http = require("http"); // <== Webserver Package const app = new http.Server(); // <== Webserver erstellen app.on("request", (req, res) => { // <== Callback Funktion für HTTP Anfragen res.writeHead(200, {"Content-Type": "text/plain"}); res.write("Hello World"); res.end("\n"); }); app.listen(5000); // <== Webserver läuft auf Port 5000
Diese Anwendung erstellt einen Webserver und beantwortet HTTP-Requests mit "Hello World". Um diese Node.js-Anwendung mit Docker ausführen zu können, benötigen wir ein Docker-Image, das durch den "docker build"-Befehl aus folgendem Dockerfile erzeugt werden kann:
FROM node:8.8.1 ENV PORT=5000 EXPOSE ${PORT}
Füge unseren Source-Code zum Docker-Image hinzu
ADD ./src /app WORKDIR /app CMD ["npm", "start"]
Nachdem wir ein Projekt in GitLab angelegt haben, können wir beide Dateien via git zu diesem Projekt hinzufügen.
Kubernetes-Ressourcen
In Kubernetes werden Anwendungen in Form von Ressourcen erstellt. Diese Ressourcen sind deklarative Darstellungen eines gewünschten Zustands. Das Bedeutet, es müssen keine prozeduralen Befehle ausgeführt werden, um eine Anwendung zu starten, sondern es wird deklarativ angegeben, wie die Anwendung im gewünschten Zustand betrieben werden soll. Für unser kleines Demo-Projekt verwenden wir drei Arten von Ressourcen, nämlich StatefulSet, Service und Ingress. Alle Ressourcen werden üblicherweise als YAML-Dateien angelegt [14] (alternativ auch JSON [15]) und können mit diesem Befehl in Kubernetes erstellt werden:
kubectl apply -f my-resource.yaml
Tipp: Neben dem deklarativen kubectl apply könnte man auch das imperative kubectl create verwenden. Wir empfehlen allerdings den deklarativen Ansatz, da dieser Patches für bereits existierende Ressourcen verwendet. Ein detaillierter Vergleich von deklarativem und imperativem Ressourcen-Management findet sich in der offiziellen Kubernetes-Dokumentation [16].
Beispiele für Kubernetes-Ressourcen, mit denen unser Demo-Projekt ausgeführt werden kann, werden in den folgenden Abschnitten erklärt.
StatefulSet
StatefulSets, die seit der Kubernetes Version 1.9 den stable-Status besitzen, sind eine spezielle Form des Deployments und dienen dazu, sicherzustellen, dass immer eine vordefinierte Anzahl an bestimmten Pods im Cluster ausgeführt werden. Ein Pod in einem Kubernetescluster beschreibt eine Gruppe Anwendungscontainer, die einen gemeinsamen Speicher- und Netzwerkraum besitzen. Sie bilden die Grundeinheit in einem Cluster und werden in der Ressourcendefinition eines StatefulSets unter dem Feld template definiert.
Zusätzlich zu normalen Deploymentressourcen, die sicherstellen, dass Pods mit einem definierten Vorgehen automatisch gestartet, geupdatet oder gelöscht werden, bieten Statefulsets eine Reihe zusätzlicher Features, um erstellte Pods einfacher zu identifizieren und deren Einzigartigkeit zu garantieren, wie z. B. einzigartige Netzwerknamen und das Deployen und Löschen von Pods in der selben Reihenfolge. Eine Beispieldefinition einer Statefulresource lässt sich hier sehen:
apiVersion: apps/v1 kind: StatefulSet metadata: name: demo-server labels: app: demo-server spec: replicas: 1 selector: matchLabels: app: demo-server template: metadata: labels: app: demo-server spec: containers: - name: nodejs-webserver image: "URL des GitLab images (z.B: gitlab.com/username/demo-server)" ports: - containerPort: 5000
Service
Pods besitzen eine bestimmte Lebensdauer und sind generell sterblich. Jedem Pod wird beim Start in einem Cluster eine eindeutige interne IP-Adresse zugewiesen, die sich allerdings ändern kann, falls ein Pod gelöscht werden sollte, was z. B. durch die Skalierung von Deployments oder die Optimierung der Nodeauslastung durch den Scheduler ausgelöst werden kann. Damit steht man vor einem Problem, wenn andere Anwendungen einen festen Endpunkt für die Kommunikation mit dem Pod erwarten.
Abhilfe schaffen Services, die eine Abstraktionsschicht innerhalb des Clusters darstellen und die Möglichkeit bieten, durch die Definition eines Pod-Selektors Anfragen auf eine Gruppe von Pods mittels eines festgelegten Verhaltens wie z. b. Round Robin weiterzuleiten. Da Services nicht neugestartet werden müssen und ihr Name und interne IP-Adresse konstant bleiben, ist es somit möglich, einen festen Endpunkt für die Kommunikation mit bestimmten Pods zu schaffen. In folgendem Codeabschnitt ist die Definition eines solchen Services zu sehen:
kind: Service apiVersion: v1 metadata: name: demo-server spec: selector: app: demo-server ports: - protocol: TCP port: 80 targetPort: 5000 type: ClusterIP
Ingress
Im Normalfall sind interne IP-Adressen von Services und Pods nicht außerhalb des Clusters erreichbar. Ein Ingress in Kubernetes definiert eine Art Regelkatalog, der dafür genutzt werden kann, eingehende Verbindungen von außerhalb des Clusters an interne Services weiterzuleiten. Die Ingressresource ist vor allem in Verbindung mit dem HTTP-Protokoll sehr nützlich, da es somit möglich ist, eingehende Verbindungen auf den selben Port sowie IP-Adresse auf entsprechende Services umzuverteilen. Dies wäre mit reinen Kubernetes-Services nicht ohne zusätzlichen Aufwand möglich, denen nur eine externe IP-Adresse zugewiesen wurde. Allerdings sollte beachtet werden, dass die Ingressresource nicht ohne einen zusätzlichen Ingress Controller funktioniert, der vorher im Cluster installiert werden muss. Einen guten Ingress Controller für eingehende HTTP/HTTPS sowie WebSocket-Verbindungen bietet Kubernetes mit dem Nginx Controller [17]. In unserem Beispiel definieren wir eine Ingressresource, die mit diesem Controller kompatibel ist:
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: demo-server spec: rules: - host: example.reviews.covexo.com http: paths: - path: / backend: serviceName: demo-server servicePort: 80
Parametrisierung von Kubernetes-Ressourcen in Form von Helm-Charts
Ein Problem der zuvor gezeigten Ressource-Definitionen für die Verwendung als Review-Apps ist jedoch, dass die gezeigten YAML-Dateien statisch sind. Da verschiedene Review-Apps jedoch parallel betrieben werden sollen, muss beispielsweise im Ingress eine unterschiedliche Domain festgelegt werden, die abhängig vom CI-Job bzw. vom Commit Hash ist. Zudem werden Kubernetes-Ressourcen über ihren Namen eindeutig identifiziert, wodurch es notwendig ist, dass die Ressourcen für verschiedene Review-Apps auch unterschiedliche Namen tragen.
Natürlich könnte man innerhalb eines CI-Jobs mit einem Befehl wie sed oder mit Template-Sprachen entsprechende Ressourcen generieren und dann übermitteln. Es gibt jedoch eine deutlich einfachere, Kubernetes-native Lösung hierfür. Seit Ende 2016 existiert eine stabile Version von Helm [18], einem Package-Manager für Kubernetes. Helm besteht aus einem Server namens Tiller, der direkt im Kubernetes Cluster läuft, und einem Client [19], der sich zu diesem Server verbindet. GitLab bietet einen One-Click-Installer für den Tiller Server an, dieser kann jedoch auch mit den folgenden Befehlen selbst in Kubernetes gestartet werden:
helm init --tiller-namespace=tiller --service-account=tiller
Dieser Befehl nutzt den Helm Client und installiert den Tiller Server im Namespace tiller. Dieser Tiller Server nutzt nur den Service-Account tiller, der über entsprechende Rechte verfügen sollte, um Kubernetes-Ressourcen in den Namespaces zu erstellen, die für die CI-Jobs und Review-Apps genutzt wird. Alle Kubernetes-Daten (API-Server, Tokens etc.) bezieht der Helm Client dabei übrigens ebenso wie kubectl aus der kubeconfig [20].
Packages für Kubernetes nennt man Helm Charts [21]. Sie bestehen mindestens aus einer Chart.yaml, einer values.yaml mit Default-Parametern im YAML-Format sowie den Templates für Kubernetes-Ressourcen, die im Ordner templates/ abgelegt werden. Eine rudimentäre Chart.yaml-Datei für unsere Review-Apps könnte so aussehen:
name: review-apps version: 0.0.1 description: review app example home: ht tps://GIT-REPO.URL sources: - ht tps://GIT-REPO.URL/tree/master
Und unsere Ressourcen könnten nun gemäß der golang-Template-Syntax [22] parametrisiert und in Form dieser Datei unter /templates/review-app.yaml gespeichert werden:
apiVersion: apps/v1 kind: StatefulSet metadata: name: {{ .Release.Name }} spec: replicas: 1 template: metadata: labels: app: {{ .Release.Name }} spec: containers: - name: nodejs-webserver image: "{{ .Values.image.url }}:{{ .Values.image.tag }}" ports: - containerPort: 5000 --- kind: Service apiVersion: v1 metadata: name: {{ .Release.Name }} spec: selector: app: {{ .Release.Name }} ports: - protocol: TCP port: 80 targetPort: 5000 type: ClusterIP --- apiVersion: extensions/v1beta1 kind: Ingress metadata: name: {{ .Release.Name }} spec: rules: - host: {{ .Release.Name }}.{{ .Values.baseUrl }} http: paths: - path: / backend: serviceName: {{ .Release.Name }} servicePort: 80
Tipp: Wie hier gezeigt, wird empfohlen, mehrere zusammengehörige Kubernetes-Ressourcen in einer YAML-Datei zusammenzufassen und mit --- zu separieren.
Die Parameter für das hier gezeigte Template werden dynamisch im CI-Job generiert und können dann bei der Installation des Charts als Argumente übergeben werden. Das Helm-Chart könnte somit wie folgt installiert werden:
helm install --wait --set baseUrl="reviews.covexo.com" "review-x" chart/
Das Ausführen dieses Befehls würde dazu führen, dass ein Helm-Release mit dem Namen review-x erstellt wird. Die Kubernetes-Ressourcen für dieses Release bietet das Helm-Chart, das im Ordner chart/ liegt, ergänzt durch die übergebenen Parameter (in diesem Fall baseUrl).
Tipp: Ist es nicht ganz sicher, ob das Release bereits existiert, kann man statt helm install auch helm upgrade --install verwenden, denn dann würde Helm zuerst versuchen, ein Upgrade bei einem potenziell existierenden Release durchzuführen und bei Fehlen eines existierenden Releases eine Installation durchführen. Dies eignet sich besonders im CI-Context, da man somit sehr leicht erzielen kann, dass eine Pipeline für eine Review-App erneut ausgeführt werden kann, z. B. wenn man eine Review-App pro git-Branch erstellt und bei jedem Commit updaten möchte.
Statt als Argumente können die Parameter für die Installation des Helm-Charts auch als Datei abgespeichert werden. Eine values.yaml-Datei mit äquivalenten Parametern könnte wie folgt aussehen:
baseUrl: review.covexo.com
Eine solche Parameter-Datei kann im Chart gespeichert werden, um Standard-Parameter festzulegen, oder kann bei der Installation des Helm-Charts wie folgt übergeben werden:
helm install --wait -f values.yaml "review-x" chart/
Um das Helm-Chart zu deinstallieren, kann folgender Befehl genutzt werden:
helm delete --purge "review-x"
Weiterführende Informationen zu Helm Charts und deren Verwendung finden sich in der offiziellen Dokumentation [23].
Deployment-Pipelines in Gitlab
Ist der GitLab Runner konfiguriert und mit GitLab verbunden, genügt es, eine Datei namens .gitlab-ci.yml mit git im Repository hinzuzufügen, die die Deployment-Pipeline definiert. Diese YAML-Datei definiert vor allem sog. Stages und Jobs. Stages werden nacheinander ausgeführt. Jeder Job ist genau einer Stage zugeteilt und enthält eine Liste von Befehlen (script), die nacheinander ausgeführt werden. Jobs, die zur selben Stage gehören, werden parallel ausgeführt.
Nutzt man einen Docker- oder Kubernetes-Executor im GitLab Runner, so kann man ein Image für jeden Job definieren. Das Script des Jobs wird dann innerhalb eines Docker-Containers ausgeführt, der von diesem Image erstellt wurde. Daneben können im YAML noch Umgebungsvariablen (variables) definiert werden. Zusätzlich setzt der GitLab Runner automatisch eine ganze Reihe an Umgebungsvariablen, die Informationen über das Repository, den aktuellen Commit und mehr enthalten. Eine vollständige Liste aller automatisch definierten Umgebungsvariablen findet sich in der Dokumentation von GitLab CI [24]. Folgende .gitlab-ci.yml-Datei könnte unsere Review-Apps mit Hilfe von Docker, Kubernetes und Helm erstellen:
image: docker:17.10.0-ce services: - docker:dind variables: DOCKER_HOST: tcp://localhost:2375 GOOGLE_ZONE: europe-west3-c GOOGLE_PROJECT: my-google-project GOOGLE_CLUSTER: cluster-1 BASE_URL: reviews.covexo.com IMAGE_TAG: "latest" stages: - package - review - cleanup docker-package: stage: package script: - export IMAGE_TAG=$CI_COMMIT_SHA - buildImage start-review: image: google/cloud-sdk stage: review script: - export IMAGE_TAG=$CI_COMMIT_SHA - gCloudConnect - setupHelmClient - deployHelmChart stop-review: image: google/cloud-sdk stage: cleanup script: - gCloudConnect - setupHelmClient - helm del --purge "review-$CI_COMMIT_REF_SLUG" when: manual
.define_functions: &define_functions | # Hier können Sie Funktionen definieren, die in allen CI Jobs verfügbar sein sollen. function buildImage() { docker build -t $CI_REGISTRY_IMAGE:$IMAGE_TAG . docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY docker push $CI_REGISTRY_IMAGE:$IMAGE_TAG } function gCloudConnect() { # Secrets wie $GOOGLE_KEY können über die GitLab CI definiert werden. echo "$GOOGLE_KEY" > key.json gcloud auth activate-service-account --key-file key.json gcloud config set compute/zone $GOOGLE_ZONE gcloud config set project $GOOGLE_PROJECT gcloud config set container/use_client_certificate True gcloud container clusters get-credentials $GOOGLE_CLUSTER } function setupHelmClient() { apt install -y openssl curl tar ca-certificates || echo "skip install basics" curl ht tps://kubernetes-helm.storage.googleapis.com/helm-v2.6.1-linux-amd64.tar.gz | tar zx mv linux-amd64/helm /usr/bin/ helm version --client helm init --client-only } function deployHelmChart() { helm dependency update chart/ helm dependency build chart/ helm upgrade --install \ --wait \ --set image.url="$CI_REGISTRY_IMAGE" \ --set image.tag="$IMAGE_TAG" \ --set baseUrl="$BASE_URL" \ --namespace="default" \ "review-$CI_COMMIT_REF_SLUG" \ chart/ } before_script: - *define_functions
Tipp: Zur Verbesserung der Übersichtlichkeit empfiehlt es sich, einen sog. Hidden-Job zu definieren, der nicht zur Pipeline gehört, aber wie in oben gezeigter Datei im before_script-Bereich aufgerufen wird. Dieser Job listet Funktionen, die aufgrund des before_script-Befehls vor der Ausführung jedes regulären Jobs definiert werden und dann innerhalb dieser regulären Jobs verwendet werden können. Die Spezifikation der .gitlab-ci.yml-Datei bietet noch viele weitere Features, die in der offiziellen Dokumentation im Detail beschreiben werden [25].
Die Ausführung dieser .gitlab-ci.yml würde für jeden git push eine Pipeline mit 3 Stages erzeugen, in denen jeweils ein Job ausgeführt wird. In der GitLab UI würde dies wie in Abb. 2 visualisiert werden.
Was passiert nun hier in den einzelnen Jobs?
- docker-package: Ein Docker-Image wird nach Vorgabe des Dockerfile gebaut und in die von GitLab bereitgestellte Docker Registry gespeichert.
- start-review: Eine Verbindung zur Google-Cloud wird hergestellt. Dann wird das im Projekt unter chart/ befindliche Helm-Chart installiert oder ein Upgrade durchgeführt, falls ein Release mit gleichem Namen bereits existiert.
- stop-review: Dieser Job ist als manual Job gekennzeichnet und wird daher nicht automatisch ausgeführt, sondern muss manuell gestartet werden. Durch einen Klick in der Gitlab UI kann mit diesem Job das Release und damit die Review-App entsprechend gelöscht werden.
Tipp: Der Output der einzelnen Befehle eines Jobs lässt sich in GitLab in Echtzeit verfolgen und auch nachträglich noch abrufen. Zudem können Pipelines manuell für einzelne Commits wiederholt gestartet werden.
Fazit und Ausblick
Review-Apps können den Entwicklungsprozess beschleunigen, indem Kollegen in die Lage versetzt werden, den veränderten Code direkt in Form einer Live-Preview testen zu können, ohne dass dabei manuelle Aufwände entstehen. Dadurch kann das Feedback auch von weniger technischen Team-Kollegen schneller eingeholt werden.
In dem hier gezeigten Beispiel sorgt Kubernetes für die Ausführung der Review-Apps in der Cloud, GitLab bzw. der GitLab Runner führt die CI-Jobs aus und Helm dient als Package-Manager zur Verwaltung und Parametrisierung der an Kubernetes übergebenen Ressourcen.
Neben Review gibt es eine weitere, weniger bekannte Möglichkeit, mit realistischen Previews in der Cloud zu arbeiten: Cloud Development [26]. Beim Cloud Development entwickelt man nicht mehr lokal, sondern hat seine Entwicklungsumgebung direkt in der Cloud, wodurch jederzeit ein Online-Prototyp verfügbar ist, der einfach via Hyperlink an Kollegen geschickt werden kann. Damit entfällt der Aufwand zur Konfiguration von Deployment-Pipelines und es kann dennoch direkt und schnell Feedback gegeben werden.
Für einen produktiven Einsatz von Review-Apps oder Cloud Development empfiehlt sich jedoch z. B. die Verwendung eines VPN (Virtual Private Network) oder einer HTTP-Authentifizierung (z. B. Basic Auth) in Verbindung mit SSL, damit Externe nicht die Möglichkeit haben, evtl. bestehende Sicherheitslücken in den noch in der Entwicklung befindlichen Prototypen auszunutzen. Zudem sollten diese Preview-Versionen niemals Zugriff auf Produktivdatenbanken oder ähnliches erhalten, sondern stets mit separaten Entwicklungsdaten arbeiten.
- Docker
- rkt
- Kubernetes
- Marathon
- GitLab
- GitHub
- Bitbucket
- Jenkins
- Gitlab: Installation
- Kubernetes Cluster mit wenigen Klicks erstellen
- oAuth
- Kubernetes Service Account Token
- Dokumentation: Role-Based Access Control in Kubernetes
- YAML
- JSON
- Dokumentation: Kubernetes
- Nginx Controller
- Helm
- Client zum Herunterladen
- Configure Access to Multiple Clusters
- Helm: Charts
- golang-Template-Syntax
- Dokumentation: Helm-Charts
- Dokumentation: GitLab CI
- Dokumentation: Yaml
- covexo
Neuen Kommentar schreiben