
— vores GitOps CLI-værktøj med åben kildekode til at bygge og levere applikationer til Kubernetes. I blev der introduceret en ny funktion i billedbyggeren: tagging af billeder baseret på indhold eller content-based tagging. Indtil nu har den typiske tagging-schema i werf antaget tagging af Docker-billeder efter Git-tag, Git-gren eller Git-commit. Men alle disse ordninger har ulemper, som den nye tagging-strategi fuldstændigt løser. Flere detaljer om dette og hvad der er så godt ved det — længst nede.
Udrulning af en suite af mikrotjenester fra et enkelt Git-repositorium
Det er ofte tilfældet, at en applikation er opdelt i mange mere eller mindre uafhængige tjenester. Udgivelser af disse tjenester kan finde sted uafhængigt: på én gang kan én eller flere tjenester blive udgivet, mens de øvrige fortsætter med at fungere uden ændringer. Men set fra et opbevarings- og projektledelsesperspektiv er det mere praktisk at holde sådanne apptjenester i et enkelt repositorium.
Der er tilfælde, hvor tjenesterne faktisk er uafhængige og ikke relateret til én applikation. I så fald vil de være placeret i separate projekter, og deres udgivelse vil finde sted gennem separate CI/CD-processer i hvert af projekterne.
Men i praksis opdeler udviklere ofte en samlet applikation i flere mikrotjenester, men at oprette et separat repositorium og projekt for hver… — ville være klart overkill. Det er netop dette scenarie, der vil blive omtalt næste gang: flere sådanne mikrotjenester ligger i et enkelt projektrepositorium, og udgivelserne sker gennem en samlet proces i CI/CD.
Tagging efter Git-gren og Git-tag
Antag, at der anvendes den mest udbredte tagging-strategi — tag-or-branch. For Git-grene bliver billederne tagget med grennavnet, for én gren eksisterer der på et givet tidspunkt kun ét offentliggjort billede med dette grennavn. For Git-tags bliver billederne tagget tilsvarende med tagnavnet.
Når der oprettes et nyt Git-tag — for eksempel når en ny version udgives — vil der for alle billeder i projektet i Docker Registry blive oprettet et nyt Docker-tag:
-
myregistry.org/myproject/frontend:v1.1.10 -
myregistry.org/myproject/myservice1:v1.1.10 -
myregistry.org/myproject/myservice2:v1.1.10 -
myregistry.org/myproject/myservice3:v1.1.10 -
myregistry.org/myproject/myservice4:v1.1.10 -
myregistry.org/myproject/myservice5:v1.1.10 -
myregistry.org/myproject/database:v1.1.10
Disse nye billednavne overføres via Helm-skabeloner til Kubernetes-konfigurationen. Ved lancering af deployment med kommandoen werf deploy opdateres feltet billede i Kubernetes-ressourcemanifesterne, hvilket resulterer i en genstart af de tilsvarende ressourcer på grund af det ændrede billednavn.
Problemet: i tilfælde af at indholdet fra den forrige version (Git-tag) faktisk ikke har ændret sig, men kun dens Docker-tag, sker der en unødvendig genstart af denne applikation, og der kan derfor opstå visse problemer. Selvom der ikke var nogen reelle grunde til at udføre denne genstart.
Som følge heraf, under den nuværende tagging-ordning, er det nødvendigt at oprette flere separate Git-repositorier, og der opstår problemer med at organisere deployment af disse forskellige repositories. Generelt set bliver en sådan ordning overbelastet og kompleks. Det er bedre at samle mange tjenester i et enkelt repository og oprette sådanne Docker-tags, så der ikke sker unødvendige genstarter.
Tagging efter Git-commit
I werf findes der også en tagging-strategi, der er relateret til Git-commits.
Git-commit er en identifikator for indholdet af Git-repositoriet og afhænger af historikken for ændringer i filer i Git-repositoriet, så det virker logisk at bruge det til tagging af billeder i Docker Registry.
Dog har tagging efter Git-commit de samme ulemper som tagging efter Git-grene eller Git-tags:
- Der kunne være oprettet et tomt commit, som ikke ændrer filer, og Docker-tagget for billedet vil blive ændret.
- Der kunne være oprettet et merge-commit, som ikke ændrer filer, og Docker-tagget for billedet vil blive ændret.
- Der kunne være oprettet et commit, som ændrer de filer i Git, der ikke importeres i billedet, og Docker-tagget for billedet vil igen blive ændret.
Tagging efter navnet på Git-grenen afspejler ikke billedversionen
Der er også et andet problem forbundet med tagging-strategien baseret på Git-grene.
Tagging efter grenens navn fungerer så længe, som commits af denne gren bliver samlet i kronologisk rækkefølge.
Hvis brugeren i det nuværende skema starter rekonstruktionen af et gammelt commit relateret til en bestemt gren, vil werf overskrive billedet med den relevante Docker-tag med den nyopbyggede version af billedet for det gamle commit. Deployments, der bruger denne tag, risikerer fra nu af at trække en anden version af billedet ved genstart af pods, hvilket medfører, at vores applikation mister forbindelsen til CI-systemet og bliver desynkroniseret.
Desuden, ved følgende push til en gren med kort tidsinterval imellem, kan det gamle commit blive bygget senere end det nyere: den gamle version af billedet vil overskrive den nye i henhold til Git-grenen. Sådanne problemer kan håndteres af CI/CD-systemet (f.eks. i GitLab CI starter en pipeline for den seneste serie af commits). Dog understøtter ikke alle systemer dette, og der bør findes en mere pålidelig metode til at forebygge sådan en fundamental problem.
Hvad er content-based tagging?
Så hvad er content-based tagging — tagging af billeder baseret på indhold.
Til at skabe Docker-tags bruges ikke Git-primitiverne (Git-gren, Git-tag...), men en kontrolsum, der er relateret til:
- indholdet af billedet. Tag-id'et af billedet reflekterer dets indhold. Ved opbygningen af en ny version ændres dette id ikke, hvis filerne i billedet ikke har ændret sig;
- historikken for opbygningen af dette billede i Git. Billeder, der er relateret til forskellige Git-grene og forskellig opbygningshistorik gennem werf, vil have forskellige tag-id'er.
Som et sådant tag-id fungerer den såkaldte signatur af billedet i stadier.
Hvert billede består af et sæt stadier: fra, før-installation, git-arkiv, installation, importer-efter-installation, før-opsætning,… git-seneste-patch osv. Hver fase har et id, der reflekterer dens indhold, — fase-signatur (stage signature).
Det endelige billede, der består af disse faser, tagges med den såkaldte signatur af sættet af disse faser — stages signature, — som er generaliserende for alle faser af billedet.
Hver billede fra konfigurationen werf.yaml vil generelt set have sin egen sådan signatur, og dermed et Docker-tag.
Signaturen af stadierne løser alle de nævnte problemer:
- Den er modstandsdygtig over for tomme Git-commits.
- Den er modstandsdygtig over for Git-commits, der ændrer filer, som ikke er relevante for billedet.
- Den medfører ikke en problem med at overskrive den aktuelle version af billedet, når man genstarter opbygninger for gamle Git-commits i grenen.
Nu er dette den anbefalede tagging-strategi, som bruges som standard i werf for alle CI-systemer.
Hvordan man aktiverer og bruger det i werf
Den relevante mulighed er tilgængelig for kommandoen werf publish: --tag-by-stages-signature=true|false
I CI-systemet angives tagging-strategien med kommandoen werf ci-env. Tidligere blev der angivet en parameter for den werf ci-env --tagging-strategy=tag-or-branch. Nu, hvis du angiver werf ci-env --tagging-strategy=stages-signature eller ikke angiver denne mulighed, vil werf som standard bruge tagging-strategien stages-signature. Kommandoen werf ci-env vil automatisk sætte de nødvendige flag for kommandoen werf build-and-publish (eller werf publish), så der er ikke behov for at angive yderligere muligheder for disse kommandoer.
For eksempel, kommandoen:
werf publish --stages-storage :local --images-repo registry.hello.com/web/core/system --tag-by-stages-signature… kan oprette følgende billeder:
-
registry.hello.com/web/core/system/backend:4ef339f84ca22247f01fb335bb19f46c4434014d8daa3d5d6f0e386d -
registry.hello.com/web/core/system/frontend:f44206457e0a4c8a54655543f749799d10a9fe945896dab1c16996c6
Her 4ef339f84ca22247f01fb335bb19f46c4434014d8daa3d5d6f0e386d — er billedets stages-signatur backend, og f44206457e0a4c8a54655543f749799d10a9fe945896dab1c16996c6 — billedets stages-signatur frontend.
Når man bruger særlige funktioner werf_container_image og werf_container_env i Helm-skabeloner kræves der ikke ændringer: disse funktioner vil automatisk generere de korrekte billednavne.
Eksempelkonfiguration i CI-systemet:
type multiwerf && source <(multiwerf use 1.1 beta)
type werf && source <(werf ci-env gitlab)
werf build-and-publish|deployMere information om konfigurationen er tilgængelig i dokumentationen:
- ;
- ;
- .
I alt
- Den nye mulighed
werf publish --tag-by-stages-signature=true|false. - Den nye værdi for indstillingen
werf ci-env --tagging-strategy=stages-signature|tag-or-branch(hvis ikke angivet, vil standarden værestages-signature). - Hvis der tidligere blev brugt taggingmuligheder baseret på Git-commits (
WERF_TAG_GIT_COMMITeller indstillingenwerf publish --tag-git-commit COMMIT), så skal man bestemt skifte til tagging-strategien stages-signature. - Nye projekter bør straks skiftes til den nye tagging-scheme.
- Gamle projekter bør ved opgradering til werf 1.1 skiftes til den nye tagging-scheme, men den gamle tag-or-branch understøttes stadig.
Content-based tagging løser alle de problemer, der er beskrevet i artiklen:
- Modstandsdygtighed af Docker-tagget mod tomme Git-commits.
- Modstandsdygtighed af Docker-tagget mod Git-commits, der ændrer irrelevante filer for billedet.
- Forårsager ikke problemer med at overskrive den aktuelle version af billedet ved genstart af bygninger for gamle Git-commits i Git-grene.
Brug det! Og glem ikke at besøge os på , for at oprette et issue eller finde et eksisterende, give et plus, oprette en PR eller blot følge udviklingen af projektet.
P.S.
Læs også på vores blog:
- «»
- «»
- «»;
- Cykelnotater om nyheder i werf:
- «»;
- «»;
- «»;
- «».
Kilde: habr.com
