La nostra esperienza nello sviluppo di un driver CSI in Kubernetes per Yandex.Cloud

La nostra esperienza nello sviluppo di un driver CSI in Kubernetes per Yandex.Cloud

Siamo lieti di annunciare che Flant sta espandendo il suo contributo agli strumenti Open Source per Kubernetes rilasciando versione alpha del driver CSI (Interfaccia di archiviazione del contenitore) per Yandex.Cloud.

Ma prima di passare ai dettagli di implementazione, rispondiamo alla domanda sul perché è necessario quando Yandex ha già un servizio Servizio gestito per Kubernetes.

Introduzione

Perché questo?

All'interno della nostra azienda, fin dall'inizio dell'utilizzo di Kubernetes in produzione (ovvero ormai da diversi anni), abbiamo sviluppato il nostro strumento (tuga), che tra l'altro prevediamo di rendere presto disponibile anche come progetto Open Source . Con il suo aiuto, configuriamo e configuriamo in modo uniforme tutti i nostri cluster, e attualmente ce ne sono già più di 100, su un'ampia varietà di configurazioni hardware e in tutti i servizi cloud disponibili.

I cluster che utilizzano deckhouse dispongono di tutti i componenti necessari al funzionamento: bilanciatori, monitoraggio con comodi grafici, metriche e alert, autenticazione degli utenti tramite provider esterni per l'accesso a tutte le dashboard, e così via. Non ha senso installare un cluster così "pompato" in una soluzione gestita, poiché spesso ciò è impossibile o porterà alla necessità di disabilitare metà dei componenti.

NB: Questa è la nostra esperienza ed è abbastanza specifica. Non stiamo in alcun modo suggerendo che tutti dovrebbero implementare i cluster Kubernetes da soli invece di utilizzare soluzioni già pronte. A proposito, non abbiamo una reale esperienza nell'utilizzo di Kubernetes da Yandex e non forniremo alcuna valutazione di questo servizio in questo articolo.

Cos'è e per chi?

Quindi, abbiamo già parlato dell'approccio moderno allo storage in Kubernetes: come funziona il CSI? и come è venuta la comunità a questo approccio.

Attualmente, molti grandi fornitori di servizi cloud hanno sviluppato driver per utilizzare i propri dischi cloud come volume persistente in Kubernetes. Se il fornitore non dispone di tale driver, ma tutte le funzioni necessarie vengono fornite tramite API, nulla ti impedisce di implementare tu stesso il driver. Questo è quello che è successo con Yandex.Cloud.

Abbiamo preso come base per lo sviluppo Driver CSI per il cloud DigitalOcean e un paio di idee da driver per GCP, poiché l'interazione con l'API di questi cloud (Google e Yandex) presenta una serie di somiglianze. In particolare, l'API e GCPe tu Yandex restituire un oggetto Operation per tenere traccia dello stato delle operazioni di lunga durata (ad esempio, la creazione di un nuovo disco). Per interagire con l'API Yandex.Cloud, utilizzare SDK Yandex.Cloud Go.

Il risultato del lavoro svolto pubblicato su GitHub e può essere utile per coloro che, per qualche motivo, utilizzano la propria installazione Kubernetes su macchine virtuali Yandex.Cloud (ma non un cluster gestito già pronto) e vorrebbero utilizzare (ordinare) i dischi tramite CSI.

implementazione

Caratteristiche principali

Attualmente il driver supporta le seguenti funzioni:

  • Ordinare i dischi in tutte le zone del cluster in base alla topologia dei nodi nel cluster;
  • Rimozione dei dischi precedentemente ordinati;
  • Ridimensionamento offline per dischi (Yandex.Cloud non supportano aumentando i dischi montati sulla macchina virtuale). Per informazioni su come è stato necessario modificare il driver per rendere il ridimensionamento il più semplice possibile, vedere di seguito.

In futuro prevediamo di implementare il supporto per la creazione e l'eliminazione di snapshot del disco.

Le principali difficoltà e come superarle

La mancata possibilità di aumentare i dischi in tempo reale nelle API Yandex.Cloud è una limitazione che complica l'operazione di ridimensionamento per PV (Persistent Volume): in questo caso è necessario che il pod dell'applicazione che utilizza il disco venga fermato, e questo può causare tempi di inattività delle applicazioni.

Secondo Specifiche CSI, se il controller CSI segnala che può ridimensionare i dischi solo “offline” (VolumeExpansion.OFFLINE), quindi il processo di aumento del disco dovrebbe procedere in questo modo:

Se il plugin ha solo VolumeExpansion.OFFLINE la capacità di espansione e il volume sono attualmente pubblicati o disponibili su un nodo in quel momento ControllerExpandVolume DEVE essere chiamato SOLO dopo:

  • Il plugin ha un controller PUBLISH_UNPUBLISH_VOLUME capacità e ControllerUnpublishVolume è stato invocato con successo.

O ALTRO

  • Il plugin NON ha un controller PUBLISH_UNPUBLISH_VOLUME capacità, il plugin ha node STAGE_UNSTAGE_VOLUME capacità e NodeUnstageVolume è stato completato con successo.

O ALTRO

  • Il plugin NON ha un controller PUBLISH_UNPUBLISH_VOLUME capacità, né nodo STAGE_UNSTAGE_VOLUME capacità e NodeUnpublishVolume è stato completato con successo.

Ciò significa essenzialmente che è necessario scollegare il disco dalla macchina virtuale prima di espanderlo.

Tuttavia, sfortunatamente implementazione La specifica CSI tramite sidecar non soddisfa questi requisiti:

  • In un contenitore sidecar csi-attacher, che dovrebbe essere responsabile della presenza dello spazio richiesto tra i montaggi, questa funzionalità semplicemente non è implementata nel ridimensionamento offline. È stata avviata una discussione a riguardo qui.
  • Cos'è esattamente un contenitore sidecar in questo contesto? Il plug-in CSI stesso non interagisce con l'API Kubernetes, ma risponde solo alle chiamate gRPC inviate dai contenitori sidecar. Ultimo sono in fase di sviluppo dalla comunità Kubernetes.

Nel nostro caso (plug-in CSI), l'operazione di aumento del disco si presenta così:

  1. Riceviamo una chiamata gRPC ControllerExpandVolume;
  2. Stiamo tentando di aumentare il disco nelle API, ma riceviamo un errore relativo all'impossibilità di eseguire l'operazione perché il disco è montato;
  3. Memorizziamo l'identificatore del disco nella mappa, che contiene i dischi per i quali è necessario eseguire l'operazione di aumento. Di seguito, per brevità, chiameremo questa mappa come volumeResizeRequired;
  4. Rimuovere manualmente il pod che utilizza il disco. Kubernetes lo riavvierà. In modo che il disco non abbia il tempo di montare (ControllerPublishVolume) prima di completare l'operazione di aumento durante il tentativo di montaggio, controlliamo che il disco indicato sia ancora inserito volumeResizeRequired e restituire un errore;
  5. Il driver CSI tenta di rieseguire l'operazione di ridimensionamento. Se l'operazione è andata a buon fine, rimuovere il disco da volumeResizeRequired;
  6. Perché Manca l'ID del disco volumeResizeRequired, ControllerPublishVolume passa con successo, il disco viene montato, il pod si avvia.

Tutto sembra abbastanza semplice, ma come sempre ci sono delle insidie. Ingrandisce i dischi ridimensionatore esterno, che in caso di errore durante l'operazione utilizza una coda con aumento esponenziale del tempo di timeout fino a 1000 secondi:

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

Ciò può periodicamente comportare che l'operazione di espansione del disco venga prolungata per oltre 15 minuti e, quindi, che il pod corrispondente non sia disponibile.

L'unica opzione che ci ha permesso di ridurre i potenziali tempi di inattività in modo abbastanza semplice e indolore è stata l'uso della nostra versione di external-resizer con un limite massimo di timeout in 5 secondi:

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

Non abbiamo ritenuto necessario avviare urgentemente una discussione e applicare una patch al ridimensionatore esterno, perché il ridimensionamento offline dei dischi è un ritorno al passato che presto scomparirà da tutti i fornitori di servizi cloud.

Come iniziare a utilizzare?

Il driver è supportato su Kubernetes versione 1.15 e successive. Affinché il conducente possa lavorare, devono essere soddisfatti i seguenti requisiti:

  • bandiera --allow-privileged impostato su valore true per server API e kubelet;
  • Incluso --feature-gates=VolumeSnapshotDataSource=true,KubeletPluginsWatcher=true,CSINodeInfo=true,CSIDriverRegistry=true per server API e kubelet;
  • Propagazione del monte (montare la propagazione) deve essere abilitato sul cluster. Quando si utilizza Docker, il demone deve essere configurato per consentire i montaggi condivisi.

Tutti i passaggi necessari per l'installazione stessa descritto nel README. L'installazione prevede la creazione di oggetti in Kubernetes dai manifesti.

Affinché il driver funzioni, avrai bisogno di quanto segue:

  • Specificare l'identificatore della directory nel manifest (folder-id) Yandex.Cloud (vedere la documentazione);
  • Per interagire con l'API Yandex.Cloud, il driver CSI utilizza un account di servizio. Nel manifesto è necessario passare Secret chiavi autorizzate dal conto del servizio. Nella documentazione descritto, come creare un account di servizio e ottenere le chiavi.

Nel complesso - provalo, e saremo lieti di ricevere feedback e nuove questionise riscontri problemi!

Ulteriore supporto

Di conseguenza, vorremmo sottolineare che abbiamo implementato questo driver CSI non per un grande desiderio di divertirci a scrivere applicazioni in Go, ma per un'urgente necessità all'interno dell'azienda. Non ci sembra pratico mantenere la nostra implementazione, quindi se Yandex mostra interesse e decide di continuare a supportare il driver, saremo felici di trasferire loro il repository.

Inoltre, Yandex probabilmente ha una propria implementazione del driver CSI nel suo cluster Kubernetes gestito, che può essere rilasciato in Open Source. Consideriamo vantaggiosa anche questa opzione di sviluppo: la comunità potrà utilizzare un driver collaudato di un fornitore di servizi e non di un'azienda terza.

PS

Leggi anche sul nostro blog:

Fonte: habr.com

Aggiungi un commento