
Vi er glade for at annoncere, at virksomheden "Flant" udvider sin indsats inden for Open Source-værktøjer til Kubernetes ved at udgive (Container Storage Interface) til Yandex.Cloud.
Men før vi går videre til detaljer om implementeringen, lad os besvare spørgsmålet: hvorfor er dette overhovedet nødvendigt, når Yandex allerede har tjenesten .
Introduktion
Hvorfor det?
Inden for vores virksomhed har vi, siden vi begyndte at bruge Kubernetes i produktion (dvs. i flere år), udviklet et eget værktøj (deckhouse), som vi også planlægger at gøre tilgængeligt som et Open Source-projekt. Ved hjælp af dette værktøj konfigurerer og indstiller vi ensartet alle vores klynger, og i øjeblikket har vi allerede over 100, som er på meget forskellige hardwarekonfigurationer og i alle tilgængelige cloud-tjenester.
Klynger, der bruger deckhouse, har alle de nødvendige komponenter til drift: load balancere, overvågning med brugervenlige grafer, metrikker og alarmer, brugerautentificering gennem eksterne udbydere for adgang til alle dashboards osv. En sådan "opgraderet" klynge giver ikke mening at sætte i en managed-løsning, da det ofte enten er umuligt, eller det vil kræve at de fleste komponenter skal deaktiveres.
NB: Dette er vores erfaring, og den er ret speciel. Vi hævder på ingen måde, at alle skal tage sig af opsætningen af Kubernetes-klynger selv i stedet for at bruge færdige løsninger. For øvrigt har vi ikke nogen konkret erfaring med Yandex' Kubernetes-service, og vi vil ikke give nogen vurdering af denne tjeneste i den nuværende artikel.
Hvad er dette, og for hvem?
Så vi har allerede fortalt om den moderne tilgang til lagring i Kubernetes: og til denne tilgang.
I øjeblikket har mange store cloud-udbydere udviklet drivere til at bruge deres "cloud"-diske som Persistent Volume i Kubernetes. Hvis en leverandør ikke har en sådan driver, men stadig tilbyder alle nødvendige funktioner via API, er der intet, der forhindrer at implementere en driver selv. Sådan lykkedes det os med Yandex.Cloud.
Vi tog udgangspunkt i og et par ideer fra , da interaktionen med API'erne fra disse skyer (Google og Yandex) har en række ligheder. Specifikt, API'et fra , og fra returnerer et objekt Operation til overvågning af status for langvarige operationer (f.eks. oprettelse af en ny disk). For at interagere med Yandex.Cloud API'et bruges .
Resultatet af det udførte arbejde og kan være nyttigt for dem, der af en eller anden grund bruger deres egen installation af Kubernetes på virtuelle maskiner i Yandex.Cloud (men ikke en færdig administreret klynge) og ønsker at bruge (bestille) diske via CSI.
Implementering
Grundlæggende funktioner
På nuværende tidspunkt understøtter driveren følgende funktioner:
- Bestilling af diske i alle zoner af klyngen i henhold til topologien af de eksisterende noder i klyngen;
- Sletning af tidligere bestilte diske;
- Offline resize for diske (Yandex.Cloud forøgelse af diske, som er monteret på den virtuelle maskine). Hvordan driveren blev modificeret for at udføre resize så smertefrit som muligt, er beskrevet nedenfor.
I fremtiden planlægges det at implementere support til oprettelse og sletning af snapshots af diske.
Den primære udfordring og dens overvindelse
Manglen på muligheden for at øge diske i realtid i Yandex.Cloud API'et — en begrænsning, der komplicerer resize-operationen for PV (Persistent Volume): for i så fald er det nødvendigt, at pod'en af applikationen, der bruger disken, stopper, hvilket kan forårsage nedetid for applikationen.
Ifølge , hvis CSI-controlleren rapporterer, at den kun kan udføre disk-resize 'offline' (VolumeExpansion.OFFLINE), så skal processen for at øge disken forløbe således:
Hvis pluginnet kun har
VolumeExpansion.OFFLINEudvidelseskapacitet og volumen i øjeblikket er publiceret eller tilgængeligt på en node, såControllerExpandVolumeSKAL kun kaldes efter enten:
- Pluginnet har controller
PUBLISH_UNPUBLISH_VOLUMEkapacitet ogControllerUnpublishVolumeer blevet invokeret med succes.ELLER
- Pluginnet HAR IKKE controller
PUBLISH_UNPUBLISH_VOLUMEkapacitet, pluginnet har nodeSTAGE_UNSTAGE_VOLUMEkapacitet, ogNodeUnstageVolumeer blevet gennemført med succes.ELLER
- Pluginnet HAR IKKE controller
PUBLISH_UNPUBLISH_VOLUMEkapacitet, ej nodeSTAGE_UNSTAGE_VOLUMEkapacitet, ogNodeUnpublishVolumeer blevet gennemført med succes.
Dette betyder i realiteten, at det er nødvendigt at afmontere disken fra den virtuelle maskine, før den kan forøges.
Desværre en implementering , opfylder CSI-specifikationerne ikke disse krav gennem sidekæder:
- I sidecar-containeren
csi-attacher, som skal sikre tilstedeværelsen af det nødvendige tidsrum mellem monteringer, er denne funktionalitet simpelthen ikke implementeret ved offline-resize. Diskussionen om dette er blevet iværksat. . - Hvad er en sidecar-container i denne sammenhæng? Den specifikke CSI-plugin interagerer ikke med Kubernetes API, men reagerer kun på gRPC-opkald, som sidstnævnte sender til sidecar-containere. Sidste Kubernetes-fællesskabet.
I vores tilfælde (CSI-plugin) ser processen for udvidelse af disken således ud:
- Vi modtager et gRPC-opkald
ControllerExpandVolume; - Vi forsøger at udvide disken i API'et, men får en fejl om, at operationen ikke kan udføres, da disken er monteret;
- Vi gemmer diskens ID i et kort, der indeholder de diske, som vi skal udføre udvidelsesoperationen for. Fremover kalder vi dette kort
volumeResizeRequired; - Vi fjerner manuelt den pod, der bruger disken. Kubernetes genstarter den i mellemtiden. For at sikre, at disken ikke når at blive monteret (
ControllerPublishVolume) inden udvidelsesoperationen er afsluttet, kontrollerer vi, om denne disk stadig er ivolumeResizeRequiredog returnerer en fejl; - CSI-driveren forsøger at udføre resize-operationen igen. Hvis operationen lykkes, fjerner vi disken fra
volumeResizeRequired; - Da diskens ID ikke er til stede i
volumeResizeRequired,ControllerPublishVolumelykkes det, disken monteres, og pod'en startes.
Det ser ret simpelt ud, men som altid er der faldgruber. Udvidelse af diske håndteres af , som i tilfælde af en fejl under udførelsen af operationen med eksponentiel forøgelse af timeout'ens tid op til 1000 sekunder:
func DefaultControllerRateLimiter() RateLimiter {
return NewMaxOfRateLimiter(
NewItemExponentialFailureRateLimiter(5*time.Millisecond, 1000*time.Second),
\/\/ 10 qps, 100 bucket size. Dette er kun for retry hastighed og det er kun den samlede faktor (ikke per element)
&BucketRateLimiter{Limiter: rate.NewLimiter(rate.Limit(10), 100)},
)
}Dette kan periodisk betyde, at udvidelsen af disken strækker sig over 15+ minutter og dermed forårsager, at den tilsvarende pod er utilgængelig.
Den eneste mulighed, der har givet os mulighed for at reducere potentiel nedetid på en forholdsvis nem og smertefri måde, er at anvende vores egen version af external-resizer med en maksimal timeout-grænse :
workqueue.NewItemExponentialFailureRateLimiter(5*time.Millisecond, 5*time.Second)Vi mente ikke, det var nødvendigt at iværksætte en hastediskussion og patchere external-resizer, fordi offline resize af diske er et levn, som snart vil forsvinde hos alle cloud-udbydere.
Hvordan kommer man i gang?
Driveren understøttes i Kubernetes version 1.15 og nyere. For at driveren kan fungere, skal følgende betingelser være opfyldt:
- Flaget
--allow-privilegedindstillet tiltruefor API-serveren og kubelet; - Aktiveret
--feature-gates=VolumeSnapshotDataSource=true,KubeletPluginsWatcher=true,CSINodeInfo=true,CSIDriverRegistry=truefor API-serveren og kubelet; - Monteringsfordeling () skal være aktiveret i klyngen. Når du bruger Docker, skal dæmonen konfigureres til at tillade delte monteringsobjekter (shared mounts).
Alle nødvendige trin til selve installationen . Installationen indebærer oprettelse af objekter i Kubernetes fra manifester.
For at køre driveren skal du have følgende:
- Angive katalog-id i manifestet (
folder-id) fra Yandex.Cloud (); - For at interagere med Yandex.Cloud API i CSI-driveren bruges en servicekonto. I manifestet Secret skal de fra servicekontoen overføres. I dokumentationen , hvordan man opretter en servicekonto og får nøgler.
Generelt — , og vi ser frem til feedback og , hvis du støder på nogle problemer!
Yderligere support
Som konklusion vil vi gerne nævne, at denne CSI-driver ikke blev udviklet ud af et stort ønske om at have det sjovt med at skrive applikationer i Go, men på grund af et akut behov internt i virksomheden. At vedligeholde vores egen implementering virker ikke hensigtsmæssigt, så hvis Yandex viser interesse og beslutter at fortsætte med at støtte driveren, vil vi med glæde overdrage repositoryet til deres disposition.
Derudover har Yandex formentlig deres egen implementering af CSI-driveren i det administrerede Kubernetes-klynge, som kan frigives som Open Source. Sådan et udviklingsscenarie ser vi også som gavnligt — fællesskabet vil kunne bruge en verificeret driver fra en serviceudbyder, i stedet for fra et tredjepartsfirma.
P.S.
Læs også på vores blog:
- «»;
- «»;
- «»;
- «».
Kilde: habr.com
