Tagowanie oparte na treści w kolektorze werf: dlaczego i jak to działa?

Tagowanie oparte na treści w kolektorze werf: dlaczego i jak to działa?

werf to nasze narzędzie GitOps CLI typu open source do tworzenia i dostarczania aplikacji do Kubernetes. W wydanie wersji 1.1 w kolektorze obrazów wprowadzono nową funkcję: oznaczanie obrazów według treści lub tagowanie oparte na treści. Do tej pory typowy schemat tagowania w werf obejmował tagowanie obrazów Dockera za pomocą tagu Git, gałęzi Git lub zatwierdzenia Git. Jednak wszystkie te schematy mają wady, które całkowicie eliminuje nowa strategia tagowania. Szczegóły na ten temat i dlaczego jest tak dobry, są poniżej.

Wdrażanie zestawu mikrousług z jednego repozytorium Git

Często zdarza się, że aplikacja jest podzielona na wiele mniej lub bardziej niezależnych usług. Wydania tych usług mogą nastąpić niezależnie: jedna lub więcej usług może zostać wydanych na raz, podczas gdy pozostałe muszą nadal działać bez żadnych zmian. Jednak z punktu widzenia przechowywania kodu i zarządzania projektami wygodniej jest trzymać takie usługi aplikacji w jednym repozytorium.

Zdarzają się sytuacje, gdy usługi są naprawdę niezależne i nie są powiązane z jedną aplikacją. W tym przypadku będą one zlokalizowane w odrębnych projektach, a ich wydanie będzie realizowane poprzez odrębne procesy CI/CD w każdym z projektów.

Jednak w rzeczywistości programiści często dzielą pojedynczą aplikację na kilka mikrousług, ale tworzenie dla każdego osobnego repozytorium i projektu… jest wyraźną przesadą. To właśnie ta sytuacja zostanie omówiona dalej: kilka takich mikrousług znajduje się w jednym repozytorium projektu, a wydania odbywają się w ramach jednego procesu w CI/CD.

Tagowanie za pomocą gałęzi Git i tagu Git

Załóżmy, że używana jest najpopularniejsza strategia tagowania - znacznik lub gałąź. W przypadku gałęzi Git obrazy są oznaczone nazwą gałęzi, w przypadku jednej gałęzi w danym momencie publikowany jest tylko jeden obraz o nazwie tej gałęzi. W przypadku tagów Git obrazy są oznaczane zgodnie z nazwą tagu.

Po utworzeniu nowego tagu Git — na przykład po wydaniu nowej wersji — dla wszystkich obrazów projektu w rejestrze Docker zostanie utworzony nowy tag 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

Te nowe nazwy obrazów są przekazywane przez szablony Helm do konfiguracji Kubernetes. Rozpoczynając wdrażanie za pomocą polecenia werf deploy pole jest aktualizowane image w manifestach zasobów Kubernetes i ponownym uruchomieniu odpowiednich zasobów ze względu na zmienioną nazwę obrazu.

problem: w przypadku, gdy tak naprawdę od poprzedniego rolloutu nie zmieniła się zawartość obrazu (tag Git), a jedynie jego tag Docker dodatkowy ponowne uruchomienie tej aplikacji i w związku z tym możliwe są pewne przestoje. Chociaż nie było prawdziwego powodu, aby wykonać ten restart.

W rezultacie przy obecnym schemacie tagowania konieczne jest odgrodzenie kilku oddzielnych repozytoriów Git i pojawia się problem zorganizowania wdrożenia tych kilku repozytoriów. Ogólnie taki schemat okazuje się przeciążony i złożony. Lepiej połączyć wiele usług w jedno repozytorium i utworzyć tagi Dockera, aby nie było niepotrzebnych restartów.

Tagowanie przez zatwierdzenie Git

werf ma również strategię tagowania powiązaną z zatwierdzeniami Git.

Git-commit jest identyfikatorem zawartości repozytorium Git i zależy od historii edycji plików w repozytorium Git, dlatego logiczne wydaje się użycie go do oznaczania obrazów w Rejestrze Dockera.

Jednakże tagowanie za pomocą zatwierdzenia Git ma te same wady, co tagowanie za pomocą gałęzi Git lub tagów Git:

  • Można utworzyć puste zatwierdzenie, które nie zmienia żadnych plików, ale znacznik Docker obrazu zostanie zmieniony.
  • Można utworzyć zatwierdzenie scalania, które nie powoduje zmiany plików, ale znacznik Docker obrazu zostanie zmieniony.
  • Można dokonać zatwierdzenia, które zmieni te pliki w Git, które nie zostały zaimportowane do obrazu, a znacznik Docker obrazu zostanie ponownie zmieniony.

Oznaczenie nazwy gałęzi Git nie odzwierciedla wersji obrazu

Istnieje inny problem związany ze strategią tagowania gałęzi Git.

Oznaczanie według nazwy gałęzi działa, o ile zatwierdzenia w tej gałęzi są zbierane sekwencyjnie w porządku chronologicznym.

Jeśli w bieżącym schemacie użytkownik zacznie odbudowywać stare zatwierdzenie powiązane z określoną gałęzią, wówczas werf przepisze obraz przy użyciu odpowiedniego tagu Docker z nowo zbudowaną wersją obrazu dla starego zatwierdzenia. Wdrożenia korzystające z tego tagu od teraz wiążą się z ryzykiem pobrania innej wersji obrazu podczas ponownego uruchamiania podów, w wyniku czego nasza aplikacja utraci połączenie z systemem CI i ulegnie desynchronizacji.

Dodatkowo, przy kolejnych pushach do jednej gałęzi z krótkim odstępem czasu pomiędzy nimi, stare zatwierdzenie może zostać skompilowane później niż nowsze: stara wersja obrazu nadpisze nową za pomocą tagu gałęzi Git. Takie problemy można rozwiązać za pomocą systemu CI/CD (przykładowo w GitLab CI potok tego ostatniego jest uruchamiany dla serii zatwierdzeń). Jednak nie wszystkie systemy to obsługują i musi istnieć bardziej niezawodny sposób zapobiegania tak fundamentalnemu problemowi.

Co to jest tagowanie oparte na treści?

Czym więc jest tagowanie oparte na treści - oznaczanie obrazów według treści.

Do tworzenia tagów Dockera nie są używane prymitywy Git (gałąź Git, tag Git...), ale suma kontrolna powiązana z:

  • zawartość obrazu. Znacznik identyfikacyjny obrazu odzwierciedla jego zawartość. Podczas budowania nowej wersji identyfikator ten nie ulegnie zmianie, jeśli pliki na obrazie nie uległy zmianie;
  • historia tworzenia tego obrazu w Git. Obrazy powiązane z różnymi gałęziami Git i różnymi historiami kompilacji za pośrednictwem werf będą miały różne znaczniki identyfikacyjne.

Takim znacznikiem identyfikacyjnym jest tzw podpis sceniczny obrazu.

Każdy obraz składa się z zestawu etapów: from, before-install, git-archive, install, imports-after-install, before-setup, ... git-latest-patch itp. Każdy etap ma identyfikator odzwierciedlający jego zawartość − podpis sceniczny (podpis sceniczny).

Ostateczny obraz, składający się z tych etapów, oznaczony jest tzw. sygnaturą zbioru tych etapów – podpis etapów, - co jest uogólnieniem na wszystkie etapy obrazu.

Dla każdego obrazu z konfiguracji werf.yaml w ogólnym przypadku będzie własny podpis i odpowiednio tag Docker.

Podpis sceniczny rozwiązuje wszystkie te problemy:

  • Odporny na puste zatwierdzenia Git.
  • Odporne na Git zatwierdzenia, które zmieniają pliki, które nie są istotne dla obrazu.
  • Nie prowadzi do problemu zmiany bieżącej wersji obrazu podczas ponownego uruchamiania kompilacji dla starych zatwierdzeń Git gałęzi.

Jest to obecnie zalecana strategia znakowania i domyślna w werf dla wszystkich systemów CI.

Jak włączyć i używać w werf

Polecenie ma teraz odpowiednią opcję werf publish: --tag-by-stages-signature=true|false

W systemie CI strategia znakowania jest określana za pomocą polecenia werf ci-env. Wcześniej zdefiniowano dla niego parametr werf ci-env --tagging-strategy=tag-or-branch. Teraz, jeśli określisz werf ci-env --tagging-strategy=stages-signature lub nie określisz tej opcji, werf domyślnie użyje strategii tagowania stages-signature. Zespół werf ci-env automatycznie ustawi niezbędne flagi dla polecenia werf build-and-publish (or werf publish), więc nie ma potrzeby określania dodatkowych opcji dla tych poleceń.

Na przykład polecenie:

werf publish --stages-storage :local --images-repo registry.hello.com/web/core/system --tag-by-stages-signature

...może stworzyć następujące obrazy:

  • registry.hello.com/web/core/system/backend:4ef339f84ca22247f01fb335bb19f46c4434014d8daa3d5d6f0e386d
  • registry.hello.com/web/core/system/frontend:f44206457e0a4c8a54655543f749799d10a9fe945896dab1c16996c6

Tutaj 4ef339f84ca22247f01fb335bb19f46c4434014d8daa3d5d6f0e386d jest sygnaturą etapów obrazu backendI f44206457e0a4c8a54655543f749799d10a9fe945896dab1c16996c6 - podpis etapów obrazu frontend.

Podczas korzystania z funkcji specjalnych werf_container_image и werf_container_env Nie ma potrzeby zmieniania czegokolwiek w szablonach Helma: te funkcje automatycznie wygenerują prawidłowe nazwy obrazów.

Przykładowa konfiguracja w systemie CI:

type multiwerf && source <(multiwerf use 1.1 beta)
type werf && source <(werf ci-env gitlab)
werf build-and-publish|deploy

Więcej informacji na temat konfiguracji można znaleźć w dokumentacji:

Razem

  • Nowa opcja werf publish --tag-by-stages-signature=true|false.
  • Nowa wartość opcji werf ci-env --tagging-strategy=stages-signature|tag-or-branch (jeśli nie zostanie określony, wartością domyślną będzie stages-signature).
  • Jeśli wcześniej korzystałeś z opcji tagowania dla zatwierdzeń Git (WERF_TAG_GIT_COMMIT lub opcja werf publish --tag-git-commit COMMIT), a następnie pamiętaj o przejściu na strategię tagowania podpis sceniczny.
  • Lepiej od razu przełączyć nowe projekty na nowy schemat tagowania.
  • Przy przechodzeniu do werf 1.1 wskazane jest przełączenie starych projektów na nowy schemat tagowania, ale stary znacznik lub gałąź jest nadal obsługiwany.

Tagowanie oparte na treści rozwiązuje wszystkie problemy omówione w artykule:

  • Odporność nazwy tagu Docker na puste zatwierdzenia Git.
  • Odporność nazwy tagu Docker na Git zatwierdzenia, które zmieniają pliki nieistotne dla obrazu.
  • Nie prowadzi do problemu zmiany bieżącej wersji obrazu podczas ponownego uruchamiania kompilacji dla starych zatwierdzeń Git dla gałęzi Git.

Użyj tego! I nie zapomnij odwiedzić nas o godz GitHubstworzyć problem lub znaleźć istniejący, dodać plusa, stworzyć PR lub po prostu obserwować rozwój projektu.

PS

Przeczytaj także na naszym blogu:

Źródło: www.habr.com

Dodaj komentarz