Nuestra experiencia en el desarrollo de un controlador CSI en Kubernetes para Yandex.Cloud

Nuestra experiencia en el desarrollo de un controlador CSI en Kubernetes para Yandex.Cloud

Nos complace anunciar que Flant está ampliando su contribución a las herramientas de código abierto para Kubernetes con el lanzamiento versión alfa del controlador CSI (Interfaz de almacenamiento de contenedores) para Yandex.Cloud.

Pero antes de pasar a los detalles de la implementación, respondamos la pregunta de por qué es necesario cuando Yandex ya tiene un servicio. Servicio gestionado para Kubernetes.

introducción

Porque es esto

Dentro de nuestra empresa, desde el comienzo del uso de Kubernetes en producción (es decir, desde hace varios años), hemos estado desarrollando nuestra propia herramienta (deckhouse), que, por cierto, también planeamos poner a disposición pronto como un proyecto de código abierto. . Con su ayuda, configuramos y configuramos de manera uniforme todos nuestros clústeres, y actualmente ya hay más de 100, en una amplia variedad de configuraciones de hardware y en todos los servicios en la nube disponibles.

Los clusters que utilizan deckhouse tienen todos los componentes necesarios para su funcionamiento: balanceadores, monitoreo con gráficos, métricas y alertas convenientes, autenticación de usuarios a través de proveedores externos para acceder a todos los paneles, etc. No tiene sentido instalar un clúster tan "mejorado" en una solución administrada, ya que esto a menudo es imposible o conducirá a la necesidad de desactivar la mitad de los componentes.

NB: Esta es nuestra experiencia y es bastante específica. De ninguna manera estamos sugiriendo que todos deban implementar clústeres de Kubernetes por su cuenta en lugar de utilizar soluciones listas para usar. Por cierto, no tenemos experiencia real en el funcionamiento de Kubernetes desde Yandex y no daremos ninguna valoración de este servicio en este artículo.

¿Qué es y para quién?

Entonces, ya hemos hablado sobre el enfoque moderno del almacenamiento en Kubernetes: ¿Cómo funciona CSI? и cómo surgió la comunidad a este enfoque.

Actualmente, muchos grandes proveedores de servicios en la nube han desarrollado controladores para utilizar sus discos en la nube como volumen persistente en Kubernetes. Si el proveedor no tiene dicho controlador, pero todas las funciones necesarias se proporcionan a través de la API, nada le impide implementar el controlador usted mismo. Esto es lo que pasó con Yandex.Cloud.

Tomamos como base para el desarrollo. Controlador CSI para la nube DigitalOcean y un par de ideas de controladores para GCP, ya que la interacción con la API de estas nubes (Google y Yandex) tiene varias similitudes. En particular, la API y GCPy tu Yandex devolver un objeto Operation para rastrear el estado de operaciones de larga duración (por ejemplo, crear un nuevo disco). Para interactuar con la API Yandex.Cloud, utilice SDK de Yandex.Cloud Go.

El resultado del trabajo realizado publicado en GitHub y puede ser útil para aquellos que, por alguna razón, usan su propia instalación de Kubernetes en máquinas virtuales Yandex.Cloud (pero no en un clúster administrado ya preparado) y les gustaría usar (pedir) discos a través de CSI.

implementación

Características principales

Actualmente el controlador admite las siguientes funciones:

  • Ordenar discos en todas las zonas del clúster según la topología de los nodos del clúster;
  • Extracción de discos pedidos previamente;
  • Cambio de tamaño de discos sin conexión (Yandex.Cloud no es compatible aumentando los discos que están montados en la máquina virtual). Para obtener información sobre cómo se tuvo que modificar el controlador para que el cambio de tamaño sea lo más sencillo posible, consulte a continuación.

En el futuro, planeamos implementar soporte para crear y eliminar instantáneas de disco.

La principal dificultad y cómo superarla.

La falta de capacidad de aumentar los discos en tiempo real en la API de Yandex.Cloud es una limitación que complica la operación de cambio de tamaño para PV (Volumen Persistente): en este caso, es necesario detener el pod de la aplicación que utiliza el disco. y esto puede causar aplicaciones de tiempo de inactividad.

según Especificaciones CSI, si el controlador CSI informa que puede cambiar el tamaño de los discos sólo "sin conexión" (VolumeExpansion.OFFLINE), entonces el proceso de aumentar el disco debería ser así:

Si el complemento solo tiene VolumeExpansion.OFFLINE La capacidad de expansión y el volumen están actualmente publicados o disponibles en un nodo. ControllerExpandVolume DEBE ser llamado SÓLO después de:

  • El complemento tiene controlador. PUBLISH_UNPUBLISH_VOLUME Capacidad y ControllerUnpublishVolume ha sido invocado exitosamente.

SI NO

  • El complemento NO tiene controlador PUBLISH_UNPUBLISH_VOLUME capacidad, el complemento tiene nodo STAGE_UNSTAGE_VOLUME capacidad, y NodeUnstageVolume Se ha completado con éxito.

SI NO

  • El complemento NO tiene controlador PUBLISH_UNPUBLISH_VOLUME capacidad, ni nodo STAGE_UNSTAGE_VOLUME capacidad, y NodeUnpublishVolume se ha completado con éxito.

Básicamente, esto significa que debe desconectar el disco de la máquina virtual antes de expandirlo.

Sin embargo, lamentablemente implementación La especificación CSI mediante sidecars no cumple estos requisitos:

  • En un contenedor con sidecar csi-attacher, que debería ser responsable de la presencia del espacio requerido entre los montajes, esta funcionalidad simplemente no está implementada en el cambio de tamaño fuera de línea. Se inició una discusión sobre esto. aquí.
  • ¿Qué es exactamente un contenedor sidecar en este contexto? El complemento CSI en sí no interactúa con la API de Kubernetes, solo responde a las llamadas gRPC que le envían los contenedores sidecar. El último siendo desarrollado por la comunidad de Kubernetes.

En nuestro caso (complemento CSI), la operación de aumentar el disco se ve así:

  1. Recibimos una llamada de gRPC ControllerExpandVolume;
  2. Estamos intentando aumentar el disco en la API, pero recibimos un error sobre la imposibilidad de realizar la operación porque el disco está montado;
  3. Almacenamos el identificador del disco en el mapa, que contiene los discos para los cuales se debe realizar la operación de aumento. A continuación, por brevedad, llamaremos a este mapa como volumeResizeRequired;
  4. Retire manualmente el pod que está utilizando el disco. Kubernetes lo reiniciará. Para que el disco no tenga tiempo de montarse (ControllerPublishVolume) antes de completar la operación de aumento al intentar montar, verificamos que el disco dado todavía esté en volumeResizeRequired y devolver un error;
  5. El controlador CSI intenta volver a ejecutar la operación de cambio de tamaño. Si la operación fue exitosa, retire el disco de volumeResizeRequired;
  6. Porque Falta el ID del disco volumeResizeRequired, ControllerPublishVolume pasa con éxito, el disco está montado y el pod se inicia.

Todo parece bastante sencillo, pero, como siempre, hay trampas. Agranda discos redimensionador externo, que en caso de error durante la operación usa una cola con un aumento exponencial del tiempo de espera de hasta 1000 segundos:

func DefaultControllerRateLimiter() RateLimiter {
  return NewMaxOfRateLimiter(
  NewItemExponentialFailureRateLimiter(5*time.Millisecond, 1000*time.Second),
  // 10 qps, 100 bucket size.  This is only for retry speed and its only the overall factor (not per item)
  &BucketRateLimiter{Limiter: rate.NewLimiter(rate.Limit(10), 100)},
  )
}

Esto puede provocar periódicamente que la operación de expansión del disco se extienda por más de 15 minutos y, por lo tanto, que el pod correspondiente no esté disponible.

La única opción que nos permitió reducir el posible tiempo de inactividad de manera bastante fácil y sin complicaciones fue el uso de nuestra versión de cambio de tamaño externo con un límite máximo de tiempo de espera. en 5 segundos:

workqueue.NewItemExponentialFailureRateLimiter(5*time.Millisecond, 5*time.Second)

No consideramos necesario iniciar una discusión urgente y parchear el redimensionador externo, porque el redimensionamiento de discos sin conexión es un retroceso que pronto desaparecerá de todos los proveedores de la nube.

¿Cómo empezar a usarlo?

El controlador es compatible con Kubernetes versión 1.15 y superiores. Para que el conductor pueda trabajar se deben cumplir los siguientes requisitos:

  • Bandera --allow-privileged establecer en valor true para servidor API y kubelet;
  • Incluido --feature-gates=VolumeSnapshotDataSource=true,KubeletPluginsWatcher=true,CSINodeInfo=true,CSIDriverRegistry=true para servidor API y kubelet;
  • Propagación de montaje (propagación de montaje) debe estar habilitado en el clúster. Cuando se utiliza Docker, el demonio debe configurarse para permitir montajes compartidos.

Todos los pasos necesarios para la propia instalación. descrito en LÉAME. La instalación implica la creación de objetos en Kubernetes a partir de manifiestos.

Para que el controlador funcione necesitarás lo siguiente:

  • Especifique el identificador del directorio en el manifiesto (folder-id) Yandex.Cloud (ver documentación);
  • Para interactuar con la API Yandex.Cloud, el controlador CSI utiliza una cuenta de servicio. En el manifiesto, se debe pasar el secreto. claves autorizadas de la cuenta de servicio. en la documentacion descrito, cómo crear una cuenta de servicio y obtener claves.

Considerándolo todo - Intentar, y estaremos encantados de recibir comentarios y nuevos problemassi encuentra algún problema!

Soporte adicional

Como resultado, nos gustaría señalar que implementamos este controlador CSI no por un gran deseo de divertirnos escribiendo aplicaciones en Go, sino por una necesidad urgente dentro de la empresa. No nos parece práctico mantener nuestra propia implementación, por lo que si Yandex muestra interés y decide continuar brindando soporte al controlador, estaremos encantados de transferirles el repositorio.

Además, Yandex probablemente tenga su propia implementación del controlador CSI en su clúster Kubernetes administrado, que puede lanzarse en código abierto. También consideramos favorable esta opción de desarrollo: la comunidad podrá utilizar un controlador probado de un proveedor de servicios y no de una empresa externa.

PS

Lea también en nuestro blog:

Fuente: habr.com

Añadir un comentario