Gaan? Bash! Ontmoet die dop-operateur (resensie en videoverslag van KubeCon EU'2020)

Hierdie jaar was die belangrikste Europese Kubernetes-konferensie - KubeCon + CloudNativeCon Europe 2020 - virtueel. So 'n verandering in formaat het ons egter nie verhinder om ons lank beplande verslag “Gaan? Bash! Ontmoet die Shell-operateur” toegewy aan ons Open Source-projek dop-operateur.

Hierdie artikel, geïnspireer deur die toespraak, bied 'n benadering om die proses van die skep van operateurs vir Kubernetes te vereenvoudig en wys hoe jy jou eie kan maak met minimale moeite deur 'n dop-operateur te gebruik.

Gaan? Bash! Ontmoet die dop-operateur (resensie en videoverslag van KubeCon EU'2020)

Bekendstelling video met die verslag (~23 minute in Engels, merkbaar meer insiggewend as die artikel) en die hoofuittreksel daaruit in teksvorm. Gaan!

By Flant optimaliseer en outomatiseer ons voortdurend alles. Vandag sal ons praat oor 'n ander opwindende konsep. Ontmoet: wolk-inheemse dop scripting!

Kom ons begin egter by die konteks waarin dit alles gebeur: Kubernetes.

Kubernetes API en beheerders

Die API in Kubernetes kan voorgestel word as 'n soort lêerbediener met gidse vir elke tipe voorwerp. Voorwerpe (hulpbronne) op hierdie bediener word verteenwoordig deur YAML-lêers. Daarbenewens het die bediener 'n basiese API waarmee u drie dinge kan doen:

  • ontvang hulpbron volgens sy soort en naam;
  • verandering hulpbron (in hierdie geval stoor die bediener slegs "korrekte" voorwerpe - almal wat verkeerd gevorm is of bedoel is vir ander gidse word weggegooi);
  • spoor vir die hulpbron (in hierdie geval ontvang die gebruiker onmiddellik sy huidige/bygewerkte weergawe).

Kubernetes tree dus op as 'n soort lêerbediener (vir YAML-manifeste) met drie basiese metodes (ja, eintlik is daar ander, maar ons sal hulle vir eers weglaat).

Gaan? Bash! Ontmoet die dop-operateur (resensie en videoverslag van KubeCon EU'2020)

Die probleem is dat die bediener slegs inligting kan stoor. Om dit te laat werk het jy nodig kontroleerder - die tweede belangrikste en fundamentele konsep in die wêreld van Kubernetes.

Daar is twee hooftipes beheerders. Die eerste neem inligting van Kubernetes, verwerk dit volgens geneste logika en stuur dit terug na K8s. Die tweede een neem inligting van Kubernetes af, maar, anders as die eerste tipe, verander die toestand van sommige eksterne hulpbronne.

Kom ons kyk van naderby na die proses om 'n ontplooiing in Kubernetes te skep:

  • Ontplooiingsbeheerder (ingesluit in kube-controller-manager) ontvang inligting oor Ontplooiing en skep 'n ReplicaSet.
  • ReplicaSet skep twee replikas (twee peule) gebaseer op hierdie inligting, maar hierdie peule is nog nie geskeduleer nie.
  • Die skeduleerder skeduleer peule en voeg nodusinligting by hul YAML's.
  • Kubelets maak veranderinge aan 'n eksterne hulpbron (sê Docker).

Dan word hierdie hele volgorde in omgekeerde volgorde herhaal: die kubelet gaan die houers na, bereken die peul se status en stuur dit terug. Die ReplicaSet-beheerder ontvang die status en werk die toestand van die replika-stel op. Dieselfde ding gebeur met die Ontplooiingsbeheerder en die gebruiker kry uiteindelik die opgedateerde (huidige) status.

Gaan? Bash! Ontmoet die dop-operateur (resensie en videoverslag van KubeCon EU'2020)

Shell-operateur

Dit blyk dat Kubernetes gebaseer is op die gesamentlike werk van verskeie beheerders (Kubernetes-operateurs is ook beheerders). Die vraag ontstaan, hoe om jou eie operateur met minimale moeite te skep? En hier kom die een wat ons ontwikkel het tot die redding dop-operateur. Dit laat stelseladministrateurs toe om hul eie stellings te skep met behulp van bekende metodes.

Gaan? Bash! Ontmoet die dop-operateur (resensie en videoverslag van KubeCon EU'2020)

Eenvoudige voorbeeld: kopiëring van geheime

Kom ons kyk na 'n eenvoudige voorbeeld.

Kom ons sê ons het 'n Kubernetes-kluster. Dit het 'n naamruimte default met een of ander Geheim mysecret. Daarbenewens is daar ander naamruimtes in die groepie. Sommige van hulle het 'n spesifieke etiket aan hulle geheg. Ons doel is om Geheim in naamruimtes met 'n etiket te kopieer.

Die taak word bemoeilik deur die feit dat nuwe naamruimtes in die groep kan verskyn, en sommige van hulle kan hierdie etiket hê. Aan die ander kant, wanneer die etiket uitgevee word, moet Geheim ook uitgevee word. Daarbenewens kan die Geheim self ook verander: in hierdie geval moet die nuwe Geheim na alle naamruimtes met etikette gekopieer word. As Geheim per ongeluk in enige naamruimte uitgevee word, moet ons operateur dit onmiddellik herstel.

Noudat die taak geformuleer is, is dit tyd om dit met behulp van die dopoperateur te begin implementeer. Maar eers is dit die moeite werd om 'n paar woorde oor die dopoperateur self te sê.

Hoe dop-operateur werk

Soos ander werkladings in Kubernetes, loop shell-operateur in sy eie pod. In hierdie pod in die gids /hooks uitvoerbare lêers gestoor word. Dit kan skrifte in Bash, Python, Ruby, ens. Ons noem sulke uitvoerbare lêers hake (hakies).

Gaan? Bash! Ontmoet die dop-operateur (resensie en videoverslag van KubeCon EU'2020)

Shell-operateur teken in op Kubernetes-geleenthede en voer hierdie hakies uit in reaksie op daardie gebeurtenisse wat ons nodig het.

Gaan? Bash! Ontmoet die dop-operateur (resensie en videoverslag van KubeCon EU'2020)

Hoe weet die dopoperateur watter haak om te hardloop en wanneer? Die punt is dat elke haak twee stadiums het. Tydens opstart loop die dopoperateur alle hake met 'n argument --config Dit is die konfigurasie stadium. En daarna word hake op die normale manier gelanseer – in reaksie op die gebeure waaraan hulle geheg is. In laasgenoemde geval ontvang die haak die bindende konteks (bindende konteks) - data in JSON-formaat, waaroor ons hieronder in meer besonderhede sal praat.

Maak 'n operateur in Bash

Nou is ons gereed vir implementering. Om dit te doen, moet ons twee funksies skryf (terloops, ons beveel aan die biblioteek shell_lib, wat skryfhakies in Bash aansienlik vereenvoudig):

  • die eerste is nodig vir die konfigurasie stadium - dit vertoon die bindende konteks;
  • die tweede bevat die hooflogika van die haak.

#!/bin/bash

source /shell_lib.sh

function __config__() {
  cat << EOF
    configVersion: v1
    # BINDING CONFIGURATION
EOF
}

function __main__() {
  # THE LOGIC
}

hook::run "$@"

Die volgende stap is om te besluit watter voorwerpe ons benodig. In ons geval moet ons naspoor:

  • brongeheim vir veranderinge;
  • alle naamruimtes in die groepie, sodat jy weet watter een 'n etiket aan hulle het;
  • teiken geheime om te verseker dat hulle almal gesinchroniseer is met die brongeheim.

Teken in op die geheime bron

Bindende konfigurasie daarvoor is redelik eenvoudig. Ons dui aan dat ons belangstel in Geheim met die naam mysecret in naamruimte default:

Gaan? Bash! Ontmoet die dop-operateur (resensie en videoverslag van KubeCon EU'2020)

function __config__() {
  cat << EOF
    configVersion: v1
    kubernetes:
    - name: src_secret
      apiVersion: v1
      kind: Secret
      nameSelector:
        matchNames:
        - mysecret
      namespace:
        nameSelector:
          matchNames: ["default"]
      group: main
EOF

As gevolg hiervan sal die haak geaktiveer word wanneer die brongeheim verander (src_secret) en ontvang die volgende bindende konteks:

Gaan? Bash! Ontmoet die dop-operateur (resensie en videoverslag van KubeCon EU'2020)

Soos jy kan sien, bevat dit die naam en die hele voorwerp.

Bly op hoogte van naamruimtes

Nou moet jy op naamruimtes inteken. Om dit te doen, spesifiseer ons die volgende bindende konfigurasie:

- name: namespaces
  group: main
  apiVersion: v1
  kind: Namespace
  jqFilter: |
    {
      namespace: .metadata.name,
      hasLabel: (
       .metadata.labels // {} |  
         contains({"secret": "yes"})
      )
    }
  group: main
  keepFullObjectsInMemory: false

Soos u kan sien, het 'n nuwe veld met die naam in die konfigurasie verskyn jqFilter. Soos sy naam aandui, jqFilter filter alle onnodige inligting uit en skep 'n nuwe JSON-voorwerp met die velde wat vir ons van belang is. 'n Haak met 'n soortgelyke konfigurasie sal die volgende bindende konteks ontvang:

Gaan? Bash! Ontmoet die dop-operateur (resensie en videoverslag van KubeCon EU'2020)

Dit bevat 'n skikking filterResults vir elke naamruimte in die groepie. Boole veranderlike hasLabel dui aan of 'n etiket aan 'n gegewe naamruimte geheg is. Kieser keepFullObjectsInMemory: false dui aan dat dit nie nodig is om volledige voorwerpe in die geheue te hou nie.

Volg teikengeheime

Ons teken in op alle geheime wat 'n aantekening gespesifiseer het managed-secret: "yes" (dit is ons teiken dst_secrets):

- name: dst_secrets
  apiVersion: v1
  kind: Secret
  labelSelector:
    matchLabels:
      managed-secret: "yes"
  jqFilter: |
    {
      "namespace":
        .metadata.namespace,
      "resourceVersion":
        .metadata.annotations.resourceVersion
    }
  group: main
  keepFullObjectsInMemory: false

In hierdie geval jqFilter filter alle inligting behalwe die naamruimte en parameter uit resourceVersion. Die laaste parameter is na die aantekening oorgedra toe die geheim geskep is: dit laat jou toe om weergawes van geheime te vergelyk en op datum te hou.

'n Haak wat op hierdie manier gekonfigureer is, sal, wanneer dit uitgevoer word, die drie bindingskontekste wat hierbo beskryf word, ontvang. Hulle kan beskou word as 'n soort momentopname (momentopname) groepie.

Gaan? Bash! Ontmoet die dop-operateur (resensie en videoverslag van KubeCon EU'2020)

Op grond van al hierdie inligting kan 'n basiese algoritme ontwikkel word. Dit herhaal oor alle naamruimtes en:

  • indien hasLabel sake true vir die huidige naamruimte:
    • vergelyk die globale geheim met die plaaslike een:
      • as hulle dieselfde is, doen dit niks;
      • as hulle verskil - voer uit kubectl replace of create;
  • indien hasLabel sake false vir die huidige naamruimte:
    • maak seker dat Secret nie in die gegewe naamruimte is nie:
      • as die plaaslike geheim teenwoordig is, vee dit uit met behulp van kubectl delete;
      • as die plaaslike geheim nie opgespoor word nie, doen dit niks.

Gaan? Bash! Ontmoet die dop-operateur (resensie en videoverslag van KubeCon EU'2020)

Implementering van die algoritme in Bash jy kan aflaai in ons bewaarplekke met voorbeelde.

Dit is hoe ons 'n eenvoudige Kubernetes-beheerder kon skep deur 35 reëls YAML-konfigurasie en omtrent dieselfde hoeveelheid Bash-kode te gebruik! Die dopoperateur se taak is om hulle aan mekaar te koppel.

Die kopiëring van geheime is egter nie die enigste toepassingsgebied van die nut nie. Hier is nog 'n paar voorbeelde om te wys waartoe hy in staat is.

Voorbeeld 1: Maak veranderinge aan ConfigMap

Kom ons kyk na 'n ontplooiing wat uit drie peule bestaan. Peule gebruik ConfigMap om sekere konfigurasies te stoor. Toe die peule bekendgestel is, was ConfigMap in 'n sekere toestand (kom ons noem dit v.1). Gevolglik gebruik alle peule hierdie spesifieke weergawe van ConfigMap.

Kom ons neem nou aan dat die ConfigMap verander het (v.2). Die peule sal egter die vorige weergawe van ConfigMap (v.1) gebruik:

Gaan? Bash! Ontmoet die dop-operateur (resensie en videoverslag van KubeCon EU'2020)

Hoe kan ek hulle kry om na die nuwe ConfigMap (v.2) oor te skakel? Die antwoord is eenvoudig: gebruik 'n sjabloon. Kom ons voeg 'n kontrolesom-aantekening by die afdeling template Ontplooiing konfigurasies:

Gaan? Bash! Ontmoet die dop-operateur (resensie en videoverslag van KubeCon EU'2020)

Gevolglik sal hierdie kontrolesom in alle peule geregistreer word, en dit sal dieselfde wees as dié van Ontplooiing. Nou moet jy net die aantekening bywerk wanneer die ConfigMap verander. En die dop-operateur kom handig te pas in hierdie geval. Al wat jy hoef te doen is om te programmeer 'n haak wat sal inteken op die ConfigMap en die kontrolesom sal opdateer.

As die gebruiker veranderinge aan die ConfigMap maak, sal die dopoperateur dit opmerk en die kontrolesom herbereken. Daarna sal die magie van Kubernetes in werking tree: die orkeseerder sal die peul doodmaak, 'n nuwe een skep, wag dat dit word Ready, en gaan aan na die volgende een. As gevolg hiervan, sal Ontplooiing sinchroniseer en na die nuwe weergawe van ConfigMap oorskakel.

Gaan? Bash! Ontmoet die dop-operateur (resensie en videoverslag van KubeCon EU'2020)

Voorbeeld 2: Werk met pasgemaakte hulpbrondefinisies

Soos u weet, laat Kubernetes u toe om persoonlike tipes voorwerpe te skep. Byvoorbeeld, jy kan soort skep MysqlDatabase. Kom ons sê hierdie tipe het twee metadataparameters: name и namespace.

apiVersion: example.com/v1alpha1
kind: MysqlDatabase
metadata:
  name: foo
  namespace: bar

Ons het 'n Kubernetes-kluster met verskillende naamruimtes waarin ons MySQL-databasisse kan skep. In hierdie geval kan dop-operateur gebruik word om hulpbronne op te spoor MysqlDatabase, koppel hulle aan die MySQL-bediener en sinchroniseer die verlangde en waargenome toestande van die groepering.

Gaan? Bash! Ontmoet die dop-operateur (resensie en videoverslag van KubeCon EU'2020)

Voorbeeld 3: Groepsnetwerkmonitering

Soos u weet, is die gebruik van ping die eenvoudigste manier om 'n netwerk te monitor. In hierdie voorbeeld sal ons wys hoe om sulke monitering te implementeer met behulp van shell-operator.

Eerstens moet u inteken op nodusse. Die dopoperateur benodig die naam en IP-adres van elke nodus. Met hul hulp sal hy hierdie nodusse ping.

configVersion: v1
kubernetes:
- name: nodes
  apiVersion: v1
  kind: Node
  jqFilter: |
    {
      name: .metadata.name,
      ip: (
       .status.addresses[] |  
        select(.type == "InternalIP") |
        .address
      )
    }
  group: main
  keepFullObjectsInMemory: false
  executeHookOnEvent: []
schedule:
- name: every_minute
  group: main
  crontab: "* * * * *"

Parameter executeHookOnEvent: [] verhoed dat die haak loop in reaksie op enige gebeurtenis (dit is, in reaksie op die verandering, byvoeging, verwydering van nodusse). Hy het egter sal hardloop (en werk die lys nodusse op) Geskeduleer - elke minuut, soos deur die veld voorgeskryf schedule.

Nou ontstaan ​​die vraag, hoe presies weet ons van probleme soos pakkieverlies? Kom ons kyk na die kode:

function __main__() {
  for i in $(seq 0 "$(context::jq -r '(.snapshots.nodes | length) - 1')"); do
    node_name="$(context::jq -r '.snapshots.nodes['"$i"'].filterResult.name')"
    node_ip="$(context::jq -r '.snapshots.nodes['"$i"'].filterResult.ip')"
    packets_lost=0
    if ! ping -c 1 "$node_ip" -t 1 ; then
      packets_lost=1
    fi
    cat >> "$METRICS_PATH" <<END
      {
        "name": "node_packets_lost",
        "add": $packets_lost,
        "labels": {
          "node": "$node_name"
        }
      }
END
  done
}

Ons herhaal die lys nodusse, kry hul name en IP-adresse, ping dit en stuur die resultate na Prometheus. Shell-operateur kan metrieke na Prometheus uitvoer, stoor hulle in 'n lêer wat geleë is volgens die pad gespesifiseer in die omgewingsveranderlike $METRICS_PATH.

Hier so jy kan 'n operateur maak vir eenvoudige netwerkmonitering in 'n groepering.

Tou meganisme

Hierdie artikel sal onvolledig wees sonder om 'n ander belangrike meganisme wat in die dopoperateur ingebou is, te beskryf. Stel jou voor dat dit 'n soort haak uitvoer in reaksie op 'n gebeurtenis in die groep.

  • Wat gebeur as daar terselfdertyd iets in die groep gebeur? nog een gebeurtenis?
  • Sal dopoperateur nog 'n voorbeeld van die haak laat loop?
  • Wat as, sê, vyf gebeurtenisse op een slag in die groep gebeur?
  • Sal die dopoperateur hulle parallel verwerk?
  • Wat van verbruikte hulpbronne soos geheue en SVE?

Gelukkig het dop-operateur 'n ingeboude tou-meganisme. Alle gebeurtenisse word in 'n tou geplaas en opeenvolgend verwerk.

Kom ons illustreer dit met voorbeelde. Kom ons sê ons het twee hake. Die eerste gebeurtenis gaan na die eerste hoek. Sodra die verwerking voltooi is, beweeg die tou vorentoe. Die volgende drie gebeurtenisse word na die tweede haak herlei - hulle word uit die tou verwyder en in 'n "bondel" daarin ingevoer. Dit is haak ontvang 'n verskeidenheid gebeurtenisse - of, meer presies, 'n verskeidenheid bindende kontekste.

Ook hierdie geleenthede kan in een groot gekombineer word. Die parameter is hiervoor verantwoordelik group in die bindende opset.

Gaan? Bash! Ontmoet die dop-operateur (resensie en videoverslag van KubeCon EU'2020)

Jy kan enige aantal toue/hake en hul verskillende kombinasies skep. Byvoorbeeld, een tou kan met twee hake werk, of andersom.

Gaan? Bash! Ontmoet die dop-operateur (resensie en videoverslag van KubeCon EU'2020)

Al wat jy hoef te doen is om die veld dienooreenkomstig op te stel queue in die bindende opset. As 'n tounaam nie gespesifiseer is nie, loop die haak op die verstekwaglys (default). Hierdie tou-meganisme laat jou toe om alle hulpbronbestuurprobleme heeltemal op te los wanneer jy met hake werk.

Gevolgtrekking

Ons het verduidelik wat 'n dop-operateur is, gewys hoe dit gebruik kan word om vinnig en moeiteloos Kubernetes-operateurs te skep, en het verskeie voorbeelde van die gebruik daarvan gegee.

Gedetailleerde inligting oor die dopoperateur, sowel as 'n vinnige handleiding oor hoe om dit te gebruik, is beskikbaar in die ooreenstemmende bewaarplekke op GitHub. Moenie huiwer om ons te kontak met vrae nie: jy kan dit in 'n spesiale bespreek Telegram groep (in Russies) of in hierdie forum (in Engels).

En as jy daarvan gehou het, is ons altyd bly om nuwe uitgawes/PR/sterre op GitHub te sien, waar jy terloops ander kan vind interessante projekte. Onder hulle is dit die moeite werd om uit te lig addon-operateur, wat die groot broer van dop-operateur is. Hierdie hulpprogram gebruik Helm-kaarte om byvoegings te installeer, kan opdaterings lewer en verskeie grafiekparameters/waardes monitor, beheer die installasieproses van kaarte, en kan dit ook verander in reaksie op gebeure in die groepering.

Gaan? Bash! Ontmoet die dop-operateur (resensie en videoverslag van KubeCon EU'2020)

Video's en skyfies

Video van die optrede (~23 minute):


Verslagaanbieding:

PS

Lees ook op ons blog:

Bron: will.com

Voeg 'n opmerking