
— nossa ferramenta CLI do GitOps de código aberto para compilar e entregar aplicativos no Kubernetes. No foi apresentada uma nova funcionalidade no construtor de imagens: etiquetagem de imagens por conteúdo ou content-based tagging. Até agora, o esquema típico de etiquetagem no werf assumia a etiquetagem de imagens Docker por tag Git, branch Git ou commit Git. Mas todas essas esquemas possuem desvantagens que são completamente resolvidas pela nova estratégia de etiquetagem. Detalhes sobre isso e por que é tão bom estão abaixo.
Implantação de um conjunto de microsserviços de um único repositório Git
É comum a situação em que um aplicativo é dividido em muitos serviços mais ou menos independentes. Os releases desses serviços podem ocorrer de forma independente: um ou mais serviços podem ser lançados ao mesmo tempo, enquanto os outros devem continuar funcionando sem quaisquer alterações. Mas, do ponto de vista de armazenamento de código e gerenciamento de projeto, é mais conveniente manter esses serviços de aplicativos em um único repositório.
Há situações em que os serviços realmente são independentes e não estão relacionados a um único aplicativo. Nesse caso, eles estarão localizados em projetos separados e seu lançamento será realizado através de processos CI/CD distintos em cada um dos projetos.
No entanto, na realidade, os desenvolvedores muitas vezes dividem um único aplicativo em vários microsserviços, mas criar um repositório e um projeto separado para cada um... é um excesso evidente. Este é o cenário que será abordado a seguir: vários desses microsserviços estão em um único repositório de projeto e os releases acontecem por meio de um único processo em CI/CD.
Etiquetagem por branch Git e tag Git
Suponha que a estratégia de etiquetagem mais comum seja tag-or-branch. Para branches Git, as imagens são etiquetadas com o nome da branch, para uma branch existe apenas uma imagem publicada no momento com o nome dessa branch. Para tags Git, as imagens são etiquetadas de acordo com o nome da tag.
Ao criar uma nova tag Git — por exemplo, ao lançar uma nova versão — uma nova tag Docker será criada para todas as imagens do projeto no Docker Registry:
-
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
Esses novos nomes de imagens são inseridos através de templates Helm na configuração do Kubernetes. Durante a execução da implantação pelo comando werf deploy ocorre a atualização do campo image nos manifests de recursos do Kubernetes e a reinicialização dos recursos correspondentes devido à mudança do nome da imagem.
O problema: no caso em que o conteúdo da imagem não mudou realmente desde a última versão (tag do Git), mas apenas seu tag Docker, ocorre um reinício extra desse aplicativo e, consequentemente, pode ocorrer algum downtime. Embora não houvesse razões reais para realizar esse reinício.
Como consequência, com a atual estratégia de tagging é necessário criar vários repositórios Git separados e surge o problema da organização da implantação desses múltiplos repositórios. De modo geral, essa estratégia acaba sendo sobrecarregada e complexa. É melhor agrupar muitos serviços em um único repositório e criar tags Docker que evitem reinícios desnecessários.
Tagueamento por commit do Git
No werf, também existe uma estratégia de tagueamento relacionada aos commits do Git.
O commit do Git é um identificador do conteúdo do repositório Git e depende do histórico de alterações dos arquivos no repositório Git, portanto, parece lógico usá-lo para tagueamento de imagens no Docker Registry.
No entanto, o tagueamento por commit do Git tem as mesmas desvantagens que o de branches ou tags do Git:
- Um commit vazio pode ter sido criado que não altera arquivos, mas o tag Docker da imagem será alterado.
- Um commit de merge pode ter sido criado que não altera arquivos, mas o tag Docker da imagem será alterado.
- Um commit pode ter sido criado que altera arquivos no Git que não são importados na imagem, e o tag Docker da imagem será novamente alterado.
Tagueamento pelo nome da branch do Git não reflete a versão da imagem
Há também um problema relacionado à estratégia de tagueamento por branches do Git.
O tagueamento pelo nome da branch funciona desde que os commits dessa branch sejam coletados de forma sequencial em ordem cronológica.
Se na estrutura atual o usuário iniciar a recompilação de um commit antigo relacionado a certa branch, o werf sobrescreverá a imagem com a nova versão do Docker tag correspondente ao commit antigo. Os Deployments que usam esse tag correm o risco de, durante a reinicialização dos pods, fazer pull de outra versão da imagem, resultando em nosso aplicativo perdendo o vínculo com o sistema CI, desincronizando-se.
Além disso, ao se fazer push de forma sequencial em um mesmo branch com um pequeno intervalo de tempo entre eles, um commit antigo pode ser construído depois de um mais recente: uma versão antiga da imagem pode sobrepor uma nova pela tag do branch do Git. Esses problemas podem ser resolvidos por um sistema CI/CD (por exemplo, no GitLab CI, um pipeline é acionado para a última série de commits). No entanto, nem todos os sistemas suportam isso, e deve haver uma forma mais confiável de evitar um problema tão fundamental.
O que é tagging baseado em conteúdo?
Então, o que é tagging baseado em conteúdo — a tagueamento de imagens por seu conteúdo.
Para criar tags do Docker, não são utilizados primitivos do Git (branch do Git, tag do Git...), mas sim um checksum relacionado a:
- o conteúdo da imagem. O identificador da tag da imagem reflete seu conteúdo. Ao construir uma nova versão, esse identificador não mudará se os arquivos da imagem não forem alterados;
- a história de criação dessa imagem no Git. Imagens associadas a diferentes branches do Git e a diferentes histórias de construção através do werf terão identificadores de tags diferentes.
Como tal identificador de tag, temos uma assinatura das fases da imagem.
Cada imagem consiste em um conjunto de fases: Harvard University, before-install, git-archive, install, imports-after-install, before-setup,… git-latest-patch etc. Cada fase tem um identificador que reflete seu conteúdo, — assinatura da fase (stage signature).
A imagem final, composta por essas fases, é tagueada pela chamada assinatura do conjunto dessas fases — stages signature, — que é geral para todas as fases da imagem.
Cada imagem da configuração werf.yaml geralmente terá sua própria assinatura e, consequentemente, a tag do Docker.
A assinatura das fases resolve todos os problemas mencionados:
- É resistente a commits vazios do Git.
- É resistente a commits do Git que alteram arquivos que não são relevantes para a imagem.
- Não leva ao problema de sobrescrever a versão atual da imagem ao reiniciar construções para commits antigos do branch do Git.
Agora essa é a estratégia de tagueamento recomendada e é usada por padrão no werf para todos os sistemas CI.
Como ativar e usar no werf
A opção correspondente foi adicionada ao comando werf publish: --tag-by-stages-signature=true|false
Na sistema CI, a estratégia de tagueamento é definida pelo comando werf ci-env. Anteriormente, um parâmetro foi definido para isso werf ci-env --tagging-strategy=tag-or-branch. Agora, se essa opção for especificada werf ci-env --tagging-strategy=stages-signature ou não, o werf usará, por padrão, a estratégia de tagueamento assinatura-dos-estágios. O comando werf ci-env automaticamente definirá as flags necessárias para o comando werf build-and-publish (ou werf publish), portanto, não é necessário especificar opções adicionais para esses comandos.
Por exemplo, o comando:
werf publish --stages-storage :local --images-repo registry.hello.com/web/core/system --tag-by-stages-signature… pode criar as seguintes imagens:
-
registry.hello.com/web/core/system/backend:4ef339f84ca22247f01fb335bb19f46c4434014d8daa3d5d6f0e386d -
registry.hello.com/web/core/system/frontend:f44206457e0a4c8a54655543f749799d10a9fe945896dab1c16996c6
Aqui 4ef339f84ca22247f01fb335bb19f46c4434014d8daa3d5d6f0e386d — é a assinatura das fases da imagem backend, e f44206457e0a4c8a54655543f749799d10a9fe945896dab1c16996c6 — assinatura das fases da imagem frontend.
Ao usar funções especiais werf_container_image e werf_container_env nos templates Helm, nada precisa ser alterado: essas funções gerarão automaticamente os nomes corretos das imagens.
Exemplo de configuração no sistema CI:
type multiwerf && source <(multiwerf use 1.1 beta)
type werf && source <(werf ci-env gitlab)
werf build-and-publish|deployMais informações sobre a configuração estão disponíveis na documentação:
- ;
- ;
- .
Total
- A nova opção
werf publish --tag-by-stages-signature=true|false. - Novo valor da opção
werf ci-env --tagging-strategy=stages-signature|tag-or-branch(se não especificado, o padrão seráassinatura-dos-estágios). - Se anteriormente foram usadas opções de tagueamento por commits Git (
WERF_TAG_GIT_COMMITou a opçãowerf publish --tag-git-commit COMMIT), é obrigatório mudar para a estratégia de tagueamento assinatura-dos-estágios. - Novos projetos devem ser imediatamente migrados para o novo esquema de tagueamento.
- Projetos antigos ao serem migrados para o werf 1.1 devem ser mudados para o novo esquema de tagueamento, embora o antigo tag-or-branch ainda seja suportado.
A tagging baseada no conteúdo resolve todos os problemas abordados no artigo:
- A resistência do nome da tag Docker a commits Git vazios.
- A resistência do nome da tag Docker a commits Git que alteram arquivos irrelevantes para a imagem.
- Não resulta em problemas de sobrescrever a versão atual da imagem ao reiniciar builds para commits Git antigos em branches Git.
Aproveite! E não esqueça de nos visitar em , para criar uma issue ou encontrar uma já existente, dar um like, criar PR ou apenas acompanhar o desenvolvimento do projeto.
P.S.
Confira também em nosso blog:
- «»
- «»
- «»;
- Ciclo de notas sobre novidades no werf:
- «»;
- «»;
- «»;
- «».
Fonte: habr.com
