werf 收集器中基於內容的標記:它為何以及如何運作?

werf 收集器中基於內容的標記:它為何以及如何運作?

韋爾夫 是我們的開源 GitOps CLI 實用程序,用於建立應用程式並將其交付到 Kubernetes。 在 發布v1.1 在影像收集器中引入了一項新功能:按內容或標記影像 基於內容的標籤。 到目前為止,werf 中的典型標記方案涉及透過 Git 標記、Git 分支或 Git 提交來標記 Docker 映像。 但所有這些方案都有缺點,新的標記策略完全解決了這些缺點。 有關它的詳細資訊以及它為何如此出色的內容都在下文中。

從一個 Git 儲存庫推出一組微服務

當應用程式被分成許多或多或少獨立的服務時,經常會發生這種情況。 這些服務的發布可以獨立進行:一次可以發布一個或多個服務,而其餘服務必須繼續工作而不做任何更改。 但從程式碼儲存和專案管理的角度來看,將此類應用程式服務保存在單一儲存庫中更為方便。

在某些情況下,服務是真正獨立的並且不與單一應用程式關聯。 在這種情況下,它們將位於不同的項目中,並且它們的發布將透過每個項目中單獨的 CI/CD 流程進行。

然而,實際上,開發人員經常將單個應用程式拆分為多個微服務,但為每個微服務創建單獨的存儲庫和項目......顯然是一種矯枉過正。 我們將進一步討論這種情況:多個此類微服務位於單一專案儲存庫中,並且透過 CI/CD 中的單一流程進行發布。

透過 Git 分支和 Git 標籤進行標記

假設使用最常見的標記策略 - 標籤或分支。 對於 Git 分支,映像以分支名稱標記,對於一個分支,一次只有一個以該分支名稱發布的映像。 對於 Git 標籤,圖像根據標籤名稱進行標記。

當建立新的 Git 標籤時(例如,發布新版本時),將為 Docker 註冊表中的所有專案映像建立一個新的 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

這些新的鏡像名稱透過 Helm 範本傳遞到 Kubernetes 配置。 使用命令啟動部署時 werf deploy 字段正在更新中 image 在 Kubernetes 資源清單中,由於鏡像名稱變更而重新啟動對應的資源。

問題:事實上,自上次發布(Git 標籤)以來,映像的內容沒有發生變化,而只有 Docker 標籤發生變化,就會發生這種情況 額外的 重新啟動此應用程序,因此可能會出現一些停機時間。 儘管沒有真正的理由執行此重啟。

因此,使用目前的標記方案,有必要隔離幾個單獨的 Git 儲存庫,並且出現了組織這幾個儲存庫的推出的問題。 一般來說,這樣的方案結果是超載且複雜的。 最好將許多服務合併到一個儲存庫中並建立 Docker 標籤,這樣就不會出現不必要的重新啟動。

透過 Git 提交標記

werf 還有一個與 Git 提交相關的標記策略。

Git-commit 是 Git 儲存庫內容的標識符,依賴 Git 儲存庫中檔案的編輯歷史記錄,因此使用它來標記 Docker 註冊表中的映像似乎是合乎邏輯的。

但是,透過 Git 提交進行標記與透過 Git 分支或 Git 標籤進行標記具有相同的缺點:

  • 可以建立一個不更改任何檔案的空提交,但映像的 Docker 標記將被更改。
  • 可以建立不更改檔案的合併提交,但映像的 Docker 標記將被更改。
  • 可以進行提交來更改 Git 中未匯入映像中的那些文件,並且映像的 Docker 標記將再次變更。

標記 Git 分支名稱不反映鏡像版本

還有另一個與 Git 分支的標記策略相關的問題。

只要按時間順序順序收集該分支上的提交,就可以按分支名稱進行標記。

如果在目前方案中,使用者開始重建與某個分支關聯的舊提交,那麼 werf 將使用對應的 Docker 標籤和舊提交的新建置版本的映像來重寫映像。 從現在開始,使用此標籤的部署在重新啟動 pod 時存在拉取不同版本映像的風險,因此我們的應用程式將失去與 CI 系統的連線並變得不同步。

此外,如果連續推送到一個分支且時間間隔很短,則舊提交的編譯時間可能會晚於新提交:舊版本的映像將使用 Git 分支標籤覆蓋新版本。 此類問題可以透過 CI/CD 系統來解決(例如,在 GitLab CI 中,後者的管道是針對一系列提交啟動的)。 然而,並非所有系統都支援這一點,必須有更可靠的方法來防止這種根本問題。

什麼是基於內容的標記?

那麼,什麼是基於內容的標記——按內容標記圖像。

要建立 Docker 標籤,使用的不是 Git 原語(Git 分支、Git 標籤...),而是與以下內容關聯的校驗和:

  • 圖像的內容。 圖像ID標籤反映其內容。 當建構新版本時,如果鏡像中的檔案沒有改變,這個標識符也不會改變;
  • 在 Git 中建立此映像的歷史記錄。 與不同 Git 分支和透過 werf 的不同建構歷史關聯的映像將具有不同的 ID 標籤。

這樣的識別符標籤就是所謂的 影像階段簽名.

每個影像由一組階段組成: from, before-install, git-archive, install, imports-after-install, before-setup,... git-latest-patch ETC。 每個階段都有一個反映其內容的識別碼 - 舞台簽名 (舞台簽名).

由這些階段組成的最終影像被標記為這些階段組的所謂簽名 - 階段簽名, - 這概括了圖像的所有階段。

對於配置中的每個影像 werf.yaml 一般情況下,會有自己的簽名,以及對應的 Docker 標籤。

階段簽名解決了所有這些問題:

  • 抵抗空 Git 提交。
  • 抵抗 Git 提交更改與圖像不相關的檔案。
  • 當為分支的舊 Git 提交重新啟動建置時,不會導致徹底修改目前版本的映像的問題。

這是現在建議的標記策略,也是所有 CI 系統 werf 中的預設策略。

如何在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 是影像階段的簽名 backendf44206457e0a4c8a54655543f749799d10a9fe945896dab1c16996c6 - 影像階段的簽名 frontend.

使用特殊功能時 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),那麼一定要切換到標記策略 階段簽名.
  • 最好立即將新項目切換到新的標記方案。
  • 轉移到werf 1.1時,建議將舊項目切換到新標記方案,但舊項目 標籤或分支 仍然支持。

基於內容的標記解決了本文中涉及的所有問題:

  • Docker 標記名稱對空 Git 提交的抵抗力。
  • Docker 標籤名稱對 Git 提交的彈性,可變更與映像無關的檔案。
  • 當重新啟動 Git 分支的舊 Git 提交建置時,不會導致徹底修改目前版本的鏡像的問題。

用它! 並且不要忘記訪問我們 GitHub上建立問題或尋找現有問題、新增加號、建立 PR 或只是觀看專案的開發。

聚苯乙烯

另請閱讀我們的博客:

來源: www.habr.com

添加評論