A nosa experiencia no desenvolvemento dun controlador CSI en Kubernetes para Yandex.Cloud

A nosa experiencia no desenvolvemento dun controlador CSI en Kubernetes para Yandex.Cloud

Temos o pracer de anunciar que Flant está ampliando a súa contribución ás ferramentas de código aberto para Kubernetes lanzando versión alfa do controlador CSI (Interface de almacenamento de contedores) para Yandex.Cloud.

Pero antes de pasar aos detalles da implementación, imos responder á pregunta de por que isto é necesario cando Yandex xa ten un servizo Servizo xestionado para Kubernetes.

Introdución

Por que isto?

Dentro da nosa empresa, dende o inicio do uso de Kubernetes na produción (é dicir, dende hai varios anos), estivemos desenvolvendo a nosa propia ferramenta (deckhouse), que, por certo, tamén pensamos poñer a disposición en breve como proxecto de código aberto. . Coa súa axuda, configuramos e configuramos de forma uniforme todos os nosos clústeres, e actualmente xa son máis de 100, nunha gran variedade de configuracións de hardware e en todos os servizos na nube dispoñibles.

Os clústeres que utilizan deckhouse teñen todos os compoñentes necesarios para o seu funcionamento: equilibradores, monitorización con gráficos convenientes, métricas e alertas, autenticación de usuarios a través de provedores externos para o acceso a todos os paneis, etc. Non ten sentido instalar un clúster tan "bombado" nunha solución xestionada, xa que moitas veces é imposible ou levará á necesidade de desactivar a metade dos compoñentes.

NB: Esta é a nosa experiencia, e é bastante específica. De ningún xeito estamos suxerindo que todos deberían implementar clústeres de Kubernetes pola súa conta en lugar de utilizar solucións preparadas. Por certo, non temos experiencia real en operar Kubernetes desde Yandex e non valoraremos este servizo neste artigo.

Que é e para quen?

Entón, xa falamos do enfoque moderno do almacenamento en Kubernetes: como funciona CSI? и como chegou a comunidade a este enfoque.

Actualmente, moitos grandes provedores de servizos na nube desenvolveron controladores para usar os seus discos na nube como volume persistente en Kubernetes. Se o provedor non ten tal controlador, pero todas as funcións necesarias son proporcionadas a través da API, nada lle impide implementar o controlador por si mesmo. Isto é o que pasou con Yandex.Cloud.

Tomamos como base para o desenvolvemento Controlador CSI para DigitalOcean cloud e un par de ideas de controladores para GCP, xa que a interacción coa API destas nubes (Google e Yandex) ten unha serie de semellanzas. En particular, a API e GCP, e ás Yandex devolver un obxecto Operation para rastrexar o estado das operacións de longa duración (por exemplo, a creación dun novo disco). Para interactuar coa API de Yandex.Cloud, usa Yandex.Cloud Go SDK.

O resultado do traballo realizado publicado en GitHub e pode ser útil para aqueles que, por algún motivo, usan a súa propia instalación de Kubernetes en máquinas virtuais Yandex.Cloud (pero non un clúster xestionado preparado) e quere utilizar (pedir) discos a través de CSI.

Implantación

Características clave

Actualmente o controlador admite as seguintes funcións:

  • Ordenar discos en todas as zonas do clúster segundo a topoloxía dos nodos do clúster;
  • Eliminar discos previamente solicitados;
  • Cambiar o tamaño fóra de liña para os discos (Yandex.Cloud non admite aumentando os discos que se montan na máquina virtual). Para obter información sobre como se tivo que modificar o controlador para que o cambio de tamaño sexa o máis sinxelo posible, consulte a continuación.

No futuro, pensamos implementar compatibilidade para crear e eliminar instantáneas de disco.

A principal dificultade e como superala

A falta da capacidade de aumentar os discos en tempo real na API de Yandex.Cloud é unha limitación que complica a operación de cambio de tamaño para PV (Volumen persistente): neste caso, é necesario que se deteña o pod de aplicación que usa o disco, e isto pode provocar tempo de inactividade das aplicacións.

Conforme Especificacións de CSI, se o controlador CSI informa que só pode cambiar o tamaño dos discos "sen conexión" (VolumeExpansion.OFFLINE), entón o proceso de aumentar o disco debería ser así:

Se o complemento só ten VolumeExpansion.OFFLINE a capacidade de expansión e o volume está actualmente publicado ou dispoñible nun nodo ControllerExpandVolume DEBE chamarse SÓ despois de:

  • O complemento ten controlador PUBLISH_UNPUBLISH_VOLUME capacidade e ControllerUnpublishVolume invocouse con éxito.

OU MAIS

  • O complemento NON ten controlador PUBLISH_UNPUBLISH_VOLUME capacidade, o complemento ten un nodo STAGE_UNSTAGE_VOLUME capacidade, e NodeUnstageVolume completouse con éxito.

OU MAIS

  • O complemento NON ten controlador PUBLISH_UNPUBLISH_VOLUME capacidade, nin nodo STAGE_UNSTAGE_VOLUME capacidade, e NodeUnpublishVolume completouse con éxito.

Isto significa esencialmente que cómpre separar o disco da máquina virtual antes de expandilo.

Con todo, por desgraza implementación A especificación CSI a través de sidecars non cumpre estes requisitos:

  • Nun contedor sidecar csi-attacher, que debería ser responsable da presenza do espazo necesario entre as montaxes, esta funcionalidade simplemente non se implementa no cambio de tamaño fóra de liña. Iniciouse unha discusión sobre isto aquí.
  • Que é exactamente un contedor sidecar neste contexto? O complemento CSI en si non interactúa coa API de Kubernetes, senón que só responde ás chamadas gRPC que lle envían os contedores sidecar. Últimos están sendo desenvolvidos pola comunidade Kubernetes.

No noso caso (complemento CSI), a operación de aumentar o disco ten o seguinte aspecto:

  1. Recibimos unha chamada de gRPC ControllerExpandVolume;
  2. Estamos tentando aumentar o disco na API, pero recibimos un erro sobre a imposibilidade de realizar a operación porque o disco está montado;
  3. Almacenamos o identificador do disco no mapa, que contén os discos para os que se debe realizar a operación de aumento. A continuación, para brevidade, chamaremos a este mapa como volumeResizeRequired;
  4. Elimina manualmente o pod que está a usar o disco. Kubernetes reinicialo. Para que o disco non teña tempo de montar (ControllerPublishVolume) antes de completar a operación de aumento ao tentar montar, comprobamos que o disco indicado aínda está dentro volumeResizeRequired e devolver un erro;
  5. O controlador CSI tenta volver executar a operación de cambio de tamaño. Se a operación foi exitosa, elimine o disco de volumeResizeRequired;
  6. Porque Falta o ID do disco volumeResizeRequired, ControllerPublishVolume pasa con éxito, o disco está montado, o pod comeza.

Todo parece sinxelo, pero como sempre hai trampas. Amplía os discos redimensionador externo, que en caso de erro durante a operación usa unha cola cun aumento exponencial do tempo de espera ata 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)},
  )
}

Isto pode provocar periodicamente que a operación de expansión do disco se estenda durante máis de 15 minutos e, polo tanto, o pod correspondente non estea dispoñible.

A única opción que nos permitiu reducir con bastante facilidade e sen dor o tempo de inactividade potencial foi o uso da nosa versión de redimensionador externo cun límite máximo de tempo de espera. en 5 segundos:

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

Non consideramos necesario iniciar con urxencia unha discusión e parchear o redimensionador externo, porque o cambio de tamaño dos discos fóra de liña é un retroceso que pronto desaparecerá de todos os provedores de nube.

Como comezar a usalo?

O controlador é compatible con Kubernetes versión 1.15 ou superior. Para que o condutor poida traballar, deben cumprir os seguintes requisitos:

  • Bandeira --allow-privileged establecer en valor true para servidor API e kubelet;
  • Incluído --feature-gates=VolumeSnapshotDataSource=true,KubeletPluginsWatcher=true,CSINodeInfo=true,CSIDriverRegistry=true para servidor API e kubelet;
  • Propagación do monte (propagación do monte) debe estar activado no clúster. Cando se usa Docker, o daemon debe estar configurado para permitir montaxes compartidas.

Todos os pasos necesarios para a propia instalación descrito en README. A instalación implica crear obxectos en Kubernetes a partir de manifestos.

Para que o condutor funcione, necesitará o seguinte:

  • Especifique o identificador do directorio no manifesto (folder-id) Yandex.Cloud (ver documentación);
  • Para interactuar coa API de Yandex.Cloud, o controlador CSI usa unha conta de servizo. No manifesto secreto, debes pasar claves autorizadas desde a conta de servizo. Na documentación descrito, como crear unha conta de servizo e obter claves.

Todo en todo - probar, e estaremos encantados de recibir comentarios e novos temasse atopas algún problema!

Máis apoio

Como resultado, queremos sinalar que implementamos este controlador CSI non por un gran desexo de divertirnos escribindo aplicacións en Go, senón por unha necesidade urxente dentro da empresa. Non nos parece práctico manter a nosa propia implementación, polo que se Yandex mostra interese e decide seguir apoiando o controlador, estaremos encantados de transferirlles o repositorio.

Ademais, probablemente Yandex teña a súa propia implementación do controlador CSI no seu clúster Kubernetes xestionado, que se pode lanzar en código aberto. Tamén vemos que esta opción de desenvolvemento é favorable: a comunidade poderá utilizar un controlador comprobado dun provedor de servizos e non dunha empresa de terceiros.

PS

Lea tamén no noso blog:

Fonte: www.habr.com

Engadir un comentario