Operador de kubernetes de Tarantool



Kubernetes se está convirtiendo en el estándar de facto para ejecutar aplicaciones sin estado. Principalmente porque puede reducir significativamente el tiempo de comercialización para la entrega de nuevas funciones. El lanzamiento de aplicaciones con estado (bases de datos, microservicios con estado) sigue siendo una tarea difícil, pero la necesidad de resistir la competencia y mantener una alta tasa de entrega empuja a las empresas a experimentar en esta área y crea una demanda de tales soluciones.

Le presentamos nuestra solución para el lanzamiento de clústeres con estado . Cartucho de Tarantool : Operador de Tarantool Kubernetes , para obtener más detalles, pido en cat.

Tabla de contenido:

  1. En lugar de mil palabras
  2. ¿Qué hace el operador?
  3. Un poco sobre los matices.
  4. Cómo funciona el operador
  5. Lo que el operador expande
  6. Resumen


Tarantool es una base de datos de código abierto y un servidor de aplicaciones en un solo paquete. Como base de datos, tiene una serie de características únicas: alta eficiencia de utilización de hierro, esquema de datos flexible, soporte para almacenamiento en disco y en memoria, y la posibilidad de expansión mediante el uso del lenguaje Lua. Como servidor de aplicaciones, le permite mover el código de la aplicación lo más cerca posible de los datos, al tiempo que logra un tiempo de respuesta mínimo y un rendimiento máximo. Además, Tarantool tiene un extenso ecosistema , que proporciona módulos listos para resolver problemas de aplicación: fragmentación , cola , módulos para facilitar el desarrollo ( cartucho , luatest ), soluciones para la operación ( métrica , ansible ): estos son solo algunos ejemplos.

Por todos sus méritos, las posibilidades de una instancia de Tarantool no son ilimitadas: para almacenar terabytes de datos y procesar millones de solicitudes, debe generar decenas y cientos de instancias, y este es un sistema distribuido con todos sus problemas inherentes. Para resolverlos, tenemos Tarantool Cartridge , un marco cuya tarea principal es ocultar todo tipo de dificultades para escribir aplicaciones distribuidas y permitir a los desarrolladores centrarse en el valor comercial de la aplicación. Cartridge proporciona un poderoso conjunto de componentes para la organización automática de clústeres, distribución automática de datos, webui para operación y herramientas de desarrollo.

Tarantool no es solo tecnología, sino también un equipo de ingenieros que se dedican al desarrollo de sistemas empresariales llave en mano, soluciones de caja y soporte para componentes de código abierto.

A nivel mundial, nuestras tareas se pueden dividir en dos áreas: el desarrollo de nuevos sistemas y el aumento de las soluciones existentes. Por ejemplo, hay una gran base de un vendedor famoso. Para escalarlo para leer, pusieron un caché finalmente consistente en Tarantool detrás de él. O viceversa: para escalar la grabación, ponen Tarantool en la configuración frío / calor, donde a medida que se "enfrían" los datos se vuelcan al almacenamiento en frío y en paralelo a la cola de análisis. O para realizar una copia de seguridad de un sistema existente, se escribe una versión ligera de este sistema (reserva funcional), que reserva el principal "activo" con la replicación de datos del sistema principal. Se puede encontrar más información en los informes de T + 2019 .

Todos estos sistemas tienen una cosa en común: son bastante difíciles de operar. Implemente rápidamente un clúster de más de 100 instancias con redundancia en 3 centros de datos, actualice una aplicación que almacene datos sin tiempo de inactividad y reducciones de mantenimiento, realice una restauración de respaldo en caso de catástrofe o errores provocados por el hombre, garantice una conmutación por error discreta de los componentes, organice la administración de la configuración ... En general, hay mucho interesante

Y sería genial si todo esto se operara tan simplemente como se está desarrollando. Kubernetes hace posible lograr el resultado deseado, pero el uso de un operador especializado facilita aún más la vida.

En lugar de mil palabras


Hemos preparado un pequeño ejemplo basado en el cartucho de Tarantool, y trabajaremos con él. Una aplicación simple como "almacenamiento de valor clave distribuido con interfaz HTTP". Después del lanzamiento, obtenemos esta imagen:



Donde:

  • Enrutadores: la parte del clúster responsable de aceptar y procesar las solicitudes HTTP entrantes;
  • Los almacenamientos son la parte del clúster que es responsable del almacenamiento y el procesamiento de datos, 3 fragmentos se levantan de la caja, en cada maestro y réplica.

Para equilibrar el tráfico HTTP entrante en los enrutadores, se utiliza el Ingreso Kubernetian. Los datos se distribuyen en el almacenamiento al nivel de Tarantool utilizando el componente vshard .

Necesitamos kubernetes 1.14+, minikube funcionará . Además, la disponibilidad de kubectl no afectará. Para iniciar el operador, debe crear una cuenta de servicio, rol y enlace de rol para él:

$ kubectl create -f https://raw.githubusercontent.com/tarantool/tarantool-operator/0.0.1/deploy/service_account.yaml $ kubectl create -f https://raw.githubusercontent.com/tarantool/tarantool-operator/0.0.1/deploy/role.yaml $ kubectl create -f https://raw.githubusercontent.com/tarantool/tarantool-operator/0.0.1/deploy/role_binding.yaml 

Tarantool Operator extiende la API de Kubernetes con sus definiciones de recursos, las crearemos:

 $ kubectl create -f https://raw.githubusercontent.com/tarantool/tarantool-operator/0.0.1/deploy/crds/tarantool_v1alpha1_cluster_crd.yaml $ kubectl create -f https://raw.githubusercontent.com/tarantool/tarantool-operator/0.0.1/deploy/crds/tarantool_v1alpha1_role_crd.yaml $ kubectl create -f https://raw.githubusercontent.com/tarantool/tarantool-operator/0.0.1/deploy/crds/tarantool_v1alpha1_replicasettemplate_crd.yaml 

Todo está listo para lanzar el operador, vamos:

 $ kubectl create -f https://raw.githubusercontent.com/tarantool/tarantool-operator/0.0.1/deploy/operator.yaml 

Estamos esperando que comience el operador y podemos proceder a iniciar la aplicación:

 $ kubectl create -f https://raw.githubusercontent.com/tarantool/tarantool-operator/0.0.1/examples/kv/deployment.yaml 

En el archivo yaml con el ejemplo, Ingress se declara en la interfaz de usuario web; Está disponible en cluster_ip/admin/cluster . Cuando al menos un Pod de Ingress está activo, puede ir allí y ver cómo se agregan nuevas instancias al clúster y cómo cambia su topología.

Estamos esperando que se use el clúster:

 $ kubectl describe clusters.tarantool.io examples-kv-cluster 

Esperamos que en el estado del clúster haya lo siguiente:

 … Status: State: Ready … 

¡Todo, la aplicación está lista para usar!

¿Necesitas más espacio de almacenamiento? Agregar fragmentos:

 $ kubectl scale roles.tarantool.io storage --replicas=3 

Los fragmentos no pueden hacer frente a la carga? Aumente el número de instancias en el fragmento editando la plantilla de conjunto de réplicas:

 $ kubectl edit replicasettemplates.tarantool.io storage-template 

Establezca .spec.replicas , por ejemplo 2, para aumentar el número de instancias en cada conjunto de réplicas a dos.

¿Ya no se necesita un clúster? Lo eliminamos junto con todos los recursos:

 $ kubectl delete clusters.tarantool.io examples-kv-cluster 

¿Algo salió mal? Marque el boleto , lo desmontaremos rápidamente. :)

¿Qué hace el operador?


El lanzamiento y la operación del clúster de cartucho de Tarantool es la historia de realizar ciertas acciones, en un orden específico, en un momento determinado.

El clúster en sí se administra principalmente a través de la API de administración: GraphQL sobre HTTP. Por supuesto, puede bajar un nivel y dirigir los comandos directamente a la consola, pero esto rara vez sucede. Por ejemplo, así es como se inicia el clúster:

  1. Elevamos el número requerido de instancias de Tarantool, por ejemplo, en systemd.
  2. Fusionar instancias en membresía:

     mutation { probe_instance: probe_server(uri: "storage:3301") } 

  3. Asigne roles a instancias, prescriba identificadores de instancias y conjuntos de réplicas. La API GraphQL también se usa para esto:

     mutation { join_server( uri:"storage:3301", instance_uuid: "cccccccc-cccc-4000-b000-000000000001", replicaset_uuid: "cccccccc-0000-4000-b000-000000000000", roles: ["storage"], timeout: 5 ) } 

  4. Realizamos bootstrap del componente responsable del fragmentación. También a través de la API:

     mutation { bootstrap_vshard cluster { failover(enabled:true) } } 


Fácil, verdad?

Todo se vuelve más interesante cuando se trata de expandir un clúster. La función de los enrutadores del ejemplo se escala simplemente: generar más instancias, conectarlas a un clúster existente: ¡ya está! El papel de los almacenes es algo más complicado. El almacenamiento está fragmentado, por lo que al agregar / eliminar instancias, es necesario reequilibrar los datos para pasar a nuevas instancias / para pasar de instancias eliminadas. Si esto no se hace, entonces en un caso tenemos instancias subcargadas, en el segundo, perdemos datos. ¿Y si no solo uno, sino una docena de clústeres con diferentes topologías en funcionamiento?

En general, el operador de Tarantool está ocupado con todo esto. El usuario describe el estado deseado del clúster de cartucho de Tarantool, y el operador lo traduce en un conjunto de acciones en los recursos de k8s y en ciertas llamadas a las API del panel de administración del clúster de Tarantool, en un orden específico, en un momento determinado, y generalmente intenta ocultar todos los matices del usuario.

Un poco sobre los matices.


Cuando se trabaja con la API del clúster de administración de Tarantool Cartridge, es importante tanto el orden de las llamadas como el lugar de donde provienen. Por qué

Tarantool Cartridge lleva su repositorio de topología, su componente de descubrimiento de servicios y su componente de configuración. Cada instancia del clúster almacena una copia de la topología y la configuración en un archivo yaml.

 servers: d8a9ce19-a880-5757-9ae0-6a0959525842: uri: storage-2-0.examples-kv-cluster:3301 replicaset_uuid: 8cf044f2-cae0-519b-8d08-00a2f1173fcb 497762e2-02a1-583e-8f51-5610375ebae9: uri: storage-0-0.examples-kv-cluster:3301 replicaset_uuid: 05e42b64-fa81-59e6-beb2-95d84c22a435 … vshard: bucket_count: 30000 ... 

La actualización ocurre en concierto usando el mecanismo de confirmación de dos fases . Una actualización exitosa requiere un quórum del 100%: cada instancia debe responder, de lo contrario, retroceder. ¿Qué significa esto en términos de operación? Todas las solicitudes a la API de administrador que modifican el estado del clúster son más confiables para enviar a una instancia, al líder, de lo contrario corremos el riesgo de obtener diferentes configuraciones en diferentes instancias. Tarantool Cartridge no sabe cómo hacer una elección de líder (pero no sabe cómo), pero el operador de Tarantool sí puede, y usted solo puede saberlo como un hecho entretenido, porque el operador lo arruinará todo.

Además, cada instancia debe tener una identidad fija, es decir, un conjunto de instance_uuid y replicaset_uuid , así como advertise_uri . Si el almacenamiento se reinicia repentinamente y uno de estos parámetros cambia, entonces corre el riesgo de romper el quórum; el operador también lo hace.

Cómo funciona el operador


La tarea del operador es llevar el sistema al estado establecido por el usuario y mantener el sistema en este estado hasta que se reciban nuevas instrucciones. Para que el operador pueda llevar a cabo su trabajo, necesita:

  1. Descripción del estado del sistema.
  2. El código que lleva al sistema a este estado.
  3. Un mecanismo para integrar este código en k8 (por ejemplo, para recibir notificaciones de cambios de estado).

El grupo de cartuchos de Tarantool se describe en términos de k8 a través de una Definición de recursos personalizados (CRD) ; el operador necesita 3 de estos recursos personalizados, unidos bajo el grupo tarantool.io/v1alpha:

  • El clúster es un recurso de nivel superior que corresponde a un clúster de cartucho de Tarantool.
  • Rol: en términos de cartucho de Tarantool, este es un rol de usuario .
  • ReplicasetTemplate: una plantilla mediante la cual se crearán StatefulSets (por qué con estado: te lo diré un poco más tarde; no debes confundirlo con k8s ReplicaSet).

Todos estos recursos reflejan directamente el modelo de descripción del clúster de cartucho de Tarantool. Al tener un diccionario común, es más fácil para un operador comunicarse con los desarrolladores y comprender lo que quieren ver en el producto.

El código que lleva el sistema al estado dado: en términos de k8, este es el controlador. En el caso del operador Tarantool, hay varios controladores:

  • ClusterController: es responsable de interactuar con el clúster de cartucho de Tarantool, conecta instancias al clúster, desconecta instancias del clúster.
  • RoleController es un controlador de roles de usuario, es responsable de implementar StatefulSets desde una plantilla y mantener su número en un número determinado.

¿Cómo es un controlador? Un conjunto de códigos que gradualmente pone en orden el mundo que te rodea. ClusterController se puede representar esquemáticamente de esta manera:



Un punto de entrada es una verificación para ver si existe un recurso Cluster con respecto al cual ocurrió el evento. No existe? Nos vamos ¿Hay? Pasamos al siguiente bloque: tomar la propiedad sobre los roles de los usuarios. Capturado uno - izquierda, en el segundo círculo capturamos el segundo. Y así sucesivamente, hasta que capturemos todo. ¿Se capturan todos los roles? Así que ve al siguiente bloque de operaciones. Y así, hasta llegar al final; entonces podemos suponer que el sistema controlado está en un estado dado.

En general, todo es simple. Es importante determinar los criterios de éxito para pasar cada etapa. Por ejemplo, consideramos exitosa la operación de unir un clúster no cuando devuelve éxito condicional = verdadero, sino cuando devuelve un error como "ya se unió".

Y la última parte de este mecanismo es la integración del controlador con k8s. Vista aérea, todo el k8 consiste en un conjunto de controladores que generan eventos y responden a ellos. Los eventos pasan por colas a las que podemos suscribirnos. Esquemáticamente, esto se puede representar de la siguiente manera:



El usuario llama a kubectl create -f tarantool_cluster.yaml , se crea el recurso Cluster correspondiente. ClusterController es notificado de la creación de un recurso Cluster. Y lo primero que intenta hacer es encontrar todos los recursos de rol que deberían formar parte de este clúster. Si encuentra, asigna el Clúster como Propietario para el Rol y actualiza el recurso del Rol. RoleController recibe una notificación de actualización de roles, ve que el recurso tiene un propietario y comienza a crear StatefulSets. Y así sucesivamente en un círculo: el primer tirador del segundo, el segundo tirador del tercero, y así sucesivamente hasta que alguien se detenga. Y también puede disparar a tiempo, por ejemplo, cada 5 segundos, lo que a veces es útil.

Ese es todo el operador: crear un recurso personalizado y escribir código que responda a eventos en los recursos.

Lo que el operador expande


Las acciones del operador finalmente conducen a que los k8 creen Pods y contenedores. En el clúster de cartucho de Tarantool implementado en k8s, todos los pods se fusionan en StatefulSets.

¿Por qué StatefulSet? Como escribí anteriormente, cada instancia de Tarantool Cluster mantiene una copia de la topología y la configuración del clúster, y a menudo en el servidor de aplicaciones no, no, y usan algún tipo de espacio, por ejemplo, a su vez o datos de referencia, y esto ya es un estado completo . Y StatefulSet también garantiza la preservación de los pods de identidad, lo cual es importante cuando se agrupan instancias en un clúster: la identidad de las instancias debe repararse; de ​​lo contrario, corremos el riesgo de perder el quórum al reiniciar.

Cuando todos los recursos del clúster se crean y se llevan al estado deseado, forman la siguiente jerarquía:



Las flechas indican la relación dependiente del propietario entre los recursos. Es necesario que el recolector de basura limpie después de nosotros en el caso de, por ejemplo, la eliminación de Cluster.

Además de StatefulSets, el operador de Tarantool crea el servicio sin cabeza, que es necesario para la elección del líder y, a través de él, las instancias se comunican entre sí.

Bajo el capó del operador de Tarantool se encuentra el marco del operador, el código del operador en sí está en golang, nada extraordinario aquí.

Resumen


¡Eso es todo, en general! Estamos esperando sus comentarios y boletos, donde sin ellos, la versión alfa es la misma. Que sigue Y luego hay mucho trabajo para recordar todo esto:

  • Unidad, prueba E2E;
  • Prueba del mono del caos
  • prueba de esfuerzo;
  • copia de seguridad / restauración;
  • proveedor de topología externo.

Cada uno de estos temas es extenso en sí mismo y merece un material separado, ¡espere actualizaciones!

Source: https://habr.com/ru/post/465823/


All Articles