Content-based tagging в сборщика werf: защо и как работи това?

Content-based tagging в сборщика werf: защо и как работи това?

werf — нашата GitOps CLI утилита с отворен код за сглобяване и доставка на приложения в Kubernetes. В издание v1.1 бе представена нова възможност в сборщика на образи: етикетиране на образи по съдържание или 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-клонове.

Ползвайте! И не забравяйте да погледнете при нас на GitHub, за да създадете issue или да намерите вече съществуваща, да поставите плюс, да създадете PR или просто да следите развитието на проекта.

P.S.

Прочетете също в нашия блог:

Източник: habr.com

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster