Si si Dailymotion përdor Kubernetes: implementimi i aplikacioneve
Ne në Dailymotion filluam të përdorim Kubernetes në prodhim 3 vjet më parë. Por të implementosh aplikacione në disa klasterë është një kënaqësi e veçantë, prandaj gjatë këtyre viteve kemi shkuar për të përmirësuar mjetet dhe proceset tona të punës.
Si filloi gjithçka
Këtu do të tregojmë se si e implementojmë aplikacionet tona në disa klasterë Kubernetes në të gjithë botën.
Për të implementuar disa objekte Kubernetes njëherësh, ne përdorim , dhe të gjithë kartat tona ruhen në një depo git. Për të implementuar një stack të plotë të aplikacionit nga disa shërbime, ne përdorim atë që quhet kartë e përmbledhur. Në thelb, kjo është një kartë që shpall varësitë dhe lejon inicializimin e API-së dhe shërbimeve të saj me një komandë.
Gjithashtu, kemi shkruar një skenar të vogël në Python mbi Helm, për të bërë verifikime, krijuar karta, shtuar sekrete dhe implementuar aplikacione. Të gjitha këto detyra kryhen në një platformë CI qendrore duke përdorur një imazh docker.
Të kalojmë në thelb.
Shënim. Kur po e lexoni këtë, kandidati i parë për lëshim i Helm 3 është shpallur tashmë. Versioni kryesor përmban një grup të tërë përmirësimesh, të destinuara për të zgjidhur disa probleme me të cilat u përballëm në të kaluarën.
Procesi i punës për zhvillimin e kartave
Për aplikacionet, ne përdorim degëzim, dhe ky qasje e kemi aplikuar edhe te kartat.
- Dega dev përdoret për krijimin e kartave që do të testohet në klasterët e zhvillimit.
- Kur kërkesa e palës së tretë dërgohet në master, ato kontrollohen në skenë.
- Më në fund, ne krijojmë një kërkesë të palës së tretë për të transferuar ndryshimet në degë prod dhe për t'i aplikuar ato në prodhim.
Ădo mjedis ka depo private qĂ« ruan kartat tona dhe ne pĂ«rdorim me API shumĂ« tĂ« dobishme. KĂ«shtu, ne kemi garantuar izolim tĂ« fortĂ« midis ambienteve dhe verifikim tĂ« kartave nĂ« kushte reale para se t'i pĂ«rdorim nĂ« prodhim.
Depo kartash në ambiente të ndryshme
Vlen të theksohet se kur zhvilluesit dërgojnë degën dev, versioni i kartës së tyre dërgohet automatikisht në Chartmuseum dev. Kështu, të gjithë zhvilluesit përdorin një depo dev, dhe është e nevojshme të specifikohet me kujdes versioni i kartës për të mos përdorur rastësisht ndryshimet e dikujt tjetër.
Për më tepër, skenari ynë i vogël Python kontrollon objektet Kubernetes sipas specifikimeve të Kubernetes OpenAPI duke përdorur , para se t'i publikojë në Chartmuseum.
Përmbledhje e procesit të punës për zhvillimin e kartave
- Konfigurimi i detyrave të pipeline sipas specifikimit për kontrollin e cilësisë (lint, test të njësi).
- Dërgimi i imazhit docker me mjetet Python, të cilat implementojnë aplikacionet tona.
- Konfigurimi i mjedisit sipas emrit të degës.
- Kontrolli i skedarëve yaml Kubernetes duke përdorur Kubeval.
- Rritja automatike e versionit të kartës dhe kartave të saj prind (kartat që varen nga karta e ndryshuar).
- Dërgimi i kartës në Chartmuseum, i cili është në përputhje me ambientin e saj.
Menaxhimi i diferencave në klasterë
Federata e klasterëve
Ishte një herë një kohë kur ne përdornim , ku mund të shpallnim objekte Kubernetes nga një pikë fundore API. Por patëm probleme. Për shembull, disa objekte Kubernetes nuk mund të krijoheshin në pikën fundore të federatës, prandaj ishte e vështirë të menaxhoheshin objektet e bashkuara dhe objekte të tjera për klasterë të veçantë.
Për të zgjidhur problemin, filluam të menaxhonim klasterët në mënyrë të pavarur, gjë që e thjeshtoi shumë procesin (përdorëm versionin e parë të federatës; në të dytin diçka mund të ketë ndryshuar).
Platforma gjeo-distribuar
Tani platforma jonĂ« Ă«shtĂ« e shpĂ«rndarĂ« nĂ« 6 regione â 3 lokalisht dhe 3 nĂ« cloud.
Implementimi i shpërndarë
Vlerat globale të Helm
4 vlera globale të Helm lejojnë përcaktimin e diferencave midis klasterëve. Për të gjitha kartat tona, ka vlera minimale sipas parazgjedhjes.
global:
cloud: True
env: staging
region: us-central1
clusterName: staging-us-central1Vlerat globale
Këto vlera ndihmojnë në përcaktimin e kontekstit për aplikacionet tona dhe përdoren për detyra të ndryshme: monitorimi, ndjekja, regjistrimi, kryerja e thirrjeve të jashtme, shkallëzimi, etj.
- «cloud»: ne kemi një platformë hibrid Kubernetes. Për shembull, API-ja jonë implementohet në zonat GCP dhe në qendrat tona të të dhënave.
- «env»: disa vlera mund të ndryshojnë për ambientet joaktive. Për shembull, përcaktimet e burimeve dhe konfigurimi i automatikë shkallëzimin.
- «region»: kjo informacion ndihmon në përcaktimin e vendndodhjes së klasterit dhe mund të përdoret për të përcaktuar pikë fundore më të afërt për shërbime të jashtme.
- «clusterName»: nëse dhe kur duam të përcaktojmë një vlerë për një klaster të veçantë.
Ja një shembull konkret:
{{/* Kthe numrin e replikave të Horizontal Pod Autoscaler për GraphQL*/}}
{{- define "graphql.hpaReplicas" -}}
{{- if eq .Values.global.env "prod" }}
{{- if eq .Values.global.region "europe-west1" }}
minReplicas: 40
{{- else }}
minReplicas: 150
{{- end }}
maxReplicas: 1400
{{- else }}
minReplicas: 4
maxReplicas: 20
{{- end }}
{{- end -}}Shembulli i shabllonit Helm
Kjo logjikë është përcaktuar në një shabllon ndihmës, për të mos ngarkuar YAML-në e Kubernetes.
Deklarata e aplikacionit
Veglat tona të vendosjes bazohen në disa skedarë YAML. Më poshtë është një shembull se si ne deklarojmë shërbimin dhe topologjinë e tij të shkallëzimit (numri i replikave) në klaster.
releases:
- foo.world
foo.world: # Emri i lëshimit
services: # Lista e aplikacioneve/projekteve të dailymotion
foobar:
chart_name: foo-foobar
repo: git@github.com:dailymotion/foobar
contexts:
prod-europe-west1:
deployments:
- name: foo-bar-baz
replicas: 18
- name: another-deployment
replicas: 3Përcaktimi i shërbimit
Kjo është skema e të gjithë hapave që përcaktojnë procesin tonë të vendosjes. Hapi i fundit vendos aplikacionin në mënyrë të njëkohshme në disa klasterë të punës.
Hapat e vendosjes në Jenkins
Dhe sekretet?
Sa i përket sigurisë, ne ndjekim të gjithë sekretet nga vende të ndryshme dhe i ruajmë ato në një depo unike në Paris.
Veglat tona të vendosjes nxjerrin vlerat e sekretëve nga Vault dhe, kur vjen koha e vendosjes, i inkuadrojnë ato në Helm.
Për këtë, ne kemi përcaktuar një lidhje mes sekretëve në Vault dhe sekretëve që i nevojiten aplikacioneve tona:
secrets:
- secret_id: "stack1-app1-password"
contexts:
- name: "default"
vaultPath: "/kv/dev/stack1/app1/test"
vaultKey: "password"
- name: "cluster1"
vaultPath: "/kv/dev/stack1/app1/test"
vaultKey: "password"- Ne kemi përcaktuar rregulla të përgjithshme që duhet të ndiqen kur shkruhen sekretet në Vault.
- Nëse një sekret i përket një konteksti ose klasteri të caktuar, duhet të shtohet një regjistër specifik. (Këtu konteksti cluster1 ka një vlerë të vetme për sekretin stack-app1-password).
- Në të kundërt, përdoret vlera në mënyrë default.
- Për çdo pikë në këtë listë në sekretin e Kubernetes shtohet një çift çelës-vlerë. Prandaj, shablloni i sekretit në chart-ët tanë është shumë i thjeshtë.
apiVersion: v1
data:
{{- range $key,$value := .Values.secrets }}
{{ $key }}: {{ $value | b64enc | quote }}
{{ end }}
kind: Secret
metadata:
name: "{{ .Chart.Name }}"
labels:
chartVersion: "{{ .Chart.Version }}"
tillerVersion: "{{ .Capabilities.TillerVersion.SemVer }}"
type: OpaqueProblemet dhe kufizimet
Puna me depo të shumta
Aktualisht ne ndajmë zhvillimin e chart-eve dhe aplikacioneve. Kjo do të thotë që zhvilluesit duhet të punojnë në dy depo git: një për aplikacionin dhe tjetra për përcaktimin e vendosjes së tij në Kubernetes. 2 depo git janë 2 procese punë, dhe një fillestar lehtë mund të ngatërrohet.
Të menaxhosh chart-et e përgjithshëm është e lodhshme
Siç e thashë, chart-et e përgjithshëm janë shumë të dobishme për përcaktimin e varësive dhe për vendosjen e shpejtë të disa aplikacioneve. Por ne përdorim --reuse-values, për të shmangur transferimin e të gjitha vlerave çdo herë kur vendosim një aplikacion që bën pjesë në këtë chart të përgjithshëm.
Në procesin e vazhdueshëm të furnizimit kemi vetëm dy vlera që ndryshojnë rregullisht: numri i replikave dhe etiketa e imazhit (versioni). Vlera të tjera, më të qëndrueshme, ndryshojnë manualisht, dhe kjo është mjaft e vështirë. Për më tepër, një gabim në vendosjen e chart-it të përgjithshëm mund të çojë në dështime të rënda, siç e kemi përjetuar në përvojën tonë.
Përditësimi i disa skedarëve të konfigurimit
Kur një zhvillues shton një aplikacion të ri, duhet të ndryshojë disa skedarë: deklarata e aplikacionit, lista e sekretëve, shtimi i aplikacionit në varësi, nëse bën pjesë në chart-in e përgjithshëm.
Lejet e Jenkins janë shumë të gjera në Vault
Aktualisht kemi një , që lexon të gjitha sekretet nga Vault.
Procesi i rikthimit nuk është automatizuar
Për rikthim ne duhet të ekzekutojmë një komandë në disa klasterë, që sjell mundësi për gabime. Ne e kryejmë këtë operacion manualisht, për të siguruar që të tregojmë identifikuesin e duhur të versionit.
Ne jemi në drejtim të GitOps
Qëllimi ynë
Duam ta kthejmë chart-in në depozitën e aplikacionit që po e shpërndajmë.
Procesi do të jetë i njëjtë si për zhvillimin. Për shembull, kur dega dërgohet në master, shpërndarja do të nisë automatikisht. Diferenca kryesore midis këtij qasjeje dhe procesit aktual do të jetë që gjithçka do të menaxhohet në git (si aplikacioni ashtu edhe mënyra e shpërndarjes së tij në Kubernetes).
Ka disa përfitime:
- Shumë më e qartë për zhvilluesin. Më e lehtë për t'u mësuar të aplikosh ndryshime në chart-in lokal.
- Definimi i shpërndarjes së shërbimeve mund të përcaktohet aty ku është kodi i shërbimit.
- Menaxhimi i heqjes së chart-ëve të përgjithshme. Shërbimi do të ketë lëshimin e tij Helm. Kjo do të lejojë menaxhimin e ciklit të jetës së aplikacionit (rikthim, përmirësim) në një nivel të imët, për të mos prekur shërbimet e tjera.
- Përfitimet e git për menaxhimin e chart-eve: anulimi i ndryshimeve, regjistri i auditimeve dhe të tjera. Nëse është e nevojshme të anullohet një ndryshim në chart, kjo mund të bëhet përmes git. Shpërndarja nis automatikisht.
- Mund të mendohet për përmirësimin e procesit të zhvillimit me ndihmën e mjeteve të tilla si Skaffold, me të cilat zhvilluesit mund të testojnë ndryshimet në një kontekst të ngjashëm me prodhimin.
Migrimi në dy etapa
Zhvilluesit tanë e përdorin këtë proces prej 2 vitesh, kështu që na nevojitet një migrim sa më pa dhimbje. Prandaj, ne vendosëm të shtojmë një fazë ndërmjetëse në rrugën drejt qëllimit.
Faza e parë është e thjeshtë:
- Ne ruajmë një strukturë të ngjashme për konfigurimin e shpërndarjes së aplikacioneve, por në një objekt me emrin DailymotionRelease.
apiVersion: "v1"
kind: "DailymotionRelease"
metadata:
name: "app1.ns1"
environment: "dev"
branch: "mybranch"
spec:
slack_channel: "#admin"
chart_name: "app1"
scaling:
- context: "dev-us-central1-0"
replicas:
- name: "hermes"
count: 2
- context: "dev-europe-west1-0"
replicas:
- name: "app1-deploy"
count: 2
secrets:
- secret_id: "app1"
contexts:
- name: "default"
vaultPath: "/kv/dev/ns1/app1/test"
vaultKey: "password"
- name: "dev-europe-west1-0"
vaultPath: "/kv/dev/ns1/app1/test"
vaultKey: "password"- 1 lëshim për aplikacion (pa chart-e të përgjithshme).
- Chart-e në depozitën git të aplikacionit.
Kemi biseduar me të gjithë zhvilluesit, kështu që procesi i migrimit ka filluar tashmë. Faza e parë ende kontrollohet duke përdorur platformën CI. Shpejt do të shkruaj një postim tjetër për fazën e dytë: si kaluam në procesin GitOps me . Do të tregoj se si e kemi konceptuar gjithçka dhe me çfarë vështirësish jemi përballur (disa depozita, sekrete, etj.). Qëndroni të informuar.
Këtu përpiqemi të përshkruajmë progresin tonë në procesin e shpërndarjes së aplikacioneve gjatë viteve të fundit, që na ka çuar në mendimin për qasjen GitOps. Endae nuk e kemi arritur qëllimin dhe do të raportojmë rezultatet, por tani jemi të bindur se vepruam si duhet kur vendosëm të thjeshtojmë gjithçka dhe ta afrojmë me zakonet e zhvilluesve.
Burimi: habr.com
