
— нашата GitOps CLI утилита с отворен код за сглобяване и доставка на приложения в Kubernetes. В бе представена нова възможност в сборщика на образи: етикетиране на образи по съдържание или content-based tagging. Досега типичната схема за етикетиране в werf предполагаше етикетиране на Docker образи по Git етикет, Git клон или Git комит. Но всички тези схеми имат недостатъци, които новата стратегия за етикетиране напълно решава. Подробности за нея и какво я прави толкова добра — под кат.
Изпускане на набор от микросервизи от едно Git хранилище
Често се среща ситуация, в която приложението е разделено на множество независими услуги. Изданията на тези услуги могат да се случват независимо: едновременно може да се издаде една или няколко услуги, а останалите да продължат да работят без никакви промени. Но от гледна точка на съхраняване на кода и управление на проекта е по-удобно да се държат такива услуги в единно хранилище.
Има случаи, когато услугите действително са независими и не са свързани с едно приложение. В този случай те ще бъдат разположени в отделни проекти и издаването им ще се извършва чрез отделни CI/CD процеси в всеки от проектите.
Въпреки това, в реалността разработчиците често разделят едно приложение на няколко микросервиза, но да се създаде отделно хранилище и проект за всеки… — е очевиден overkill. Точно за тази ситуация ще става дума по-нататък: няколко от тези микросервизи се намират в единно хранилище на проекта и изданията се осъществяват чрез единен процес в CI/CD.
Етикетиране по Git клон и Git етикет
Да предположим, че се използва най-разпространената стратегия за етикетиране — tag-or-branch. За Git клоновете образите се етикетират с името на клона, за един клон по едно време съществува само един публикуван образ с името на този клон. За Git етикетите образите се етикетират съответно с името на етикета.
При създаването на нов Git етикет — например, при пускането на нова версия — за всички образи на проекта в Docker Registry ще бъде създаден нов Docker етикет:
-
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
Новите имена на изображения попадат в конфигурацията на Kubernetes чрез шаблони на Helm. При стартиране на деплой с команда werf deploy се извършва актуализация на полето image в манифестите на ресурсите на Kubernetes и се презареждат съответните ресурси заради промененото име на изображението.
Проблема: в случай, че реално съдържанието на изображението от предишното издание (Git таг) не е променено, а само Docker тагът му, се случва излишно презареждане на това приложение и, съответно, е възможно известен престой. Въпреки че нямаше реални причини за извършване на това презареждане.
В резултат на това, при текущата схема на тагиране, е необходимо да се създадат няколко отделни Git репозитория и възниква проблемът с организацията на разпространението на тези няколко репозитория. В общи линии, такава схема се оказва претоварена и сложна. По-добре е да се обединят много услуги в един репозиторий и да се създават такива Docker тагове, че да няма излишни презареждания.
Тагиране по Git комит
В werf има стратегия за тагиране, свързана с Git комитите.
Git комитът е идентификатор на съдържанието на Git репозитория и зависи от историята на промените в файловете в Git репозитория, затова изглежда логично да се използва за тагиране на изображения в Docker Registry.
Въпреки това, тагирането по Git комит има същите недостатъци, както тагирането по Git клонове или Git тагове:
- Може да бъде създаден празен комит, който не променя файловете, а Docker тагът на изображението ще бъде променен.
- Може да бъде създаден merge комит, който не променя файловете, а Docker тагът на изображението отново ще бъде променен.
- Може да бъде създаден комит, който променя файловете в Git, които не се импортират в изображението, а Docker тагът на изображението отново ще бъде променен.
Тагирането по името на Git клон не отразява версията на изображението
Има и още един проблем, свързан със стратегията за тагиране по Git клонове.
Тагирането по името на клона работи, дотогава, докато комитите на този клон се събират последователно в хронологичен ред.
Ако в текущата схема потребителят стартира повторна компилация на стар комит, свързан с определен клон, то werf ще замени изображението за съответния Docker таг с новосъздадената версия на изображението за стария комит. Използващите този таг Deployment-и от този момент рискуват при рестартиране на pod-ове да изтеглят друга версия на изображението, в резултат на което нашето приложение ще загуби връзката с CI системата и ще стане несинхронизирано.
Освен това, при последователни push операции в един клон с малък интервал между тях, старият комит може да бъде събран по-късно от новия: старата версия на образа ще замести новата по етикет на Git клона. Такива проблеми могат да бъдат решени от CI/CD системата (например, в GitLab CI за серия от комити се стартира pipeline на последния). Въпреки това, не всички системи го поддържат, и трябва да има по-надежден начин за предотвратяване на толкова основен проблем.
Какво е теглинг на базата на съдържание?
И така, какво представлява теглингът на базата на съдържание – етикетиране на образи по съдържание.
За създаване на Docker етикети се използват не примитивите на Git (Git клон, Git етикет...), а контролната сума, свързана с:
- съдържанието на образа. Идентификаторът-етикет на образа отразява неговото съдържание. При изграждане на нова версия, този идентификатор няма да се промени, ако файловете в образа не са изменени;
- историята на създаването на този образ в Git. Образите, свързани с различни Git клонове и различна история на сборка чрез werf, ще имат различни идентификатори-етикети.
В качеството си на такъв идентификатор-етикет служи т.н. сигнатура на етапите на образа.
Всеки образ се състои от набор от етапи: from, before-install, git-archive, инсталиране, imports-after-install, before-setup,… git-latest-patch и т.н. Всеки етап има идентификатор, отразяващ неговото съдържание, – сигнатура на етапа (stage signature).
Финалният образ, съставен от тези етапи, се етикетира с т.н. сигнатура на набора от тези етапи – stages signature, – която обобщава всички етапи на образа.
Всеки образ от конфигурацията werf.yaml общо взето ще има своя такава сигнатура и, съответно, Docker етикет.
Сигнатурата на етапите решава всички посочени проблеми:
- Устойчива на празни Git комити.
- Устойчива на Git комити, които променят файлове, които не са релевантни за образа.
- Не води до проблема с подменяне на актуалната версия на образа при повторно стартиране на сборки за стари Git комити на клона.
Сега това е препоръчителната стратегия за етикетиране и се използва по подразбиране в werf за всички CI системи.
Как да активирам и да използвам в werf
Съответната опция се появи при командата werf publish: --tag-by-stages-signature=true|false
В CI системата, стратегията за етикетиране се задава с командата werf ci-env. По-рано за нея се определяше параметър werf ci-env --tagging-strategy=tag-or-branch. Сега, ако се посочи werf ci-env --tagging-strategy=stages-signature или не се посочи тази опция, werf по подразбиране ще използва стратегията за етикетиране. stages-signature. Командата werf ci-env автоматично ще зададе нужните флагове за командата werf build-and-publish (или werf publish), затова не е нужно да се посочват допълнителни опции за тези команди.
Например, командата:
werf publish --stages-storage :local --images-repo registry.hello.com/web/core/system --tag-by-stages-signature… може да създаде следните образи:
-
registry.hello.com/web/core/system/backend:4ef339f84ca22247f01fb335bb19f46c4434014d8daa3d5d6f0e386d -
registry.hello.com/web/core/system/frontend:f44206457e0a4c8a54655543f749799d10a9fe945896dab1c16996c6
Тук 4ef339f84ca22247f01fb335bb19f46c4434014d8daa3d5d6f0e386d — това е подписът на етапа на образа backend, а f44206457e0a4c8a54655543f749799d10a9fe945896dab1c16996c6 — подписът на етапа на образа фронтенд.
При използване на специални функции werf_container_image и werf_container_env в шаблоните Helm не е нужно да се променя нищо: тези функции ще генерират автоматично правилните имена на образите.
Пример за конфигурация в CI-системата:
type multiwerf && source <(multiwerf use 1.1 beta)
type werf && source <(werf ci-env gitlab)
werf build-and-publish|deployДопълнителна информация за конфигуриране е налична в документацията:
- ;
- ;
- .
Общо
- Нова опция
werf publish --tag-by-stages-signature=true|false. - Нова стойност на опцията
werf ci-env --tagging-strategy=stages-signature|tag-or-branch(ако не бъде посочено, по подразбиране ще бъдеstages-signature). - Ако преди това са използвани опции за тагиране по Git-комити (
WERF_TAG_GIT_COMMITили опциятаwerf publish --tag-git-commit COMMIT), то е задължително да се превключи на стратегия за тагиране stages-signature. - Новите проекти е най-добре да се преминат веднага на новата схема за тагиране.
- Старите проекти, при преминаване на werf 1.1, е желателно да се прехвърлят на новата схема за тагиране, но старата tag-or-branch все още се поддържа.
Content-based tagging решава всички обсъдени в статията проблеми:
- Устойчивост на името на Docker-тага спрямо празни Git-комити.
- Устойчивост на името на Docker-тага спрямо Git-комити, които променят нематериални за образа файлове.
- Не води до проблем с презаписване на актуалната версия на образа при повторно стартиране на изграждането за стари Git-комити на Git-клонове.
Ползвайте! И не забравяйте да погледнете при нас на , за да създадете issue или да намерите вече съществуваща, да поставите плюс, да създадете PR или просто да следите развитието на проекта.
P.S.
Прочетете също в нашия блог:
- «»
- «»
- «»;
- Цикъл от бележки за новостите в werf:
- «»;
- «»;
- «»;
- «».
Източник: habr.com
