Ta bort en föråldrad funktionsgren i ett Kubernetes-kluster
Hälsningar! Funktionsgren (alias deploy preview, review app) - det här är när inte bara huvudgrenen distribueras, utan också varje pull-begäran till en unik URL. Du kan kontrollera om koden fungerar i en produktionsmiljö; funktionen kan visas för andra programmerare eller produktspecialister. Medan du arbetar med en pull-begäran raderas varje ny commit aktuell implementering för den gamla koden, och den nya implementeringen för den nya koden rullas ut. Frågor kan uppstå när du slog ihop en pull-begäran i mastergrenen. Du behöver inte längre funktionsgrenen, men Kubernetes-resurserna finns fortfarande i klustret.
Mer om funktionsgrenar
Ett sätt att göra funktionsgrenar i Kubernetes är att använda namnutrymmen. Kort sagt ser produktionskonfigurationen ut så här:
För en funktionsgren skapas ett namnområde med dess identifierare (till exempel pull request-numret) och någon form av prefix/postfix (till exempel, -pr-):
I allmänhet skrev jag Kubernetes-operatör (en applikation som har tillgång till klusterresurser), länk till projektet på Github. Det tar bort namnutrymmen som tillhör gamla funktionsgrenar. Om du tar bort ett namnområde i Kubernetes raderas även andra resurser i det namnområdet automatiskt.
$ kubectl get pods --all-namespaces | grep -e "-pr-"
NAMESPACE ... AGE
habr-back-end-pr-264 ... 4d8h
habr-back-end-pr-265 ... 5d7h
Du kan läsa om hur du implementerar funktionsgrenar i ett kluster här и här.
Motivation
Låt oss titta på en typisk livscykel för pull-begäran med kontinuerlig integration (continuous integration):
Vi driver ett nytt engagemang för filialen.
På bygget körs linters och/eller tester.
Kubernetes pull request-konfigurationer genereras i farten (till exempel infogas dess nummer i den färdiga mallen).
Med kubectl applicera läggs konfigurationer till i klustret (deploy).
Pull-begäran slås samman med huvudgrenen.
Medan du arbetar med en pull-begäran raderas varje ny commit aktuell implementering för den gamla koden, och den nya implementeringen för den nya koden rullas ut. Men när en pull-begäran slås samman i mastergrenen kommer bara mastergrenen att byggas. Som ett resultat visar det sig att vi redan har glömt pull-begäran, och dess Kubernetes-resurser finns fortfarande i klustret.
Parameter understräng för namnutrymme behövs för att filtrera namnutrymmen för pull-förfrågningar från andra namnutrymmen. Till exempel, om klustret har följande namnrymder: habr-back-end, habr-front-end, habr-back-end-pr-17, habr-back-end-pr-33, då kommer kandidater för radering att vara habr-back-end-pr-17, habr-back-end-pr-33.
Parameter afterDaysWithoutDeploy behövs för att radera gamla namnområden. Till exempel om namnutrymme skapas 3 дня 1 час tillbaka, och parametern indikerar 3 дня, kommer detta namnområde att tas bort. Det fungerar också i motsatt riktning om namnområdet skapas 2 дня 23 часа tillbaka, och parametern indikerar 3 дня, detta namnutrymme kommer inte att tas bort.
Det finns ytterligare en parameter, den är ansvarig för hur ofta man ska skanna alla namnområden och kontrollera dagar utan distribution - checkEveryMinutes. Som standard är det lika 30 минутам.
Minikube kommer att skapa ett Kubernetes-kluster lokalt.
kubectl — Kommandoradsgränssnitt för klusterhantering.
Vi skapar ett Kubernetes-kluster lokalt:
$ 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.
Vi indikerar kubectl använd lokalt kluster som standard:
$ kubectl config use-context minikube
Switched to context "minikube".
Eftersom produktionskonfigurationer är konfigurerade för att kontrollera gamla namnutrymmen, och vårt nytillkomna kluster inte har dem, kommer vi att ersätta miljövariabeln IS_DEBUG på true. Med detta värde parametern afterDaysWithoutDeploy tas inte med i beräkningen och namnutrymmen kontrolleras inte under dagar utan distribution, endast för förekomsten av delsträngen (-pr-).
Om du är på Linux:
$ sed -i 's|false|true|g' stale-feature-branch-production-configs.yml
Om du är på macOS:
$ sed -i "" 's|false|true|g' stale-feature-branch-production-configs.yml
Vi kontrollerar att en operatör har dykt upp i klustret:
$ kubectl get pods --namespace stale-feature-branch-operator
NAME ... STATUS ... AGE
stale-feature-branch-operator-6bfbfd4df8-m7sch ... Running ... 38s
Om du tittar på dess loggar är den redo att bearbeta resurser StaleFeatureBranch:
Operatören har svarat och är redo att kontrollera namnområden:
$ 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"}
Ställ fixtures, som innehåller två namnrymder (project-pr-1, project-pr-2) och dem deployments, services, ingress, och så vidare:
$ 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
Vi kontrollerar att alla resurserna ovan har skapats framgångsrikt:
$ 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
...
Eftersom vi inkluderade debug, namnrymder project-pr-1 и project-pr-2, därför måste alla andra resurser tas bort omedelbart utan att ta hänsyn till parametern afterDaysWithoutDeploy. Detta kan ses i operatörsloggarna:
$ 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"}
Om du kontrollerar tillgängligheten av resurser kommer de att vara i status Terminating (raderingsprocess) eller redan raderad (kommandoutgången är tom).
$ 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 upprepa skapelseprocessen fixtures flera gånger och se till att de tas bort inom en minut.
alternativ
Vad kan göras istället för en operatör som arbetar i ett kluster? Det finns flera tillvägagångssätt, alla är ofullkomliga (och deras brister är subjektiva), och alla bestämmer själv vad som är bäst för ett visst projekt:
Ta bort funktionsgren under kontinuerlig integrationsuppbyggnad av mastergren.
För att göra detta måste du veta vilken pull-begäran som är relaterad till den commit som byggs. Eftersom funktionsgrenens namnutrymme innehåller pull request-identifieraren - dess nummer, eller namnet på grenen, måste identifieraren alltid anges i commit.
Bygger av mastergrenar misslyckas. Till exempel har du följande steg: ladda ner projektet, kör tester, bygg projektet, gör en release, skicka meddelanden, rensa funktionsgrenen för den senaste pull-begäran. Om konstruktionen misslyckas när du skickar ett meddelande måste du radera alla resurser i klustret manuellt.
Utan korrekt kontext är det inte självklart att ta bort funktionsgrenar i huvudbygget.
Detta kanske inte är ditt tillvägagångssätt. Till exempel i Jenkins, endast en typ av pipeline stöder möjligheten att spara sina konfigurationer i källkoden. När du använder webhooks måste du skriva ditt eget skript för att bearbeta dem. Det här skriptet måste placeras i Jenkins-gränssnittet, vilket är svårt att underhålla.
skriva Cron jobb och lägg till ett Kubernetes-kluster.
Lägg tid på skrivande och support.
Operatören arbetar redan i liknande stil, är dokumenterad och stöds.