Uitbreiding en aanvulling van Kubernetes (review en videoverslag)

Uitbreiding en aanvulling van Kubernetes (review en videoverslag)

8 april op de conferentie Sint HighLoad++ 2019, als onderdeel van de sectie “DevOps en Operations” werd een rapport “Uitbreiding en aanvulling van Kubernetes” gegeven, waaraan drie medewerkers van het bedrijf Flant deelnamen. Daarin praten we over talloze situaties waarin we de mogelijkheden van Kubernetes wilden uitbreiden en aanvullen, maar waarvoor we geen kant-en-klare en eenvoudige oplossing vonden. We hebben de nodige oplossingen in de vorm van Open Source-projecten, en deze toespraak is daar ook aan gewijd.

Traditiegetrouw presenteren wij u graag video van het rapport (50 minuten, veel informatiever dan het artikel) en de hoofdsamenvatting in tekstvorm. Gaan!

Kern en toevoegingen in K8s

Kubernetes verandert de sector en de beheersbenaderingen die al lang bestaan:

  • Dankzij hem abstracties, werken we niet langer met concepten zoals het opzetten van een configuratie of het uitvoeren van een commando (Chef, Ansible...), maar gebruiken we het groeperen van containers, services, enz.
  • We kunnen aanvragen voorbereiden zonder na te denken over de nuances van de specifieke site, waarop het gelanceerd zal worden: bare metal, cloud van een van de providers, etc.
  • Met K8s bent u nog nooit zo toegankelijk geweest beste praktijken over het organiseren van infrastructuur: schaaltechnieken, zelfherstel, fouttolerantie, enz.

Maar alles verloopt natuurlijk niet zo soepel: Kubernetes bracht ook zijn eigen nieuwe uitdagingen met zich mee.

Kubernetes geen is een maaidorser die alle problemen van alle gebruikers oplost. kern Kubernetes is alleen verantwoordelijk voor een reeks van de minimaal noodzakelijke functies die aanwezig zijn in iedereen TROS:

Uitbreiding en aanvulling van Kubernetes (review en videoverslag)

De Kubernetes-kern definieert een basisset primitieven voor het groeperen van containers, het beheren van verkeer, enzovoort. We hebben er in meer detail over gesproken verslag van 2 jaar geleden.

Uitbreiding en aanvulling van Kubernetes (review en videoverslag)

Aan de andere kant biedt K8s geweldige mogelijkheden om de beschikbare functies uit te breiden, waardoor andere worden gesloten - specifiek — gebruikersbehoeften. Toevoegingen aan Kubernetes zijn de verantwoordelijkheid van clusterbeheerders, die alles moeten installeren en configureren wat nodig is om hun cluster “in de juiste vorm” te krijgen [om hun specifieke problemen op te lossen]. Wat voor aanvullingen zijn dit? Laten we eens kijken naar enkele voorbeelden.

Voorbeelden van add-ons

Nadat we Kubernetes hebben geïnstalleerd, zullen we misschien verbaasd zijn dat de netwerken die zo noodzakelijk zijn voor de interactie van pods, zowel binnen een knooppunt als tussen knooppunten, op zichzelf niet werken. De Kubernetes-kernel garandeert niet de benodigde verbindingen, maar bepaalt het netwerk interface (CNI) voor add-ons van derden. We moeten een van deze add-ons installeren, die verantwoordelijk is voor de netwerkconfiguratie.

Uitbreiding en aanvulling van Kubernetes (review en videoverslag)

Een goed voorbeeld zijn oplossingen voor gegevensopslag (lokale schijf, netwerkblokapparaat, Ceph...). Aanvankelijk zaten ze in de kern, maar met de komst ervan CSI de situatie verandert in iets dat lijkt op wat al is beschreven: de interface bevindt zich in Kubernetes en de implementatie ervan vindt plaats in modules van derden.

Andere voorbeelden zijn:

  • Ingress-controleurs (zie hun recensie in ons recente artikel).
  • certificaat-manager:

    Uitbreiding en aanvulling van Kubernetes (review en videoverslag)

  • Операторы is een hele klasse add-ons (waaronder de genoemde cert-manager), ze definiëren primitief(en) en controller(s). De logica van hun werk wordt alleen beperkt door onze verbeeldingskracht en stelt ons in staat kant-en-klare infrastructuurcomponenten (bijvoorbeeld een DBMS) om te zetten in primitieven, waarmee veel gemakkelijker te werken is (dan met een reeks containers en hun instellingen). Er is een groot aantal operators geschreven - ook al zijn veel van hen nog niet klaar voor productie, het is slechts een kwestie van tijd:

    Uitbreiding en aanvulling van Kubernetes (review en videoverslag)

  • statistieken - nog een illustratie van hoe Kubernetes de interface (Metrics API) scheidde van de implementatie (add-ons van derden zoals Prometheus-adapter, Datadog-clusteragent...).
  • Voor monitoring en statistieken, waar in de praktijk niet alleen behoefte aan is Prometheus en Grafana, maar ook kube-state-metrics, node-exporter, enz.

En dit is niet een volledige lijst met toevoegingen... Bijvoorbeeld bij de firma Flant die we momenteel installeren 29 toevoegingen (die allemaal in totaal 249 Kubernetes-objecten creëren). Simpel gezegd: we kunnen de levensduur van een cluster niet zien zonder toevoegingen.

Automatisering

Operators zijn ontworpen om routinematige handelingen die we dagelijks tegenkomen te automatiseren. Hier zijn voorbeelden uit de praktijk waarvoor het schrijven van een operator een uitstekende oplossing zou zijn:

  1. Er is een privéregister (waarvoor een login vereist is) met afbeeldingen voor de applicatie. Er wordt aangenomen dat aan elke pod een speciaal geheim wordt toegewezen dat authenticatie in het register mogelijk maakt. Onze taak is ervoor te zorgen dat dit geheim in de naamruimte wordt gevonden, zodat pods afbeeldingen kunnen downloaden. Er kunnen veel applicaties zijn (die elk een geheim nodig hebben), en het is handig om de geheimen zelf regelmatig bij te werken, zodat de mogelijkheid om geheimen met de hand op te stellen wordt geëlimineerd. Dit is waar de operator te hulp schiet: we creëren een controller die wacht tot de naamruimte verschijnt en op basis van deze gebeurtenis een geheim aan de naamruimte toevoegt.
  2. Standaard is toegang vanaf pods tot internet verboden. Maar soms kan het nodig zijn: het is logisch dat het toegangsmachtigingsmechanisme eenvoudig werkt, zonder dat er specifieke vaardigheden voor nodig zijn, bijvoorbeeld door de aanwezigheid van een bepaald label in de naamruimte. Hoe kan de operator ons hierbij helpen? Er wordt een controller gemaakt die wacht tot het label in de naamruimte verschijnt en het juiste beleid voor internettoegang toevoegt.
  3. Een soortgelijke situatie: stel dat we een bepaald element moesten toevoegen smet, als het een soortgelijk label heeft (met een soort voorvoegsel). De acties met de operator zijn duidelijk...

In elk cluster moeten routinetaken worden opgelost juist Dit kan gedaan worden met behulp van operatoren.

Als we alle beschreven verhalen samenvatten, kwamen we tot de conclusie dat voor comfortabel werken in Kubernetes die je nodig hebt: a) installeer add-ons, B) exploitanten ontwikkelen (voor het oplossen van dagelijkse administratieve taken).

Hoe schrijf je een statement voor Kubernetes?

Over het algemeen is het schema eenvoudig:

Uitbreiding en aanvulling van Kubernetes (review en videoverslag)

... maar dan blijkt dat:

  • De Kubernetes API is een nogal niet-triviaal iets dat veel tijd kost om onder de knie te krijgen;
  • programmeren is ook niet voor iedereen weggelegd (er werd gekozen voor de Go-taal als voorkeurstaal omdat er een speciaal raamwerk voor bestaat - Operator-SDK);
  • De situatie is vergelijkbaar met het raamwerk zelf.

De bottom line: een regelaar schrijven (operator) moet aanzienlijke middelen besteden materiaal bestuderen. Dit zou gerechtvaardigd zijn voor “grote” operators, bijvoorbeeld voor het MySQL DBMS. Maar als we ons de hierboven beschreven voorbeelden herinneren (geheimen ontvouwen, toegang krijgen tot pods tot internet...), die we ook correct willen doen, dan zullen we begrijpen dat de geleverde inspanning groter zal zijn dan het resultaat dat we nu nodig hebben:

Uitbreiding en aanvulling van Kubernetes (review en videoverslag)

Over het algemeen ontstaat er een dilemma: besteed veel middelen en vind de juiste tool voor het schrijven van verklaringen, of doe het op de ouderwetse manier (maar snel). Om het op te lossen – om een ​​compromis te vinden tussen deze uitersten – hebben we ons eigen project gecreëerd: shell-operator (zie ook zijn recente aankondiging op de naaf).

Shell-operator

Hoe werkt hij? Het cluster heeft een pod met daarin een Go-binair bestand met een shell-operator. Naast hem staat een stel haken (meer details over hen - zie hieronder). De shell-operator zelf onderschrijft bepaalde ontwikkelingen in de Kubernetes API, waarna het de bijbehorende hooks lanceert.

Hoe weet de shell-operator welke hooks hij bij welke gebeurtenissen moet aanroepen? Deze informatie wordt door de haken zelf naar de shell-operator verzonden, en dat doen ze heel eenvoudig.

Een hook is een Bash-script of een ander uitvoerbaar bestand dat één enkel argument accepteert --config en reageert met JSON. Deze laatste bepaalt welke objecten voor hem interessant zijn en op welke gebeurtenissen (voor deze objecten) gereageerd moet worden:

Uitbreiding en aanvulling van Kubernetes (review en videoverslag)

Ik zal de implementatie op de shell-operator van een van onze voorbeelden illustreren: het ontleden van geheimen voor toegang tot een privéregister met applicatie-images. Het bestaat uit twee fasen.

Oefenen: 1. Schrijf een haakje

Allereerst zullen we in de haak verwerken --config, wat aangeeft dat we geïnteresseerd zijn in naamruimten, en specifiek in het moment van hun creatie:

[[ $1 == "--config" ]] ; then
  cat << EOF
{
  "onKubernetesEvent": [
    {
      "kind": "namespace",
      "event": ["add"]
    }
  ]
}
EOF
…

Hoe zou de logica eruit zien? Ook heel simpel:

…
else
  createdNamespace=$(jq -r '.[0].resourceName' $BINDING_CONTEXT_PATH)
  kubectl create -n ${createdNamespace} -f - << EOF
Kind: Secret
...
EOF
fi

De eerste stap is om erachter te komen welke naamruimte is gemaakt, en de tweede is om deze te maken met behulp van kubectl geheim voor deze naamruimte.

Oefening: 2. De afbeelding in elkaar zetten

Het enige dat overblijft is om de gemaakte hook door te geven aan de shell-operator - hoe doe je dit? De shell-operator zelf wordt geleverd als een Docker-image, dus het is onze taak om de hook toe te voegen aan een speciale map in deze image:

FROM flant/shell-operator:v1.0.0-beta.1
ADD my-handler.sh /hooks

Het enige dat overblijft is het in elkaar zetten en duwen:

$ docker build -t registry.example.com/my-operator:v1 .
$ docker push registry.example.com/my-operator:v1

De laatste hand is het implementeren van de image in het cluster. Om dit te doen, laten we schrijven Deployment:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: my-operator
spec:
  template:
    spec:
      containers:
      - name: my-operator
        image: registry.example.com/my-operator:v1 # 1
      serviceAccountName: my-operator              # 2

Er zijn twee punten waar u op moet letten:

  1. indicatie van de nieuw gecreëerde afbeelding;
  2. Dit is een systeemcomponent die (minimaal) rechten nodig heeft om zich te abonneren op gebeurtenissen in Kubernetes en om geheimen aan naamruimten toe te wijzen, dus maken we een ServiceAccount (en een set regels) voor de hook.

Resultaat - we hebben ons probleem opgelost aan familieleden voor Kubernetes op een manier die een operator creëert voor het ontleden van geheimen.

Andere shell-operatorfuncties

Om de objecten van het door u gekozen type waarmee de haak zal werken te beperken, ze kunnen worden gefilterd, selecteren op basis van bepaalde labels (of met behulp van matchExpressions):

"onKubernetesEvent": [
  {
    "selector": {
      "matchLabels": {
        "foo": "bar",
       },
       "matchExpressions": [
         {
           "key": "allow",
           "operation": "In",
           "values": ["wan", "warehouse"],
         },
       ],
     }
     …
  }
]

Mits deduplicatiemechanisme, waarmee je - met behulp van een jq-filter - grote JSON-objecten naar kleine kunt converteren, waarbij alleen die parameters overblijven die we op veranderingen willen controleren.

Wanneer een hook wordt geroepen, geeft de shell-operator deze door objectgegevens, die voor elke behoefte kan worden gebruikt.

De gebeurtenissen die hooks activeren zijn niet beperkt tot Kubernetes-gebeurtenissen: de shell-operator biedt ondersteuning voor haken op tijd roepen (vergelijkbaar met crontab in een traditionele planner), evenals een speciale gebeurtenis bij opstarten. Al deze gebeurtenissen kunnen worden gecombineerd en aan dezelfde hook worden toegewezen.

En nog twee kenmerken van de shell-operator:

  1. Het werkt asynchroon. Omdat er een Kubernetes-gebeurtenis (zoals het maken van een object) is ontvangen, kunnen andere gebeurtenissen (zoals het verwijderen van hetzelfde object) in het cluster hebben plaatsgevonden, en hooks moeten hier rekening mee houden. Als de hook met een fout is uitgevoerd, is dit standaard het geval herinneren tot succesvolle voltooiing (dit gedrag kan worden gewijzigd).
  2. Het exporteert statistieken voor Prometheus, waarmee je kunt begrijpen of de shell-operator werkt, ontdek het aantal fouten voor elke hook en de huidige wachtrijgrootte.

Om dit deel van het rapport samen te vatten:

Uitbreiding en aanvulling van Kubernetes (review en videoverslag)

Add-ons installeren

Voor comfortabel werken met Kubernetes werd ook de noodzaak genoemd om add-ons te installeren. Ik zal u erover vertellen aan de hand van het voorbeeld van het pad van ons bedrijf naar hoe we het nu doen.

We zijn met Kubernetes aan de slag gegaan met meerdere clusters, met als enige toevoeging Ingress. Het moest in elk cluster anders worden geïnstalleerd en we hebben verschillende YAML-configuraties gemaakt voor verschillende omgevingen: bare metal, AWS...

Naarmate er meer clusters waren, waren er meer configuraties. Bovendien hebben we deze configuraties zelf verbeterd, waardoor ze behoorlijk heterogeen zijn geworden:

Uitbreiding en aanvulling van Kubernetes (review en videoverslag)

Om alles op orde te krijgen, zijn we begonnen met een script (install-ingress.sh), dat als argument het type cluster nam waarop we zullen inzetten, de benodigde YAML-configuratie genereerde en deze uitrolde naar Kubernetes.

Kortom, ons verdere pad en de daarmee samenhangende redenering waren als volgt:

  • om met YAML-configuraties te werken is een sjabloon-engine vereist (in de eerste fasen is dit eenvoudig);
  • met de toename van het aantal clusters ontstond de behoefte aan automatische updates (de eerste oplossing was om het script in Git te plaatsen, het bij te werken met cron en het uit te voeren);
  • een soortgelijk script was vereist voor Prometheus (install-prometheus.sh), valt het echter op vanwege het feit dat het veel meer invoergegevens vereist, evenals de opslag ervan (op een goede manier - gecentraliseerd en in een cluster), en dat sommige gegevens (wachtwoorden) automatisch kunnen worden gegenereerd:

    Uitbreiding en aanvulling van Kubernetes (review en videoverslag)

  • het risico dat er iets verkeerd zou worden uitgerold naar een groeiend aantal clusters werd voortdurend groter, dus we realiseerden ons dat installateurs (dat wil zeggen twee scripts: voor Ingress en Prometheus) staging was nodig (verschillende branches in Git, verschillende crons om ze bij te werken in de overeenkomstige: stabiele of testclusters);
  • с kubectl apply het is moeilijk geworden om mee te werken omdat het niet declaratief is en alleen objecten kan creëren, maar geen beslissingen kan nemen over hun status/ze kan verwijderen;
  • We misten enkele functies die we op dat moment helemaal niet hadden geïmplementeerd:
    • volledige controle over het resultaat van clusterupdates,
    • automatische bepaling van enkele parameters (invoer voor installatiescripts) op basis van gegevens die uit het cluster kunnen worden verkregen (discovery),
    • de logische ontwikkeling ervan in de vorm van voortdurende ontdekking.

We hebben al deze opgebouwde ervaring geïmplementeerd in het kader van ons andere project - add-on-operator.

Addon-operator

Het is gebaseerd op de reeds genoemde shell-operator. Het hele systeem ziet er als volgt uit:

Het volgende is toegevoegd aan de shell-operator hooks:

  • waarden opslaan,
  • Helmdiagram,
  • onderdeel dat bewaakt de waardenopslag en - in geval van eventuele wijzigingen - vraagt ​​Helm om de kaart opnieuw te rollen.

Uitbreiding en aanvulling van Kubernetes (review en videoverslag)

We kunnen dus reageren op een gebeurtenis in Kubernetes, een hook lanceren en vanuit deze hook kunnen we wijzigingen aanbrengen in de opslag, waarna de grafiek opnieuw wordt gedownload. In het resulterende diagram scheiden we de set haken en het diagram in één component, die we noemen module:

Uitbreiding en aanvulling van Kubernetes (review en videoverslag)

Er kunnen veel modules zijn, en daaraan voegen we globale hooks, een globale waardenopslag en een component toe die deze globale opslag bewaakt.

Als er nu iets gebeurt in Kubernetes, kunnen we daarop reageren met behulp van een mondiale hook en iets in de mondiale winkel veranderen. Deze wijziging wordt opgemerkt en zorgt ervoor dat alle modules in het cluster worden uitgerold:

Uitbreiding en aanvulling van Kubernetes (review en videoverslag)

Dit schema voldoet aan alle vereisten voor het installeren van add-ons die hierboven zijn vermeld:

  • Helm is verantwoordelijk voor templates en declarativiteit.
  • Het probleem van automatische updates werd opgelost met behulp van een global hook, die volgens een schema naar het register gaat en, als het daar een nieuw systeemimage ziet, het uitrolt (d.w.z. “zichzelf”).
  • Het opslaan van instellingen in het cluster wordt geïmplementeerd met behulp van Configuratiekaart, dat de primaire gegevens voor de opslag bevat (bij het opstarten worden ze in de opslag geladen).
  • Problemen met het genereren, ontdekken en continu ontdekken van wachtwoorden werden opgelost met behulp van hooks.
  • Staging wordt bereikt dankzij tags, die Docker out-of-the-box ondersteunt.
  • Het resultaat wordt gemonitord met behulp van statistieken waarmee we de status kunnen begrijpen.

Dit hele systeem is geïmplementeerd in de vorm van een enkel binair bestand in Go, dat addon-operator wordt genoemd. Hierdoor ziet het diagram er eenvoudiger uit:

Uitbreiding en aanvulling van Kubernetes (review en videoverslag)

Het belangrijkste onderdeel in dit diagram is een reeks modules (hieronder grijs gemarkeerd). Nu kunnen we met een beetje moeite een module voor de vereiste add-on schrijven en er zeker van zijn dat deze in elk cluster wordt geïnstalleerd, wordt bijgewerkt en reageert op de gebeurtenissen die deze in het cluster nodig heeft.

"Flant" gebruikt add-on-operator op meer dan 70 Kubernetes-clusters. Huidige status - alpha-versie. Nu bereiden we documentatie voor om de bèta vrij te geven, maar voorlopig in de repository voorbeelden beschikbaar, op basis waarvan u uw eigen add-on kunt maken.

Waar kan ik de modules voor addon-operator verkrijgen? Het publiceren van onze bibliotheek is voor ons de volgende fase; we zijn van plan dit in de zomer te doen.

Video's en dia's

Video van de voorstelling (~50 minuten):

Presentatie van het rapport:

PS

Andere rapporten op onze blog:

Mogelijk bent u ook geïnteresseerd in de volgende publicaties:

Bron: www.habr.com

Voeg een reactie