Na continuação do artigo anterior sobre ferramentas de implantação no Kubernetes, quero falar sobre como você pode usar o Jsonnet para simplificar a descrição do trabalho em seu arquivo .gitlab-ci.yml

Dado
Existe um monorepa no qual:
- 10 dockerfiles
- 30 implantações descritas
- 3 ambientes: desenvolvimento , preparação e produção
Desafio
Configure um pipeline:
- As imagens do Docker de construção devem ser feitas adicionando uma tag git com uma versão.
- Cada operação de implantação deve ser executada ao enviar para a ramificação do ambiente e apenas alterando arquivos em um diretório específico
- Cada ambiente possui seu próprio gitlab-runner com uma tag separada que somente executa a implantação em seu ambiente.
- Nem todos os aplicativos devem ser implantados em cada um dos ambientes; precisamos descrever o pipeline para poder fazer exceções.
- Algumas implementações usam o submódulo git e devem ser iniciadas com a variável definida
GIT_SUBMODULE_STRATEGY=normal
Descrever tudo isso pode parecer um inferno, mas não nos desesperamos e, armados com o Jsonnet, faremos isso com facilidade e naturalidade.
Solução
O gitlab-ci.yml possui recursos internos para reduzir a descrição de tarefas repetidas, por exemplo, você pode usar extends ou include , mas não fornece modelos completos, o que não permite descrever o trabalho mais conciso e eficiente.
Para resolver esse problema, sugiro usar o jsonnet, que permite livrar-se quase completamente da repetição de código ao descrever qualquer estrutura de dados.
Ao trabalhar com o jsonnet, eu recomendo instalar um plugin para o seu editor
Por exemplo, para o vim, existe um plug-in vim-jsonnet que ativa o destaque de sintaxe e executa automaticamente o jsonnet fmt cada vez que é salvo (requer o jsonnet instalado).
Vamos dar uma olhada na estrutura do nosso repositório:
. ├── deploy │ ├── analyse │ ├── basin │ ├── brush │ ├── copper │ ├── dinner │ ├── dirty │ ├── drab │ ├── drunk │ ├── education │ ├── fanatical │ ├── faulty │ ├── guarantee │ ├── guitar │ ├── hall │ ├── harmonious │ ├── history │ ├── iron │ ├── maniacal │ ├── mist │ ├── nine │ ├── pleasant │ ├── polish │ ├── receipt │ ├── shop │ ├── smelly │ ├── solid │ ├── stroke │ ├── thunder │ ├── ultra │ └── yarn └── dockerfiles ├── dinner ├── drunk ├── fanatical ├── guarantee ├── guitar ├── harmonious ├── shop ├── smelly ├── thunder └── yarn
As imagens do Docker serão construídas usando o kaniko
A implantação de aplicativos no cluster será feita usando o qbec . Cada aplicativo é descrito para três ambientes diferentes. Para aplicar alterações no cluster, basta executar:
qbec apply <environment> --root deploy/<app> --yes
onde:
<app>
- o nome do nosso aplicativo<environment>
é um dos nossos ambientes: desenvolvimento , estágio ou prod .
No final, nossos trabalhos devem ficar assim:
Montagem:
build:{{ image }}: stage: build tags: - build image: name: gcr.io/kaniko-project/executor:debug entrypoint: [""] script: - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/dockerfiles/{{ image }}/Dockerfile --destination $CI_REGISTRY_IMAGE/{{ image }}:$CI_COMMIT_TAG only: refs: - tags
Onde, em vez de {{ image }}
, o nome do diretório dos dockerfiles será substituído
Implantar:
deploy:{{ environment }}:{{ app }}: stage: deploy tags: - {{ environment }} script: - qbec apply {{ environment }} --root deploy/{{ app }} --force:k8s-context __incluster__ --wait --yes only: changes: - deploy/{{ app }}/**/* refs: - {{ environment }}
Onde, em vez de {{ app }}
, o nome do diretório de deploy será substituído,
e em vez de {{ environment }}
- o nome do ambiente no qual você deseja implantar.
Vamos descrever os protótipos de nossos trabalhos como objetos em uma lib / jobs.jsonnet separada
{
Observe que eu deliberadamente não especifiquei refs
e tags
para tornar nossa biblioteca mais flexível e demonstrar totalmente os recursos do jsonnet para você; nós os adicionaremos posteriormente a partir do arquivo principal.
Agora vamos descrever o nosso .gitlab-ci.jsonnet :
Preste atenção às funções ref , tag e submodule no início do arquivo, pois elas permitem criar um objeto de substituição.
Uma pequena explicação: usar " +:
" em vez de " :
" para substituir objetos permite adicionar um valor a um objeto ou lista existente.
Por exemplo " :
" para refs :
local job = { script: ['echo 123'], only: { refs: ['tags'] }, }; local ref(x) = { only+: { refs: [x] } }; job + ref('prod')
retornará:
{ "only": { "refs": [ "prod" ] }, "script": [ "echo 123" ] }
E aqui está o " +:
" para refs :
local job = { script: ['echo 123'], only: { refs: ['tags'] }, }; local ref(x) = { only+: { refs+: [x] } }; job + ref('prod')
retornará:
{ "only": { "refs": [ "prod", "tags" ] }, "script": [ "echo 123" ] }
Como você pode ver, o uso do Jsonnet permite que você descreva e mescle com eficiência seus objetos, a saída é sempre um JSON pronto, que podemos gravar imediatamente em nosso arquivo .gitlab-ci.yml :
jsonnet .gitlab-ci.jsonnet > .gitlab-ci.yml
Verifique o número de linhas:
Na minha opinião é muito bom!
Você pode ver mais exemplos e sentir o Jsonnet diretamente no site oficial: jsonnet.org
Se você, como eu, gosta da Jsonnet, junte-se ao nosso grupo no telegrama t.me/jsonnet_ru