Entfernen des veralteten Feature-Branches im Kubernetes-Cluster.

Entfernen des veralteten Feature-Branches im Kubernetes-Cluster.

Hallo! Feature-Branch (auch als Deploy-Vorschau, Review-App bekannt) — das ist, wenn nicht nur der Master-Branch, sondern auch jeder Pull Request auf eine einzigartige URL bereitgestellt wird. So kann überprüft werden, ob der Code in der Produktionsumgebung funktioniert, und das Feature kann anderen Entwicklern oder Produktmanagern gezeigt werden. Während Sie an einem Pull Request arbeiten, wird jeder neue Commit die aktuelle Bereitstellung für den alten Code entfernen, und es wird eine neue Bereitstellung für den neuen Code bereitgestellt. Fragen können auftauchen, wenn Sie den Pull Request in den Master-Branch gemergt haben. Der Feature-Branch ist dann nicht mehr erforderlich, aber die Ressourcen von Kubernetes bleiben weiterhin im Cluster.

Weitere Informationen zu Feature-Branches

Eine der Ansätze, um Feature-Branches in Kubernetes zu erstellen, ist die Verwendung von Namespaces. Kurz gesagt, die Produktionskonfiguration sieht folgendermaßen aus:

kind: Namespace
apiVersion: v1
metadata:
  name: habr-back-end
...

kind: Deployment
apiVersion: apps/v1
metadata:
  namespace: habr-back-end
spec:
  replicas: 3
...

Ein Namespace wird für den Feature-Branch mit seiner Kennung (z. B. die Nummer des Pull Requests) und einem bestimmten Prefix/Suffix (z. B. -pr-):

kind: Namespace
apiVersion: v1
metadata:
  name: habr-back-end-pr-17
...

kind: Deployment
apiVersion: apps/v1
metadata:
  namespace: habr-back-end-pr-17
spec:
  replicas: 1
...

Im Allgemeinen habe ich geschrieben Kubernetes Operator (eine Anwendung, die Zugriff auf Cluster-Ressourcen hat), Link zum Projekt auf GitHub. Er entfernt Namespaces, die sich auf alte Feature-Branches beziehen. In Kubernetes werden bei der Löschung eines Namespaces auch automatisch andere Ressourcen in diesem Namespace entfernt.

$ kubectl get pods --all-namespaces | grep -e "-pr-"
NAMESPACE            ... ALTER
habr-back-end-pr-264 ... 4d8h
habr-back-end-pr-265 ... 5d7h

Wie man Feature-Branches in den Cluster integriert, kann man nachlesen. hier und hier.

Motivation

Lassen Sie uns auf den typischen Lebenszyklus eines Pull Requests mit kontinuierlicher Integration schauen (continuous integration):

  1. Wir pushen einen neuen Commit in den Branch.
  2. Bei der Erstellung werden Linter und/oder Tests ausgeführt.
  3. Kubernetes-Konfigurationen des Pull Requests werden dynamisch generiert (z. B. wird die Nummer in eine Vorlage eingesetzt).
  4. Mit kubectl apply gelangen die Konfigurationen in den Cluster (Deployment).
  5. Der Pull Request wird in den Master-Branch gemergt.

Während Sie an einem Pull Request arbeiten, wird jedes neue Commit die aktuelle Bereitstellung des alten Codes entfernt, und eine neue Bereitstellung für den neuen Code wird bereitgestellt. Doch wenn der Pull Request in den Master-Branch gemergt wird, wird nur der Master-Branch gebaut. Am Ende haben wir den Pull Request bereits vergessen, aber seine Kubernetes-Ressourcen sind immer noch im Cluster.

Wie verwenden

Installieren Sie das Projekt mit dem folgenden Befehl:

$ kubectl apply -f https://raw.githubusercontent.com/dmytrostriletskyi/stale-feature-branch-operator/master/configs/production.yml

Erstellen Sie eine Datei mit folgendem Inhalt und wenden Sie sie mit kubectl apply -f:

apiVersion: feature-branch.dmytrostriletskyi.com/v1
kind: StaleFeatureBranch
metadata:
  name: stale-feature-branch
spec:
  namespaceSubstring: -pr-
  afterDaysWithoutDeploy: 3

Parameter namespaceSubstring notwendig, umNamespaces für Pull Requests von anderenNamespaces zu filtern. Zum Beispiel, wenn es im Cluster folgendeNamespaces gibt: habr-back-end, habr-front-end, habr-back-end-pr-17, habr-back-end-pr-33, dann sind die Kandidaten zur Löschung habr-back-end-pr-17, habr-back-end-pr-33.

Parameter afterDaysWithoutDeploy notwendig, um alteNamespaces zu löschen. Wenn einNamespace vor 3 Tagen 1 Stunde erstellt wurde und im Parameter angegeben ist 3 Tage, wird dieserNamespace gelöscht. Es funktioniert auch umgekehrt, wenn einNamespace vor 2 Tagen 23 Stunden erstellt wurde und im Parameter angegeben ist 3 Tageerstellt wurde, wird dieserNamespace nicht gelöscht.

Es gibt einen weiteren Parameter, der angibt, wie oft alleNamespaces gescannt werden sollen, um die Tage ohne Deployment zu überprüfen — checkEveryMinutes. Standardmäßig beträgt er 30 Minuten.

Wie es funktioniert

In der Praxis wird benötigt:

  1. Docker um in einer isolierten Umgebung zu arbeiten.
  2. Minikube wird einen Kubernetes-Cluster lokal starten.
  3. kubectl — ein Befehlszeilen-Interface zur Verwaltung des Clusters.

Starten wir den Kubernetes-Cluster lokal:

$ minikube start --vm-driver=docker
minikube v1.11.0 on Darwin 10.15.5
Verwenden des Docker-Treibers basierend auf dem vorhandenen Profil.
Starte die Steuerungsebene minikube im Cluster minikube.

Angeben kubectl verwenden Sie den lokalen Standard-Cluster:

$ kubectl config use-context minikube
Wechselte zu Kontext "minikube".

Laden der Konfigurationen für die Produktionsumgebung herunter:

$ curl https://raw.githubusercontent.com/dmytrostriletskyi/stale-feature-branch-operator/master/configs/production.yml > stale-feature-branch-production-configs.yml

Da die Produktionskonfigurationen so eingerichtet sind, dass sie alte Namespaces überprüfen, und in unserem neu erstellten Cluster keine vorhanden sind, ersetzen wir die Umgebungsvariable IS_DEBUG findet man true. Mit diesem Wert wird der Parameter afterDaysWithoutDeploy nicht berücksichtigt und die Namespaces werden nicht auf Tage ohne Deployment überprüft, sondern nur auf Teilübereinstimmungen (-pr-).

Wenn Sie Linux:

$ sed -i 's|false|true|g' stale-feature-branch-production-configs.yml

Wenn Sie macOS:

$ sed -i "" 's|false|true|g' stale-feature-branch-production-configs.yml

Projekt installieren:

$ kubectl apply -f stale-feature-branch-production-configs.yml

Überprüfung, dass die Ressource im Cluster erschienen ist StaleFeatureBranch:

$ kubectl api-resources | grep stalefeaturebranches
NAME                 ... APIGROUP                             ... KIND
stalefeaturebranches ... feature-branch.dmytrostriletskyi.com ... StaleFeatureBranch

Überprüfung, dass der Operator im Cluster erschienen ist:

$ kubectl get pods --namespace stale-feature-branch-operator
NAME                                           ... STATUS  ... AGE
stale-feature-branch-operator-6bfbfd4df8-m7sch ... Running ... 38s

Wenn Sie sich seine Protokolle ansehen, ist er bereit, Ressourcen zu verarbeiten. StaleFeatureBranch:

$ kubectl logs stale-feature-branch-operator-6bfbfd4df8-m7sch -n stale-feature-branch-operator
... "msg":"Operator Version: 0.0.1"}
...
... "msg":"Starting EventSource", ... , "source":"kind source: /, Kind="}
... "msg":"Starting Controller", ...}
... "msg":"Starting workers", ..., "worker count":1}

Bereitgestellte Fixtures (vordefinierte Konfigurationen zur Modellierung von Clusterressourcen) für die Ressource StaleFeatureBranch:

$ kubectl apply -f https://raw.githubusercontent.com/dmytrostriletskyi/stale-feature-branch-operator/master/fixtures/stale-feature-branch.yml

In den Konfigurationen ist angegeben, nach Namespaces mit einem Teilstring zu suchen. -pr- alle 1 Minute.:

apiVersion: feature-branch.dmytrostriletskyi.com/v1
kind: StaleFeatureBranch
metadata:
  name: stale-feature-branch
spec:
  namespaceSubstring: -pr-
  afterDaysWithoutDeploy: 1 
  checkEveryMinutes: 1

Der Operator hat reagiert und ist bereit, die Namespaces zu überprüfen:

$ kubectl logs stale-feature-branch-operator-6bfbfd4df8-m7sch -n stale-feature-branch-operator
... "msg":"Stale feature branch wird verarbeitet.","namespaceSubstring":"-pr-","afterDaysWithoutDeploy":1,"checkEveryMinutes":1,"isDebug":"true"}

Installieren Sie Fixtures, die zwei Namespaces enthalten (project-pr-1, project-pr-2) und deren deployments, Services, ingress, und so weiter:

$ kubectl apply -f https://raw.githubusercontent.com/dmytrostriletskyi/stale-feature-branch-operator/master/fixtures/first-feature-branch.yml -f https://raw.githubusercontent.com/dmytrostriletskyi/stale-feature-branch-operator/master/fixtures/second-feature-branch.yml
...
namespace/projekt-pr-1 erstellt
deployment.apps/projekt-pr-1 erstellt
service/projekt-pr-1 erstellt
horizontalpodautoscaler.autoscaling/projekt-pr-1 erstellt
secret/projekt-pr-1 erstellt
configmap/projekt-pr-1 erstellt
ingress.extensions/projekt-pr-1 erstellt
namespace/projekt-pr-2 erstellt
deployment.apps/projekt-pr-2 erstellt
service/projekt-pr-2 erstellt
horizontalpodautoscaler.autoscaling/projekt-pr-2 erstellt
secret/projekt-pr-2 erstellt
configmap/projekt-pr-2 erstellt
ingress.extensions/projekt-pr-2 erstellt

Überprüfen Sie, ob alle oben genannten Ressourcen erfolgreich erstellt wurden:

$ kubectl get namespace,pods,deployment,service,horizontalpodautoscaler,configmap,ingress -n projekt-pr-1 && kubectl get namespace,pods,deployment,service,horizontalpodautoscaler,configmap,ingress -n projekt-pr-2
...
NAME                              ... READY ... STATUS  ... AGE
pod/projekt-pr-1-848d5fdff6-rpmzw ... 1/1   ... Running ... 67s

NAME                         ... READY ... AVAILABLE ... AGE
deployment.apps/projekt-pr-1 ... 1/1   ... 1         ... 67s
...

Da wir aktiviert haben debug, die namespaces project-pr-1 und project-pr-2, sollten auch alle anderen Ressourcen sofort gelöscht werden, ohne den Parameter afterDaysWithoutDeploy. In den Operator-Logs ist das zu sehen:

$ kubectl logs stale-feature-branch-operator-6bfbfd4df8-m7sch -n stale-feature-branch-operator
... "msg":"Namespace sollte gelöscht werden, da der Debugmodus aktiviert ist.","namespaceName":"project-pr-1"}
... "msg":"Namespace wird bearbeitet.","namespaceName":"project-pr-1","namespaceCreationTimestamp":"2020-06-16 18:43:58 +0300 EEST"}
... "msg":"Namespace wurde gelöscht.","namespaceName":"project-pr-1"}
... "msg":"Namespace sollte gelöscht werden, da der Debugmodus aktiviert ist.","namespaceName":"project-pr-2"}
... "msg":"Namespace wird bearbeitet.","namespaceName":"project-pr-2","namespaceCreationTimestamp":"2020-06-16 18:43:58 +0300 EEST"}
... "msg":"Namespace wurde gelöscht.","namespaceName":"project-pr-2"}

Wenn Sie die Verfügbarkeit von Ressourcen überprüfen, befinden sie sich im Status Wird beendet (Löschvorgang) oder wurden bereits gelöscht (Ausgabe des Befehls ist leer).

$ kubectl get namespace,pods,deployment,service,horizontalpodautoscaler,configmap,ingress -n project-pr-1 && kubectl get namespace,pods,deployment,service,horizontalpodautoscaler,configmap,ingress -n project-pr-2
...

Sie können den Erstellungsprozess Fixtures mehrmals wiederholen und sicherstellen, dass sie innerhalb einer Minute gelöscht werden.

Alternativen

Was kann anstelle des Operators gemacht werden, der im Cluster arbeitet? Es gibt mehrere Ansätze, die alle nicht ideal sind (und deren Nachteile subjektiv sind), und jeder entscheidet selbst, was am besten für das jeweilige Projekt geeignet ist:

  1. Feature-Branch während des Builds des Continuous Integration Master-Branches zu löschen.

    • Dafür müssen Sie wissen, welcher Pull-Request zu dem Commit gehört, der kompiliert wird. Da der Namespace des Feature-Branches die Identifikation des Pull-Requests enthält – seine Nummer oder den Namen des Branches – muss diese Identifikation immer im Commit angegeben werden.
    • Die Builds der Master-Branches schlagen fehl. Zum Beispiel haben Sie folgende Schritte: Projekt herunterladen, Tests ausführen, Projekt erstellen, Release durchführen, Benachrichtigungen senden, Feature-Branch des letzten Pull-Requests bereinigen. Wenn der Build beim Senden der Benachrichtigung fehlschlägt, müssen Sie alle Ressourcen im Cluster manuell löschen.
    • Ohne den richtigen Kontext ist das Löschen des Feature-Branches im Master-Build nicht offensichtlich.

  2. Verwendung von Webhooks (Nummer 00 oder).

    • Möglicherweise ist dies nicht Ihr Ansatz. Zum Beispiel in Jenkins, unterstützt nur eine Art von Pipeline die Möglichkeit, ihre Konfigurationen im Quellcode zu speichern. Bei Verwendung von Webhooks müssen Sie Ihr eigenes Skript zur Verarbeitung schreiben. Dieses Skript muss im Jenkins-Interface platziert werden, was schwer zu warten ist.

  3. Schreiben Sie Cronjob und fügen Sie einen Kubernetes-Cluster hinzu.

    • Zeitaufwand für das Schreiben und die Wartung.
    • Der Operator arbeitet bereits in einem ähnlichen Stil, ist dokumentiert und wird unterstützt.

Vielen Dank für Ihr Interesse an dem Artikel. Link zum Projekt auf Github.

Quelle: habr.com

Zuverlässiges Webhosting mit DDoS-Schutz, VPS- und VDS-Server kaufen 🔥 Zuverlässiges Webhosting mit DDoS-Schutz, VPS- und VDS-Server kaufen | ProHoster