Onze ervaring met het ontwikkelen van een CSI-driver in Kubernetes voor Yandex.Cloud

Onze ervaring met het ontwikkelen van een CSI-driver in Kubernetes voor Yandex.Cloud

We zijn verheugd te kunnen aankondigen dat Flant zijn bijdrage aan Open Source-tools voor Kubernetes uitbreidt door release alpha-versie van het CSI-stuurprogramma (Containeropslaginterface) voor Yandex.Cloud.

Maar laten we, voordat we verder gaan met de implementatiedetails, de vraag beantwoorden waarom dit überhaupt nodig is als Yandex al een service heeft Beheerde service voor Kubernetes.

Introductie

Waarom is dit?

Binnen ons bedrijf hebben we vanaf het allereerste begin met het gebruik van Kubernetes in de productie (d.w.z. al enkele jaren) onze eigen tool (deckhouse) ontwikkeld, die we overigens binnenkort ook als Open Source-project beschikbaar willen stellen . Met zijn hulp configureren en configureren we al onze clusters op uniforme wijze, en momenteel zijn er al meer dan 100, op een grote verscheidenheid aan hardwareconfiguraties en in alle beschikbare clouddiensten.

Clusters die gebruikmaken van een dekhuis beschikken over alle componenten die nodig zijn voor de werking: balancers, monitoring met handige grafieken, statistieken en waarschuwingen, gebruikersauthenticatie via externe providers voor toegang tot alle dashboards, enzovoort. Het heeft geen zin om zo'n “opgepompt” cluster in een beheerde oplossing te installeren, omdat dit vaak onmogelijk is of ertoe zal leiden dat de helft van de componenten moet worden uitgeschakeld.

NB: Dit is onze ervaring, en deze is vrij specifiek. We suggereren geenszins dat iedereen zelf Kubernetes-clusters moet inzetten in plaats van gebruik te maken van kant-en-klare oplossingen. We hebben overigens geen echte ervaring met het exploiteren van Kubernetes vanuit Yandex en we zullen in dit artikel geen enkele beoordeling van deze service geven.

Wat is het en voor wie?

We hebben het dus al gehad over de moderne benadering van opslag in Kubernetes: hoe werkt CSI? и hoe de gemeenschap tot stand kwam aan deze aanpak.

Momenteel hebben veel grote cloudserviceproviders stuurprogramma's ontwikkeld voor het gebruik van hun cloudschijven als Persistent Volume in Kubernetes. Als de leverancier niet over zo'n driver beschikt, maar alle benodigde functies via de API worden geleverd, staat niets je in de weg om de driver zelf te implementeren. Dit is wat er gebeurde met Yandex.Cloud.

We hebben als basis voor ontwikkeling genomen CSI-stuurprogramma voor DigitalOcean cloud en een paar ideeën van stuurprogramma's voor GCP, aangezien de interactie met de API van deze clouds (Google en Yandex) een aantal overeenkomsten vertoont. Met name de API en GCP, en bij Yandex een voorwerp retourneren Operation om de status van langlopende bewerkingen bij te houden (bijvoorbeeld het maken van een nieuwe schijf). Gebruik om te communiceren met de Yandex.Cloud API Yandex.Cloud Go SDK.

Het resultaat van het geleverde werk gepubliceerd op GitHub en kan nuttig zijn voor degenen die om de een of andere reden hun eigen Kubernetes-installatie op virtuele Yandex.Cloud-machines gebruiken (maar geen kant-en-klaar beheerd cluster) en schijven via CSI willen gebruiken (bestellen).

uitvoering

Belangrijkste kenmerken

Momenteel ondersteunt de driver de volgende functies:

  • Schijven bestellen in alle zones van het cluster volgens de topologie van de knooppunten in het cluster;
  • Eerder bestelde schijven verwijderen;
  • Offline formaat wijzigen voor schijven (Yandex.Cloud niet ondersteunen het vergroten van het aantal schijven dat aan de virtuele machine is gekoppeld). Zie hieronder voor informatie over hoe de driver moest worden aangepast om het wijzigen van de grootte zo pijnloos mogelijk te maken.

In de toekomst zijn we van plan ondersteuning te implementeren voor het maken en verwijderen van schijfmomentopnamen.

De grootste moeilijkheid en hoe deze te overwinnen

Het ontbreken van de mogelijkheid om schijven in realtime te vergroten in de Yandex.Cloud API is een beperking die het wijzigen van de grootte voor PV (Persistent Volume) bemoeilijkt: in dit geval is het noodzakelijk dat de applicatiepod die de schijf gebruikt, wordt gestopt, en dit kan downtime-applicaties veroorzaken.

Volgens CSI-specificaties, als de CSI-controller meldt dat hij de grootte van schijven alleen “offline” kan wijzigen (VolumeExpansion.OFFLINE), dan zou het proces van het vergroten van de schijf als volgt moeten gaan:

Als de plug-in alleen VolumeExpansion.OFFLINE uitbreidingsmogelijkheden en volume zijn momenteel gepubliceerd of beschikbaar op een knooppunt ControllerExpandVolume MOET ALLEEN worden gebeld na:

  • De plug-in heeft een controller PUBLISH_UNPUBLISH_VOLUME capaciteit en ControllerUnpublishVolume is met succes aangeroepen.

OF ANDERS

  • De plug-in heeft GEEN controller PUBLISH_UNPUBLISH_VOLUME mogelijkheid, de plug-in heeft node STAGE_UNSTAGE_VOLUME vermogen, en NodeUnstageVolume is succesvol afgerond.

OF ANDERS

  • De plug-in heeft GEEN controller PUBLISH_UNPUBLISH_VOLUME vermogen, noch knooppunt STAGE_UNSTAGE_VOLUME vermogen, en NodeUnpublishVolume is met succes voltooid.

Dit betekent in wezen dat u de schijf moet loskoppelen van de virtuele machine voordat u deze uitbreidt.

Helaas echter implementatie De CSI-specificatie via zijspannen voldoet niet aan deze eisen:

  • In een zijspancontainer csi-attacher, die verantwoordelijk zou moeten zijn voor de aanwezigheid van de vereiste opening tussen mounts, wordt deze functionaliteit eenvoudigweg niet geïmplementeerd in de offline formaatwijziging. Hierover werd een discussie op gang gebracht hier.
  • Wat is in dit verband precies een zijspancontainer? De CSI-plug-in zelf heeft geen interactie met de Kubernetes API, maar reageert alleen op gRPC-aanroepen die door zijspancontainers ernaar worden verzonden. Laatste worden ontwikkeld door de Kubernetes-gemeenschap.

In ons geval (CSI-plug-in) ziet de bewerking van het vergroten van de schijf er als volgt uit:

  1. We ontvangen een gRPC-oproep ControllerExpandVolume;
  2. We proberen de schijf in de API te vergroten, maar we krijgen een foutmelding over de onmogelijkheid om de bewerking uit te voeren omdat de schijf is aangekoppeld;
  3. We slaan de schijf-ID op in een kaart met de schijven waarvoor de vergrotingsbewerking moet worden uitgevoerd. Hieronder zullen we deze kaart kortheidshalve noemen als volumeResizeRequired;
  4. Verwijder handmatig de pod die de schijf gebruikt. Kubernetes zal het opnieuw opstarten. Zodat de schijf geen tijd heeft om te mounten (ControllerPublishVolume) voordat we de vergrotingsbewerking voltooien wanneer we proberen te mounten, controleren we of de gegeven schijf er nog in zit volumeResizeRequired en retourneer een fout;
  5. Het CSI-stuurprogramma probeert de formaatwijzigingsbewerking opnieuw uit te voeren. Als de bewerking succesvol was, verwijdert u de schijf volumeResizeRequired;
  6. Omdat Schijf-ID ontbreekt in volumeResizeRequired, ControllerPublishVolume verloopt succesvol, de schijf is gemonteerd en de pod start.

Alles lijkt eenvoudig genoeg, maar zoals altijd zijn er valkuilen. Vergroot schijven externe resizer, wat in geval van een fout tijdens de bediening maakt gebruik van een wachtrij met een exponentiële toename van de time-outtijd tot 1000 seconden:

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

Dit kan er periodiek toe leiden dat de schijfuitbreidingsbewerking met meer dan 15 minuten wordt verlengd, waardoor de bijbehorende pod niet beschikbaar is.

De enige optie waarmee we vrij gemakkelijk en pijnloos potentiële downtime konden verminderen, was het gebruik van onze versie van external-resizer met een maximale time-outlimiet in 5 seconden:

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

We vonden het niet nodig om dringend een discussie op gang te brengen en de externe resizer te patchen, omdat het offline aanpassen van de grootte van schijven een erfenis is die binnenkort bij alle cloudproviders zal verdwijnen.

Hoe begin je het te gebruiken?

Het stuurprogramma wordt ondersteund op Kubernetes versie 1.15 en hoger. Om de bestuurder te laten werken, moet aan de volgende vereisten worden voldaan:

  • vlag --allow-privileged ingesteld op waarde true voor API-server en kubelet;
  • Inbegrepen --feature-gates=VolumeSnapshotDataSource=true,KubeletPluginsWatcher=true,CSINodeInfo=true,CSIDriverRegistry=true voor API-server en kubelet;
  • Mount-voortplanting (propagatie monteren) moet zijn ingeschakeld op het cluster. Wanneer u Docker gebruikt, moet de daemon worden geconfigureerd om gedeelde koppelingen toe te staan.

Alle noodzakelijke stappen voor de installatie zelf beschreven in README. Bij de installatie worden objecten in Kubernetes gemaakt op basis van manifesten.

Om de chauffeur te laten werken, heeft u het volgende nodig:

  • Geef de directory-ID op in het manifest (folder-id) Yandex.Cloud (zie documentatie);
  • Voor interactie met de Yandex.Cloud API gebruikt het CSI-stuurprogramma een serviceaccount. In het manifest moet Secret worden doorgegeven geautoriseerde sleutels van het serviceaccount. In de documentatie beschreven, hoe u een serviceaccount kunt maken en sleutels kunt verkrijgen.

Globaal genomen - попробуйте, en we ontvangen graag feedback en nieuwe problemenals u problemen ondervindt!

Verdere ondersteuning

Als gevolg hiervan willen we opmerken dat we deze CSI-driver niet hebben geïmplementeerd uit een groot verlangen om plezier te hebben bij het schrijven van applicaties in Go, maar vanwege een dringende behoefte binnen het bedrijf. Het lijkt ons niet praktisch om onze eigen implementatie te behouden, dus als Yandex interesse toont en besluit de driver te blijven ondersteunen, dragen we de repository graag aan hen over.

Daarnaast heeft Yandex waarschijnlijk een eigen implementatie van de CSI-driver in zijn beheerde Kubernetes-cluster, die in Open Source kan worden uitgebracht. Wij beschouwen deze ontwikkelingsoptie ook als gunstig: de gemeenschap zal gebruik kunnen maken van een bewezen driver van een dienstverlener, en niet van een derde partij.

PS

Lees ook op onze blog:

Bron: www.habr.com

Voeg een reactie