
Siamo felici di annunciare che l'azienda «Flant» sta ampliando il proprio contributo agli strumenti Open Source per Kubernetes, rilasciando (Container Storage Interface) per Yandex.Cloud.
Ma prima di passare ai dettagli dell'implementazione, rispondiamo alla domanda su perché sia necessario, quando Yandex dispone già del servizio .
Introduzione
Perché farlo?
Dall'inizio dell'utilizzo di Kubernetes in produzione (cioè già da diversi anni), all'interno della nostra azienda si è sviluppato uno strumento proprio (deckhouse), che, tra l'altro, abbiamo intenzione di rendere presto disponibile come progetto Open Source. Grazie a esso configuriamo e gestiamo in modo uniforme tutti i nostri cluster, e attualmente ne abbiamo già più di 100, su configurazioni hardware molto diverse e in tutti i servizi cloud disponibili.
I cluster che utilizzano deckhouse contengono tutti i componenti necessari per il funzionamento: bilanciatori di carico, monitoraggio con grafici intuitivi, metriche e avvisi, autenticazione degli utenti attraverso fornitori esterni per l'accesso a tutte le dashboard e così via. Non ha senso installare un cluster "potenziato" in una soluzione gestita, poiché spesso ciò è o impossibile o porterà alla necessità di disabilitare metà dei componenti.
NB: Questa è la nostra esperienza, e è piuttosto specifica. Non affermiamo in alcun modo che tutti dovrebbero occuparsi autonomamente del dispiegamento dei cluster Kubernetes anziché utilizzare soluzioni pronte. A proposito, non abbiamo esperienza reale nell'utilizzo di Kubernetes da parte di Yandex e non daremo alcuna valutazione a questo servizio in questo articolo.
Che cos'è e per chi?
Quindi, abbiamo già parlato dell'approccio moderno agli storage in Kubernetes: e a questo approccio.
Attualmente, molti grandi fornitori di servizi cloud hanno sviluppato driver per utilizzare i propri dischi "cloud" come Persistent Volume in Kubernetes. Se il fornitore non dispone di tale driver, ma tutte le funzioni necessarie sono comunque fornite tramite API, nulla impedisce di implementare il driver con le proprie forze. Così abbiamo fatto noi con Yandex.Cloud.
Abbiamo preso come base per lo sviluppo e un paio di idee dal , poiché l'interazione con le API di questi cloud (Google e Yandex) presenta alcune somiglianze. In particolare, le API di , e di restituiscono l'oggetto Operazione per il monitoraggio dello stato delle operazioni prolungate (ad esempio, la creazione di un nuovo disco). Per interagire con l'API di Yandex.Cloud viene utilizzato .
Il risultato del lavoro svolto e potrebbe essere utile a chi, per qualche motivo, utilizza la propria installazione di Kubernetes su macchine virtuali di Yandex.Cloud (ma non un cluster gestito) e vorrebbe utilizzare (richiedere) dischi attraverso CSI.
Implementazione
Caratteristiche principali
Attualmente il driver supporta le seguenti funzionalità:
- Richiesta di dischi in tutte le zone del cluster secondo la topologia dei nodi presenti nel cluster;
- Cancellazione dei dischi ordinati in precedenza;
- Ridimensionamento offline per i dischi (Yandex.Cloud aumento dei dischi che sono montati sulla macchina virtuale). Riguardo a come è stato necessario modificare il driver per eseguire il ridimensionamento senza problemi, vedere sotto.
In futuro si prevede di implementare il supporto per la creazione e la cancellazione di snapshot dei dischi.
La principale difficoltà e la sua risoluzione
L’assenza nell'API di Yandex.Cloud della possibilità di aumentare i dischi in tempo reale è una limitazione che complica l'operazione di ridimensionamento per PV (Persistent Volume): infatti, in questo caso, è necessario che il pod dell'applicazione che utilizza il disco sia fermo, e ciò può causare un'interruzione dell'applicazione.
Secondo , se il controller CSI segnala che sa fare il ridimensionamento dei dischi solo "in offline" (VolumeExpansion.OFFLINE), il processo di aumento del disco deve avvenire in questo modo:
Se il plugin ha solo
VolumeExpansion.OFFLINEcapacità di espansione e il volume è attualmente pubblicato o disponibile su un nodo, alloraControllerExpandVolumeDEVE essere chiamato SOLO dopo che:
- Il plugin ha il controller
PUBLISH_UNPUBLISH_VOLUMEcapacità eControllerUnpublishVolumeè stato invocato con successo.ALTRIMENTI
- Il plugin NON ha capacità di controller, il plugin ha nodo
PUBLISH_UNPUBLISH_VOLUMESTAGE_UNSTAGE_VOLUMEcapacità eNodeUnstageVolumeè stato completato con successo.capacità, né nodoALTRIMENTI
- Il plugin NON ha capacità di controller, il plugin ha nodo
PUBLISH_UNPUBLISH_VOLUMENodeUnpublishVolumecapacità eNodeUnstageVolumeè stato completato con successo.In sostanza, ciò significa che è necessario scollegare il disco dalla macchina virtuale prima di aumentarlo.
Tuttavia, sfortunatamente,
le specifiche CSI tramite sidecar non soddisfano questi requisiti: una realizzazione Nel contenitore sidecar
- csi-attacher
, che dovrebbe occuparsi di garantire il giusto intervallo tra i montaggi, la funzionalità non è semplicemente implementata durante il ridimensionamento offline. È stata avviata una discussione su questo, che deve garantire la presenza della giusta intervallo tra i montaggi, poiché questa funzionalità non è semplicemente implementata nell'opzione di ridimensionamento offline. La discussione su questo è stata avviata . - Cos'è esattamente un container sidecar in questo contesto? Il plugin CSI non interagisce con l'API di Kubernetes, ma risponde solo alle chiamate gRPC che gli inviano i container sidecar. Questi ultimi dalla comunità Kubernetes.
Nel nostro caso (plugin CSI) l'operazione di aumento del disco appare come segue:
- Riceviamo una chiamata gRPC
ControllerExpandVolume; - Cerchiamo di aumentare il disco nell'API, ma riceviamo un errore di impossibilità di eseguire l'operazione, poiché il disco è montato;
- Salviamo l'identificatore del disco in una mappa contenente i dischi per i quali è necessario eseguire l'operazione di aumento. D'ora in poi, per brevità, chiameremo questa mappa
volumeResizeRequired; - Rimuoviamo manualmente il pod che utilizza il disco. Kubernetes lo riavvierà. Affinché il disco non venga montato (
ControllerPublishVolume) prima del completamento dell'operazione di aumento al momento del tentativo di montaggio, verifichiamo che il disco sia ancora involumeResizeRequirede restituiamo un errore; - Il driver CSI tenta di eseguire nuovamente l'operazione di resize. Se l'operazione ha successo, rimuoviamo il disco da
volumeResizeRequired; - Poiché l'identificatore del disco non è presente in
volumeResizeRequired,ControllerPublishVolumela chiamata ha successo, il disco viene montato, il pod si avvia.
Tutto sembra piuttosto semplice, ma come sempre ci sono insidie. L'aumento dei dischi è gestito da , che in caso di errore durante l'esecuzione dell'operazione con un incremento esponenziale del tempo di timeout fino a 1000 secondi:
func DefaultControllerRateLimiter() RateLimiter {
return NewMaxOfRateLimiter(
NewItemExponentialFailureRateLimiter(5*time.Millisecond, 1000*time.Second),
&BucketRateLimiter{Limiter: rate.NewLimiter(rate.Limit(10), 100)},
)
}Questo può portare periodicamente a un allungamento dell'operazione di aumento del disco di oltre 15 minuti e, di conseguenza, alla non disponibilità del relativo pod.
L'unica opzione che ci ha permesso di ridurre in modo relativamente semplice e indolore il potenziale tempo di inattività è stata l'uso di una nostra versione di external-resizer con un limite massimo di timeout :
workqueue.NewItemExponentialFailureRateLimiter(5*time.Millisecond, 5*time.Second)Non abbiamo ritenuto necessario avviare una discussione urgente e patchare external-resizer, poiché la ridimensionamento offline dei dischi è un retaggio che presto scomparirà da tutti i fornitori di cloud.
Come iniziare a utilizzare?
Il driver è supportato nelle versioni di Kubernetes 1.15 e successive. Per il funzionamento del driver devono essere soddisfatti i seguenti requisiti:
- Bandiera
--allow-privilegedimpostato sutrueper il server API e kubelet; - Attivata
--feature-gates=VolumeSnapshotDataSource=true,KubeletPluginsWatcher=true,CSINodeInfo=true,CSIDriverRegistry=trueper il server API e kubelet; - La propagazione dei mount () deve essere abilitata nel cluster. Quando si utilizza Docker, il demone deve essere configurato in modo da consentire mount condivisi (shared mounts).
Tutti i passaggi necessari per l'installazione . L'installazione comporta la creazione di oggetti in Kubernetes a partire dai manifest.
Per utilizzare il driver avrai bisogno di quanto segue:
- Specificare nel manifesto l'ID della cartella (
folder-id) di Yandex.Cloud (); - Per interagire con l'API di Yandex.Cloud, il driver CSI utilizza un account di servizio. Nel manifesto Secret devono essere forniti dell'account di servizio. Nella documentazione , su come creare un account di servizio e ottenere le chiavi.
In generale — , e saremo felici di ricevere feedback e , se incontri qualche problema!
Supporto ulteriore
In conclusione, ci teniamo a sottolineare che questo driver CSI è stato realizzato non per puro desiderio di divertirci a scrivere applicazioni in Go, ma per una necessità urgente all'interno dell'azienda. Non ci sembra sensato mantenere una nostra implementazione, quindi, se Yandex mostra interesse e decide di continuare il supporto per il driver, saremo felici di cedere il repository nelle loro mani.
Inoltre, probabilmente Yandex ha nel suo cluster Kubernetes gestito una propria implementazione del driver CSI, che potrebbe essere resa open source. Questa opzione ci sembra anche favorevole: la comunità potrà utilizzare un driver collaudato dal fornitore di servizi, anziché da una società terza.
P.S.
Leggi anche nel nostro blog:
- «»;
- «»;
- «»;
- «».
Fonte: habr.com
