Heqim branch-in e vjetruar të funksionalitetit në klasterin Kubernetes

Heqim branch-in e vjetruar të funksionalitetit në klasterin Kubernetes

Përshëndetje! Dega feature (në të ashtuquajturën deploy preview, review app) — kjo ndodh kur deployohet jo vetëm dega master, por edhe çdo pull request në një URL unik. Mund të kontrolloni nëse kodi funksionon në ambientin production, dhe funksionin mund ta tregoni programuesve të tjerë ose produktologëve. Ndërsa po punoni në pull request, çdo commit i ri anulon deploy-n aktual për kodin e vjetër, dhe një deploy i ri për kodin e ri hapet. Pyetje mund të lindin kur e keni bashkuar pull request-in në degën master. Dega e funksionit nuk ju nevojitet më, por resurset e Kubernetes ende ndodhen në klaster.

Më shumë për degat e funksionit

Një nga qasjet për të bërë degat e funksionit në Kubernetes është përdorimi i namespace-ve. Nëse do ta thjeshtojmë, konfigurimet e production duken kështu:

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

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

Për dega të funksionit krijohet një namespace me identifikuesin e saj (për shembull, numri i pull request-it) dhe një prefiks/postfix të caktuar (për shembull, -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
...

Në përgjithësi, unë shkrova Kubernetes Operator (aplikacioni që ka qasje në resurset e klasterit), shkolla për projektin në Github. Ai heq namespace-t që i përkasin degëve të vjetra të funksioneve. Në Kubernetes, nëse hiqet një namespace, burimet e tjera në atë namespace gjithashtu hiqen automatikisht.

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

Për mënyrën se si të implementoni degët e funksioneve në klaster, mund të lexoni këtu dhe këtu.

Motivimi

Le të shohim një cikël të zakonshëm jetësor të një kërkese për tërheqje me integrimin e vazhdueshëm (integrimi i vazhdueshëm):

  1. Shtojmë një commit të ri në degë.
  2. Gjatë ndërtimit, aktivizohen linters dhe/ose testet.
  3. Në kohë reale formohen konfigurimet e kërkesës për tërheqje në Kubernetes (për shembull, numri i saj vendoset në një shabllon të gatshëm).
  4. Me ndihmën e kubectl apply, konfigurimet hyjnë në klaster (deploy).
  5. Kërkesat për tërheqje bashkohen në degën master.

Ndërsa punoni në kërkesën për tërheqje, çdo commit i ri heq deploy-in aktual për kodin e vjetër dhe nxjerr një deploy të ri për kodin e ri. Por kur kërkesa për tërheqje bashkohet në degën master, do të ndërtohet vetëm dega master. Si rezultat, harrojmë për kërkesën për tërheqje, por burimet e saj Kubernetes ende ndodhen në klaster.

Si të përdorim

Instaloni projektin me komandën më poshtë:

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

Krijo një skedar me përmbajtjen e mëposhtme dhe vendos përmes kubectl apply -f:

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

Parametri namespaceSubstring nevojitet për të filtruar namespace-t për kërkesat e tërheqjes nga namespace të tjera. Për shembull, nëse në klaster ka këto namespace: habr-back-end, habr-front-end, habr-back-end-pr-17, habr-back-end-pr-33, atëherë kandidatët për fshirje do të jenë habr-back-end-pr-17, habr-back-end-pr-33.

Parametri afterDaysWithoutDeploy nevojitet për të fshirë namespace-t e vjetra. Për shembull, nëse namespace është krijuar 3 ditë 1 orë më parë, dhe në parametrin është caktuar 3 ditë, ky namespace do të fshihet. Funksionon edhe në anën tjetër, nëse namespace është krijuar 2 ditë 23 orë më parë, dhe në parametrin është caktuar 3 ditë, ky namespace nuk do të fshihet.

Ka edhe një parametër tjetër, ai përgjigjet për sa shpesh skanohet të gjithë namespace-t dhe kontrollohet për ditët pa deploy — checkEveryMinutes. Në mënyrë të paracaktuar, ai është i barabartë me 30 minuta.

Si funksionon

Në praktikë, do të nevojitet:

  1. Docker për të punuar në një mjedis të izoluar.
  2. Minikube do të ngrejë klasterin Kubernetes lokal.
  3. kubectl — ndërfaqja e komandave për të menaxhuar klasterin.

Ngremë klasterin Kubernetes lokal:

$ minikube start --vm-driver=docker
minikube v1.11.0 në Darwin 10.15.5
Duke përdorur drejtuesin docker në bazë të profilit ekzistues.
Duke filluar kontrollin e planeve minikube në klasterin minikube.

Tregojmë kubectl përdor klasterin lokal si parazgjedhje:

$ kubectl config use-context minikube
Kalova në kontekstin "minikube".

Po shkarkojmë konfiguratat për ambientin e production-it:

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

Pasi konfiguratat e production-it janë vendosur të kontrollojnë namespace-t e vjetra, dhe në klasterin tonë të sapo krijuar nuk ka asnjë, do të zëvendësojmë variablën e ambientit IS_DEBUGe vërtetë. Me këtë vlerë, parametri afterDaysWithoutDeploy nuk merret parasysh dhe namespace-t nuk kontrollohen për ditë pa deploy, vetëm për përmbajtjen e nënstringut (-pr-).

Nëse jeni në OpenVPN:

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

Nëse jeni në Mac Catalyst:

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

Po instalojmë projektin:

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

Po kontrollojmë që resurset janë shfaqur në klaster StaleFeatureBranch:

$ kubectl api-resources | grep stalefeaturebranches
EMRI                 ... APIGROUP                             ... LLOJI
stalefeaturebranches ... feature-branch.dmytrostriletskyi.com ... StaleFeatureBranch

Po kontrollojmë që operatori është shfaqur në klaster:

$ kubectl get pods --namespace stale-feature-branch-operator
EMRI                                           ... STATUS  ... MOSHA
stale-feature-branch-operator-6bfbfd4df8-m7sch ... Duke funksionuar ... 38s

Nëse shikoni në logjet e tij, ai është gati të përpunojë resurset StaleFeatureBranch:

$ kubectl logs stale-feature-branch-operator-6bfbfd4df8-m7sch -n stale-feature-branch-operator
... "msg":"Versioni i Operatorit: 0.0.1"}
...
... "msg":"Duke filluar EventSource", ... , "source":"lloji i burimit: /, Lloji="}
... "msg":"Duke filluar Kontrolluesin", ...}
... "msg":"Duke filluar punëtorët", ..., "numri i punëtorëve":1}

Instalojmë gotiot fixtures (konfigurime të gatshme për simulimin e burimeve të klasës) për burimin StaleFeatureBranch:

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

Konfigurimet specifikojnë të kërkojnë namespace’ë me nënpjesën -pr- një herë në 1 minutë.:

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

Operatori ka reaguar dhe është gati të kontrollojë namespace’ët:

$ kubectl logs stale-feature-branch-operator-6bfbfd4df8-m7sch -n stale-feature-branch-operator
... "msg":"Gurëza e branches së vjetra po përshkruhet.","namespaceSubstring":"-pr-","afterDaysWithoutDeploy":1,"checkEveryMinutes":1,"isDebug":"true"}

Instalojmë fixtures, që përmban dy namespace’a (project-pr-1, project-pr-2) dhe shërbimet e tyre dispozita, , dhe kështu me radhë:, ingress, dhe kështu me radhë:

$ 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

Kontrollojmë që të gjitha burimet e lartpërmendura janë krijuar me sukses:

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

Duke bërë këtë, debug, namespace-të project-pr-1 dhe project-pr-2, gjithashtu të gjitha burimet e tjera, duhet të fshihen menjëherë pa marrë parasysh parametrin afterDaysWithoutDeploy. Në logët e operatorit kjo është e dukshme:

$ kubectl logs stale-feature-branch-operator-6bfbfd4df8-m7sch -n stale-feature-branch-operator
... "msg":"Namespace duhet të fshihet për shkak se moda e debugging është e aktivizuar.","namespaceName":"project-pr-1"}
... "msg":"Namespace është duke u përpunuar.","namespaceName":"project-pr-1","namespaceCreationTimestamp":"2020-06-16 18:43:58 +0300 EEST"}
... "msg":"Namespace është fshirë.","namespaceName":"project-pr-1"}
... "msg":"Namespace duhet të fshihet për shkak se moda e debugging është e aktivizuar.","namespaceName":"project-pr-2"}
... "msg":"Namespace është duke u përpunuar.","namespaceName":"project-pr-2","namespaceCreationTimestamp":"2020-06-16 18:43:58 +0300 EEST"}
... "msg":"Namespace është fshirë.","namespaceName":"project-pr-2"}

Nëse kontrolloni disponueshmërinë e burimeve, ato do të jenë në statusin Duke u përfunduar (procesi i fshirjes) ose tashmë janë fshirë (dalja e komandës është e zbrazët).

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

Mund të përsërisni procesin e krijimit fixtures disa herë dhe të siguroheni që ato do të fshihen brenda një minute.

Alternativat

Çfarë mund të bëni në vend të operatorit që punon në klaster? Ka disa qasje, të gjitha nuk janë të përsosura (dhe disavantazhet e tyre janë subjektive), dhe secili vendos se cila është më e përshtatshme për projektin specifik:

  1. Të fshini branch-in e karakteristikave gjatë ndërtimit të integrimit të vazhdueshëm të branch-it master.

    • Për këtë, duhet të dini se cilin pull request i përket commit-it që po ndërtohet. Duke qenë se emri i hapësirës së branch-it të veçorisë përmban identifikuesin e pull request-it — numrin e tij ose emrin e branch-it, identifikuesi gjithmonë duhet të përmendet në commit.
    • Ndërtesat e branch-it master dështojnë. Për shembull, keni këto etapa: shkarkoni projektin, ekzekutoni testet, ndërtoni projektin, bëni lëshimin, dërgoni njoftimet, pastroni branch-in e veçorisë së pull request-it të fundit. Nëse ndërtimi dështoi në dërgimin e njoftimit, do t'ju duhet të fshini të gjitha burimet në klaster manualisht.
    • Pa kontekst të duhur, fshirja e branch-it të veçorisë në ndërtimin master nuk është e qartë.

  2. Përdorimi i webhook-ve (shembull).

    • Mundësisht, kjo nuk është qasja juaj. Për shembull, në Jenkins, vetëm një lloj pipeline-i mbështet mundësinë për të ruajtur konfigurimet e tij në kodin burimor. Në përdorimin e webhook-ve, duhet të shkruani skriptin tuaj për përpunimin e tyre. Ky skript do të duhet të vendoset në ndërfaqen e Jenkins-it, çka është e vështirë për t'u mbajtur.

  3. Shkruani Cronjob dhe shtoni klasterin Kubernetes.

    • Kosto kohe për të shkruar dhe mbajtur.
    • Operatori tashmë funksionon në një stil të ngjashëm, është dokumentuar dhe mbështetet.

Faleminderit për vëmendjen ndaj artikullit. Lidhja me projektin në Github.

Burimi: habr.com

Bleni hostim të besueshëm për faqe me mbrojtje nga DDoS, serverë VPS VDS 🔥 Bleni hostim të besueshëm për faqe me mbrojtje nga DDoS, serverë VPS VDS | ProHoster