
We zijn blij aan te kondigen dat het bedrijf 'Flant' zijn bijdrage aan Open Source-tools voor Kubernetes vergroot door (Container Storage Interface) voor Yandex.Cloud uit te brengen.
Maar voordat we ingaan op de details van de implementatie, laten we de vraag beantwoorden waarom dit überhaupt nodig is, aangezien Yandex al een dienst heeft .
Inleiding
Waarom is dit?
Binnen ons bedrijf, sinds het begin van de productie van Kubernetes (d.w.z. al enkele jaren), ontwikkelen we een eigen tool (deckhouse), die we trouwens ook van plan zijn binnenkort als Open Source-project beschikbaar te stellen. Hiermee configureren en stellen we al onze clusters uniform in, en op dit moment zijn dat er al meer dan 100, op de meest uiteenlopende hardwareconfiguraties en in alle beschikbare cloudservices.
Clusters die deckhouse gebruiken, bevatten alle benodigde componenten voor werking: load balancers, monitoring met handige grafieken, statistieken en alerts, gebruikersauthenticatie via externe providers voor toegang tot alle dashboards, enzovoort. Zo'n 'uitgebreide' cluster is niet geschikt voor een managed-oplossing, omdat dit vaak ofwel onmogelijk is, of leidt tot het uitschakelen van de helft van de componenten.
NB: Dit is onze ervaring, en die is vrij specifiek. We beweren in geen geval dat iedereen zelf clusters van Kubernetes moet opzetten in plaats van gebruik te maken van kant-en-klare oplossingen. Terzijde, we hebben geen daadwerkelijke ervaring met het gebruik van Kubernetes van Yandex en we zullen in dit artikel geen beoordeling van deze dienst geven.
Wat is dit en voor wie?
Dus we hebben al gesproken over de moderne benadering van opslag in Kubernetes: en deze benadering is gekomen.
Veel grote cloudproviders hebben momenteel drivers ontwikkeld voor het gebruik van hun 'cloud'-schijven als Persistent Volume in Kubernetes. Als er echter geen driver van de provider is, maar alle benodigde functies via API worden aangeboden, staat niets een implementatie van de driver met eigen middelen in de weg. Zo hebben wij dat gedaan met Yandex.Cloud.
Als basis voor onze ontwikkeling hebben we en een paar ideeën uit , omdat de interactie met de API van deze cloudservices (Google en Yandex) verschillende overeenkomsten vertoont. In het bijzonder, zowel de API van , als die van geven een object terug Bewerking voor het volgen van de status van langdurige processen (bijvoorbeeld het aanmaken van een nieuwe schijf). Voor interactie met de API van Yandex.Cloud wordt gebruik gemaakt van .
Het resultaat van het voltooide werk en kan nuttig zijn voor degenen die om een bepaalde reden hun eigen installatie van Kubernetes op virtuele machines in Yandex.Cloud gebruiken (maar niet een kant-en-klaar managed cluster) en graag schijven via CSI willen aanmaken (bestellen).
Implementatie
Belangrijkste mogelijkheden
Op dit moment ondersteunt de driver de volgende functies:
- Bestelling van schijven in alle zones van de cluster volgens de topologie van de beschikbare knooppunten in de cluster;
- Verwijdering van eerder bestelde schijven;
- Offline resizing voor schijven (Yandex.Cloud het vergroten van schijven die aan een virtuele machine zijn gekoppeld). Hoe de driver verder moest worden aangepast om resizing zo soepel mogelijk te laten verlopen, zie hieronder.
In de toekomst is het de bedoeling om ondersteuning voor het aanmaken en verwijderen van snapshots van schijven te implementeren.
De grootste uitdaging en hoe deze te overwinnen
Het ontbreken van de mogelijkheid om schijven in real-time te vergroten via de Yandex.Cloud API vormt een beperking die de resize-operatie voor PV (Persistent Volume) bemoeilijkt: in dat geval moet de pod van de applicatie die de schijf gebruikt, worden gestopt, wat kan leiden tot een onderbreking van de applicatie.
Volgens , als de CSI-controller aangeeft dat deze alleen 'offline' schijven kan resizen (VolumeExpansion.OFFLINE), dan moet het proces voor het vergroten van de schijf als volgt verlopen:
Als de plugin alleen
VolumeExpansion.OFFLINEuitbreidingscapaciteit heeft en de volume momenteel op een knooppunt is gepubliceerd of beschikbaar, danmoet ControllerExpandVolumeWORDEN aangeroepen ALS
- De plugin controller
PUBLISH_UNPUBLISH_VOLUMEcapaciteit heeft enControllerUnpublishVolumemet succes is aangeroepen.OF ANDERS
- De plugin heeft GEEN controller
PUBLISH_UNPUBLISH_VOLUMEcapaciteit, de plugin heeft knooppuntSTAGE_UNSTAGE_VOLUMEcapaciteit, enNodeUnstageVolumeis succesvol voltooid.OF ANDERS
- De plugin heeft GEEN controller
PUBLISH_UNPUBLISH_VOLUMEcapaciteit, noch knooppuntSTAGE_UNSTAGE_VOLUMEcapaciteit, enNodeUnpublishVolumeis met succes voltooid.
In wezen betekent dit dat de schijf van de virtuele machine moet worden losgekoppeld voordat deze kan worden vergroot.
Helaas, implementatie de CSI-specificaties via sidecars voldoen niet aan deze vereisten:
- In de sidecar container
csi-attacher, die verantwoordelijk zou moeten zijn voor het waarborgen van de benodigde ruimte tussen montages, is deze functionaliteit eenvoudigweg niet gerealiseerd tijdens offline resizing. Deze discussie is geïnitieerd. . - Wat is een sidecar-container in deze context? De CSI-plugin communiceert niet met de Kubernetes API, maar reageert alleen op gRPC-aanroepen die door sidecar-containers worden verzonden. Laatstgenoemden door de Kubernetes-gemeenschap.
In ons geval (CSI-plugin) ziet de schijfvergroting operatie er als volgt uit:
- We ontvangen een gRPC-aanroep
moet ControllerExpandVolume; - We proberen de schijf te vergroten via de API, maar krijgen een foutmelding over het niet kunnen uitvoeren van de operatie, omdat de schijf is gemonteerd;
- We slaan de schijf-ID op in een map met schijven waarvoor de vergrotingsoperatie moet worden uitgevoerd. Voor de duidelijkheid noemen we deze map
volumeResizeRequired; - Verwijder handmatig de pod die de schijf gebruikt. Kubernetes zal deze opnieuw opstarten. Om te voorkomen dat de schijf snel wordt gemonteerd (
ControllerPublishVolume) voordat de vergrotingsoperatie is voltooid, controleren we of deze schijf nog steeds involumeResizeRequireden geven een foutmelding terug; - De CSI-driver probeert de resize-operatie opnieuw uit te voeren. Als de operatie succesvol was, verwijderen we de schijf uit
volumeResizeRequired; - Omdat de schijf-ID afwezig is in
volumeResizeRequired,ControllerPublishVolumeverloopt succesvol, de schijf wordt gemonteerd, de pod wordt gestart.
Het lijkt allemaal vrij eenvoudig, maar zoals altijd zijn er haken en ogen. De vergroting van schijven wordt uitgevoerd door , die in geval van een fout bij het uitvoeren van de operatie met een exponentiële toename van de timeout tot 1000 seconden:
func DefaultControllerRateLimiter() RateLimiter {
return NewMaxOfRateLimiter(
NewItemExponentialFailureRateLimiter(5*time.Millisecond, 1000*time.Second),
\/\/ 10 qps, 100 bucket size. Dit is alleen voor de retry-snelheid en het is alleen de algemene factor (niet per item)
&BucketRateLimiter{Limiter: rate.NewLimiter(rate.Limit(10), 100)},
)
}Dit kan er periodiek toe leiden dat de schijfvergroting meer dan 15 minuten in beslag neemt, met als gevolg dat de bijbehorende pod niet beschikbaar is.
De enige optie die ons voldoende en pijnloos in staat stelde de potentiële stilstandtijd te verminderen, was het gebruik van onze eigen versie van de external-resizer met een maximale timeout-limiet :
workqueue.NewItemExponentialFailureRateLimiter(5*time.Millisecond, 5*time.Second)We vonden het niet nodig om een nooddiscussie te starten en de external-resizer te patchen, omdat offline schijfvergroting een relikwie is dat binnenkort zal verdwijnen bij alle cloudproviders.
Hoe te beginnen?
De driver wordt ondersteund in Kubernetes versie 1.15 en hoger. De volgende vereisten moeten worden vervuld om de driver te laten werken:
- Vlag
--allow-privilegedis ingesteld optruevoor de API-server en kubelet; - Ingeschakeld
--feature-gates=VolumeSnapshotDataSource=true,KubeletPluginsWatcher=true,CSINodeInfo=true,CSIDriverRegistry=truevoor de API-server en kubelet; - Montageverspreiding () moet ingeschakeld zijn in de cluster. Bij gebruik van Docker moet de daemon zo geconfigureerd zijn dat gedeelde montageobjecten (shared mounts) zijn toegestaan.
Alle noodzakelijke stappen voor de installatie zelf . De installatie is het creëren van objecten in Kubernetes vanuit manifesten.
Voor het functioneren van de driver heeft u het volgende nodig:
- Geef in het manifest de map-ID aan (
folder-id) van Yandex.Cloud (); - Voor interactie met de API van Yandex.Cloud in de CSI-driver wordt een serviceaccount gebruikt. In het Secret manifest moet u doorgeven van het serviceaccount. In de documentatie wordt beschreven hoe een serviceaccount wordt aangemaakt en hoe u sleutels kunt verkrijgen.
In het algemeen — , en we horen graag feedback en , mocht u tegen problemen aanlopen!
Verdere ondersteuning
Als conclusie willen we opmerken dat we deze CSI-driver niet uit een groot verlangen om plezier te hebben met het schrijven van applicaties in Go hebben ontwikkeld, maar uit dringende noodzaak binnen het bedrijf. Het lijkt ons niet zinvol om onze eigen implementatie te onderhouden, dus als Yandex interesse toont en besluit de ondersteuning van de driver voort te zetten, zullen we het repository graag aan hen overdragen.
Bovendien heeft Yandex waarschijnlijk zijn eigen implementatie van de CSI-driver in de managed Kubernetes-cluster, die als open source kan worden uitgebracht. Dit ontwikkelingstraject lijkt ons ook gunstig — de gemeenschap kan gebruikmaken van een beproefde driver van de dienstverlener in plaats van van een extern bedrijf.
P.S.
Lees ook op onze blog:
- «»;
- «»;
- «»;
- «».
Bron: habr.com
