ProHoster > Blog > administracja > 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ń.
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:
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.