Patrones de almacenamiento de datos en Kubernetes

Patrones de almacenamiento de datos en Kubernetes
¡Hola, Habr!

Te recordamos que hemos lanzado otro sumamente interesante y útil. libro sobre los patrones de Kubernetes. Todavía empezó conpatrones" Brendan Burns y, por cierto, trabaja en este segmento con nosotros. hierve. Hoy lo invitamos a leer un artículo del blog de MinIO, que describe brevemente las tendencias y las características específicas de los patrones de almacenamiento de datos en Kubernetes.

Kubernetes ha cambiado fundamentalmente los patrones tradicionales de desarrollo e implementación de aplicaciones. Ahora un equipo puede tardar días en desarrollar, probar e implementar una aplicación en múltiples entornos, todo dentro de clústeres de Kubernetes. Este tipo de trabajo con tecnologías de generaciones anteriores solía llevar semanas enteras, si no meses.

Esta aceleración es posible gracias a la abstracción proporcionada por Kubernetes, es decir, al hecho de que el propio Kubernetes interactúa con los detalles de bajo nivel de las máquinas físicas o virtuales, lo que permite a los usuarios declarar, entre otros parámetros, el procesador deseado, la cantidad requerida de memoria, el número de instancias de contenedor. Con una enorme comunidad que respalda a Kubernetes y un uso cada vez mayor de Kubernetes, es, con diferencia, el líder de todas las plataformas de orquestación de contenedores.

A medida que crece el uso de Kubernetes, también crece la confusión sobre sus patrones de almacenamiento..

Con toda la competencia por una porción del pastel de Kubernetes (es decir, por el almacenamiento de datos), cuando se trata de almacenamiento de datos, la señal aquí se ahoga en mucho ruido.
Kubernetes encarna el modelo moderno para desarrollar, implementar y administrar aplicaciones. Este modelo moderno desacopla el almacenamiento de datos de la informática. Para comprender completamente esta separación en el contexto de Kubernetes, también es necesario comprender qué son las aplicaciones con y sin estado y cómo encaja el almacenamiento de datos en ellas. Aquí es donde el enfoque API REST utilizado por S3 tiene claras ventajas sobre el enfoque POSIX/CSI que se encuentra en otras soluciones.

En este artículo, hablaremos sobre los patrones de almacenamiento en Kubernetes y abordaremos por separado el debate entre persistencia y aplicaciones sin estado para comprender mejor cuál es la diferencia y por qué es importante. Más adelante en el texto se considerarán 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 sin estado

Los contenedores son por naturaleza ligeros y efímeros. Se pueden detener, eliminar o implementar fácilmente en un host diferente, todo en segundos. En un gran sistema de orquestación de contenedores, este tipo de operaciones ocurren todo el tiempo y los usuarios ni siquiera notan dichos cambios. Sin embargo, los movimientos sólo son posibles si el contenedor no depende del host en el que se encuentra. Se dice que estos contenedores funcionan apátrida.

Contenedores con estado

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

Desde un punto de vista puramente técnico, los contenedores con estado también se pueden mover a otros nodos. Esto generalmente se logra a través de sistemas de archivos distribuidos o almacenamiento en red en bloques adjunto a todos los nodos que ejecutan contenedores. Por lo tanto, los contenedores obtienen acceso a volúmenes para el almacenamiento de datos persistentes y la información se almacena en discos ubicados en toda la red. Llamaré a este métodoenfoque en contenedores con estado”, y en el resto del artículo me referiré a él como tal en aras de la uniformidad.

Patrones de almacenamiento de datos en Kubernetes

En un enfoque típico de contenedores con estado, todos los pods de aplicaciones están conectados a un único sistema de archivos distribuido, una especie de almacenamiento compartido donde residen todos los datos de la aplicación. Si bien son posibles algunas variaciones, este es un enfoque de alto nivel.

Ahora veamos por qué un enfoque con estado y en contenedores es un antipatrón en un mundo centrado en la nube.

Diseño de aplicaciones basadas en la nube

Tradicionalmente, las aplicaciones utilizaban 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 hablaba demasiado, lo que generaba una sobrecarga significativa y, en última instancia, impedía que la aplicación avanzara a escalas realmente grandes.

Básicamente, esto contribuyó al surgimiento de un nuevo estándar de almacenamiento de datos, es decir, almacenamientos basados ​​en la nube que funcionan principalmente sobre la base de la API REST y liberan a la aplicación del engorroso mantenimiento del almacenamiento de datos local. En este caso, la aplicación realmente pasa al modo sin estado (porque el estado está en almacenamiento remoto). Las aplicaciones modernas se crean desde cero 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 construye según un paradigma orientado a la nube, donde el estado se transfiere a un sistema de software especialmente dedicado para su almacenamiento.

¡El enfoque del contenedor con estado hace que todo este paradigma vuelva exactamente a donde comenzó!

Cuando se utilizan las interfaces POSIX para almacenar datos, las aplicaciones se comportan como si tuvieran estado y, debido a esto, se desvían de los principios más importantes del diseño centrado en la nube, es decir, la capacidad de variar el tamaño de los subprocesos de trabajo de la aplicación dependiendo del carga de entrada, moverse a un nuevo nodo tan pronto como el nodo actual falle, y así sucesivamente.

Si analizamos más de cerca esta situación, encontramos que al elegir un almacén de datos, nos enfrentamos una y otra vez al dilema de "POSIX versus REST API", PERO con la exacerbación adicional de los problemas de POSIX debido a la naturaleza distribuida de los entornos de Kubernetes. En particular,

  • POSIX hablador: La semántica POSIX requiere que se asocien metadatos y descriptores de archivos con cada operación para ayudar a mantener el estado de la operación. Esto genera costes importantes que no tienen valor real. Las API de almacenamiento de objetos, específicamente la API de S3, eliminaron estos requisitos, permitiendo que la aplicación se activara y luego "olvidara" la llamada. La respuesta del sistema de almacenamiento indica si la acción fue exitosa o no. Si no tiene éxito, la aplicación puede intentarlo nuevamente.
  • Restricciones de red: En un sistema distribuido, se entiende que puede haber varias aplicaciones intentando escribir datos en el mismo medio adjunto. Por lo tanto, no sólo las aplicaciones competirán entre sí por el ancho de banda de transferencia de datos (para enviar datos a los medios), sino que el propio sistema de almacenamiento competirá por este ancho de banda, enviando datos a través de discos físicos. Debido a la locuacidad de POSIX, el número de llamadas a la red crece varias veces. Por otro lado, la API de S3 proporciona una distinción clara entre las llamadas de red que provienen del cliente al servidor y las que ocurren dentro del servidor.
  • seguridad: El modelo de seguridad POSIX está diseñado para la participación humana activa: los administradores configuran niveles de acceso específicos para cada usuario o grupo. Es difícil adaptar un paradigma así a un mundo centrado en la nube. Las aplicaciones modernas dependen de modelos de seguridad basados ​​en API, donde los derechos de acceso se definen como un conjunto de políticas, se asignan cuentas de servicio, credenciales temporales, etc.
  • Manejabilidad: Los contenedores con estado tienen cierta sobrecarga de gestión. Se trata de sincronizar el acceso a datos paralelos, de garantizar la coherencia de los datos; todo esto requiere una consideración cuidadosa de qué patrones de acceso a datos utilizar. Debe instalar, administrar y configurar software adicional, sin mencionar el esfuerzo de desarrollo adicional.

Interfaz de contenedor de almacén de datos

Si bien la interfaz de almacenamiento de datos en contenedores (CSI) hizo un gran trabajo al ayudar a propagar la capa de volumen de Kubernetes, descargándola en parte a proveedores de almacenamiento de datos de terceros, también contribuyó inadvertidamente a la creencia de que el enfoque de contenedor con estado es 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 a aplicaciones heredadas cuando se trabaja con Kubernetes. Y, como ha demostrado este artículo, la única situación en la que un enfoque de contenedor con estado (y CSI en su forma actual) tiene sentido es cuando la aplicación en sí es un sistema heredado donde no es posible agregar soporte para la API de almacenamiento de objetos.

Es importante entender que usando CSI en su forma actual, es decir, montando volúmenes en aplicaciones modernas, nos encontraremos con problemas similares a los que tenemos en sistemas donde los datos están organizados en el estilo POSIX.

Un mejor enfoque

En este caso, es importante comprender que la mayoría de las aplicaciones no están inherentemente diseñadas específicamente para trabajo con o sin estado. Este comportamiento depende de la arquitectura general del sistema y de las opciones específicas elegidas durante el diseño. Hablemos un poco de 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 (objetos binarios grandes)

Todos estos tipos de datos están muy bien soportados en las plataformas de almacenamiento actuales y existen varias plataformas nativas de la nube disponibles 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 contenedores o los datos de blobs se pueden almacenar en un registro acoplable basado en MinIO. Los datos de marca de tiempo se pueden almacenar en una base de datos de series de tiempo como InfluxDB, etc. No entraremos aquí en detalles de cada tipo de datos y sus respectivas aplicaciones, pero la idea general es evitar el almacenamiento de datos persistente basado en discos de montaje local.

Patrones de almacenamiento de datos en Kubernetes

Además, suele ser eficaz proporcionar una capa de caché temporal que sirva como una especie de depósito de archivos temporales para las aplicaciones, pero las aplicaciones no deberían depender de esta capa como fuente de información.

Almacenamiento para 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 (como bases de datos, almacenes de objetos, almacenes de claves y valores) deben tener estado. Veamos por qué estas aplicaciones se implementan en Kubernetes. Tomemos MinIO como ejemplo, pero se aplican principios similares a cualquier otro gran sistema de almacenamiento basado en la nube.

Las aplicaciones nativas de la nube están diseñadas para aprovechar 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 suficiente resiliencia para mantenerlo funcionando incluso si la mitad de los discos fallan. MinIO también gestiona la integridad y seguridad de los datos utilizando su propio hash y cifrado del lado del servidor.

Para estas aplicaciones nativas de la nube, los volúmenes persistentes locales (PV) son el almacenamiento de respaldo más útil. Un PV local brinda la capacidad de almacenar datos sin procesar, mientras que las aplicaciones que se ejecutan sobre estos PV recopilan información por sí mismas para escalar los datos y gestionar las crecientes demandas de datos.

Este enfoque es mucho más simple y escalable que los PV basados ​​en CSI, que introducen sus propios niveles de gestión de datos y redundancia en el sistema; El punto es que estas capas tienden a entrar en conflicto con las aplicaciones con estado.

Avanzando constantemente hacia el desacoplamiento de los datos de la informática

En este artículo, hablamos sobre cómo las aplicaciones se reorientan para que funcionen sin estado o, en otras palabras, el almacenamiento de datos está delimitado de la computación en ellas. En conclusión, veamos algunos ejemplos reales de tal tendencia.

Spark, la famosa plataforma de análisis de datos, tradicionalmente ha tenido estado y se ha implementado en el sistema de archivos HDFS. Sin embargo, a medida que Spark pasa a un mundo centrado en la nube, esta plataforma se utiliza cada vez más sin estado utilizando `s3a`. Spark usa s3a para pasar el estado a otros sistemas, mientras que los contenedores Spark se ejecutan completamente sin estado. Otros grandes actores empresariales en el campo del análisis de big data, en particular, vertical, Teradata, Ciruela verde Continúe también trabajando con la separación del almacenamiento de datos y los cálculos sobre ellos.

También se pueden ver patrones similares en otras plataformas analíticas importantes, incluidas Presto, Tensorflow to R, Jupyter. Al descargar el estado a sistemas remotos de almacenamiento en la nube, resulta mucho más fácil administrar y escalar su aplicación. Además, contribuye a la portabilidad de la aplicación en una variedad de entornos.

Fuente: habr.com

Añadir un comentario