Pag-alis ng lumang feature na branch sa isang Kubernetes cluster

Pag-alis ng lumang feature na branch sa isang Kubernetes cluster

ΠŸΡ€ΠΈΠ²Π΅Ρ‚! Tampok na sangay (aka deploy preview, review app) - ito ay kapag hindi lang master branch ang na-deploy, kundi pati na rin ang bawat pull request sa isang natatanging URL. Maaari mong suriin kung gumagana ang code sa isang kapaligiran ng produksyon; ang tampok ay maaaring ipakita sa iba pang mga programmer o mga espesyalista sa produkto. Habang nagtatrabaho ka sa isang pull request, ang bawat bagong commit na kasalukuyang deploy para sa lumang code ay tatanggalin, at ang bagong deploy para sa bagong code ay ilulunsad. Maaaring lumitaw ang mga tanong kapag pinagsama mo ang isang pull request sa master branch. Hindi mo na kailangan ang feature branch, ngunit ang mga mapagkukunan ng Kubernetes ay nasa cluster pa rin.

Higit pa tungkol sa mga feature na sangay

Ang isang diskarte sa paggawa ng mga feature na sangay sa Kubernetes ay ang paggamit ng mga namespace. Sa madaling salita, ganito ang hitsura ng configuration ng produksyon:

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

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

Para sa isang feature na sangay, ang isang namespace ay ginawa kasama ang identifier nito (halimbawa, ang pull request number) at ilang uri ng prefix/postfix (halimbawa, -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
...

Sa pangkalahatan, nagsulat ako Operator ng Kubernetes (isang application na may access sa mga mapagkukunan ng cluster), link sa proyekto sa Github. Inaalis nito ang mga namespace na kabilang sa mga lumang feature na sangay. Sa Kubernetes, kung tatanggalin mo ang isang namespace, ang ibang mga mapagkukunan sa namespace na iyon ay awtomatikong tatanggalin din.

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

Maaari mong basahin ang tungkol sa kung paano ipatupad ang mga sangay ng tampok sa isang kumpol dito ΠΈ dito.

Pagganyak

Tingnan natin ang isang tipikal na pull request lifecycle na may tuluy-tuloy na pagsasama (continuous integration):

  1. Nagpu-push kami ng bagong commit sa branch.
  2. Sa build, ang mga linter at/o mga pagsubok ay pinapatakbo.
  3. Kubernetes pull request configuration ay nabuo sa mabilisang (halimbawa, ang numero nito ay ipinasok sa tapos na template).
  4. Gamit ang kubectl apply, idinaragdag ang mga configuration sa cluster (deploy).
  5. Ang kahilingan sa paghila ay pinagsama sa master branch.

Habang nagtatrabaho ka sa isang pull request, ang bawat bagong commit na kasalukuyang deploy para sa lumang code ay tatanggalin, at ang bagong deploy para sa bagong code ay ilulunsad. Ngunit kapag ang pull request ay pinagsama sa master branch, master branch lang ang itatayo. Bilang resulta, lumalabas na nakalimutan na namin ang tungkol sa kahilingan sa paghila, at ang mga mapagkukunang Kubernetes nito ay nasa cluster pa rin.

Paano gamitin

I-install ang proyekto gamit ang command sa ibaba:

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

Lumikha ng isang file na may sumusunod na nilalaman at i-install sa pamamagitan ng kubectl apply -f:

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

Parametro namespaceSubstring kailangan upang i-filter ang mga namespace para sa mga pull request mula sa iba pang mga namespace. Halimbawa, kung ang cluster ay may mga sumusunod na namespace: habr-back-end, habr-front-end, habr-back-end-pr-17, habr-back-end-pr-33, kung gayon ang mga kandidato para sa pagtanggal ay magiging habr-back-end-pr-17, habr-back-end-pr-33.

Parametro afterDaysWithoutDeploy kailangan upang tanggalin ang mga lumang namespace. Halimbawa, kung ginawa ang namespace 3 дня 1 час pabalik, at ang parameter ay nagpapahiwatig 3 дня, ang namespace na ito ay tatanggalin. Gumagana rin ito sa kabaligtaran ng direksyon kung nilikha ang namespace 2 дня 23 часа pabalik, at ang parameter ay nagpapahiwatig 3 дня, hindi matatanggal ang namespace na ito.

May isa pang parameter, ito ang may pananagutan sa kung gaano kadalas i-scan ang lahat ng namespace at suriin ang mga araw na walang deployment - checkEveryMinutes. Bilang default, ito ay katumbas ng 30 ΠΌΠΈΠ½ΡƒΡ‚Π°ΠΌ.

Как это Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚

Sa pagsasagawa, kakailanganin mo:

  1. Manggagawa sa pantalan para sa pagtatrabaho sa isang nakahiwalay na kapaligiran.
  2. Minikube ay magtataas ng Kubernetes cluster nang lokal.
  3. kubectl β€” interface ng command line para sa pamamahala ng kumpol.

Nagtataas kami ng Kubernetes cluster nang lokal:

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

Ipinapahiwatig namin kubectl gumamit ng lokal na kumpol bilang default:

$ kubectl config use-context minikube
Switched to context "minikube".

Mag-download ng mga configuration para sa kapaligiran ng produksyon:

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

Dahil ang mga configuration ng produksyon ay na-configure upang suriin ang mga lumang namespace, at ang aming bagong itinaas na cluster ay wala ang mga ito, papalitan namin ang environment variable IS_DEBUG sa true. Sa halagang ito ang parameter afterDaysWithoutDeploy ay hindi isinasaalang-alang at ang mga namespace ay hindi sinusuri para sa mga araw na walang pag-deploy, para lamang sa paglitaw ng substring (-pr-).

Kung ikaw ay nasa Linux:

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

Kung ikaw ay nasa macOS:

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

Pag-install ng proyekto:

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

Sinusuri kung may lumabas na mapagkukunan sa cluster StaleFeatureBranch:

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

Sinusuri namin na may lumitaw na operator sa cluster:

$ kubectl get pods --namespace stale-feature-branch-operator
NAME                                           ... STATUS  ... AGE
stale-feature-branch-operator-6bfbfd4df8-m7sch ... Running ... 38s

Kung titingnan mo ang mga log nito, handa na itong iproseso ang mga mapagkukunan 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}

Nag-install kami ng handa na fixtures (mga handa nang configuration para sa pagmomodelo ng mga mapagkukunan ng cluster) para sa isang mapagkukunan StaleFeatureBranch:

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

Isinasaad ng mga pagsasaayos na maghanap ng mga namespace na may substring -pr- sabay pasok 1 ΠΌΠΈΠ½ΡƒΡ‚Ρƒ.:

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

Tumugon ang operator at handang suriin ang mga namespace:

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

Itakda fixtures, na naglalaman ng dalawang namespaces (project-pr-1, project-pr-2) at sila deployments, services, ingress, at iba pa:

$ 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

Sinusuri namin na ang lahat ng mga mapagkukunan sa itaas ay matagumpay na nalikha:

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

Since kasama namin debug, mga namespace project-pr-1 ΠΈ project-pr-2, samakatuwid ang lahat ng iba pang mapagkukunan ay kailangang tanggalin kaagad nang hindi isinasaalang-alang ang parameter afterDaysWithoutDeploy. Ito ay makikita sa mga log ng operator:

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

Kung titingnan mo ang pagkakaroon ng mga mapagkukunan, ang mga ito ay nasa katayuan Terminating (proseso ng pagtanggal) o tinanggal na (walang laman ang output ng command).

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

Maaari mong ulitin ang proseso ng paglikha fixtures ilang beses at siguraduhing maalis ang mga ito sa loob ng isang minuto.

Mga alternatibo

Ano ang maaaring gawin sa halip na isang operator na nagtatrabaho sa isang kumpol? Mayroong ilang mga diskarte, lahat ng mga ito ay hindi perpekto (at ang kanilang mga pagkukulang ay subjective), at lahat ay nagpapasya para sa kanyang sarili kung ano ang pinakamahusay para sa isang partikular na proyekto:

  1. Tanggalin ang sangay ng tampok sa panahon ng patuloy na pagbuo ng pagsasama ng master branch.

    • Para magawa ito, kailangan mong malaman kung aling pull request ang nauugnay sa commit na ginagawa. Dahil naglalaman ang namespace ng feature na branch ng pull request identifier - ang numero nito, o ang pangalan ng branch, palaging kailangang tukuyin ang identifier sa commit.
    • Nabigo ang mga master branch build. Halimbawa, mayroon kang mga sumusunod na yugto: i-download ang proyekto, patakbuhin ang mga pagsubok, buuin ang proyekto, gumawa ng release, magpadala ng mga abiso, i-clear ang feature branch ng huling pull request. Kung nabigo ang build kapag nagpapadala ng notification, kakailanganin mong i-delete nang manu-mano ang lahat ng mapagkukunan sa cluster.
    • Kung walang wastong konteksto, ang pagtanggal ng mga sangay ng tampok sa master build ay hindi halata.

  2. Paggamit ng mga webhook (halimbawa).

    • Maaaring hindi ito ang iyong diskarte. Halimbawa, sa Jenkins, isang uri lamang ng pipeline ang sumusuporta sa kakayahang i-save ang mga configuration nito sa source code. Kapag gumagamit ng webhooks, kailangan mong magsulat ng sarili mong script para maproseso ang mga ito. Ang script na ito ay kailangang ilagay sa Jenkins interface, na mahirap panatilihin.

  3. Upang magsulat Cronjob at magdagdag ng Kubernetes cluster.

    • Gumugugol ng oras sa pagsulat at suporta.
    • Gumagana na ang operator sa katulad na istilo, dokumentado at sinusuportahan.

Salamat sa iyong pansin sa artikulo. Mag-link sa proyekto sa Github.

Pinagmulan: www.habr.com

Magdagdag ng komento