La nostra experiència en el desenvolupament d'un controlador CSI a Kubernetes per a Yandex.Cloud

La nostra experiència en el desenvolupament d'un controlador CSI a Kubernetes per a Yandex.Cloud

Ens complau anunciar que Flant està ampliant la seva contribució a les eines de codi obert per a Kubernetes llançant versió alfa del controlador CSI (Interfície d'emmagatzematge de contenidors) per a Yandex.Cloud.

Però abans de passar als detalls de la implementació, responem a la pregunta per què això és necessari quan Yandex ja té un servei. Servei gestionat per a Kubernetes.

Introducció

Per què és això?

Dins de la nostra empresa, des dels primers inicis d'utilitzar Kubernetes en producció (és a dir, des de fa uns quants anys), hem estat desenvolupant la nostra pròpia eina (deckhouse), que, per cert, també tenim previst posar a disposició aviat com a projecte de codi obert. . Amb la seva ajuda, configurem i configurem de manera uniforme tots els nostres clústers, i actualment ja n'hi ha més de 100, en una gran varietat de configuracions de maquinari i en tots els serveis al núvol disponibles.

Els clústers que utilitzen deckhouse tenen tots els components necessaris per al funcionament: equilibradors, monitorització amb gràfics convenients, mètriques i alertes, autenticació d'usuaris mitjançant proveïdors externs per accedir a tots els taulers, etc. No té sentit instal·lar un clúster d'aquest tipus en una solució gestionada, ja que sovint és impossible o comportarà la necessitat de desactivar la meitat dels components.

NB: Aquesta és la nostra experiència, i és força específica. De cap manera estem suggerint que tothom ha de desplegar els clústers de Kubernetes pel seu compte en lloc d'utilitzar solucions ja fetes. Per cert, no tenim experiència real en operar Kubernetes des de Yandex i no farem cap valoració d'aquest servei en aquest article.

Què és i per a qui?

Per tant, ja hem parlat de l'enfocament modern de l'emmagatzematge a Kubernetes: com funciona CSI? и com va arribar la comunitat a aquest plantejament.

Actualment, molts grans proveïdors de serveis al núvol han desenvolupat controladors per utilitzar els seus discs al núvol com a volum persistent a Kubernetes. Si el proveïdor no té aquest controlador, però totes les funcions necessàries es proporcionen mitjançant l'API, res no us impedeix implementar el controlador vosaltres mateixos. Això és el que va passar amb Yandex.Cloud.

Vam prendre com a base per al desenvolupament Controlador CSI per al núvol DigitalOcean i un parell d'idees de controladors per a GCP, ja que la interacció amb l'API d'aquests núvols (Google i Yandex) té una sèrie de similituds. En particular, l'API i GCP, i a Yandex retornar un objecte Operation per fer un seguiment de l'estat de les operacions de llarga durada (per exemple, la creació d'un disc nou). Per interactuar amb l'API Yandex.Cloud, utilitzeu Yandex.Cloud Go SDK.

El resultat de la feina feta опубликован a GitHub i pot ser útil per a aquells que, per algun motiu, utilitzen la seva pròpia instal·lació de Kubernetes a màquines virtuals Yandex.Cloud (però no un clúster gestionat preparat) i vulguin utilitzar (ordenar) discs mitjançant CSI.

Implementació

Característiques clau

Actualment, el controlador admet les funcions següents:

  • Ordenar discs a totes les zones del clúster segons la topologia dels nodes del clúster;
  • Eliminació de discs ordenats prèviament;
  • Canviar la mida fora de línia per als discos (Yandex.Cloud no donen suport augmentant els discs que es munten a la màquina virtual). Per obtenir informació sobre com s'ha hagut de modificar el controlador perquè el canvi de mida sigui el més fàcil possible, vegeu a continuació.

En el futur, tenim previst implementar suport per crear i suprimir instantànies de disc.

La principal dificultat i com superar-la

La manca de la capacitat d'augmentar els discs en temps real a l'API Yandex.Cloud és una limitació que complica l'operació de redimensionament per a PV (Volum persistent): en aquest cas, és necessari que el pod d'aplicació que utilitza el disc estigui aturat, i això pot provocar temps d'inactivitat de les aplicacions.

Segons Especificacions CSI, si el controlador CSI informa que només pot canviar la mida dels discs "fora de línia" (VolumeExpansion.OFFLINE), llavors el procés d'augment del disc hauria de ser així:

Si el connector només té VolumeExpansion.OFFLINE La capacitat i el volum d'expansió es publiquen actualment o estan disponibles en un node aleshores ControllerExpandVolume S'HA de trucar NOMÉS després de:

  • El connector té un controlador PUBLISH_UNPUBLISH_VOLUME capacitat i ControllerUnpublishVolume s'ha invocat correctament.

O SINO

  • El connector NO té controlador PUBLISH_UNPUBLISH_VOLUME capacitat, el connector té un node STAGE_UNSTAGE_VOLUME capacitat, i NodeUnstageVolume s'ha completat amb èxit.

O SINO

  • El connector NO té controlador PUBLISH_UNPUBLISH_VOLUME capacitat, ni node STAGE_UNSTAGE_VOLUME capacitat, i NodeUnpublishVolume s'ha completat amb èxit.

Això significa bàsicament que heu de desconnectar el disc de la màquina virtual abans d'ampliar-lo.

Tanmateix, malauradament implementació L'especificació CSI mitjançant sidecars no compleix aquests requisits:

  • En un contenidor sidecar csi-attacher, que hauria de ser responsable de la presència de l'espai necessari entre muntatges, aquesta funcionalitat simplement no s'implementa en el canvi de mida fora de línia. Es va iniciar una discussió sobre això aquí.
  • Què és exactament un contenidor sidecar en aquest context? El connector CSI en si no interactua amb l'API de Kubernetes, sinó que només respon a les trucades gRPC que li envien contenidors sidecar. Última s'estan desenvolupant per la comunitat Kubernetes.

En el nostre cas (connector CSI), l'operació d'augmentar el disc té aquest aspecte:

  1. Rebem una trucada de gRPC ControllerExpandVolume;
  2. Estem intentant augmentar el disc a l'API, però rebem un error sobre la impossibilitat de realitzar l'operació perquè el disc està muntat;
  3. Desem l'identificador del disc en un mapa que conté els discs per als quals s'ha de realitzar l'operació d'augment. A continuació, per concisió, anomenarem aquest mapa com volumeResizeRequired;
  4. Traieu manualment el pod que utilitza el disc. Kubernetes el reiniciarà. Perquè el disc no tingui temps de muntar (ControllerPublishVolume) abans de completar l'operació d'augment quan intentem muntar, comprovem que el disc donat encara estigui dins volumeResizeRequired i retorna un error;
  5. El controlador CSI intenta tornar a executar l'operació de canvi de mida. Si l'operació ha tingut èxit, traieu el disc volumeResizeRequired;
  6. Perquè Falta l'identificador de disc volumeResizeRequired, ControllerPublishVolume passa correctament, el disc està muntat, el pod comença.

Tot sembla prou senzill, però com sempre hi ha inconvenients. Amplia els discos redimensionador extern, que en cas d'error durant l'operació utilitza una cua amb un augment exponencial del temps d'espera fins a 1000 segons:

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)},
  )
}

Això pot provocar periòdicament que l'operació d'expansió del disc s'ampliï durant més de 15 minuts i, per tant, el pod corresponent no estigui disponible.

L'única opció que ens va permetre reduir de manera senzilla i indolora el temps d'inactivitat potencial va ser l'ús de la nostra versió de redimensionador extern amb un límit de temps d'espera màxim. en 5 segons:

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

No vam considerar necessari iniciar una discussió urgent i aplicar un pedaç al redimensionador extern, perquè el redimensionament fora de línia dels discos és un retrocés que aviat desapareixerà de tots els proveïdors de núvol.

Com començar a utilitzar-lo?

El controlador és compatible amb Kubernetes versió 1.15 i superior. Perquè el conductor pugui treballar, s'han de complir els requisits següents:

  • Bandera --allow-privileged posat en valor true per al servidor API i kubelet;
  • Inclòs --feature-gates=VolumeSnapshotDataSource=true,KubeletPluginsWatcher=true,CSINodeInfo=true,CSIDriverRegistry=true per al servidor API i kubelet;
  • Propagació de muntatge (propagació de muntatge) ha d'estar habilitat al clúster. Quan utilitzeu Docker, el dimoni s'ha de configurar per permetre muntatges compartits.

Tots els passos necessaris per a la pròpia instal·lació descrit a README. La instal·lació implica la creació d'objectes a Kubernetes a partir de manifests.

Perquè el conductor funcioni, necessitareu el següent:

  • Especifiqueu l'identificador del directori al manifest (folder-id) Yandex.Cloud (veure documentació);
  • Per interactuar amb l'API Yandex.Cloud, el controlador CSI utilitza un compte de servei. Al manifest, s'ha de passar Secret claus autoritzades des del compte de servei. A la documentació descrit, com crear un compte de servei i obtenir claus.

Considerant-ho tot - proveu, i estarem encantats de rebre comentaris i nous temessi trobeu algun problema!

Més suport

Com a resultat, ens agradaria assenyalar que vam implementar aquest controlador CSI no per un gran desig de divertir-nos escrivint aplicacions a Go, sinó per una necessitat urgent dins de l'empresa. No ens sembla pràctic mantenir la nostra pròpia implementació, de manera que si Yandex mostra interès i decideix continuar donant suport al controlador, estarem encantats de transferir-los el repositori.

A més, probablement Yandex té la seva pròpia implementació del controlador CSI al seu clúster Kubernetes gestionat, que es pot llançar en codi obert. També veiem que aquesta opció de desenvolupament és favorable: la comunitat podrà utilitzar un controlador provat d'un proveïdor de serveis i no d'una empresa de tercers.

PS

Llegeix també al nostre blog:

Font: www.habr.com

Afegeix comentari