
— нашият 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 се обновява полето изображение в манифестите на ресурсите на Kubernetes и се рестартират съответните ресурси заради промененото име на изображението.
Проблема: в случай, когато съдържанието на изображението не се е променило от предишния билд (Git таг), а само Docker тагът му, се случва излишно рестартиране на това приложение и съответно е възможен известен простой. Въпреки че нямаше реални причини за извършване на това рестартиране.
Вследствие на това, при текущата схема на тагиране, е необходимо да се създадат няколко отделни Git хранилища и възниква проблемът с организирането на разпространението на тези няколко хранилища. Като цяло, такава схема се оказва претоварена и сложна. По-добре е да се обединят много услуги в единно хранилище и да се създадат такива Docker тагове, за да не се случват излишни рестартирания.
Тагиране по Git комит
В werf също съществува стратегия за тагиране, свързана с Git комитите.
Git комитът е идентификатор на съдържанието на Git хранилището и зависи от историята на промените на файловете в Git хранилището, затова изглежда логично да се използва за тагиране на изображенията в Docker Registry.
Въ cependant, тагирането по Git комити има същите недостатъци, както и при Git клонове или Git тагове:
- Може да е направен пуст комит, който не променя файловете, а Docker тагът на изображението ще бъде променен.
- Може да е направен merge комит, който не променя файловете, а Docker тагът на изображението ще бъде променен.
- Може да е направен комит, който променя файлове в Git, които не са импортирани в изображението, а Docker тагът на изображението отново ще бъде променен.
Тагирането по името на Git клона не отразява версията на изображението
Има и още един проблем, свързан със стратегията за тагиране по Git клонове.
Тагирането по името на клона работи, докато комитите на този клон се събират последователно в хронологичен ред.
Ако в текущата схема потребителят стартира повторно изграждане на стар комит, свързан с някакъв клон, то werf ще презапише изображението по съответния Docker таг с новосъздадената версия на изображението за стария комит. Използващите този таг разгръщания от този момент рискуват при рестартиране на подовете да направят pull на друга версия на изображението, в резултат на което нашето приложение ще загуби връзка с CI системата и ще се десинхронизира.
Освен това, при последователни push-ове в една клонка с малък интервал между тях, старият commit може да бъде обработен по-късно от по-новия: старата версия на образа ще замести новата по Git-тага на клонка. Тези проблеми могат да бъдат решавани от CI/CD системата (например, в GitLab CI за серия от commits се стартира pipeline на последния). Въпреки това, не всички системи поддържат това, и трябва да има по-надежден начин за предотвратяване на толкова фундаментален проблем.
Какво е tagging основан на съдържанието?
И така, какво представлява tagging основан на съдържанието — тагиране на образи според съдържанието.
За създаване на Docker тагове не се използват примитиви на Git (Git-клонка, Git-таг…), а контролната сума, свързана с:
- съдържанието на образа. Идентификаторът на таг образа отразява неговото съдържание. При изграждане на нова версия, този идентификатор няма да се промени, ако файловете в образа не са се променили;
- историята на създаване на този образ в Git. Образи, свързани с различни Git-клонки и различна история на изграждане чрез werf, ще имат различни идентификатори на тагове.
Като такъв идентификатор на таг служи така наречената сигнатура на етапите на образа.
Всеки образ се състои от набор от етапи: from, before-install, git-archive, install, imports-after-install, before-setup,… git-latest-patch и т.н. Всеки етап има идентификатор, отразяващ неговото съдържание, — сигнатура на етапа (stage signature).
Финалният образ, състоящ се от тези етапи, се тагира с така наречената сигнатура на набора от тези етапи — stages signature, — която е обобщаваща за всички етапи на образа.
Всеки образ от конфигурацията werf.yaml обикновено ще има своя собствена такава сигнатура и, съответно, Docker таг.
Сигнатурата на етапите решава всички посочени проблеми:
- Устойчивост на празни Git commits.
- Устойчивост на Git commits, които променят файлове, които не са релевантни за образа.
- Не води до проблем с заместването на актуалната версия на образа при повторно стартиране на изграждането за стари Git commits на клонката.
Сега това е препоръчителната стратегия за тагиране и се използва по подразбиране в 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
