{"id":96065,"date":"2020-10-07T13:42:09","date_gmt":"2020-10-07T11:42:09","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/problema-umnoj-ochistki-obrazov-kontejnerov-i-eyo-reshenie-v-werf"},"modified":"2020-10-07T13:42:09","modified_gmt":"2020-10-07T11:42:09","slug":"problema-umnoj-ochistki-obrazov-kontejnerov-i-eyo-reshenie-v-werf","status":"publish","type":"post","link":"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/problema-umnoj-ochistki-obrazov-kontejnerov-i-eyo-reshenie-v-werf","title":{"rendered":"El problema de la \"limpieza inteligente\" de im\u00e1genes de contenedores y su soluci\u00f3n en werf","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"El problema de la &quot;limpieza inteligente&quot; de im\u00e1genes de contenedores y su soluci\u00f3n en werf\" src=\"\/wp-content\/uploads\/2020\/10\/1410cea46bb8dcdc3ac06db11ed5a402.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEl art\u00edculo aborda la problem\u00e1tica de la limpieza de im\u00e1genes que se acumulan en los registros de contenedores (Docker Registry y sus an\u00e1logos) en el contexto de las modernas tuber\u00edas CI\/CD para aplicaciones cloud native entregadas en Kubernetes. Se presentan los principales criterios de relevancia de las im\u00e1genes y las complicaciones que surgen en su limpieza automatizada, preservaci\u00f3n de espacio y satisfacci\u00f3n de las necesidades de los equipos. Finalmente, a trav\u00e9s de un ejemplo concreto de un proyecto de c\u00f3digo abierto, describiremos c\u00f3mo se pueden superar estas dificultades.<\/p>\n<h2>Introducci\u00f3n<\/h2>\n<p>\nLa cantidad de im\u00e1genes en el registro de contenedores puede crecer r\u00e1pidamente, ocupando m\u00e1s espacio en el almacenamiento y, en consecuencia, aumentando significativamente su costo. Para controlar, limitar o mantener un crecimiento aceptable del espacio ocupado en el registry, se establece:<\/p>\n<ol>\n<li>utilizar un n\u00famero fijo de etiquetas para las im\u00e1genes;<\/li>\n<li>limpiar las im\u00e1genes de alguna manera.<\/li>\n<\/ol>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><br \/>\nLa primera limitaci\u00f3n es a veces aceptable para equipos peque\u00f1os. Si a los desarrolladores les bastan etiquetas fijas (<code>latest<\/code>, <code>main<\/code>, <code>test<\/code>, <code>boris<\/code> ), el registro no se expandir\u00e1 en tama\u00f1o y durante mucho tiempo se puede no pensar en la limpieza. Dado que todas las im\u00e1genes obsoletas se sobrescriben, no queda trabajo para limpiar (todo lo hace el recolector de basura est\u00e1ndar).<\/p>\n<p>Sin embargo, este enfoque limita severamente el desarrollo y rara vez se aplica a CI\/CD de proyectos modernos. La <strong>automatizaci\u00f3n<\/strong>ha pasado a ser parte integral del desarrollo, permitiendo probar, desplegar y entregar nuevas funcionalidades a los usuarios con mayor rapidez. Por ejemplo, en todos nuestros proyectos, se crea autom\u00e1ticamente una tuber\u00eda CI con cada commit. En ella, se construye la imagen, se prueba, se despliega en varios entornos de Kubernetes para depuraci\u00f3n y comprobaciones restantes, y si todo va bien, los cambios llegan al usuario final. Y esto ya no es ciencia espacial, sino una rutina para muchos \u2014 probablemente tambi\u00e9n para usted, dado que est\u00e1 leyendo este art\u00edculo.<\/p>\n<p>Dado que la correcci\u00f3n de errores y el desarrollo de nuevas funcionalidades se llevan a cabo en paralelo, y los lanzamientos pueden realizarse varias veces al d\u00eda, es evidente que el proceso de desarrollo genera una cantidad sustancial de commits, lo que significa que hay <strong>un gran n\u00famero de im\u00e1genes en el registry.<\/strong>Como resultado, surge con urgencia la cuesti\u00f3n de organizar una limpieza efectiva del registry, es decir, eliminar im\u00e1genes obsoletas.<\/p>\n<p>\u00bfPero c\u00f3mo determinar si la imagen es realmente relevante?<\/p>\n<h2>Criterios de relevancia de la imagen<\/h2>\n<p>\nEn la gran mayor\u00eda de los casos, los criterios principales ser\u00e1n los siguientes:<\/p>\n<p>1. El primero (el m\u00e1s obvio y cr\u00edtico de todos) son las im\u00e1genes que <strong>actualmente se utilizan en Kubernetes<\/strong>. Eliminar estas im\u00e1genes puede resultar en costos significativos debido a la inactividad de la producci\u00f3n (por ejemplo, es posible que se necesiten im\u00e1genes durante la replicaci\u00f3n) o puede anular los esfuerzos del equipo que est\u00e1 depurando en cualquiera de los entornos. <i>(Por esta raz\u00f3n, incluso hemos creado un <\/i><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/flant\/k8s-image-availability-exporter\"><i>exportador de Prometheus<\/i><\/a><\/noindex><i>, que monitorea la ausencia de tales im\u00e1genes en cualquier cl\u00faster de Kubernetes.)<\/i><\/p>\n<p>2. El segundo (menos obvio, pero tambi\u00e9n muy importante y que nuevamente se relaciona con la operaci\u00f3n) son las im\u00e1genes que <strong>se requieren para un revertir en caso de que se detecten problemas graves<\/strong> en la versi\u00f3n actual. Por ejemplo, en el caso de Helm, son las im\u00e1genes que se utilizan en las versiones guardadas del lanzamiento. (Por cierto, de forma predeterminada, Helm tiene un l\u00edmite de 256 revisiones, pero es poco probable que alguien realmente necesite conservar <i>de eso<\/i> una gran cantidad de versiones?..) De hecho, guardamos versiones precisamente para que se puedan usar posteriormente, es decir, \"revertir\" a ellas en caso de necesidad.<\/p>\n<p>3. El tercero son las <strong>necesidades de los desarrolladores<\/strong>: todas las im\u00e1genes que est\u00e1n relacionadas con su trabajo actual. Por ejemplo, si estamos considerando un PR, tiene sentido mantener la imagen correspondiente al \u00faltimo commit y, digamos, al commit anterior: as\u00ed el desarrollador podr\u00e1 regresar r\u00e1pidamente a cualquier tarea y trabajar con los cambios m\u00e1s recientes. <\/p>\n<p>4. El cuarto son las im\u00e1genes que <strong>corresponden a las versiones de nuestra aplicaci\u00f3n<\/strong>, es decir, son el producto final: v1.0.0, 20.04.01, sierra, etc.<\/p>\n<p>NB: Los criterios aqu\u00ed definidos se han formulado en base a la experiencia de interacci\u00f3n con decenas de equipos de desarrollo de diferentes empresas. Sin embargo, por supuesto, dependiendo de las caracter\u00edsticas en los procesos de desarrollo y de la infraestructura utilizada (por ejemplo, si no se utiliza Kubernetes), estos criterios pueden variar. <\/p>\n<h2>Cumplimiento de los criterios y soluciones existentes<\/h2>\n<p>\nLos servicios populares de container registry suelen ofrecer sus propias pol\u00edticas de limpieza de im\u00e1genes: en ellas puedes definir las condiciones bajo las cuales una etiqueta se elimina del registry. Sin embargo, las posibilidades de estas condiciones se limitan a par\u00e1metros como nombres, tiempo de creaci\u00f3n y cantidad de etiquetas*.<\/p>\n<p><i>* Depende de las implementaciones espec\u00edficas del registro de contenedores. Hemos considerado las capacidades de las siguientes soluciones: Azure CR, Docker Hub, ECR, GCR, GitHub Packages, GitLab Container Registry, Harbor Registry, JFrog Artifactory, Quay.io \u2014 a fecha de septiembre de 2020.<\/i><\/p>\n<p>Este conjunto de par\u00e1metros es m\u00e1s que suficiente para satisfacer el cuarto criterio \u2014 es decir, seleccionar im\u00e1genes que correspondan a las versiones. Sin embargo, para todos los dem\u00e1s criterios, hay que optar por alguna soluci\u00f3n de compromiso (una pol\u00edtica m\u00e1s estricta o, por el contrario, m\u00e1s indulgente) \u2014 dependiendo de las expectativas y las capacidades financieras.<\/p>\n<p>Por ejemplo, el tercer criterio \u2014 relacionado con las necesidades de los desarrolladores \u2014 puede resolverse organizando procesos dentro de los equipos: nombramiento espec\u00edfico de im\u00e1genes, mantenimiento de listas de permitidos y acuerdos internos. Pero, al final, a\u00fan es necesario automatizarlo. Y si las capacidades de las soluciones listas no son suficientes, hay que hacer algo propio.<\/p>\n<p>La situaci\u00f3n es similar con los dos primeros criterios: no se pueden satisfacer sin obtener datos de un sistema externo \u2014 el mismo donde se realiza la implementaci\u00f3n de aplicaciones (en nuestro caso, es Kubernetes).<\/p>\n<h3>Ilustraci\u00f3n del flujo de trabajo en Git<\/h3>\n<p>\nSupongamos que trabajas m\u00e1s o menos con este esquema en Git:<\/p>\n<p><img decoding=\"async\" alt=\"El problema de la &quot;limpieza inteligente&quot; de im\u00e1genes de contenedores y su soluci\u00f3n en werf\" src=\"\/wp-content\/uploads\/2020\/10\/45c9bfb6755da1b4d6be05b51ab17429.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<i>La imagen con un icono de cabeza en el esquema marca las im\u00e1genes de contenedor que actualmente est\u00e1n desplegadas en Kubernetes para ciertos usuarios (usuarios finales, testers, gerentes, etc.) o son utilizadas por los desarrolladores para depuraci\u00f3n y objetivos similares.<\/i><\/p>\n<p>\u00bfQu\u00e9 suceder\u00e1 si las pol\u00edticas de limpieza permiten dejar (no eliminar) im\u00e1genes solo <b>por nombres de etiquetas espec\u00edficos?<\/b>?<\/p>\n<p><img decoding=\"async\" alt=\"El problema de la &quot;limpieza inteligente&quot; de im\u00e1genes de contenedores y su soluci\u00f3n en werf\" src=\"\/wp-content\/uploads\/2020\/10\/e57ff24cb818799d28e8eb006aea2eb5.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nObviamente, tal escenario no le agradar\u00e1 a nadie.<\/p>\n<p>\u00bfQu\u00e9 cambiar\u00e1 si las pol\u00edticas permiten no eliminar im\u00e1genes <b>por un intervalo de tiempo espec\u00edfico \/ n\u00famero de \u00faltimos commits?<\/b>?<\/p>\n<p><img decoding=\"async\" alt=\"El problema de la &quot;limpieza inteligente&quot; de im\u00e1genes de contenedores y su soluci\u00f3n en werf\" src=\"\/wp-content\/uploads\/2020\/10\/7743581e6e64affb0a207ee156c00f6e.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEl resultado es significativamente mejor, aunque todav\u00eda est\u00e1 lejos de ser ideal. Despu\u00e9s de todo, todav\u00eda tenemos desarrolladores que necesitan im\u00e1genes en el registry (o incluso desplegadas en K8s) para depurar errores...<\/p>\n<p>Resumiendo la situaci\u00f3n actual del mercado: las funciones disponibles en los registros de contenedores no ofrecen la flexibilidad suficiente para la limpieza, y la principal raz\u00f3n es que <strong>no hay posibilidad de interactuar con el mundo exterior.<\/strong>Esto significa que los equipos que requieren dicha flexibilidad deben implementar por su cuenta la eliminaci\u00f3n de im\u00e1genes \"externamente\", utilizando la API de Docker Registry (o la API nativa de la implementaci\u00f3n correspondiente).<\/p>\n<p>Sin embargo, est\u00e1bamos buscando una soluci\u00f3n universal que automatizara la limpieza de im\u00e1genes para diferentes equipos que utilizan diferentes registros...<\/p>\n<h2>Nuestro camino hacia la limpieza universal de im\u00e1genes.<\/h2>\n<p>\n\u00bfDe d\u00f3nde proviene esta necesidad? La cuesti\u00f3n es que no somos un grupo aislado de desarrolladores, sino un equipo que atiende a muchos de ellos, ayudando a resolver integralmente los problemas de CI\/CD. Y la principal herramienta t\u00e9cnica para esto es una utilidad de c\u00f3digo abierto <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.werf.io\/\">werf<\/a><\/noindex>. Su caracter\u00edstica es que no realiza una \u00fanica funci\u00f3n, sino que acompa\u00f1a los procesos de entrega continua en todas las etapas: desde la construcci\u00f3n hasta el despliegue.<\/p>\n<p>La publicaci\u00f3n en el registro* de im\u00e1genes (inmediatamente despu\u00e9s de su construcci\u00f3n) es una funci\u00f3n evidente de dicha utilidad. Y dado que las im\u00e1genes se almacenan all\u00ed, si su almacenamiento no es ilimitado, tambi\u00e9n se debe responder por su posterior limpieza. A continuaci\u00f3n, se explicar\u00e1 c\u00f3mo logramos esto, cumpliendo con todos los criterios establecidos.<\/p>\n<p><i>* Aunque los registros en s\u00ed pueden ser diversos (Docker Registry, GitLab Container Registry, Harbor, etc.), sus usuarios se enfrentan a los mismos problemas. La soluci\u00f3n universal en nuestro caso no depende de la implementaci\u00f3n del registro, ya que se lleva a cabo fuera de los propios registros y ofrece un comportamiento uniforme para todos.<\/i><\/p>\n<p>A pesar de que utilizamos werf como ejemplo de implementaci\u00f3n, esperamos que los enfoques utilizados sean \u00fatiles para otros equipos que enfrenten dificultades similares.<\/p>\n<p>As\u00ed que nos dedicamos a <i>la<\/i> implementaci\u00f3n externa de un mecanismo para limpiar im\u00e1genes \u2014 en lugar de las capacidades que ya est\u00e1n integradas en los registros para contenedores. El primer paso fue utilizar la API de Docker Registry para crear las mismas pol\u00edticas primitivas sobre la cantidad de etiquetas y el tiempo de su creaci\u00f3n (mencionadas anteriormente). A ellas se a\u00f1adi\u00f3 <strong>una lista permitida basada en las im\u00e1genes utilizadas en la infraestructura desplegada.<\/strong>, es decir, Kubernetes. Para esto \u00faltimo, bastaba con recorrer todos los recursos desplegados a trav\u00e9s de la API de Kubernetes y obtener una lista de valores. <code>image<\/code>.<\/p>\n<p>Esta soluci\u00f3n trivial resolvi\u00f3 el problema m\u00e1s cr\u00edtico (criterio n.\u00ba 1), pero solo fue el comienzo de nuestro camino hacia la mejora del mecanismo de limpieza. El siguiente, y mucho m\u00e1s interesante, paso fue encontrar <strong>la forma de vincular las im\u00e1genes publicadas con el historial de Git.<\/strong>.<\/p>\n<h3>Esquemas de etiquetado<\/h3>\n<p>\nPara comenzar, elegimos un enfoque en el que la imagen final debe almacenar la informaci\u00f3n necesaria para la limpieza, y construimos el proceso sobre esquemas de etiquetado. Al publicar la imagen, el usuario seleccionaba una opci\u00f3n de etiquetado espec\u00edfica (<code>git-branch<\/code>, <code>git-commit<\/code> o <code>git-tag<\/code>) y utilizaba el valor correspondiente. En los sistemas CI, la configuraci\u00f3n de estos valores se realizaba autom\u00e1ticamente seg\u00fan las variables de entorno. En esencia, <strong>la imagen final se vinculaba a un determinado primitivo de Git,<\/strong>almacenando los datos necesarios para la limpieza en las etiquetas.<\/p>\n<p>Con este enfoque, se logr\u00f3 un conjunto de pol\u00edticas que permitieron usar Git como la \u00fanica fuente de verdad:<\/p>\n<ul>\n<li>Al eliminar una rama\/etiqueta en Git, se eliminaban autom\u00e1ticamente las im\u00e1genes relacionadas en el registro.<\/li>\n<li>La cantidad de im\u00e1genes vinculadas a las etiquetas y commits de Git se pod\u00eda regular mediante la cantidad de etiquetas utilizadas en el esquema elegido y el tiempo de creaci\u00f3n del commit relacionado.<\/li>\n<\/ul>\n<p>\nEn general, la implementaci\u00f3n resultante satisfac\u00eda nuestras necesidades, pero pronto nos esperar\u00eda un nuevo desaf\u00edo. Resulta que, durante el uso de esquemas de etiquetado basados en primitivos de Git, nos encontramos con varias desventajas. <i>(Dado que su descripci\u00f3n est\u00e1 fuera del alcance de este art\u00edculo, todos los interesados pueden consultar los detalles. <\/i><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/495112\/\"><i>aqu\u00ed<\/i><\/a><\/noindex><i>.)<\/i> Por lo tanto, al decidir pasar a un enfoque de etiquetado m\u00e1s eficiente (etiquetado basado en contenido), tuvimos que reconsiderar tambi\u00e9n la implementaci\u00f3n de la limpieza de im\u00e1genes.<\/p>\n<h3>Nuevo algoritmo<\/h3>\n<p>\n\u00bfPor qu\u00e9? En el etiquetado dentro del etiquetado basado en contenido, cada etiqueta puede satisfacer a m\u00faltiples commits en Git. En la limpieza de im\u00e1genes ya no se puede basar <i>solo<\/i> en el commit en el que se a\u00f1adi\u00f3 una nueva etiqueta al registro.<\/p>\n<p>Para el nuevo algoritmo de limpieza, se decidi\u00f3 prescindir de los esquemas de etiquetado y construir <strong>el proceso sobre meta-im\u00e1genes,<\/strong>cada una de las cuales almacena un par de:<\/p>\n<ul>\n<li>el commit en el que se realiz\u00f3 la publicaci\u00f3n (no importa si se agreg\u00f3, cambi\u00f3 o permaneci\u00f3 igual en el registro de contenedores);<\/li>\n<li>y nuestro identificador interno correspondiente a la imagen compilada.<\/li>\n<\/ul>\n<p>\nEn otras palabras, se garantiz\u00f3 <strong>la conexi\u00f3n entre las etiquetas publicadas y los commits en Git<\/strong>.<\/p>\n<h3>La configuraci\u00f3n final y el algoritmo general<\/h3>\n<p>\nA los usuarios se les hicieron disponibles pol\u00edticas para la configuraci\u00f3n de limpieza, que determinan la selecci\u00f3n de im\u00e1genes actuales. Cada una de estas pol\u00edticas se define por:<\/p>\n<ul>\n<li>un conjunto de references, es decir, etiquetas de Git o ramas de Git que se utilizan durante el escaneo;<\/li>\n<li>y un l\u00edmite de im\u00e1genes buscadas para cada reference del conjunto.<\/li>\n<\/ul>\n<p>\nPara ilustrar: as\u00ed es como se configur\u00f3 la pol\u00edtica predeterminada:<\/p>\n<pre><code class=\"plaintext\">cleanup:\n  keepPolicies:\n  - references:\n      tag: \\\/.*\\\/\\\n      limit:\n        last: 10\n  - references:\n      branch: \\\/.*\\\/\\\n      limit:\n        last: 10\n        in: 168h\n        operator: And\n    imagesPerReference:\n      last: 2\n      in: 168h\n      operator: And\n  - references:  \n      branch: \\\/^(main|staging|production)$\\\/\\\n    imagesPerReference:\n      last: 10\n<\/code><\/pre>\n<p>\nEsta configuraci\u00f3n contiene tres pol\u00edticas, que corresponden a las siguientes reglas:<\/p>\n<ol>\n<li>Conservar la imagen para las 10 \u00faltimas etiquetas de Git (seg\u00fan la fecha de creaci\u00f3n de la etiqueta).<\/li>\n<li>Conservar no m\u00e1s de 2 im\u00e1genes publicadas en la \u00faltima semana para no m\u00e1s de 10 ramas con actividad durante la \u00faltima semana.<\/li>\n<li>Conservar 10 im\u00e1genes para las ramas <code>main<\/code>, <code>staging<\/code> y <code>producci\u00f3n<\/code>.<\/li>\n<\/ol>\n<p>\nEl algoritmo final se reduce a los siguientes pasos:<\/p>\n<ul>\n<li>Obtener los manifiestos del registro de contenedores.<\/li>\n<li>Excluir las im\u00e1genes utilizadas en Kubernetes, ya que estas ya las hemos seleccionado previamente, consultando la API de K8s.<\/li>\n<li>Escanear el historial de Git y excluir im\u00e1genes seg\u00fan las pol\u00edticas establecidas.<\/li>\n<li>Eliminar las im\u00e1genes restantes.<\/li>\n<\/ul>\n<p>\nRegresando a nuestra ilustraci\u00f3n, esto es lo que sucede con werf:<\/p>\n<p><img decoding=\"async\" alt=\"El problema de la &quot;limpieza inteligente&quot; de im\u00e1genes de contenedores y su soluci\u00f3n en werf\" src=\"\/wp-content\/uploads\/2020\/10\/c453092dca23860a0dda604843845507.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nSin embargo, incluso si no usas werf, un enfoque similar para la limpieza avanzada de im\u00e1genes \u2014 en alguna implementaci\u00f3n (de acuerdo con el enfoque preferido para etiquetar im\u00e1genes) \u2014 puede aplicarse tambi\u00e9n en otros sistemas\/utilidades. Solo es necesario tener en cuenta los problemas que surgen y encontrar las oportunidades en tu stack que permiten integrar su soluci\u00f3n de la manera m\u00e1s fluida. Esperamos que el camino que hemos recorrido ayude a ver tu caso particular con nuevos detalles y reflexiones.<\/p>\n<h2>Conclusi\u00f3n<\/h2>\n<p><\/p>\n<ul>\n<li>Tarde o temprano, la mayor\u00eda de los equipos se enfrentan al problema de la saturaci\u00f3n del registro. <\/li>\n<li>Al buscar soluciones, es esencial establecer primero los criterios de relevancia de la imagen.<\/li>\n<li>Las herramientas ofrecidas por los servicios populares de registro de contenedores permiten organizar una limpieza muy sencilla que no tiene en cuenta el \"mundo exterior\": las im\u00e1genes utilizadas en Kubernetes y las peculiaridades de los flujos de trabajo del equipo.<\/li>\n<li>Un algoritmo flexible y eficaz debe tener en cuenta los procesos de CI\/CD y no solo operar con los datos de las im\u00e1genes de Docker.<\/li>\n<\/ul>\n<p><\/p>\n<h2>P.D.<\/h2>\n<p>\nTambi\u00e9n puedes leer en nuestro blog:<\/p>\n<ul>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/495112\/\">Etiquetado basado en contenido en el recolector werf: \u00bfpor qu\u00e9 y c\u00f3mo funciona?<\/a><\/noindex>\u00bb;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/476646\/\">fusi\u00f3n de 3 v\u00edas en werf: despliegue en Kubernetes con Helm 'a tope'<\/a><\/noindex>\u00bb;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/465131\/\">Soporte para monorepos y multirepos en werf y qu\u00e9 tiene que ver Docker Registry<\/a><\/noindex>\u00bb;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/493170\/\">Lanzamiento de werf 1.1: mejoras en el compilador hoy y planes para el futuro<\/a><\/noindex>\u00bb.<\/li>\n<\/ul>\n<p>Fuente: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/522024\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0412 \u0441\u0442\u0430\u0442\u044c\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u0442\u0438\u043a\u0430 \u043e\u0447\u0438\u0441\u0442\u043a\u0438 \u043e\u0431\u0440\u0430\u0437\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u043a\u0430\u043f\u043b\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0432 \u0440\u0435\u0435\u0441\u0442\u0440\u0430\u0445 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432 (Docker Registry \u0438 \u0435\u0433\u043e \u0430\u043d\u0430\u043b\u043e\u0433\u0430\u0445) \u0432 \u0440\u0435\u0430\u043b\u0438\u044f\u0445 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 CI\/CD-\u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u043e\u0432 \u0434\u043b\u044f cloud native-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439, \u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0445 \u0432 Kubernetes. \u041f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u044b \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043a\u0440\u0438\u0442\u0435\u0440\u0438\u0438 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043e\u0431\u0440\u0430\u0437\u043e\u0432 \u0438 \u0432\u044b\u0442\u0435\u043a\u0430\u044e\u0449\u0438\u0435 \u0438\u0437 \u043d\u0438\u0445 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043f\u0440\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u043e\u0447\u0438\u0441\u0442\u043a\u0438, \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043c\u0435\u0441\u0442\u0430 \u0438 \u0443\u0434\u043e\u0432\u043b\u0435\u0442\u0432\u043e\u0440\u0435\u043d\u0438\u044f \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u044f\u043c \u043a\u043e\u043c\u0430\u043d\u0434. \u041d\u0430\u043a\u043e\u043d\u0435\u0446, \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e Open Source-\u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043c\u044b \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0435\u043c, \u043a\u0430\u043a \u044d\u0442\u0438 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":96066,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-96065","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.2 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0412 \u0441\u0442\u0430\u0442\u044c\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u0430.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/problema-umnoj-ochistki-obrazov-kontejnerov-i-eyo-reshenie-v-werf\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"es_ES\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u00ab\u0443\u043c\u043d\u043e\u0439\u00bb \u043e\u0447\u0438\u0441\u0442\u043a\u0438 \u043e\u0431\u0440\u0430\u0437\u043e\u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432 \u0438 \u0435\u0451 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0432 werf | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0412 \u0441\u0442\u0430\u0442\u044c\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u0430.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/problema-umnoj-ochistki-obrazov-kontejnerov-i-eyo-reshenie-v-werf\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-10-07T11:42:09+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-10-07T11:42:09+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47El problema de la limpieza \"inteligente\" de las im\u00e1genes de contenedores y su soluci\u00f3n en werf | ProHoster","description":"El art\u00edculo est\u00e1 revisado.","canonical_url":"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/problema-umnoj-ochistki-obrazov-kontejnerov-i-eyo-reshenie-v-werf","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"es_ES","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u00ab\u0443\u043c\u043d\u043e\u0439\u00bb \u043e\u0447\u0438\u0441\u0442\u043a\u0438 \u043e\u0431\u0440\u0430\u0437\u043e\u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432 \u0438 \u0435\u0451 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0432 werf | ProHoster","og:description":"\u0412 \u0441\u0442\u0430\u0442\u044c\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u0430.","og:url":"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/problema-umnoj-ochistki-obrazov-kontejnerov-i-eyo-reshenie-v-werf","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-10-07T11:42:09+00:00","article:modified_time":"2020-10-07T11:42:09+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"96065","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 10:52:24","updated":"2022-10-01 08:58:07","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts\/96065","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/comments?post=96065"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts\/96065\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/media\/96066"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/media?parent=96065"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/categories?post=96065"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/tags?post=96065"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}