O problema da limpeza "intelixente" de imaxes de contedores e a súa solución en werf

O problema da limpeza "intelixente" de imaxes de contedores e a súa solución en werf

O artigo analiza os problemas de limpeza de imaxes que se acumulan nos rexistros de contedores (Docker Registry e os seus análogos) nas realidades das modernas canalizacións CI/CD para aplicacións nativas da nube entregadas a Kubernetes. Indícanse os principais criterios de relevancia das imaxes e as dificultades resultantes para automatizar a limpeza, aforrar espazo e satisfacer as necesidades dos equipos. Por último, co exemplo dun proxecto de código aberto específico, dirémosche como se poden superar estas dificultades.

Introdución

O número de imaxes nun rexistro de contedores pode crecer rapidamente, ocupando máis espazo de almacenamento e, polo tanto, aumentando significativamente o seu custo. Para controlar, limitar ou manter un crecemento aceptable do espazo ocupado no rexistro, acéptase:

  1. utilizar un número fixo de etiquetas para as imaxes;
  2. limpar as imaxes dalgún xeito.


A primeira limitación ás veces é aceptable para equipos pequenos. Se os desenvolvedores teñen suficientes etiquetas permanentes (latest, main, test, boris etc.), o rexistro non aumentará de tamaño e durante moito tempo non terás que pensar en limpalo. Despois de todo, bórranse todas as imaxes irrelevantes e simplemente non queda traballo para a limpeza (todo o fai un colector de lixo normal).

Non obstante, este enfoque limita moito o desenvolvemento e raramente é aplicable a proxectos modernos de CI/CD. Unha parte integral do desenvolvemento foi automatización, que che permite probar, implementar e ofrecer novas funcionalidades aos usuarios moito máis rápido. Por exemplo, en todos os nosos proxectos, créase automaticamente unha canalización de CI con cada commit. Nela, a imaxe é montada, probada, desenvolvida a varios circuítos de Kubernetes para a depuración e as comprobacións restantes e, se todo está ben, os cambios chegan ao usuario final. E isto xa non é ciencia de foguetes, senón unha ocorrencia cotiá para moitos, moi probablemente para ti, xa que estás lendo este artigo.

Dado que a corrección de erros e o desenvolvemento de novas funcionalidades lévase a cabo en paralelo, e os lanzamentos pódense realizar varias veces ao día, é obvio que o proceso de desenvolvemento vai acompañado dun número importante de commits, o que significa un gran número de imaxes no rexistro. Como resultado, xorde a cuestión de organizar unha limpeza efectiva do rexistro, é dicir. eliminando imaxes irrelevantes.

Pero como se determina se unha imaxe é relevante?

Criterios de relevancia da imaxe

Na gran maioría dos casos, os criterios principais serán:

1. A primeira (a máis evidente e a máis crítica de todas) son as imaxes que usado actualmente en Kubernetes. A eliminación destas imaxes pode producir custos significativos de inactividade da produción (por exemplo, as imaxes poden ser necesarias para a súa replicación) ou anular os esforzos do equipo depurando calquera dos bucles. (Por este motivo ata fixemos un especial Exportador Prometeo, que rastrexa a ausencia de tales imaxes en calquera clúster de Kubernetes.)

2. Segundo (menos obvio, pero tamén moi importante e de novo relacionado coa explotación) - imaxes que necesario para a recuperación en caso de detectar problemas graves na versión actual. Por exemplo, no caso de Helm, estas son imaxes que se usan nas versións gardadas do lanzamento. (Por certo, por defecto en Helm o límite é de 256 revisións, pero é pouco probable que alguén teña que gardar tal un gran número de versións?..) Despois de todo, nós, en particular, almacenamos versións para poder utilizalas máis tarde, é dicir. "retrocede" a eles se é necesario.

3. Terceiro - necesidades do desenvolvedor: Todas as imaxes relacionadas co seu traballo actual. Por exemplo, se estamos considerando un PR, entón ten sentido deixar unha imaxe correspondente ao último compromiso e, por exemplo, ao anterior: deste xeito, o desenvolvedor pode volver rapidamente a calquera tarefa e traballar cos últimos cambios.

4. Cuarto - imaxes que corresponden ás versións da nosa aplicación, é dicir. son o produto final: v1.0.0, 20.04.01/XNUMX/XNUMX, serra, etc.

NB: Os criterios aquí definidos foron formulados en base á experiencia de interactuar con decenas de equipos de desenvolvemento de diferentes empresas. Non obstante, por suposto, dependendo das características específicas dos procesos de desenvolvemento e da infraestrutura utilizada (por exemplo, non se utiliza Kubernetes), estes criterios poden diferir.

Elixibilidade e solucións existentes

Os servizos populares con rexistros de contedores, por regra xeral, ofrecen as súas propias políticas de limpeza de imaxes: neles pode definir as condicións nas que se elimina unha etiqueta do rexistro. Non obstante, estas condicións están limitadas por parámetros como nomes, tempo de creación e número de etiquetas*.

* Depende das implementacións específicas do rexistro de contedores. Consideramos as posibilidades das seguintes solucións: Azure CR, Docker Hub, ECR, GCR, paquetes GitHub, GitLab Container Registry, Harbour Registry, JFrog Artifactory, Quay.io - a partir de setembro de 2020.

Este conxunto de parámetros é suficiente para satisfacer o cuarto criterio, é dicir, seleccionar imaxes que correspondan ás versións. Non obstante, para todos os demais criterios, hai que escoller algún tipo de solución de compromiso (unha política máis dura ou, pola contra, máis indulgente), dependendo das expectativas e das capacidades financeiras.

Por exemplo, o terceiro criterio -relacionado coas necesidades dos desenvolvedores- pódese resolver organizando procesos dentro dos equipos: nomeamento específico das imaxes, mantemento de listas de permisos especiais e acordos internos. Pero, finalmente, aínda ten que ser automatizado. E se as capacidades das solucións preparadas non son suficientes, tes que facer algo propio.

A situación cos dous primeiros criterios é semellante: non se poden satisfacer sen recibir datos dun sistema externo, aquel no que se despregan as aplicacións (no noso caso, Kubernetes).

Ilustración do fluxo de traballo en Git

Digamos que estás a traballar algo así en Git:

O problema da limpeza "intelixente" de imaxes de contedores e a súa solución en werf

A icona cunha cabeceira no diagrama indica imaxes de contedores que están actualmente implantadas en Kubernetes para calquera usuario (usuarios finais, probadores, xestores, etc.) ou que son utilizadas polos desenvolvedores para depuración e fins similares.

Que pasa se as políticas de limpeza só permiten que as imaxes se conserven (non se eliminen) por nomes de etiquetas dados?

O problema da limpeza "intelixente" de imaxes de contedores e a súa solución en werf

Obviamente, tal escenario non fará feliz a ninguén.

Que cambiará se as políticas permiten que non se eliminen as imaxes? segundo un determinado intervalo de tempo/número de últimos commits?

O problema da limpeza "intelixente" de imaxes de contedores e a súa solución en werf

O resultado foi moito mellor, pero aínda está lonxe de ser ideal. Despois de todo, aínda temos desenvolvedores que necesitan imaxes no rexistro (ou incluso implantadas en K8s) para depurar erros...

Para resumir a situación actual do mercado: as funcións dispoñibles nos rexistros de contedores non ofrecen suficiente flexibilidade á hora de limpar, e a principal razón é non hai forma de interactuar co mundo exterior. Resulta que os equipos que requiren tal flexibilidade vense obrigados a implementar de forma independente a eliminación de imaxes "desde fóra", utilizando a API de Docker Registry (ou a API nativa da implementación correspondente).

Non obstante, buscabamos unha solución universal que automatizase a limpeza de imaxes para diferentes equipos mediante rexistros diferentes...

O noso camiño cara á limpeza universal de imaxes

De onde vén esta necesidade? O caso é que non somos un grupo separado de desenvolvedores, senón un equipo que atende a moitos deles á vez, axudando a resolver de forma integral os problemas de CI/CD. E a principal ferramenta técnica para iso é a utilidade Open Source werf. A súa peculiaridade é que non realiza unha soa función, senón que acompaña procesos de entrega continuos en todas as fases: desde a montaxe ata o despregamento.

A publicación de imaxes no rexistro* (inmediatamente despois de crealas) é unha función obvia desta utilidade. E dado que as imaxes colócanse alí para o seu almacenamento, entón -se o seu almacenamento non é ilimitado- debe ser responsable da súa posterior limpeza. Como conseguimos o éxito neste, satisfacendo todos os criterios especificados, comentarase máis adiante.

* Aínda que os propios rexistros poden ser diferentes (Docker Registry, GitLab Container Registry, Harbour, etc.), os seus usuarios afrontan os mesmos problemas. A solución universal no noso caso non depende da implantación do rexistro, porque execútase fóra dos propios rexistros e ofrece o mesmo comportamento para todos.

Aínda que estamos usando werf como exemplo de implementación, esperamos que os enfoques utilizados sexan útiles para outros equipos que se enfrontan a dificultades similares.

Así que nos ocupamos externo implementación dun mecanismo para a limpeza de imaxes, en lugar daquelas capacidades que xa están integradas nos rexistros de contedores. O primeiro paso foi utilizar a API do Rexistro de Docker para crear as mesmas políticas primitivas para o número de etiquetas e o momento da súa creación (mencionado anteriormente). Engadido a eles lista de permisos baseada nas imaxes utilizadas na infraestrutura despregada, é dicir. Kubernetes. Para este último, bastaba con usar a API de Kubernetes para iterar a través de todos os recursos despregados e obter unha lista de valores image.

Esta solución trivial resolveu o problema máis crítico (criterio no 1), pero foi só o comezo da nosa viaxe para mellorar o mecanismo de limpeza. O seguinte paso -e moito máis interesante- foi a decisión asociar imaxes publicadas co historial de Git.

Esquemas de etiquetado

Para comezar, escollemos un enfoque no que a imaxe final debería almacenar a información necesaria para a limpeza, e construímos o proceso sobre esquemas de etiquetado. Ao publicar unha imaxe, o usuario seleccionou unha opción de etiquetado específica (git-branch, git-commit ou git-tag) e utilizou o valor correspondente. Nos sistemas CI, estes valores fixéronse automaticamente en función de variables de ambiente. De feito a imaxe final estaba asociada a unha primitiva específica de Git, almacenando en etiquetas os datos necesarios para a limpeza.

Este enfoque deu lugar a un conxunto de políticas que permitiron usar Git como fonte única de verdade:

  • Ao eliminar unha rama/etiqueta en Git, as imaxes asociadas no rexistro elimináronse automaticamente.
  • O número de imaxes asociadas coas etiquetas e as confirmacións de Git podería controlarse polo número de etiquetas utilizadas no esquema seleccionado e o momento no que se creou a confirmación asociada.

En xeral, a implantación resultante satisfizo as nosas necesidades, pero pronto nos agardaba un novo reto. O feito é que ao usar esquemas de etiquetado baseados en primitivas de Git, atopamos unha serie de deficiencias. (Xa que a súa descrición está fóra do alcance deste artigo, todos poden familiarizarse cos detalles aquí.) Polo tanto, tendo decidido cambiar a un enfoque máis eficiente para o etiquetado (etiquetado baseado no contido), tivemos que reconsiderar a implementación da limpeza de imaxes.

Novo algoritmo

Por que? Coa etiquetaxe baseada no contido, cada etiqueta pode satisfacer varias commits en Git. Ao limpar imaxes, xa non pode asumir desde o commit onde se engadiu a nova etiqueta ao rexistro.

Para o novo algoritmo de limpeza, decidiuse afastarse dos esquemas de etiquetado e construír proceso de meta-imaxe, cada un dos cales almacena unha morea de:

  • o compromiso sobre o que se realizou a publicación (non importa se a imaxe se engadiu, cambiou ou permaneceu igual no rexistro de contedores);
  • e o noso identificador interno correspondente á imaxe ensamblada.

Noutras palabras, proporcionouse vincular etiquetas publicadas con commits en Git.

Configuración final e algoritmo xeral

Ao configurar a limpeza, os usuarios agora teñen acceso ás políticas que seleccionan as imaxes actuais. Cada política deste tipo defínese:

  • moitas referencias, i.e. Etiquetas Git ou ramas Git que se usan durante a dixitalización;
  • e o límite de imaxes buscadas para cada referencia do conxunto.

Para ilustralo, este é o aspecto da configuración da política predeterminada:

cleanup:
  keepPolicies:
  - references:
      tag: /.*/
      limit:
        last: 10
  - references:
      branch: /.*/
      limit:
        last: 10
        in: 168h
        operator: And
    imagesPerReference:
      last: 2
      in: 168h
      operator: And
  - references:  
      branch: /^(main|staging|production)$/
    imagesPerReference:
      last: 10

Esta configuración contén tres políticas que cumpren as seguintes regras:

  1. Garda a imaxe das últimas 10 etiquetas Git (por data de creación da etiqueta).
  2. Non gardar máis de 2 imaxes publicadas na última semana para non máis de 10 temas con actividade na última semana.
  3. Garda 10 imaxes para as ramas main, staging и production.

O algoritmo final redúcese nos seguintes pasos:

  • Recuperando manifestos do rexistro de contedores.
  • Excluíndo as imaxes utilizadas en Kubernetes, porque Xa os seleccionamos previamente mediante a consulta da API de K8s.
  • Analizando o historial de Git e excluíndo imaxes en función das políticas especificadas.
  • Eliminando as imaxes restantes.

Volvendo á nosa ilustración, isto é o que ocorre con werf:

O problema da limpeza "intelixente" de imaxes de contedores e a súa solución en werf

Non obstante, aínda que non use werf, pódese aplicar un enfoque similar á limpeza avanzada de imaxes -nunha implementación ou outra (segundo o enfoque preferido para a etiquetaxe de imaxes)- a outros sistemas/utilidades. Para iso, abonda con lembrar os problemas que xorden e atopar na túa pila aquelas oportunidades que che permitan integrar a súa solución da forma máis fluida posible. Agardamos que o camiño que percorremos che axude a mirar o teu caso particular con novos detalles e reflexións.

Conclusión

  • Tarde ou cedo, a maioría dos equipos atopan o problema do desbordamento do rexistro.
  • Ao buscar solucións, primeiro é necesario determinar os criterios para a relevancia da imaxe.
  • As ferramentas que ofrecen os populares servizos de rexistro de contedores permiten organizar unha limpeza moi sinxela que non ten en conta o "mundo exterior": as imaxes utilizadas en Kubernetes e as peculiaridades dos fluxos de traballo do equipo.
  • Un algoritmo flexible e eficiente debe ter unha comprensión dos procesos CI/CD e operar non só con datos de imaxe de Docker.

PS

Lea tamén no noso blog:

Fonte: www.habr.com

Engadir un comentario