Löschen Sie einen veralteten Funktionszweig in einem Kubernetes-Cluster

Löschen Sie einen veralteten Funktionszweig in einem Kubernetes-Cluster

Hallo! Feature-Zweig (auch bekannt als Vorschau bereitstellen, App überprüfen) bedeutet, dass nicht nur der Master-Zweig bereitgestellt wird, sondern auch jede Pull-Anfrage an eine eindeutige URL. Sie können überprüfen, ob der Code in der Produktionsumgebung funktioniert, und die Funktion anderen Programmierern oder Produktmanagern zeigen. Während Sie an einer Pull-Anfrage arbeiten, wird bei jedem neuen Commit die aktuelle Bereitstellung für den alten Code entfernt und eine neue Bereitstellung für den neuen Code eingeführt. Wenn Sie einen Pull-Request in den Master-Zweig eingebunden haben, können Fragen auftauchen. Sie benötigen den Feature-Zweig nicht mehr, aber die Kubernetes-Ressourcen befinden sich weiterhin im Cluster.

Mehr über Feature-Branches

Ein Ansatz zum Erstellen von Feature-Branches in Kubernetes ist die Verwendung von Namespaces. Kurz gesagt sieht die Produktionskonfiguration so aus:

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

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

Für einen Feature-Zweig wird ein Namespace mit seiner Kennung (z. B. der Pull-Request-Nummer) und einem Präfix/Postfix (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 (Anwendung, die Zugriff auf Clusterressourcen hat), Projektlink auf Github. Es entfernt Namespaces, die zu alten Feature-Branches gehören. Wenn Sie in Kubernetes einen Namespace löschen, werden auch andere Ressourcen in diesem Namespace automatisch gelöscht.

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

Sie können lesen, wie Sie Feature-Branches in einem Cluster implementieren hier и hier.

Motivation

Werfen wir einen Blick auf einen typischen Pull-Request-Lebenszyklus für die kontinuierliche Integration (continuous integration):

  1. Wir pushen einen neuen Commit in die Filiale.
  2. Beim Build werden Linters und/oder Tests ausgeführt.
  3. Kubernetes-Pull-Request-Konfigurationen werden im Handumdrehen erstellt (z. B. wird ihre Nummer in die fertige Vorlage eingefügt).
  4. Mit kubectl apply gelangen die Konfigurationen in den Cluster (Deploy).
  5. Der Pull-Request wird in den Master-Zweig eingebunden.

Während Sie an einer Pull-Anfrage arbeiten, wird bei jedem neuen Commit die aktuelle Bereitstellung für den alten Code entfernt und eine neue Bereitstellung für den neuen Code eingeführt. Wenn jedoch eine Pull-Anfrage mit dem Master-Zweig zusammengeführt wird, wird nur der Master-Zweig erstellt. Infolgedessen stellt sich heraus, dass wir die Pull-Anfrage bereits vergessen haben und sich ihre Kubernetes-Ressourcen noch im Cluster befinden.

Wie zu 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 installieren Sie sie über kubectl apply -f:

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

Parameter namespaceSubstring Wird benötigt, um Pull-Request-Namespaces aus anderen Namespaces zu filtern. Wenn der Cluster beispielsweise über die folgenden Namespaces verfügt: habr-back-end, habr-front-end, habr-back-end-pr-17, habr-back-end-pr-33, dann werden die Kandidaten für die Löschung sein habr-back-end-pr-17, habr-back-end-pr-33.

Parameter afterDaysWithoutDeploy erforderlich, um alte Namespaces zu entfernen. Zum Beispiel, wenn ein Namespace erstellt wird 3 дня 1 час zurück, und der Parameter gibt an 3 дня, wird dieser Namespace entfernt. Funktioniert umgekehrt, wenn ein Namespace erstellt wird 2 дня 23 часа zurück, und der Parameter gibt an 3 дня, dieser Namespace wird nicht entfernt.

Es gibt noch einen weiteren Parameter, der dafür verantwortlich ist, wie oft alle Namespaces gescannt und nach Tagen ohne Bereitstellung gesucht werden sollen – checkEveryMinutes. Standardmäßig ist es gleich 30 минутам.

Wie funktioniert das

In der Praxis benötigen Sie:

  1. Docker in einer isolierten Umgebung zu arbeiten.
  2. Minikube wird lokal einen Kubernetes-Cluster erstellen.
  3. kubectl - Befehlszeilenschnittstelle für die Clusterverwaltung.

Wir erstellen den Kubernetes-Cluster lokal:

$ minikube start --vm-driver=docker
minikube v1.11.0 on Darwin 10.15.5
Using the docker driver based on existing profile.
Starting control plane node minikube in cluster minikube.

Angeben kubectl Verwenden Sie den lokalen Standardcluster:

$ kubectl config use-context minikube
Switched to context "minikube".

Laden Sie die Konfiguration 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 konfiguriert sind, dass sie nach alten Namespaces suchen und es in unserem neu erstellten Cluster keine gibt, werden wir die Umgebungsvariable ersetzen IS_DEBUG auf true. Mit diesem Wert ist der Parameter afterDaysWithoutDeploy wird nicht berücksichtigt und Namespaces werden nicht für Tage ohne Bereitstellung überprüft, sondern nur für das Vorkommen eines Teilstrings (-pr-).

Wenn Sie eingeschaltet sind Linux:

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

Wenn Sie eingeschaltet sind macOS:

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

Installation des Projekts:

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

Überprüfen, ob eine Ressource im Cluster angezeigt wurde StaleFeatureBranch:

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

Wir prüfen, ob ein Operator im Cluster aufgetaucht 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}

Wir installieren fertig fixtures (vorgefertigte Konfigurationen zur Modellierung von Clusterressourcen) für eine Ressource StaleFeatureBranch:

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

Die Konfigurationen geben an, nach Namespaces mit einer Teilzeichenfolge zu suchen -pr- einmal in 1 минуту.:

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

Der Betreiber hat reagiert und ist bereit, Namensräume zu prüfen:

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

Setzen fixtures, enthält zwei Namespaces (project-pr-1, project-pr-2) und ihnen deployments, services, ingress, usw:

$ 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/project-pr-1 created
deployment.apps/project-pr-1 created
service/project-pr-1 created
horizontalpodautoscaler.autoscaling/project-pr-1 created
secret/project-pr-1 created
configmap/project-pr-1 created
ingress.extensions/project-pr-1 created
namespace/project-pr-2 created
deployment.apps/project-pr-2 created
service/project-pr-2 created
horizontalpodautoscaler.autoscaling/project-pr-2 created
secret/project-pr-2 created
configmap/project-pr-2 created
ingress.extensions/project-pr-2 created

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

$ 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
...
NAME                              ... READY ... STATUS  ... AGE
pod/project-pr-1-848d5fdff6-rpmzw ... 1/1   ... Running ... 67s

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

Da haben wir eingeschlossen debug, Namensräume project-pr-1 и project-pr-2Daher müssen alle anderen Ressourcen sofort gelöscht werden, ohne den Parameter zu berücksichtigen afterDaysWithoutDeploy. Dies ist in den Protokollen des Betreibers ersichtlich:

$ kubectl logs stale-feature-branch-operator-6bfbfd4df8-m7sch -n stale-feature-branch-operator
... "msg":"Namespace should be deleted due to debug mode is enabled.","namespaceName":"project-pr-1"}
... "msg":"Namespace is being processing.","namespaceName":"project-pr-1","namespaceCreationTimestamp":"2020-06-16 18:43:58 +0300 EEST"}
... "msg":"Namespace has been deleted.","namespaceName":"project-pr-1"}
... "msg":"Namespace should be deleted due to debug mode is enabled.","namespaceName":"project-pr-2"}
... "msg":"Namespace is being processing.","namespaceName":"project-pr-2","namespaceCreationTimestamp":"2020-06-16 18:43:58 +0300 EEST"}
... "msg":"Namespace has been deleted.","namespaceName":"project-pr-2"}

Wenn Sie die Verfügbarkeit von Ressourcen prüfen, werden diese im Status angezeigt Terminating (Löschvorgang) oder bereits gelöscht (Befehlsausgabe 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 Erstellungsvorgang wiederholen fixtures mehrmals und stellen Sie sicher, dass sie innerhalb einer Minute entfernt werden.

Alternativen

Was kann man anstelle eines Operators tun, der in einem Cluster arbeitet? Es gibt mehrere Ansätze, alle sind nicht ideal (und ihre Mängel sind subjektiv), und jeder entscheidet selbst, was für ein bestimmtes Projekt das Beste ist:

  1. Entfernen Sie den Feature-Branch während der Erstellung der kontinuierlichen Integration des Master-Branchs.

    • Dazu müssen Sie wissen, welcher Pull-Request zu dem Commit gehört, der erstellt wird. Da der Feature-Branch-Namespace die Pull-Request-ID enthält – seine Nummer oder den Namen des Branchs – muss die ID immer im Commit angegeben werden.
    • Builds von Master-Branches schlagen fehl. Sie haben beispielsweise die folgenden Phasen: Projekt herunterladen, Tests ausführen, Projekt erstellen, Release erstellen, Benachrichtigungen senden, Funktionszweig der letzten Pull-Anfrage löschen. Wenn der Build beim Senden einer Benachrichtigung fehlschlägt, müssen Sie alle Ressourcen im Cluster manuell löschen.
    • Ohne den richtigen Kontext ist das Löschen eines Feature-Zweigs in einem Master-Build nicht offensichtlich.

  2. Webhooks verwenden (Beispiel).

    • Vielleicht ist das nicht Ihr Ansatz. Zum Beispiel in Jenkins, unterstützt nur ein Pipelinetyp die Möglichkeit, seine Konfigurationen im Quellcode zu speichern. Wenn Sie Webhooks verwenden, müssen Sie ein eigenes Skript schreiben, um diese zu verarbeiten. Dieses Skript muss in die schwer zu wartende Jenkins-Schnittstelle eingefügt werden.

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

    • Zeitaufwand für das Schreiben und Pflegen.
    • Der Betreiber arbeitet bereits in einem ähnlichen Stil, wird dokumentiert und unterstützt.

Vielen Dank für Ihre Aufmerksamkeit auf den Artikel. Link zum Projekt auf Github.

Source: habr.com

Kommentar hinzufügen