Suppression de la branche de fonctionnalités obsolÚte dans le cluster Kubernetes

Suppression de la branche de fonctionnalités obsolÚte dans le cluster Kubernetes

Bonjour ! Branche de fonctionnalitĂ© (Ă©galement appelĂ©e dĂ©ploiement de prĂ©visualisation, application de rĂ©vision) — c'est lorsque non seulement la branche master est dĂ©ployĂ©e, mais aussi chaque pull request sur une URL unique. Vous pouvez vĂ©rifier si le code fonctionne dans un environnement de production, et la fonctionnalitĂ© peut ĂȘtre montrĂ©e Ă  d'autres dĂ©veloppeurs ou chefs de produit. Tant que vous travaillez dans un pull request, chaque nouveau commit remplace le dĂ©ploiement actuel du vieux code, et un nouveau dĂ©ploiement pour le nouveau code est mis en place. Des questions peuvent se poser lorsque vous avez fusionnĂ© le pull request dans la branche master. La branche de fonctionnalitĂ© n'est plus nĂ©cessaire, mais les ressources Kubernetes sont toujours prĂ©sentes dans le cluster.

Encore au sujet des branches de fonctionnalités

Une des approches pour créer des branches de fonctionnalités dans Kubernetes consiste à utiliser des namespaces. En résumant, la configuration de production ressemble à ceci :

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

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

Pour la branche de fonctionnalité, un namespace est créé avec son identifiant (par exemple, le numéro de la pull request) et un préfixe/suffixe (par exemple, -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
...

En général, j'ai écrit Kubernetes Operator (une application qui a accÚs aux ressources du cluster), lien vers le projet sur Github. Il supprime les namespaces associés aux anciennes branches de fonctionnalités. Dans Kubernetes, si vous supprimez un namespace, d'autres ressources dans ce namespace sont également supprimées automatiquement.

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

Pour savoir comment intégrer les branches de fonctionnalités dans le cluster, vous pouvez lire ici et ici.

Motivation

Jetons un Ɠil Ă  un cycle de vie typique d'une pull request avec intĂ©gration continue (intĂ©gration continue):

  1. Nous poussons un nouveau commit dans la branche.
  2. Lors de la construction, des linters et/ou des tests sont lancés.
  3. Les configurations Kubernetes de la pull request sont gĂ©nĂ©rĂ©es Ă  la volĂ©e (par exemple, le numĂ©ro est insĂ©rĂ© dans un modĂšle prĂȘt).
  4. Les configurations sont appliquées au cluster à l'aide de kubectl (déploiement).
  5. La pull request est fusionnée dans la branche master.

Tant que vous travaillez dans la pull request, chaque nouveau commit remplace le déploiement actuel du vieux code, et un nouveau déploiement pour le nouveau code est mis en place. Mais lorsque la pull request est fusionnée dans la branche master, seul le master sera construit. Au final, nous oublions la pull request, mais ses ressources Kubernetes sont toujours présentes dans le cluster.

Comment utiliser

Installez le projet avec la commande ci-dessous :

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

Créez un fichier avec le contenu suivant et installez-le via kubectl apply -f:

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

ParamÚtre namespaceSubstring nécessaire pour filtrer les namespaces des pull requests d'autres namespaces. Par exemple, si le cluster contient les namespaces suivants : habr-back-end, habr-front-end, habr-back-end-pr-17, habr-back-end-pr-33, alors les candidats à la suppression seront habr-back-end-pr-17, habr-back-end-pr-33.

ParamÚtre afterDaysWithoutDeploy nécessaire pour supprimer les vieux namespaces. Par exemple, si un namespace a été créé il y a 3 jours et 1 heure , et que le paramÚtre spécifie 3 jours, ce namespace sera supprimé. Cela fonctionne aussi dans l'autre sens, si le namespace a été créé il y a 2 jours et 23 heures , et que le paramÚtre spécifie 3 jours, ce namespace ne sera pas supprimé.

Il y a un autre paramĂštre, il dĂ©termine Ă  quelle frĂ©quence scanner tous les namespaces et vĂ©rifier les jours sans dĂ©ploiement — checkEveryMinutes. Par dĂ©faut, il est Ă©gal Ă  30 minutes.

Comment cela fonctionne

En pratique, il faut :

  1. Docker pour fonctionner dans un environnement isolé.
  2. Minikube va lancer un cluster Kubernetes localement.
  3. kubectl — interface en ligne de commande pour gĂ©rer le cluster.

Lançons le cluster Kubernetes localement :

$ minikube start --vm-driver=docker
minikube v1.11.0 sur Darwin 10.15.5
Utilisation du pilote docker basé sur le profil existant.
DĂ©marrage du nƓud du plan de contrĂŽle minikube dans le cluster minikube.

Indiquons kubectl d'utiliser le cluster local par défaut :

$ kubectl config use-context minikube
Contexte changé pour "minikube".

Téléchargeons les configurations pour l'environnement de production :

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

Étant donnĂ© que les configurations de production sont rĂ©glĂ©es pour vĂ©rifier les vieux namespaces, et qu'il n'y en a pas dans notre nouveau cluster, remplaçons la variable d'environnement IS_DEBUG sur true. Avec cette valeur, le paramĂštre afterDaysWithoutDeploy n'est pas pris en compte et les namespaces ne sont pas vĂ©rifiĂ©s pour les jours sans dĂ©ploiement, seulement pour la prĂ©sence de la sous-chaĂźne (-pr-).

Si vous ĂȘtes sur Linux:

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

Si vous ĂȘtes sur macOS:

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

Installons le projet :

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

Vérifions que la ressource est apparue dans le cluster StaleFeatureBranch:

$ kubectl api-resources | grep stalefeaturebranches
NOM                 ... APIGROUP                             ... TYPE
stalefeaturebranches ... feature-branch.dmytrostriletskyi.com ... StaleFeatureBranch

Vérifions que l'opérateur est apparu dans le cluster :

$ kubectl get pods --namespace stale-feature-branch-operator
NOM                                           ... ÉTAT  ... ÂGE
stale-feature-branch-operator-6bfbfd4df8-m7sch ... En cours d'exécution ... 38s

Si nous regardons ses logs, il est prĂȘt Ă  traiter les ressources StaleFeatureBranch:

$ kubectl logs stale-feature-branch-operator-6bfbfd4df8-m7sch -n stale-feature-branch-operator
... "msg":"Version de l'opérateur : 0.0.1"}
...
... "msg":"Démarrage de EventSource", ... , "source":"type source : /, Type="}
... "msg":"Démarrage du contrÎleur", ...}
... "msg":"Démarrage des travailleurs", ..., "nombre de travailleurs":1}

Installons les fixtures (configurations prĂȘtes pour la modĂ©lisation des ressources de cluster) pour la ressource StaleFeatureBranch:

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

Les configurations spécifient de rechercher des namespaces contenant la sous-chaßne -pr- toutes les 1 minute.:

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

L'opĂ©rateur a rĂ©agi et est prĂȘt Ă  vĂ©rifier les namespaces :

$ kubectl logs stale-feature-branch-operator-6bfbfd4df8-m7sch -n stale-feature-branch-operator
... "msg":"La branche de fonctionnalité obsolÚte est en cours de traitement.","namespaceSubstring":"-pr-","afterDaysWithoutDeploy":1,"checkEveryMinutes":1,"isDebug":"true"}

Nous installons fixtures, contenant deux namespaces (project-pr-1, project-pr-2) et leurs déploiements, services, ingress, et ainsi de suite :

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

Vérifions que toutes les ressources ci-dessus ont été créées avec succÚs :

$ kubectl get namespace,pods,déploiement,service,horizontalpodautoscaler,configmap,ingress -n project-pr-1 && kubectl get namespace,pods,déploiement,service,horizontalpodautoscaler,configmap,ingress -n project-pr-2
...
NOM                              ... PRÊT ... STATUT  ... ÂGE
pod/project-pr-1-848d5fdff6-rpmzw ... 1/1   ... En cours d'exécution ... 67s

NOM                         ... PRÊT ... DISPONIBLE ... ÂGE
déploiement.apps/project-pr-1 ... 1/1   ... 1         ... 67s
...

Puisque nous avons activĂ© debug, les namespaces project-pr-1 et project-pr-2, tous les autres ressources devraient Ă©galement ĂȘtre supprimĂ©es immĂ©diatement, sans tenir compte du paramĂštre afterDaysWithoutDeploy. Dans les logs de l'opĂ©rateur, cela est visible :

$ kubectl logs stale-feature-branch-operator-6bfbfd4df8-m7sch -n stale-feature-branch-operator
... "msg":"Le namespace doit ĂȘtre supprimĂ© car le mode dĂ©bogage est activĂ©.","namespaceName":"project-pr-1"}
... "msg":"Le namespace est en cours de traitement.","namespaceName":"project-pr-1","namespaceCreationTimestamp":"2020-06-16 18:43:58 +0300 EEST"}
... "msg":"Le namespace a été supprimé.","namespaceName":"project-pr-1"}
... "msg":"Le namespace doit ĂȘtre supprimĂ© car le mode dĂ©bogage est activĂ©.","namespaceName":"project-pr-2"}
... "msg":"Le namespace est en cours de traitement.","namespaceName":"project-pr-2","namespaceCreationTimestamp":"2020-06-16 18:43:58 +0300 EEST"}
... "msg":"Le namespace a été supprimé.","namespaceName":"project-pr-2"}

Si nous vérifions la présence des ressources, elles seront dans l'état Terminating (processus de suppression) ou déjà supprimées (le résultat de la commande est vide).

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

Vous pouvez répéter le processus de création fixtures assurez-vous plusieurs fois qu'ils seront supprimés dans la minute.

Alternatives

Que peut-on faire à la place d'un opérateur fonctionnant dans un cluster ? Plusieurs approches sont possibles, toutes ne sont pas idéales (et leurs inconvénients sont subjectifs), et chacun décide ce qui convient le mieux à son projet spécifique :

  1. Supprimer la branche feature pendant le build de la branche master d'intégration continue.

    • Pour cela, il faut savoir quel pull request se rapporte au commit qui est en cours de build. Étant donnĂ© que le namespace de la branche feature contient l'identifiant du pull request — son numĂ©ro ou le nom de la branche, il faudra toujours le spĂ©cifier dans le commit.
    • Les builds des branches master Ă©chouent. Par exemple, vous avez les Ă©tapes suivantes : tĂ©lĂ©charger le projet, exĂ©cuter des tests, compiler le projet, faire une release, envoyer des notifications, nettoyer la branche feature du dernier pull request. Si le build Ă©choue lors de l'envoi de la notification, vous devrez supprimer toutes les ressources du cluster manuellement.
    • Sans le contexte appropriĂ©, la suppression de la branche feature dans le build master n'est pas Ă©vidente.

  2. L'utilisation des webhooks (exemple).

    • Peut-ĂȘtre que ce n'est pas votre approche. Par exemple, dans Jenkins, seul un type de pipeline prend en charge la possibilitĂ© de conserver ses configurations dans le code source. Lors de l'utilisation des webhooks, il faut Ă©crire son propre script pour les traiter. Ce script devra ĂȘtre placĂ© dans l'interface de Jenkins, ce qui est difficile Ă  maintenir.

  3. Écrire Cronjob et ajouter un cluster Kubernetes.

    • Une perte de temps pour Ă©crire et maintenir.
    • L'opĂ©rateur fonctionne dĂ©jĂ  dans un style similaire, est documentĂ© et supportĂ©.

Merci pour votre attention Ă  l'article. Lien vers le projet sur Github.

Source : habr.com

Acheter un hĂ©bergement fiable pour les sites avec protection DDoS, serveurs VPS VDS đŸ”„ Acheter un hĂ©bergement fiable pour les sites avec protection DDoS, serveurs VPS VDS | ProHoster