En la continuación del artículo anterior sobre las herramientas de implementación en Kubernetes, quiero contarte cómo puedes usar Jsonnet para simplificar la descripción del trabajo en tu .gitlab-ci.yml

Dado
Hay una monorepa en la que:
- 10 dockerfiles
- 30 despliegues descritos
- 3 ambientes: desarrollo , puesta en escena y producción
Desafío
Configurar una tubería:
- La construcción de imágenes de Docker debe hacerse agregando una etiqueta git con una versión.
- Cada operación de implementación se debe realizar al pasar a la rama de entorno y solo cambiando los archivos en un directorio específico
- Cada entorno tiene su propio gitlab-runner con una etiqueta separada que solo realiza la implementación en su entorno.
- No todas las aplicaciones deben implementarse en cada uno de los entornos; debemos describir la canalización para poder hacer excepciones.
- Algunas implementaciones usan el submódulo git y deben iniciarse con la variable establecida
GIT_SUBMODULE_STRATEGY=normal
Describir todo esto puede parecer un verdadero infierno, pero no nos desesperamos y armados con Jsonnet lo haremos fácil y naturalmente.
Solución
gitlab-ci.yml tiene capacidades incorporadas para reducir la descripción de trabajos repetidos, por ejemplo, puede usar extensiones o incluir , pero no proporciona plantillas completas, lo que no nos permite describir las más concisas y eficientes.
Para resolver este problema, sugiero usar jsonnet, que le permite deshacerse casi por completo de la repetición de código al describir cualquier estructura de datos.
Cuando trabaje con jsonnet, le recomiendo instalar un complemento para su editor
Por ejemplo, para vim hay un complemento vim-jsonnet que activa el resaltado de sintaxis y realiza automáticamente jsonnet fmt cada vez que se guarda (requiere la instalación de jsonnet).
Veamos la estructura de nuestro repositorio:
. ├── 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
Las imágenes de Docker se construirán con kaniko
La implementación de aplicaciones en el clúster se realizará con qbec . Cada aplicación se describe para tres entornos diferentes, para aplicar cambios al clúster, es suficiente realizar:
qbec apply <environment> --root deploy/<app> --yes
donde:
<app>
- el nombre de nuestra aplicación<environment>
es uno de nuestros entornos: desarrollo , escenario o producción .
Al final, nuestros trabajos deberían verse así:
Asamblea
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
Donde en lugar de {{ image }}
, el nombre del directorio de dockerfiles será sustituido
Implementar:
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 }}
Donde en lugar de {{ app }}
, se sustituirá el nombre del directorio de implementación ,
y en lugar de {{ environment }}
, el nombre del entorno en el que desea implementar.
Describamos los prototipos de nuestros trabajos como objetos en una lib / jobs.jsonnet separada
{
Tenga en cuenta que deliberadamente no especifiqué refs
y tags
para hacer que nuestra biblioteca sea más flexible y demostrar completamente las capacidades de jsonnet, las agregaremos más tarde desde el archivo principal.
Ahora describiremos nuestro .gitlab-ci.jsonnet :
Presta atención a las funciones de ref , etiqueta y submódulo al comienzo del archivo, te permiten crear un objeto primordial.
Una pequeña explicación: usar " +:
" en lugar de " :
" para anular objetos le permite agregar un valor a un objeto o lista existente.
Por ejemplo " :
" para las referencias :
local job = { script: ['echo 123'], only: { refs: ['tags'] }, }; local ref(x) = { only+: { refs: [x] } }; job + ref('prod')
volverá:
{ "only": { "refs": [ "prod" ] }, "script": [ "echo 123" ] }
Y aquí está el " +:
" para las referencias :
local job = { script: ['echo 123'], only: { refs: ['tags'] }, }; local ref(x) = { only+: { refs+: [x] } }; job + ref('prod')
volverá:
{ "only": { "refs": [ "prod", "tags" ] }, "script": [ "echo 123" ] }
Como puede ver, el uso de Jsonnet le permite describir y fusionar sus objetos de manera muy eficiente, en la salida siempre obtiene JSON listo, que podemos escribir inmediatamente en nuestro archivo .gitlab-ci.yml :
jsonnet .gitlab-ci.jsonnet > .gitlab-ci.yml
Verifique el número de líneas:
¡En mi opinión es muy bueno!
Puedes ver más ejemplos y sentir Jsonnet directamente en el sitio web oficial: jsonnet.org
Si, como yo, como Jsonnet, únete a nuestro grupo en el telegrama t.me/jsonnet_ru