Ta bort en föråldrad funktionsgren i ett Kubernetes-kluster

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:

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

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

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-):

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
...

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):

  1. Vi driver ett nytt engagemang för filialen.
  2. På bygget körs linters och/eller tester.
  3. Kubernetes pull request-konfigurationer genereras i farten (till exempel infogas dess nummer i den färdiga mallen).
  4. Med kubectl applicera läggs konfigurationer till i klustret (deploy).
  5. 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.

Hur man använder

Installera projektet med kommandot nedan:

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

Skapa en fil med följande innehåll och installera via kubectl apply -f:

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

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 минутам.

Hur fungerar den här

I praktiken behöver du:

  1. Hamnarbetare för att arbeta i en isolerad miljö.
  2. Minikube kommer att skapa ett Kubernetes-kluster lokalt.
  3. 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".

Ladda ner konfigurationer för produktionsmiljön:

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

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_DEBUGtrue. 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

Installera projektet:

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

Kontrollera att en resurs har dykt upp i klustret StaleFeatureBranch:

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

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:

$ 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}

Vi installerar färdigt fixtures (färdiga konfigurationer för modellering av klusterresurser) för en resurs StaleFeatureBranch:

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

Konfigurationerna indikerar att söka efter namnutrymmen med en delsträng -pr- en gång varje 1 минуту.:

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

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:

  1. 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.

  2. Använda webhooks (exempel).

    • 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.

  3. 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.

Tack för din uppmärksamhet på artikeln. Länk till projektet på Github.

Källa: will.com

Lägg en kommentar