
Hej! Funktionsgren (aka deploy preview, review app) — det er, når ikke kun master-grenen implementeres, men hver pull request på en unik URL. Det gør det muligt at teste om koden fungerer i produktionsmiljøet, og funktionen kan vises for andre udviklere eller produkteksperter. Mens du arbejder i pull request'en, fjernes den aktuelle implementering for den gamle kode med hver ny commit, og en ny implementering for den nye kode bliver rullet ud. Spørgsmål kan opstå, når du har fusioneret pull request'en til master-grenen. Funktionsgrenen er ikke længere nødvendig, men Kubernetes-ressourcerne er stadig i klyngen.
Mere om funktionsgrene
En af tilgange til at lave funktionsgrene i Kubernetes er at bruge namespaces. Kort sagt ser produktionskonfigurationen sådan ud:
kind: Namespace
apiVersion: v1
metadata:
name: habr-back-end
...
kind: Deployment
apiVersion: apps/v1
metadata:
namespace: habr-back-end
spec:
replicas: 3
...For funktionsgrenen oprettes et namespace med dens identifikator (for eksempel nr. på pull request'en) og et eller andet præfiks/suffiks (for eksempel, -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
...Generelt har jeg skrevet Kubernetes Operator (applikationen, der har adgang til klyngens ressourcer), . Den fjerner namespaces, der vedrører gamle funktionsgrene. I Kubernetes, hvis du sletter et namespace, slettes andre ressourcer i dette namespace også automatisk.
$ kubectl get pods --all-namespaces | grep -e "-pr-"
NAMESPACE ... AGE
habr-back-end-pr-264 ... 4d8h
habr-back-end-pr-265 ... 5d7hOm hvordan man implementerer funktionsgrene i klyngen, kan man læse og .
Motivation
Lad os se på en typisk livscyklus for en pull request med kontinuerlig integration (kontinuerlig integration):
- Vi push'er en ny commit til grenen.
- Ved bygningene køres linters og/eller tests.
- Konfigurationerne for Kubernetes-pull request'en dannes dynamisk (for eksempel indsættes dens nummer i den færdige skabelon).
- Med kubectl apply bliver konfigurationerne sendt til klyngen (deploy).
- Pull request'en flettes ind i master-grenen.
Mens du arbejder i pull request'en, fjernes den aktuelle implementering for den gamle kode med hver ny commit, og en ny implementering for den nye kode bliver rullet ud. Men når pull request'en flettes ind i master-grenen, vil kun master-grenen blive bygget. Resultatet er, at vi allerede har glemt pull request'en, mens dens Kubernetes-ressourcer stadig er i klyngen.
Hvordan man bruger
Installer projektet med kommandoen nedenfor:
$ kubectl apply -f https://raw.githubusercontent.com/dmytrostriletskyi/stale-feature-branch-operator/master/configs/production.ymlOpret en fil med følgende indhold og installer gennem kubectl apply -f:
apiVersion: feature-branch.dmytrostriletskyi.com/v1
kind: StaleFeatureBranch
metadata:
name: stale-feature-branch
spec:
namespaceSubstring: -pr-
afterDaysWithoutDeploy: 3Parameter namespaceSubstring er nødvendig for at filtrere namespace's for pull requests fra andre namespaces. For eksempel, hvis der er følgende namespaces i klyngen: habr-back-end, habr-front-end, habr-back-end-pr-17, habr-back-end-pr-33, så vil kandidaterne til sletning være habr-back-end-pr-17, habr-back-end-pr-33.
Parameter afterDaysWithoutDeploy er nødvendig for at slette gamle namespaces. For eksempel, hvis et namespace blev oprettet 3 dage 1 time siden, og parameteren angiver 3 dage, vil dette namespace blive slettet. Det fungerer også i den modsatte retning; hvis et namespace blev oprettet 2 dage 23 timer siden, og parameteren angiver 3 dage, vil dette namespace ikke blive slettet.
Der er en anden parameter, som bestemmer, hvor ofte alle namespaces scannes og kontrolleres for dage uden deployment — checkEveryMinutes. Som standard er den sat til 30 minutter.
Hvordan fungerer det
I praksis vil vi have brug for:
- til drift i et isoleret miljø.
- vil starte Kubernetes-klyngen lokalt.
- — et kommandolinjeinterface til styring af klyngen.
Starter Kubernetes-klyngen lokalt:
$ minikube start --vm-driver=docker
minikube v1.11.0 på Darwin 10.15.5
Bruger docker-driveren baseret på eksisterende profil.
Starter kontrolplanet node minikube i klyngen minikube.Angiv kubectl for at bruge den lokale klynge som standard:
$ kubectl config use-context minikube
Skiftet til kontekst "minikube".Downloader konfigurationerne til produktionsmiljøet:
$ curl https://raw.githubusercontent.com/dmytrostriletskyi/stale-feature-branch-operator/master/configs/production.yml > stale-feature-branch-production-configs.ymlDa produktionskonfigurationerne er indstillet til at kontrollere gamle namespaces, og der ikke er nogen i vores nyoprettede klynge, vil vi ændre miljøvariablen IS_DEBUG og få en fungerende kommando. true. Ved denne værdi vil parameteren afterDaysWithoutDeploy ikke blive taget i betragtning, og namespaces vil ikke blive kontrolleret for dage uden deployment, kun for substrings (-pr-).
Hvis du er på Linux:
$ sed -i 's|false|true|g' stale-feature-branch-production-configs.ymlHvis du er på macOS:
$ sed -i "" 's|false|true|g' stale-feature-branch-production-configs.ymlInstallerer projektet:
$ kubectl apply -f stale-feature-branch-production-configs.ymlKontrollerer, at ressourcen er til stede i klyngen StaleFeatureBranch:
$ kubectl api-resources | grep stalefeaturebranches
NAVN ... APIGROUP ... TYPE
stalefeaturebranches ... feature-branch.dmytrostriletskyi.com ... StaleFeatureBranchKontrollerer, at operatøren er til stede i klyngen:
$ kubectl get pods --namespace stale-feature-branch-operator
NAVN ... STATUS ... AGE
stale-feature-branch-operator-6bfbfd4df8-m7sch ... Kørende ... 38sHvis du ser i dens logs, er den klar til at behandle ressourcer StaleFeatureBranch:
$ kubectl logs stale-feature-branch-operator-6bfbfd4df8-m7sch -n stale-feature-branch-operator
... "msg":"Operatørversion: 0.0.1"}
...
... "msg":"Starter EventSource", ... , "source":"kind source: \, Kind="}
... "msg":"Starter Controller", ...}
... "msg":"Starter arbejdstagere", ..., "arbejder antal":1}Installerer de færdige fixtures (færdige konfigurationer til modellering af clusterressourcer) til ressourcen StaleFeatureBranch:
$ kubectl apply -f https://raw.githubusercontent.com/dmytrostriletskyi/stale-feature-branch-operator/master/fixtures/stale-feature-branch.ymlI konfigurationerne er der angivet at lede efter namespaces med substrengen -pr- en gang hvert 1 minut.:
apiVersion: feature-branch.dmytrostriletskyi.com/v1
kind: StaleFeatureBranch
metadata:
name: stale-feature-branch
spec:
namespaceSubstring: -pr-
afterDaysWithoutDeploy: 1
checkEveryMinutes: 1Operatøren reagerede og er klar til at tjekke namespaces:
$ 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"}Installerer fixtures, der indeholder to namespaces (project-pr-1, project-pr-2) og deres deployments, services, ingress, og så videre:
$ 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
...
namespaces/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 createdVi tjekker, om alle ovennævnte ressourcer er blevet oprettet:
$ 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 vi har aktiveret debug, namespaces project-pr-1 og project-pr-2, vil alle andre ressourcer også straks blive fjernet uanset parameteren afterDaysWithoutDeploy. Dette ses i operatørens logs:
$ 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"}Hvis du tjekker for ressourcer, vil de være i status Terminating (sletningsprocess) eller allerede slettet (kommandoens output er tomt).
$ 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
...Du kan gentage oprettelsesprocessen fixtures flere gange og sikre dig, at de vil blive slettet inden for et minut.
Alternativer
Hvad kan man gøre i stedet for en operator, der arbejder i et cluster? Der er flere tilgange, alle har deres mangler (og disse mangler er subjektive), og hver person må selv vurdere, hvad der passer bedst til det specifikke projekt:
Fjerne feature branch under byggeriet af master-branchens kontinuerlige integration.
- For dette skal man vide, hvilket pull request der vedrører den commit, der bliver bygget. Da feature branch-namespace indeholder identifikatoren for pull requesten – dens nummer eller branchens navn, skal identificatoren altid angives i commit'en.
- Builds af master branches fejler. For eksempel, hvis du har følgende trin: downloade projektet, køre tests, samle projektet, lave en release, sende notifikationer, rydde den feature branch for den seneste pull request. Hvis builden fejler ved afsendelse af notifikationer, skal du manuelt fjerne alle ressourcer i clustret.
- Uden tilstrækkelig kontekst er det ikke indlysende at fjerne feature branch i master builden.
Brug af webhooks ().
- Måske er dette ikke din tilgang. For eksempel, i , understøtter kun én type pipeline muligheden for at gemme dens konfigurationer i kildekoden. Ved brug af webhooks skal du skrive dit eget script til at håndtere dem. Dette script skal placeres i Jenkins-grænsefladen, hvilket er svært at vedligeholde.
Skrive og tilføje Kubernetes-clusteret.
- Tidsforbrug på udvikling og vedligeholdelse.
- Operatoren arbejder allerede i en lignende stil, er dokumenteret og vedligeholdt.
Tak for din opmærksomhed på artiklen. .
Kilde: habr.com
