Patrones de almacenamiento de Kubernetes


Hola Habr!

Le recordamos que hemos lanzado otro libro extremadamente interesante y útil sobre los patrones de Kubernetes. Todo comenzó con los " Patrones " de Brendan Burns y, por cierto, el trabajo en este segmento está en pleno apogeo . Hoy lo invitamos a leer un artículo del blog de MinIO que resume las tendencias y detalles de los patrones de almacenamiento de datos en Kubernetes.


Kubernetes cambió fundamentalmente los patrones tradicionales de desarrollo e implementación de aplicaciones. Ahora el equipo puede tardar unos días en desarrollar, probar e implementar la aplicación, en diferentes entornos, y todo esto dentro de los clústeres de Kubernetes. Tal trabajo con tecnología de generaciones anteriores usualmente tomó semanas, si no meses.

Tal aceleración fue posible gracias a la abstracción proporcionada por Kubernetes, es decir, debido al hecho de que Kubernetes interactúa con detalles de bajo nivel de máquinas físicas o virtuales, lo que permite a los usuarios declarar, entre otros parámetros, el procesador deseado, la memoria requerida, el número de instancias de contenedor. Como Kubernetes cuenta con el respaldo de una gran comunidad y el alcance de Kubernetes se expande constantemente, lidera por un amplio margen entre todas las plataformas de orquestación de contenedores.

A medida que se expande el uso de Kubernetes, también lo hace la confusión sobre los patrones de almacenamiento utilizados en él .

Con la competencia general por un pedazo de pastel de Kubernetes (es decir, para el almacenamiento de datos), cuando se trata de hablar sobre el almacenamiento de datos, la señal se está ahogando en un ruido fuerte.
Kubernetes incorpora un modelo moderno para desarrollar, implementar y administrar aplicaciones. Un modelo tan moderno separa el almacenamiento de datos de la informática. Para comprender completamente esta separación en el contexto de Kubernetes, también debe comprender qué son las aplicaciones con estado y sin estado, y cómo se combina el almacenamiento de datos con esto. Aquí es donde el enfoque REST API utilizado por S3 tiene claras ventajas sobre el enfoque POSIX / CSI que es típico de otras soluciones.

En este artículo hablaremos sobre los patrones de almacenamiento en Kubernetes y discutiremos por separado el debate sobre las aplicaciones aptas y sin estado, para que podamos comprender claramente la diferencia entre ellas y por qué es importante. Más adelante en el texto, consideraremos las aplicaciones y los patrones de almacenamiento de datos utilizados en ellas a la luz de las mejores prácticas para trabajar con contenedores y Kubernetes.

Contenedores apátridas


Los contenedores son inherentemente livianos y efímeros. Se pueden detener, eliminar o implementar fácilmente en otro nodo; todo esto lleva unos segundos. En un sistema de orquestación de contenedores grandes, tales operaciones ocurren todo el tiempo, y los usuarios ni siquiera notan tales cambios. Sin embargo, los movimientos son posibles solo si el contenedor no tiene dependencias en el nodo en el que se encuentra. Se dice que estos contenedores funcionan sin preservación del estado .

Contenedores con estado


Si el contenedor almacena datos en dispositivos conectados localmente (o en un dispositivo de bloque), entonces el almacén de datos en el que está ubicado deberá trasladarse a un nuevo nodo junto con el contenedor en sí mismo, en caso de falla. Esto es importante, porque de lo contrario la aplicación que se ejecuta en el contenedor no podrá funcionar correctamente, ya que necesita acceder a los datos almacenados en los medios locales. Se dice que estos contenedores tienen estado .

Desde un punto de vista puramente técnico, los contenedores con estado también se pueden mover a otros nodos. Por lo general, esto se logra utilizando sistemas de archivos distribuidos o almacenamientos de red en bloque conectados a todos los nodos en los que operan los contenedores. Por lo tanto, los contenedores obtienen acceso a los volúmenes para el almacenamiento persistente de datos, y la información se almacena en discos ubicados en toda la red. Llamaré a este método un " enfoque de contenedor para preservar el estado " , y en el resto del artículo lo llamaré en aras de la uniformidad.



En un enfoque típico de contenedor con estado, todos los pods de aplicaciones se conectan a un sistema de archivos distribuido: se obtiene un tipo de almacenamiento compartido, donde se obtienen todos los datos de la aplicación. Si bien son posibles algunas variaciones, este es un enfoque de alto nivel.

Ahora veamos por qué el enfoque de contenedor con estado en el mundo basado en la nube es antipatrón.

Diseño de aplicaciones basadas en la nube


Tradicionalmente, las aplicaciones usaban bases de datos para el almacenamiento estructurado de información y discos locales o sistemas de archivos distribuidos, donde se volcaban todos los datos no estructurados o incluso semiestructurados. A medida que crecía el volumen de datos no estructurados, los desarrolladores se dieron cuenta de que POSIX era demasiado hablador, asociado con costos significativos y, en última instancia, interfiere con la aplicación cuando se mueve a una escala realmente grande.

Esto contribuyó principalmente a la aparición de un nuevo estándar para el almacenamiento de datos, es decir, almacenamientos basados ​​en la nube que funcionan principalmente sobre la base de la API REST y liberan la aplicación del mantenimiento oneroso del almacén de datos local. En este caso, la aplicación ingresa al modo de operación sin guardar el estado (ya que el estado está en el almacenamiento remoto). Las aplicaciones modernas se están construyendo desde cero ya teniendo en cuenta este factor. Como regla general, cualquier aplicación moderna que procese datos de un tipo u otro (registros, metadatos, blobs, etc.) se basa en un paradigma orientado a la nube, donde el estado se transfiere a un sistema de software especialmente asignado para su almacenamiento.

¡El enfoque de contenedor de preservación del estado hace que todo este paradigma retroceda exactamente a donde comenzó!

Cuando se utilizan interfaces POSIX para almacenar datos, las aplicaciones funcionan de la misma manera que si mantuvieran el estado, y debido a esto, se apartan de los postulados más importantes del diseño basado en la nube, es decir, de la capacidad de variar el tamaño de los flujos de trabajo de la aplicación dependiendo de la entrada cargar, moverse a un nuevo nodo tan pronto como el nodo actual falle, y así sucesivamente.

Una mirada más cercana a esta situación revela que al elegir un almacén de datos, nos enfrentamos una y otra vez con el dilema "POSIX versus REST API", PERO con un agravamiento adicional de los problemas POSIX causados ​​por la naturaleza distribuida de los entornos de Kubernetes. En particular,

  • POSIX : POSIX , . , . API , , S3 API, , , «» . , . .
  • : , , . , , ( ), , . - POSIX . , S3 API , , , .
  • : POSIX : . - . , API, , , ..
  • : , . , , , . , , , .


Mientras que la interfaz de almacenamiento de datos de contenedor (CSI) ayudó mucho con la distribución del nivel de volumen de Kubernetes, pasándolo parcialmente a proveedores de almacenamiento de datos de terceros, pero también contribuyó accidentalmente a la convicción de que el enfoque de contenedor con estado era el método recomendado de almacenamiento de datos en Kubernetes.

CSI se desarrolló como un estándar para proporcionar sistemas de almacenamiento de archivos y bloques arbitrarios para aplicaciones heredadas cuando se trabaja con Kubernetes. Y, como se mostró en este artículo, la única situación en la que es apropiado un enfoque de contenedor con estado (y CSI en su forma actual) es cuando la aplicación en sí es un sistema heredado en el que es imposible agregar soporte para la API de almacenamiento de datos de objetos.

Es importante comprender que al usar CSI en su forma actual, es decir, al montar volúmenes cuando se trabaja con aplicaciones modernas, encontraremos aproximadamente los mismos problemas que los que se encuentran en los sistemas donde el almacenamiento de datos se organiza en el estilo POSIX.

Mejor enfoque


En este caso, es importante comprender que la mayoría de las aplicaciones no están afiladas inherentemente específicamente para trabajar con o sin preservación del estado. Este comportamiento depende de la arquitectura general del sistema y de las opciones específicas seleccionadas durante el diseño. Hablemos un poco sobre las aplicaciones con estado.

En principio, todos los datos de la aplicación se pueden dividir en varios tipos generales:

  • Dato de registro
  • Datos de marca de tiempo
  • Datos de la transacción
  • Metadatos
  • Imágenes de contenedores
  • Datos de blobs (blobs)

Todos estos tipos de datos son muy compatibles con las plataformas modernas de almacenamiento de datos, y hay varias plataformas basadas en la nube adaptadas para entregar datos en cada uno de estos formatos específicos. Por ejemplo, los datos y metadatos de las transacciones pueden residir en una base de datos moderna basada en la nube, como CockroachDB, YugaByte, etc. Las imágenes de contenedor o los datos de blob se pueden almacenar en el registro de Docker basado en MinIO. Los datos de la marca de tiempo se pueden almacenar en una base de datos de series de tiempo, como InfluxDB, etc. No entraremos en detalles de cada tipo de datos y aplicaciones relacionadas, pero la idea general es evitar el almacenamiento persistente de datos basado en el montaje del disco local.



Además, a menudo es eficaz proporcionar una capa de almacenamiento en caché temporal, que sirve como un tipo de almacenamiento de archivos temporal para aplicaciones, pero las aplicaciones no deben depender de este nivel como fuente de verdad.

Almacenamiento de aplicaciones con estado


Si bien en la mayoría de los casos es útil mantener las aplicaciones sin estado, aquellas aplicaciones que están diseñadas para almacenar datos, por ejemplo, bases de datos, almacenes de objetos, almacenes de claves y valores, deben mantener el estado. Veamos por qué estas aplicaciones se implementan en Kubernetes. Tome MinIO como ejemplo, pero se aplican principios similares a cualquier otro gran sistema de almacenamiento basado en la nube.

Las aplicaciones centradas en la nube están diseñadas para maximizar el uso de la flexibilidad inherente a los contenedores. Esto significa que no hacen suposiciones sobre el entorno en el que se implementarán. Por ejemplo, MinIO utiliza un mecanismo de codificación de borrado interno, que proporciona al sistema una estabilidad suficiente para que permanezca operativo incluso si falla la mitad de las unidades. MinIO también gestiona la integridad y seguridad de los datos utilizando su propio cifrado y hashing del lado del servidor.

Para tales aplicaciones basadas en la nube, los volúmenes locales persistentes (PV) son más convenientes como almacenamiento de respaldo. El PV local proporciona la capacidad de almacenar datos sin procesar, mientras que las aplicaciones que se ejecutan sobre estos PV recopilan información de forma independiente para escalar datos y gestionar los crecientes requisitos de datos.

Este enfoque es mucho más simple y significativamente mejor escalable en comparación con la PV basada en CSI, que aporta sus propios niveles de gestión de datos y redundancia al sistema; El hecho es que estos niveles generalmente entran en conflicto con las aplicaciones diseñadas de acuerdo con el principio de preservación del estado.

Movimiento seguro para desanclar datos de la informática


En este artículo, hablamos sobre cómo las aplicaciones se reorientan para que funcionen sin guardar el estado o, en otras palabras, el almacenamiento de datos se delimita de la computación en ellas. En conclusión, considere algunos ejemplos del mundo real de tal tendencia.

Spark , la reconocida plataforma de análisis de datos, se ha utilizado tradicionalmente con despliegue con estado y despliegue en el sistema de archivos HDFS. Sin embargo, a medida que Spark pasa a un mundo basado en la nube, esta plataforma se usa cada vez más sin la preservación del estado usando 's3a'. Spark usa s3a para transferir el estado a otros sistemas, mientras que los contenedores de Spark funcionan completamente sin preservación del estado. Otros actores de grandes empresas en el campo del análisis de big data, en particular, Vertica , Teradata, Greenplum también trabaja con la división de almacenamiento de datos y computación sobre ellos.

También se pueden ver patrones similares en otras grandes plataformas analíticas, incluidas Presto, Tensorflow to R, Jupyter. La carga de estado a sistemas de almacenamiento en la nube remotos hace que sea mucho más fácil administrar y escalar su aplicación. Además, ayuda a la portabilidad de la aplicación a una variedad de entornos.

All Articles