
Hallo! Feature branch (ook wel deploy preview, review app) ā dit is wanneer niet alleen de master branch wordt gedeployed, maar elke pull request op een unieke URL. Je kunt controleren of de code in een productieomgeving werkt, en de functie kan aan andere ontwikkelaars of producteigenaren worden getoond. Terwijl je in de pull request werkt, wordt elke nieuwe commit de huidige deploy voor oude code verwijderd, en wordt een nieuwe deploy voor nieuwe code uitgerold. Er kunnen vragen ontstaan wanneer je de pull request naar de master branch hebt samengevoegd. De feature branch is dan niet meer nodig, maar de resources van Kubernetes zijn nog steeds in het cluster.
Meer over feature branches
Een van de benaderingen om feature branches in Kubernetes te maken ā gebruik namespaces. In het kort, de productieconfiguraties zien er als volgt uit:
kind: Namespace
apiVersion: v1
metadata:
name: habr-back-end
...
kind: Deployment
apiVersion: apps/v1
metadata:
namespace: habr-back-end
spec:
replicas: 3
...Voor elke feature branch wordt er een namespace aangemaakt met de identificatie ervan (bijvoorbeeld het nummer van de pull request) en een of andere prefix/suffix (bijvoorbeeld, -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
...Over het algemeen, ik schreef Kubernetes Operator (een applicatie die toegang heeft tot de clusterresources), . Deze verwijdert namespaces die verband houden met oude feature branches. In Kubernetes, als je een namespace verwijdert, worden andere resources in deze namespace ook automatisch verwijderd.
$ kubectl get pods --all-namespaces | grep -e "-pr-"
NAMESPACE ... AGE
habr-back-end-pr-264 ... 4d8h
habr-back-end-pr-265 ... 5d7hOver hoe je feature branches in het cluster kunt implementeren, kun je lezen en .
Motivatie
Laten we eens kijken naar de typische levenscyclus van een pull request met continue integratie (continue integratie):
- We pushen een nieuwe commit naar de branch.
- Bij de build worden linter- en/of tests uitgevoerd.
- Op dat moment worden de Kubernetes-configuraties van de pull request on-the-fly gevormd (bijvoorbeeld, zijn nummer wordt in de kant-en-klare sjabloon geplaatst).
- Met behulp van kubectl apply komen de configuraties in het cluster (deploy).
- De pull request wordt samengevoegd met de master branch.
Terwijl je in de pull request werkt, wordt elke nieuwe commit de huidige deploy voor oude code verwijderd, en wordt een nieuwe deploy voor nieuwe code uitgerold. Maar wanneer de pull request naar de master branch wordt samengevoegd, wordt er alleen voor de master branch gebouwd. Uiteindelijk blijkt dat we de pull request al zijn vergeten, maar de Kubernetes-resources nog steeds in het cluster zijn.
Hoe te gebruiken
Installeer het project met de onderstaande opdracht:
$ kubectl apply -f https://raw.githubusercontent.com/dmytrostriletskyi/stale-feature-branch-operator/master/configs/production.ymlMaak een bestand met de volgende inhoud en installeer het via kubectl apply -f:
apiVersion: feature-branch.dmytrostriletskyi.com/v1
kind: StaleFeatureBranch
metadata:
name: stale-feature-branch
spec:
namespaceSubstring: -pr-
afterDaysWithoutDeploy: 3Parameter namespaceSubstring is nodig om namespace's te filteren voor pull requests van andere namespace's. Bijvoorbeeld, als er de volgende namespace's in de cluster zijn: habr-back-end, habr-front-end, habr-back-end-pr-17, habr-back-end-pr-33, dan zullen de kandidaten voor verwijdering zijn habr-back-end-pr-17, habr-back-end-pr-33.
Parameter afterDaysWithoutDeploy is nodig om oude namespace's te verwijderen. Bijvoorbeeld, als de namespace is aangemaakt 3 dagen 1 uur geleden, en de parameter is ingesteld op 3 dagen, dan zal deze namespace worden verwijderd. Het werkt ook omgekeerd, als de namespace is aangemaakt 2 dagen 23 uur geleden, en de parameter is ingesteld op 3 dagen, dan zal deze namespace niet worden verwijderd.
Er is nog een parameter, deze bepaalt hoe vaak alle namespace's moeten worden gescand en gecontroleerd op dagen zonder deployment - checkEveryMinutes. Standaard is deze ingesteld op 30 minuten.
Hoe het werkt
In de praktijk heeft men nodig:
- voor gebruik in een geĆÆsoleerde omgeving.
- zal de Kubernetes cluster lokaal opzetten.
- ā de commandoregelinterface voor het beheren van de cluster.
We zetten de Kubernetes cluster lokaal op:
$ minikube start --vm-driver=docker
minikube v1.11.0 op Darwin 10.15.5
Gebruik de docker-driver op basis van het bestaande profiel.
Start de beheersnode minikube in cluster minikube.Geef op kubectl gebruik de lokale cluster als standaard:
$ kubectl config use-context minikube
Overgeschakeld naar context "minikube".We downloaden de configuraties voor de productieomgeving:
$ curl https://raw.githubusercontent.com/dmytrostriletskyi/stale-feature-branch-operator/master/configs/production.yml > stale-feature-branch-production-configs.ymlAangezien de productieconfiguraties zijn ingesteld om oude namespace's te controleren, en er zijn er geen in onze nieuw opgezette cluster, vervangen we de omgevingsvariabele IS_DEBUG en een werkende opdracht krijgen. true. Met deze waarde wordt de parameter afterDaysWithoutDeploy niet meegerekend en worden namespace's niet gecontroleerd op dagen zonder deployments, alleen op substring-overeenkomsten (-pr-).
Als je in Linux:
$ sed -i 's|false|true|g' stale-feature-branch-production-configs.ymlAls je in macOS:
$ sed -i "" 's|false|true|g' stale-feature-branch-production-configs.ymlWe installeren het project:
$ kubectl apply -f stale-feature-branch-production-configs.ymlWe controleren of de resource StaleFeatureBranch:
$ kubectl api-resources | grep stalefeaturebranches
NAAM ... APIGROUP ... TYPE
stalefeaturebranches ... feature-branch.dmytrostriletskyi.com ... StaleFeatureBranchWe controleren of de operator in de cluster aanwezig is:
$ kubectl get pods --namespace stale-feature-branch-operator
NAAM ... STATUS ... LEVENSJAREN
stale-feature-branch-operator-6bfbfd4df8-m7sch ... Draait ... 38sAls je in de logs kijkt, is hij klaar om resources te verwerken StaleFeatureBranch:
$ kubectl logs stale-feature-branch-operator-6bfbfd4df8-m7sch -n stale-feature-branch-operator
... "msg":"Operator Versie: 0.0.1"}
...
... "msg":"Starten EventSource", ... , "source":"aard soort: \/, Aard="}
... "msg":"Starten Controller", ...}
... "msg":"Starten werknemers", ..., "werknemer aantal":1}Voorgeconfigureerde fixtures (voorgeconfigureerde instellingen voor het modelleren van clusterbronnen) voor de hulpbron StaleFeatureBranch:
$ kubectl apply -f https://raw.githubusercontent.com/dmytrostriletskyi/stale-feature-branch-operator/master/fixtures/stale-feature-branch.ymlIn de configuraties is aangegeven om namespaces te zoeken met de substring -pr- eens in 1 minuut.:
apiVersion: feature-branch.dmytrostriletskyi.com/v1
kind: StaleFeatureBranch
metadata:
naam: stale-feature-branch
spec:
namespaceSubstring: -pr-
afterDaysWithoutDeploy: 1
checkEveryMinutes: 1De operator heeft gereageerd en is klaar om namespaces te controleren:
$ kubectl logs stale-feature-branch-operator-6bfbfd4df8-m7sch -n stale-feature-branch-operator
... "msg":"Stale feature branch wordt verwerkt.","namespaceSubstring":"-pr-","afterDaysWithoutDeploy":1,"checkEveryMinutes":1,"isDebug":"true"}Instellen fixtures, die twee namespaces bevatten (project-pr-1, project-pr-2) en hun deployments, services, ingress, enzovoort:
$ 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 gecreƫerd
deployment.apps/project-pr-1 gecreƫerd
service/project-pr-1 gecreƫerd
horizontalpodautoscaler.autoscaling/project-pr-1 gecreƫerd
secret/project-pr-1 gecreƫerd
configmap/project-pr-1 gecreƫerd
ingress.extensions/project-pr-1 gecreƫerd
namespace/project-pr-2 gecreƫerd
deployment.apps/project-pr-2 gecreƫerd
service/project-pr-2 gecreƫerd
horizontalpodautoscaler.autoscaling/project-pr-2 gecreƫerd
secret/project-pr-2 gecreƫerd
configmap/project-pr-2 gecreƫerd
ingress.extensions/project-pr-2 gecreƫerdWe controleren of alle bovenstaande resources succesvol zijn aangemaakt:
$ 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
...
NAAM ... KLAAR ... STATUS ... LEVENSDUUR
pod/project-pr-1-848d5fdff6-rpmzw ... 1/1 ... Actief ... 67s
NAAM ... KLAAR ... BESCHIKBAAR ... LEVENSDUUR
deployment.apps/project-pr-1 ... 1/1 ... 1 ... 67s
...Aangezien we debug, namespaces project-pr-1 en project-pr-2, en alle andere resources, moeten direct worden verwijderd ongeacht de parameter afterDaysWithoutDeploy. Dit is zichtbaar in de logs van de operator:
$ kubectl logs stale-feature-branch-operator-6bfbfd4df8-m7sch -n stale-feature-branch-operator
... "msg":"Namespace moet worden verwijderd omdat de debugmodus is ingeschakeld.","namespaceName":"project-pr-1"}
... "msg":"Namespace wordt verwerkt.","namespaceName":"project-pr-1","namespaceCreationTimestamp":"2020-06-16 18:43:58 +0300 EEST"}
... "msg":"Namespace is verwijderd.","namespaceName":"project-pr-1"}
... "msg":"Namespace moet worden verwijderd omdat de debugmodus is ingeschakeld.","namespaceName":"project-pr-2"}
... "msg":"Namespace wordt verwerkt.","namespaceName":"project-pr-2","namespaceCreationTimestamp":"2020-06-16 18:43:58 +0300 EEST"}
... "msg":"Namespace is verwijderd.","namespaceName":"project-pr-2"}Als we de resources controleren, zullen ze in status zijn Terminating (verwijderingsproces) of al verwijderd zijn (de uitvoer van het commando is leeg).
$ 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
...U kunt het proces om te maken herhalen fixtures en bevestigen dat ze binnen een minuut worden verwijderd.
Alternatieven
Wat kan men doen in plaats van de operator die in het cluster werkt? Er zijn verschillende benaderingen, allemaal zijn ze niet perfect (en hun nadelen zijn subjectief), en iedereen moet zelf beslissen welke het beste past bij het specifieke project:
Verwijder de feature branch tijdens de build van de master branch voor continue integratie.
- Hiervoor moet je weten welke pull request behoort bij de commit die wordt gebouwd. Aangezien de namespace van de feature branch de identificatie van de pull request bevat - zijn nummer of de naam van de branch, moet je deze identificatie altijd opgeven in de commit.
- Builds van de master branches falen. Bijvoorbeeld, je hebt de volgende stappen: download het project, voer tests uit, bouw het project, maak een release, verstuur meldingen, ruim de feature branch van de laatste pull request op. Als de build faalt bij het versturen van een melding, moet je alle resources in het cluster handmatig verwijderen.
- Zonder de juiste context is het verwijderen van de feature branch in de master build niet voor de hand liggend.
Het gebruik van webhooks ().
- Misschien is dit niet jouw aanpak. Bijvoorbeeld, in , ondersteunt slechts ƩƩn type pipeline de mogelijkheid om zijn configuraties in de broncode op te slaan. Bij het gebruik van webhooks moet je je eigen script schrijven voor hun verwerking. Dit script moet in de interface van Jenkins worden geplaatst, wat moeilijk te onderhouden is.
Schrijf en voeg het Kubernetes-cluster toe.
- De tijdsinspanning voor het schrijven en onderhouden.
- De operator werkt al in een vergelijkbare stijl, is gedocumenteerd en wordt ondersteund.
Bedankt voor uw aandacht voor het artikel. .
Bron: habr.com
