Kas minna? Bash! Tutvuge shell-operaatoriga (KubeCon EU'2020 ülevaade ja videoaruanne)

Sel aastal oli Euroopa peamine Kubernetese konverents – KubeCon + CloudNativeCon Europe 2020 – virtuaalne. Selline formaadimuutus ei takistanud meil aga esitamast meie kaua planeeritud aruannet „Mine? Bash! Tutvuge Shelli operaatoriga”, mis on pühendatud meie avatud lähtekoodiga projektile kesta operaator.

See kõnest inspireeritud artikkel tutvustab lähenemisviisi Kubernetese operaatorite loomise protsessi lihtsustamiseks ja näitab, kuidas saate shell-operaatori abil minimaalse vaevaga ise luua.

Kas minna? Bash! Tutvuge shell-operaatoriga (KubeCon EU'2020 ülevaade ja videoaruanne)

Tutvustame video raportist (~23 minutit inglise keeles, märgatavalt informatiivsem kui artikkel) ja põhiväljavõte sellest teksti kujul. Mine!

Flantis optimeerime ja automatiseerime pidevalt kõike. Täna räägime veel ühest põnevast kontseptsioonist. Tutvuge: pilvepõhise kesta skriptimine!

Alustame aga kontekstist, milles see kõik toimub: Kubernetes.

Kubernetes API ja kontrollerid

Kubernetese API-d saab kujutada omamoodi failiserverina, kus on kataloogid igat tüüpi objektide jaoks. Selle serveri objekte (ressursse) esindavad YAML-failid. Lisaks on serveril põhiline API, mis võimaldab teha kolme asja:

  • saada ressurss liigi ja nime järgi;
  • muutus ressurss (sel juhul salvestab server ainult “õigeid” objekte - kõik valesti moodustatud või muude kataloogide jaoks mõeldud objektid visatakse kõrvale);
  • järgi ressursi jaoks (sel juhul saab kasutaja kohe selle praeguse/uuendatud versiooni).

Seega toimib Kubernetes omamoodi failiserverina (YAML-i manifestide jaoks) kolme põhimeetodiga (jah, tegelikult on ka teisi, kuid jätame need praegu välja).

Kas minna? Bash! Tutvuge shell-operaatoriga (KubeCon EU'2020 ülevaade ja videoaruanne)

Probleem on selles, et server saab salvestada ainult teavet. Et see toimiks, on vaja kontroller - tähtsuselt ja fundamentaalsemalt teine ​​kontseptsioon Kubernetese maailmas.

Kontrollereid on kahte peamist tüüpi. Esimene võtab Kubernetesist teabe, töötleb seda vastavalt pesastatud loogikale ja tagastab selle K8-le. Teine võtab teavet Kubernetesist, kuid erinevalt esimesest tüübist muudab mõne välise ressursi olekut.

Vaatame lähemalt Kubernetes juurutamise loomise protsessi:

  • Juurutuskontroller (sisaldub komplektis kube-controller-manager) saab teavet juurutamise kohta ja loob replicaSeti.
  • ReplicaSet loob selle teabe põhjal kaks koopiat (kaks kausta), kuid need pole veel ajastatud.
  • Planeerija ajastab kaustasid ja lisab nende YAML-idele sõlmeteabe.
  • Kubeletid teevad muudatusi välises ressursis (näiteks Docker).

Seejärel korratakse kogu seda jada vastupidises järjekorras: kubelet kontrollib konteinereid, arvutab kauna oleku ja saadab selle tagasi. ReplicaSeti kontroller võtab vastu koopiakomplekti oleku ja värskendab selle olekut. Sama juhtub juurutamise kontrolleriga ja kasutaja saab lõpuks värskendatud (praeguse) oleku.

Kas minna? Bash! Tutvuge shell-operaatoriga (KubeCon EU'2020 ülevaade ja videoaruanne)

Shell-operaator

Selgub, et Kubernetes põhineb erinevate kontrollerite ühistööl (kubernetese operaatorid on ka kontrollerid). Tekib küsimus, kuidas luua oma operaator minimaalse vaevaga? Ja siin tuleb appi see, mille me välja arendasime kesta operaator. See võimaldab süsteemiadministraatoritel luua tuttavaid meetodeid kasutades oma avaldusi.

Kas minna? Bash! Tutvuge shell-operaatoriga (KubeCon EU'2020 ülevaade ja videoaruanne)

Lihtne näide: saladuste kopeerimine

Vaatame lihtsat näidet.

Oletame, et meil on Kubernetese klaster. Sellel on nimeruum default mõne saladusega mysecret. Lisaks on klastris ka teisi nimeruume. Mõnel neist on küljes konkreetne silt. Meie eesmärk on kopeerida Secret sildiga nimeruumidesse.

Ülesande teeb keeruliseks asjaolu, et klastris võivad ilmuda uued nimeruumid ja mõnel neist võib olla see silt. Teisest küljest tuleks sildi kustutamisel kustutada ka Secret. Lisaks sellele võib muutuda ka saladus ise: sel juhul tuleb uus Secret kopeerida kõikidesse siltidega nimeruumidesse. Kui saladus mis tahes nimeruumist kogemata kustutatakse, peaks meie operaator selle viivitamatult taastama.

Nüüd, kui ülesanne on sõnastatud, on aeg alustada selle rakendamist shell-operaatori abil. Kuid kõigepealt tasub öelda paar sõna shell-operaatori enda kohta.

Kuidas shell-operaator töötab

Sarnaselt muudele Kubernetese töökoormustele töötab shell-operaator oma kaustas. Selles kataloogis olevas kaustas /hooks käivitatavad failid salvestatakse. Need võivad olla Bashi, Pythoni, Ruby jne skriptid. Me nimetame selliseid käivitatavaid faile konksudeks (konksud).

Kas minna? Bash! Tutvuge shell-operaatoriga (KubeCon EU'2020 ülevaade ja videoaruanne)

Shell-operator tellib Kubernetese sündmused ja käivitab need konksud vastuseks neile sündmustele, mida vajame.

Kas minna? Bash! Tutvuge shell-operaatoriga (KubeCon EU'2020 ülevaade ja videoaruanne)

Kuidas kooreoperaator teab, millist konksu ja millal juhtida? Asi on selles, et igal konksul on kaks etappi. Käivitamise ajal käivitab shell-operaator kõik konksud argumendiga --config See on seadistamise etapp. Ja pärast seda käivitatakse konksud tavapärasel viisil - vastuseks sündmustele, millega need on seotud. Viimasel juhul saab konks siduva konteksti (siduv kontekst) - andmed JSON-vormingus, millest räägime allpool üksikasjalikumalt.

Operaatori tegemine Bashis

Nüüd oleme rakendamiseks valmis. Selleks peame kirjutama kaks funktsiooni (muide, soovitame raamatukogu shell_lib, mis lihtsustab oluliselt Bashis konksude kirjutamist):

  • esimest on vaja konfiguratsioonietapi jaoks – see kuvab sidumiskonteksti;
  • teine ​​sisaldab konksu põhiloogikat.

#!/bin/bash

source /shell_lib.sh

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

function __main__() {
  # THE LOGIC
}

hook::run "$@"

Järgmine samm on otsustada, milliseid objekte me vajame. Meie puhul peame jälgima:

  • muudatuste lähtesaladus;
  • kõik klastri nimeruumid, et saaksite teada, millistele on lisatud silt;
  • sihtsaladused, et tagada nende kõigi sünkroonis lähtesaladusega.

Telli salajane allikas

Selle sidumise konfiguratsioon on üsna lihtne. Anname nimega märku, et oleme huvitatud saladusest mysecret nimeruumis default:

Kas minna? Bash! Tutvuge shell-operaatoriga (KubeCon EU'2020 ülevaade ja videoaruanne)

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

Selle tulemusel käivitub konks, kui allika saladus muutub (src_secret) ja saada järgmine siduv kontekst:

Kas minna? Bash! Tutvuge shell-operaatoriga (KubeCon EU'2020 ülevaade ja videoaruanne)

Nagu näete, sisaldab see nime ja kogu objekti.

Nimeruumide jälgimine

Nüüd peate tellima nimeruumid. Selleks määrame järgmise sidumiskonfiguratsiooni:

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

Nagu näete, on konfiguratsioonis ilmunud uus väli nimega jqFilter. Nagu nimigi ütleb, jqFilter filtreerib välja kogu ebavajaliku teabe ja loob meile huvipakkuvate väljadega uue JSON-objekti. Sarnase konfiguratsiooniga konks saab järgmise sidumiskonteksti:

Kas minna? Bash! Tutvuge shell-operaatoriga (KubeCon EU'2020 ülevaade ja videoaruanne)

See sisaldab massiivi filterResults iga klastri nimeruumi jaoks. Boole'i ​​muutuja hasLabel näitab, kas antud nimeruumile on lisatud silt. Valija keepFullObjectsInMemory: false näitab, et täielikke objekte pole vaja mälus hoida.

Sihtmärgi saladuste jälgimine

Tellime kõik saladused, millel on täpsustatud annotatsioon managed-secret: "yes" (need on meie sihtmärk 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

Sel juhul jqFilter filtreerib välja kogu teabe, välja arvatud nimeruum ja parameeter resourceVersion. Viimane parameeter edastati annotatsioonile saladuse loomisel: see võimaldab võrrelda saladuste versioone ja hoida neid ajakohasena.

Sel viisil konfigureeritud konks saab käivitamisel kolm ülalkirjeldatud sidumiskonteksti. Neid võib pidada omamoodi hetktõmmisteks (snapshot) klaster.

Kas minna? Bash! Tutvuge shell-operaatoriga (KubeCon EU'2020 ülevaade ja videoaruanne)

Kogu selle teabe põhjal saab välja töötada põhialgoritmi. See kordub kõigis nimeruumides ja:

  • kui hasLabel küsimustes true praeguse nimeruumi jaoks:
    • võrdleb globaalset saladust kohalikuga:
      • kui need on samad, ei tee see midagi;
      • kui need erinevad - teostab kubectl replace või create;
  • kui hasLabel küsimustes false praeguse nimeruumi jaoks:
    • veendub, et Secret pole antud nimeruumis:
      • kui kohalik saladus on olemas, kustutage see kasutades kubectl delete;
      • kui kohalikku saladust ei tuvastata, ei tee see midagi.

Kas minna? Bash! Tutvuge shell-operaatoriga (KubeCon EU'2020 ülevaade ja videoaruanne)

Algoritmi rakendamine Bashis saate alla laadida meie lehelt hoidlad koos näidetega.

Nii saime luua lihtsa Kubernetese kontrolleri, kasutades 35 rida YAML-i konfiguratsiooni ja umbes sama palju Bashi koodi! Shell-operaatori ülesanne on need omavahel siduda.

Saladuste kopeerimine pole aga utiliidi ainus rakendusvaldkond. Siin on veel mõned näited, et näidata, milleks ta võimeline on.

Näide 1: ConfigMapi muudatuste tegemine

Vaatame kolmest kaustast koosnevat juurutust. Podid kasutavad teatud konfiguratsiooni salvestamiseks ConfigMapi. Kui kaustad käivitati, oli ConfigMap teatud olekus (nimetagem seda v.1). Sellest lähtuvalt kasutavad kõik kaustad seda konkreetset ConfigMapi versiooni.

Oletame nüüd, et ConfigMap on muutunud (v.2). Siiski kasutavad kaustad ConfigMapi eelmist versiooni (v.1):

Kas minna? Bash! Tutvuge shell-operaatoriga (KubeCon EU'2020 ülevaade ja videoaruanne)

Kuidas saada neid uuele ConfigMapile (v.2) lülituma? Vastus on lihtne: kasutage malli. Lisame jaotisele kontrollsumma märkuse template Juurutamise konfiguratsioonid:

Kas minna? Bash! Tutvuge shell-operaatoriga (KubeCon EU'2020 ülevaade ja videoaruanne)

Selle tulemusel registreeritakse see kontrollsumma kõigis kaustades ja see on sama, mis juurutamise puhul. Nüüd peate lihtsalt annotatsiooni värskendama, kui ConfigMap muutub. Ja shell-operaator tuleb sel juhul kasuks. Kõik, mida pead tegema, on programmeerida konks, mis tellib ConfigMapi ja värskendab kontrollsummat.

Kui kasutaja teeb ConfigMapis muudatusi, märkab shell-operaator neid ja arvutab kontrollsumma uuesti. Pärast seda hakkab mängu Kubernetese maagia: orkestraator tapab kauna, loob uue, ootab, kuni see muutub. Readyja liigub järgmise juurde. Selle tulemusena sünkroonib juurutamine ja lülitub ConfigMapi uuele versioonile.

Kas minna? Bash! Tutvuge shell-operaatoriga (KubeCon EU'2020 ülevaade ja videoaruanne)

Näide 2: Kohandatud ressursimääratlustega töötamine

Nagu teate, võimaldab Kubernetes luua kohandatud tüüpi objekte. Näiteks saate luua lahke MysqlDatabase. Oletame, et sellel tüübil on kaks metaandmete parameetrit: name и namespace.

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

Meil on erinevate nimeruumidega Kubernetese klaster, milles saame luua MySQL-i andmebaase. Sel juhul saab ressursside jälgimiseks kasutada shell-operaatorit MysqlDatabase, ühendades need MySQL-serveriga ja sünkroonides klastri soovitud ja vaadeldud olekuid.

Kas minna? Bash! Tutvuge shell-operaatoriga (KubeCon EU'2020 ülevaade ja videoaruanne)

Näide 3: klastri võrgu jälgimine

Nagu teate, on pingi kasutamine kõige lihtsam viis võrgu jälgimiseks. Selles näites näitame, kuidas sellist jälgimist shell-operaatori abil rakendada.

Kõigepealt peate tellima sõlmed. Shelli operaator vajab iga sõlme nime ja IP-aadressi. Nende abiga pingib ta need sõlmed.

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: "* * * * *"

Parameeter executeHookOnEvent: [] takistab konksu käivitamist vastuseks mis tahes sündmusele (st vastuseks sõlmede muutmisele, lisamisele, kustutamisele). Siiski ta hakkab jooksma (ja värskendage sõlmede loendit) Planeeritud - iga minut, nagu väljal ette nähtud schedule.

Nüüd tekib küsimus, kuidas me täpselt teame sellistest probleemidest nagu pakettakad? Vaatame koodi:

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
}

Kordame sõlmede loendit, hankime nende nimed ja IP-aadressid, pingime need ja saadame tulemused Prometheusele. Shell-operaator saab eksportida mõõdikuid Prometheusesse, salvestades need faili, mis asub keskkonnamuutujas määratud tee järgi $METRICS_PATH.

Siin nii saate teha operaatori lihtsaks võrgu jälgimiseks klastris.

Järjekorra mehhanism

See artikkel oleks puudulik, kirjeldamata teist olulist kestaoperaatorisse sisseehitatud mehhanismi. Kujutage ette, et see käivitab vastuseks klastri sündmusele mingi konksu.

  • Mis juhtub, kui samal ajal klastris midagi juhtub? üks veel sündmus?
  • Kas shell-operator käivitab teise konksu eksemplari?
  • Mis siis, kui klastris juhtub korraga näiteks viis sündmust?
  • Kas shell-operaator töötleb neid paralleelselt?
  • Kuidas on lood tarbitud ressurssidega, nagu mälu ja protsessor?

Õnneks on shell-operaatoril sisseehitatud järjekorra mehhanism. Kõik sündmused pannakse järjekorda ja neid töödeldakse järjest.

Illustreerime seda näidetega. Oletame, et meil on kaks konksu. Esimene sündmus läheb esimese konksu otsa. Kui selle töötlemine on lõppenud, liigub järjekord edasi. Järgmised kolm sündmust suunatakse ümber teise konksu juurde - need eemaldatakse järjekorrast ja sisestatakse sinna "kimpu". See on konks võtab vastu hulga sündmusi — või täpsemalt siduvate kontekstide massiivi.

Ka need sündmused saab ühendada üheks suureks. Selle eest vastutab parameeter group sidumiskonfiguratsioonis.

Kas minna? Bash! Tutvuge shell-operaatoriga (KubeCon EU'2020 ülevaade ja videoaruanne)

Saate luua suvalise arvu järjekordi/konkse ja nende erinevaid kombinatsioone. Näiteks võib üks järjekord töötada kahe konksuga või vastupidi.

Kas minna? Bash! Tutvuge shell-operaatoriga (KubeCon EU'2020 ülevaade ja videoaruanne)

Kõik, mida pead tegema, on väli vastavalt konfigureerida queue sidumiskonfiguratsioonis. Kui järjekorra nime pole määratud, töötab konks vaikejärjekorras (default). See järjekorramehhanism võimaldab teil konksudega töötamisel täielikult lahendada kõik ressursside haldamise probleemid.

Järeldus

Selgitasime, mis on shell-operaator, näitasime, kuidas selle abil saab kiiresti ja vaevata Kubernetese operaatoreid luua ning tõime mitmeid näiteid selle kasutamisest.

Üksikasjalik teave shell-operaatori kohta, samuti kiire õpetus selle kasutamiseks on saadaval vastavas hoidlad GitHubis. Küsimuste korral võtke meiega julgelt ühendust: saate neid arutada spetsiaalselt Telegrami grupp (vene keeles) või keeles see foorum (inglise keeles).

Ja kui teile meeldis, on meil alati hea meel näha GitHubis uusi väljaandeid/PR/staare, kust muide leiate ka teisi huvitavaid projekte. Nende hulgas tasub esile tõsta lisand-operaator, mis on shell-operaatori suur vend. See utiliit kasutab lisandmoodulite installimiseks Helmi diagramme, saab pakkuda värskendusi ja jälgida erinevaid diagrammi parameetreid/väärtusi, juhib diagrammide installiprotsessi ja saab neid ka muuta vastavalt klastris toimuvatele sündmustele.

Kas minna? Bash! Tutvuge shell-operaatoriga (KubeCon EU'2020 ülevaade ja videoaruanne)

Videod ja slaidid

Video etendusest (~23 minutit):


Aruande esitlus:

PS

Loe ka meie blogist:

Allikas: www.habr.com

Lisa kommentaar