Myšlienka shell-operátora je pomerne jednoduchá: prihláste sa na odber udalostí z objektov Kubernetes a po prijatí týchto udalostí spustite externý program, ktorý mu poskytne informácie o udalosti:
Potreba vznikla, keď sa počas prevádzky klastrov začali objavovať drobné úlohy, ktoré sme naozaj chceli automatizovať tým správnym spôsobom. Všetky tieto malé úlohy boli vyriešené pomocou jednoduchých bash skriptov, aj keď, ako viete, je lepšie písať operátory v Golangu. Je zrejmé, že investovanie do komplexného rozvoja operátora pre každú takúto malú úlohu by bolo neúčinné.
Operátor do 15 minút
Pozrime sa na príklad toho, čo sa dá automatizovať v klastri Kubernetes a ako môže pomôcť operátor shellu. Príklad by mohol byť nasledujúci: replikácia tajného kľúča na prístup k registru dockerov.
Moduly, ktoré používajú obrázky zo súkromného registra, musia vo svojom manifeste obsahovať odkaz na tajomstvo s údajmi na prístup do registra. Toto tajomstvo musí byť vytvorené v každom mennom priestore pred vytvorením modulov. Dá sa to urobiť ručne, ale ak nastavíme dynamické prostredia, menný priestor pre jednu aplikáciu bude veľa. A ak nie sú ani 2-3 aplikácie... počet tajomstiev sa stáva veľmi veľkým. A ešte jedna vec k tajomstvám: z času na čas by som chcel zmeniť kľúč na prístup do registra. nakoniec manuálne operácie ako riešenie úplne neúčinné — potrebujeme automatizovať vytváranie a aktualizáciu tajomstiev.
Jednoduchá automatizácia
Napíšme shell skript, ktorý sa spustí raz za N sekúnd a skontroluje menné priestory na prítomnosť tajomstva, a ak žiadne tajomstvo neexistuje, potom sa vytvorí. Výhodou tohto riešenia je, že vyzerá ako shell skript v crone – klasický a pre každého zrozumiteľný prístup. Nevýhodou je, že v intervale medzi jeho spustením môže byť vytvorený nový menný priestor a nejaký čas zostane bez tajomstva, čo povedie k chybám pri spúšťaní modulov.
Automatizácia pomocou shell-operátora
Aby náš skript fungoval správne, klasické spustenie cronu je potrebné nahradiť spustením, keď sa pridá priestor názvov: v tomto prípade môžete pred jeho použitím vytvoriť tajomstvo. Pozrime sa, ako to implementovať pomocou shell-operátora.
Najprv sa pozrime na scenár. Skripty v podmienkach shell-operátora sa nazývajú háčiky. Každý hák pri behu s vlajkou --config informuje prevádzkovateľa škrupiny o svojich väzbách, t.j. o akých udalostiach by sa mal spustiť. V našom prípade použijeme onKubernetesEvent:
#!/bin/bash
if [[ $1 == "--config" ]] ; then
cat <<EOF
{
"onKubernetesEvent": [
{ "kind": "namespace",
"event":["add"]
}
]}
EOF
fi
Tu je popísané, že máme záujem pridať udalosti (add) objekty typu namespace.
Teraz musíte pridať kód, ktorý sa spustí, keď nastane udalosť:
#!/bin/bash
if [[ $1 == "--config" ]] ; then
# конфигурация
cat <<EOF
{
"onKubernetesEvent": [
{ "kind": "namespace",
"event":["add"]
}
]}
EOF
else
# реакция:
# узнать, какой namespace появился
createdNamespace=$(jq -r '.[0].resourceName' $BINDING_CONTEXT_PATH)
# создать в нём нужный секрет
kubectl create -n ${createdNamespace} -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
...
data:
...
EOF
fi
Skvelé! Výsledkom bol malý, krásny scenár. Na jeho „oživenie“ zostávajú dva kroky: pripraviť obrázok a spustiť ho v klastri.
Príprava obrázka s háčikom
Ak sa pozriete na skript, môžete vidieť, že príkazy sa používajú kubectl и jq. To znamená, že obrázok musí mať nasledujúce veci: náš hák, operátor shellu, ktorý bude monitorovať udalosti a spúšťať hák, a príkazy používané hákom (kubectl a jq). Hub.docker.com už má hotový obrázok, v ktorom sú zabalené shell-operator, kubectl a jq. Ostáva už len pridať jednoduchý háčik Dockerfile:
Pozrime sa ešte raz na háčik a tentoraz si napíšme, aké akcie a s akými objektmi v klastri vykonáva:
prihlasuje sa k udalostiam vytvárania menného priestoru;
vytvorí tajomstvo v inom mennom priestore, ako je ten, v ktorom je spustený.
Ukázalo sa, že modul, v ktorom sa spustí náš obrázok, musí mať povolenia na vykonanie týchto akcií. Môžete to urobiť vytvorením vlastného ServiceAccount. Povolenie musí byť vykonané vo forme ClusterRole a ClusterRoleBinding, pretože nás zaujímajú objekty z celého zhluku.
To je všetko: shell-operátor sa spustí, prihlási sa na udalosti vytvárania menného priestoru a spustí hák, keď je to potrebné.
To znamená, že jednoduchý shell skript sa zmenil na skutočný operátor pre Kubernetes a funguje ako súčasť klastra. A to všetko bez zložitého procesu vývoja operátorov v Golang:
V tejto veci je ešte jeden príklad...
Jeho význam prezradíme podrobnejšie v niektorej z nasledujúcich publikácií.
filtrovanie
Sledovanie objektov je dobré, ale často je potrebné reagovať zmena niektorých vlastností objektu, napríklad zmeniť počet replík v Nasadení alebo zmeniť označenia objektov.
Keď príde udalosť, operátor shellu prijme manifest JSON objektu. Môžeme vybrať vlastnosti, ktoré nás zaujímajú v tomto JSON a spustiť hák iba keď sa zmenia. Je tu na to pole jqFilter, kde musíte zadať výraz jq, ktorý sa použije na manifest JSON.
Ak chcete napríklad reagovať na zmeny v návestiach objektov nasadenia, musíte pole filtrovať labels mimo poľa metadata. Konfigurácia bude takáto:
Malá odbočka: áno, podpora operátorov shellu spúšťanie skriptov v štýle crontab. Viac podrobností nájdete v dokumentáciu.
Aby bolo možné rozlíšiť, prečo bol hák spustený, shell-operátor vytvorí dočasný súbor a odovzdá cestu k nemu v premennej háku BINDING_CONTEXT_TYPE. Súbor obsahuje JSON popis dôvodu spustenia háku. Napríklad každých 10 minút sa spustí hák s nasledujúcim obsahom:
Obsah polí možno pochopiť z ich názvov a ďalšie podrobnosti si môžete prečítať dokumentáciu. Príklad získania názvu zdroja z poľa resourceName použitie jq sa už ukázalo v háku, ktorý replikuje tajomstvá:
jq -r '.[0].resourceName' $BINDING_CONTEXT_PATH
Podobným spôsobom môžete získať ďalšie polia.
Čo bude ďalej?
V projektovom úložisku, v /examples adresáre, existujú príklady hákov, ktoré sú pripravené na spustenie v klastri. Pri písaní vlastných háčikov ich môžete použiť ako základ.
Existuje podpora pre zhromažďovanie metrík pomocou Prometheus – dostupné metriky sú popísané v časti METRIKA.
Ako asi tušíte, shell-operátor je napísaný v Go a distribuovaný pod licenciou Open Source (Apache 2.0). Budeme vďační za každú rozvojovú pomoc projekt na GitHub: a hviezdy, problémy a požiadavky na stiahnutie.
Po odstránení závoja tajomstva vás budeme informovať aj o tom, že škrupinový operátor je malý súčasť nášho systému, ktorá dokáže aktualizovať doplnky nainštalované v klastri Kubernetes a vykonávať rôzne automatické akcie. Prečítajte si viac o tomto systéme povedal doslova v pondelok na HighLoad++ 2019 v Petrohrade - video a prepis tejto reportáže čoskoro zverejníme.
Máme v pláne otvoriť zvyšok systému: operátora doplnkov a našu zbierku háčikov a modulov. Mimochodom, addon-operátor už je k dispozícii na github, ale dokumentácia k nemu je stále na ceste. Vydanie kolekcie modulov je plánované na leto.