Vi i True Engineering har opsat en proces for kontinuerlig levering af opdateringer til kundens servere, og vi ønsker at dele denne erfaring.
For at begynde udviklede vi et online system for kunden og implementerede det i vores eget Kubernetes-kluster. Nu er vores højt belastede løsning flyttet til kundens platform, for hvilket vi har opsat en fuldt automatisk proces for Continuous Deployment. Dette har gjort, at vi har forkortet time-to-market – leveringen af ændringer til produktionsmiljøet.
I denne artikel vil vi fortælle om alle faserne af processen for Continuous Deployment (CD) eller levering af opdateringer til kundens platform:
- hvordan denne proces starter,
- synkronisering med kundens Git-repository,
- bygning af backend og frontend,
- automatisk implementering af applikationen i testmiljøet,
- automatisk implementering i produktion.
I processen vil vi dele detaljer om opsætningen.

1. Start af CD
Continuous Deployment starter med, at udvikleren lægger ændringer i den relevante udgivelsesgren i vores Git-repository.
Vores applikation er bygget på en mikrotjenestearkitektur, og alle dens komponenter opbevares i ét repository. Dette gør det muligt at bygge og installere alle mikrotjenester, selvom en enkelt af dem er ændret.
Vi har organiseret arbejdet gennem ét repository af flere grunde:
- Bekvemmelighed ved udvikling – applikationen udvikles aktivt, så der kan arbejdes med hele koden på én gang.
- En enkelt CI/CD-pipeline, der garanterer, at applikationen som et samlet system gennemgår alle tests og leveres til kundens prod-miljø.
- Vi undgår forvirring omkring versioner – vi behøver ikke at opbevare et kort over versioner af mikrotjenester og beskrive konfigurationen for hver mikrotjeneste i Helm-scripts.
2. Synkronisering med kundens kildekode-Git-repository
Foretagne ændringer synkroniseres automatisk med kundens Git-repository. Der er opsat en bygning af applikationen, der starter efter opdateringen af grenen, og implementering til produktion. Begge processer foregår i deres miljø fra Git-repositoryet.
Vi kan ikke arbejde direkte med kundens repository, da vi har brug for vores egne udviklings- og testmiljøer. Vi bruger vores eget Git-repository til dette formål — det er synkroniseret med deres Git-repository. Så snart en udvikler uploader ændringer til den relevante gren af vores repository, sender GitLab straks disse ændringer til kunden.

Derefter skal der laves en bygning. Den består af flere trin: bygning af backend og frontend, test og levering til produktion.
3. Bygning af backend og frontend
Bygningen af backend og frontend er to parallelle opgaver, som udføres i GitLab Runner-systemet. Konfigurationen af den oprindelige bygning ligger i dette samme repository.
.
GitLab Runner henter koden fra det nødvendige repository, bygger Java-applikationen med byggekommandoen og sender den til Docker registry. Her bygger vi backend og frontend, får Docker-images, som vi opbevarer i kundens repository. For at styre Docker-images bruger vi .
Vi synkroniserer versionerne af vores images med versionen af den release, som skal uploades til Docker. For at sikre en glat drift har vi foretaget flere indstillinger:
1. Mellem testmiljøet og produktionsmiljøet genopbygges containere ikke. Vi har lavet parametriseringer, så den samme container kan fungere uden genopbygning med alle indstillinger, miljøvariabler og services både i testmiljøet og i produktionen.
2. For at opdatere applikationen gennem Helm skal du angive dens version. Vi har bygning af backend, frontend og opdatering af applikationen – dette er tre forskellige opgaver, så det er vigtigt at bruge den samme version af applikationen overalt. Til denne opgave bruger vi data fra Git-historikken, da vores K8S-klynge- og applikationskonfiguration er i det samme Git-repository.
Vi får applikationens version fra resultaterne af kommandoen
git describe --tags --abbrev=7.
4. Automatisk deployment af alle ændringer i testmiljøet (UAT)
Det næste trin i dette build-script er automatisk opdatering af K8S-klyngen. Dette sker, hvis hele applikationen er bygget, og alle artefakter er offentliggjort i Docker Registry. Derefter begynder opdateringen af testmiljøet.
Opdateringen af klyngen startes med . Hvis noget gik galt, vil Helm automatisk og selvstændigt rulle alle sine ændringer tilbage. Det er ikke nødvendigt at kontrollere dens arbejde.
Vi leverer konfigurationen af K8S-klyngen sammen med opbygningen. Så næste skridt er at opdatere den: configMaps, deployments, services, secrets og andre K8S-konfigurationer, som vi har ændret.
Efter dette starter Helm RollOut opdateringen af selve applikationen i testmiljøet. Før applikationen vil blive implementeret på produktion. Dette gøres for at brugerne manuelt kan tjekke de forretningsfunktioner, vi har lagt i testmiljøet.
5. Automatisk udrulning af alle ændringer til Prod
For at udrulle opdateringen til produktionsmiljøet, er det kun én knap i GitLab, der skal trykkes på — og containerne leveres straks til produktionsmiljøet.
Den samme applikation kan fungere i forskellige miljøer — test og produktion — uden at blive ombygget. Vi bruger de samme artefakter uden at ændre noget i applikationen, mens parametrene angives udefra.
Fleksibel parametrisering af applikationens indstillinger afhænger af det miljø, hvori applikationen skal køre. Vi har taget alle miljøindstillinger udvendigt: alt parametriseres via K8S-konfiguration og Helm-parametre. Når Helm udruller opbygningen i testmiljøet, anvendes testparametre, og i produktionsmiljøet — produktionsparametre.
Den største udfordring var at parameterisere alle de anvendte tjenester og variabler, der afhænger af miljøet, og oversætte dem til miljøvariabler og beskrivelse-konfiguration af miljøparametre for Helm.
I applikationsparametrene bruges miljøvariabler. Deres værdier angives i containerne ved hjælp af K8S configmap, som skabeloniseres ved hjælp af Go-skabeloner. For eksempel kan tildelingen af en miljøvariabel til domænenavnet gøres sådan her:
APP_EXTERNAL_DOMAIN: {{ (pluck .Values.global.env .Values.app.properties.app_external_domain | first) }}
.Values.global.env – denne variabel indeholder navnet på miljøet (prod, stage, UAT).
.Values.app.properties.app_external_domain – i denne variabel angiver vi den ønskede domæne i filen .Values.yaml
Når Helm opdaterer applikationen, opretter den konfigurationer fra skabelonerne i configmap.yaml og fylder værdien APP_EXTERNAL_DOMAIN med den nødvendige værdi afhængigt af det miljø, opdateringen udføres i. Denne variabel er allerede tilgængelig i containeren. Den kan tilgås fra applikationen, hvilket betyder, at hver applikation i hvert miljø vil have en forskellig værdi for denne variabel.
Nyligt er der i Spring Cloud blevet tilføjet støtte til K8S, herunder arbejde med configMaps: . Da projektet aktivt udvikles og ændres radikalt, kan vi ikke bruge det i produktion. Men vi overvåger aktivt dets tilstand og bruger det i DEV-konfigurationer. Så snart det stabiliserer sig, vil vi skifte fra brug af miljøvariabler til det.
I alt
Så, Continuous Deployment er opsat og fungerer. Alle opdateringer sker med ét tryk på en knap. Levering af ændringer til produktionsmiljøet er automatisk. Og vigtigt er, at opdateringerne ikke stopper systemets drift.

Fremtidsplaner: automatisk database-migrering
Vi har overvejet at opgradere databasen og hvordan man kan rulle disse ændringer tilbage. For der kører to forskellige versioner af applikationen samtidig: den gamle version fungerer, mens den nye version starter. Vi vil kun slukke for den gamle version, når vi er sikre på, at den nye version fungerer. Database-migreringen skal muliggøre drift med begge versioner af applikationen.
Derfor kan vi ikke bare ændre kolonnenavnet eller andre data. Men vi kan oprette en ny kolonne, kopiere data fra den gamle kolonne til den nye og skrive triggere, der samtidig vil kopiere og opdatere dataene i den anden kolonne ved opdatering. Efter en vellykket deployment af den nye version af applikationen, efter en post-launch supportperiode, kan vi fjerne den gamle kolonne og den unødvendige trigger.
Hvis den nye version af applikationen ikke fungerer korrekt, kan vi rulle tilbage til den tidligere version, inklusive den tidligere version af databasen. Med andre ord, vores ændringer vil muliggøre samtidig drift med flere versioner af applikationen.
Vi planlægger at automatisere database-migreringen gennem K8S job og integrere den i CD-processen. Og vi vil bestemt dele denne erfaring på Habr.
Kilde: habr.com
