Jít? Bash! Seznamte se s operátorem shellu (recenze a videoreportáž z KubeCon EU'2020)

Hlavní evropská konference Kubernetes – KubeCon + CloudNativeCon Europe 2020 – byla letos virtuální. Taková změna formátu nám však nezabránila v předání naší dlouho plánované zprávy „Go? Bash! Seznamte se s operátorem Shell“ věnovaným našemu projektu Open Source shell-operátor.

Tento článek, inspirovaný přednáškou, představuje přístup ke zjednodušení procesu vytváření operátorů pro Kubernetes a ukazuje, jak si můžete vytvořit vlastní s minimálním úsilím pomocí shell-operátora.

Jít? Bash! Seznamte se s operátorem shellu (recenze a videoreportáž z KubeCon EU'2020)

Představujeme video reportáže (~23 minut v angličtině, znatelně informativnější než článek) a hlavní úryvek z něj v textové podobě. Jít!

Ve Flantu vše neustále optimalizujeme a automatizujeme. Dnes budeme hovořit o dalším vzrušujícím konceptu. Setkat: cloud-native shell skriptování!

Začněme však kontextem, ve kterém se to všechno děje: Kubernetes.

Kubernetes API a řadiče

API v Kubernetes může být reprezentováno jako druh souborového serveru s adresáři pro každý typ objektu. Objekty (zdroje) na tomto serveru jsou reprezentovány soubory YAML. Server má navíc základní API, které vám umožňuje dělat tři věci:

  • přijmout zdroj podle druhu a názvu;
  • RјРµРЅСЏС‚ЊЊ zdroj (v tomto případě server ukládá pouze „správné“ objekty - všechny nesprávně vytvořené nebo určené pro jiné adresáře jsou vyřazeny);
  • následovat pro zdroj (v tomto případě uživatel okamžitě obdrží jeho aktuální/aktualizovanou verzi).

Kubernetes tedy funguje jako jakýsi souborový server (pro YAML manifesty) se třemi základními metodami (ano, ve skutečnosti existují i ​​jiné, ale ty zatím vynecháme).

Jít? Bash! Seznamte se s operátorem shellu (recenze a videoreportáž z KubeCon EU'2020)

Problém je, že server může pouze ukládat informace. Aby to fungovalo, potřebujete kontrolor - druhý nejdůležitější a zásadní koncept ve světě Kubernetes.

Existují dva hlavní typy ovladačů. První přebírá informace z Kubernetes, zpracovává je podle vnořené logiky a vrací je K8s. Druhý přebírá informace z Kubernetes, ale na rozdíl od prvního typu mění stav některých externích zdrojů.

Pojďme se blíže podívat na proces vytváření Deployment v Kubernetes:

  • Deployment Controller (součástí balení kube-controller-manager) obdrží informace o nasazení a vytvoří sadu ReplicaSet.
  • ReplicaSet vytvoří dvě repliky (dva moduly) na základě těchto informací, ale tyto moduly ještě nejsou naplánovány.
  • Plánovač naplánuje pody a přidá informace o uzlech do jejich YAML.
  • Kubelets provádějí změny v externím zdroji (řekněme Docker).

Poté se celá tato sekvence opakuje v obráceném pořadí: kubelet zkontroluje kontejnery, vypočítá stav podu a odešle jej zpět. Řadič ReplicaSet přijímá stav a aktualizuje stav sady replik. Totéž se stane s Deployment Controller a uživatel konečně získá aktualizovaný (aktuální) stav.

Jít? Bash! Seznamte se s operátorem shellu (recenze a videoreportáž z KubeCon EU'2020)

Shell-operátor

Ukazuje se, že Kubernetes je založen na společné práci různých kontrolérů (operátoři Kubernetes jsou také kontroloři). Nabízí se otázka, jak vytvořit vlastního operátora s minimální námahou? A tady přichází na pomoc ten, který jsme vyvinuli shell-operátor. Umožňuje správcům systému vytvářet vlastní výpisy pomocí známých metod.

Jít? Bash! Seznamte se s operátorem shellu (recenze a videoreportáž z KubeCon EU'2020)

Jednoduchý příklad: kopírování tajemství

Podívejme se na jednoduchý příklad.

Řekněme, že máme cluster Kubernetes. Má jmenný prostor default s nějakým Tajemstvím mysecret. Kromě toho jsou v clusteru další jmenné prostory. Některé z nich jsou opatřeny zvláštním štítkem. Naším cílem je zkopírovat Secret do jmenných prostorů se štítkem.

Úkol je komplikován tím, že se v clusteru mohou objevit nové jmenné prostory a některé z nich mohou mít toto označení. Na druhou stranu, když je štítek odstraněn, měl by být smazán také Tajný. Kromě toho se může změnit i samotný Tajemství: v tomto případě musí být nový Tajemství zkopírován do všech jmenných prostorů se štítky. Pokud je Tajemství omylem smazáno v jakémkoli jmenném prostoru, náš operátor by jej měl okamžitě obnovit.

Nyní, když je úkol formulován, je čas začít jej implementovat pomocí shell-operátora. Nejprve však stojí za to říci pár slov o samotném operátorovi shellu.

Jak funguje shell-operátor

Stejně jako ostatní úlohy v Kubernetes běží shell-operátor ve svém vlastním modulu. V tomto podu v adresáři /hooks jsou uloženy spustitelné soubory. Mohou to být skripty v Bash, Python, Ruby atd. Takové spustitelné soubory nazýváme háčky (háky).

Jít? Bash! Seznamte se s operátorem shellu (recenze a videoreportáž z KubeCon EU'2020)

Shell-operator se přihlásí k odběru událostí Kubernetes a spouští tyto háky v reakci na události, které potřebujeme.

Jít? Bash! Seznamte se s operátorem shellu (recenze a videoreportáž z KubeCon EU'2020)

Jak operátor shellu ví, který hák spustit a kdy? Jde o to, že každý háček má dvě fáze. Během spouštění spustí operátor shellu všechny háky s argumentem --config Toto je fáze konfigurace. A po něm se háčky spustí normálním způsobem - v reakci na události, ke kterým jsou připojeny. V druhém případě hák obdrží kontext vazby (závazný kontext) - data ve formátu JSON, o kterých si povíme podrobněji níže.

Vytvoření operátoru v Bash

Nyní jsme připraveni k realizaci. K tomu musíme napsat dvě funkce (mimochodem, doporučujeme knihovna shell_lib, což výrazně zjednodušuje psaní háčků v Bash):

  • první je potřeba pro fázi konfigurace – zobrazuje kontext vazby;
  • druhý obsahuje hlavní logiku háku.

#!/bin/bash

source /shell_lib.sh

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

function __main__() {
  # THE LOGIC
}

hook::run "$@"

Dalším krokem je rozhodnutí, jaké objekty potřebujeme. V našem případě musíme sledovat:

  • tajemství zdroje pro změny;
  • všechny jmenné prostory v clusteru, abyste věděli, ke kterým je připojen štítek;
  • cílových tajných klíčů, aby bylo zajištěno, že jsou všechny synchronizovány se zdrojovým tajným klíčem.

Přihlaste se k odběru tajného zdroje

Konfigurace vazby pro něj je poměrně jednoduchá. Dáváme najevo, že nás zajímá Tajemství jménem mysecret ve jmenném prostoru default:

Jít? Bash! Seznamte se s operátorem shellu (recenze a videoreportáž z 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

V důsledku toho bude háček spuštěn, když se změní zdrojový tajný klíč (src_secret) a obdržíte následující vazebný kontext:

Jít? Bash! Seznamte se s operátorem shellu (recenze a videoreportáž z KubeCon EU'2020)

Jak vidíte, obsahuje název a celý objekt.

Sledování jmenných prostorů

Nyní se musíte přihlásit k odběru jmenných prostorů. K tomu zadáme následující konfiguraci vazby:

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

Jak vidíte, v konfiguraci se objevilo nové pole s názvem jqFilter. Jak jeho název napovídá, jqFilter odfiltruje všechny nepotřebné informace a vytvoří nový objekt JSON s poli, která nás zajímají. Hák s podobnou konfigurací obdrží následující kontext vazby:

Jít? Bash! Seznamte se s operátorem shellu (recenze a videoreportáž z KubeCon EU'2020)

Obsahuje pole filterResults pro každý jmenný prostor v clusteru. Booleovská proměnná hasLabel označuje, zda je k danému jmennému prostoru připojen štítek. Volič keepFullObjectsInMemory: false označuje, že není potřeba uchovávat v paměti celé objekty.

Sledování tajemství cíle

Odebíráme všechna tajemství, která mají specifikovanou anotaci managed-secret: "yes" (to jsou náš cíl 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

V tomto případě jqFilter odfiltruje všechny informace kromě jmenného prostoru a parametru resourceVersion. Poslední parametr byl předán do anotace při vytváření tajenky: umožňuje porovnávat verze tajných klíčů a udržovat je aktuální.

Hák nakonfigurovaný tímto způsobem při spuštění obdrží tři kontexty vazby popsané výše. Lze je považovat za určitý druh snímku (momentka) shluk.

Jít? Bash! Seznamte se s operátorem shellu (recenze a videoreportáž z KubeCon EU'2020)

Na základě všech těchto informací lze vytvořit základní algoritmus. Iteruje přes všechny jmenné prostory a:

  • jestliže hasLabel záležitosti true pro aktuální jmenný prostor:
    • porovnává globální tajemství s místním:
      • pokud jsou stejné, nedělá to nic;
      • pokud se liší - provede kubectl replace nebo create;
  • jestliže hasLabel záležitosti false pro aktuální jmenný prostor:
    • zajišťuje, že Secret není v daném jmenném prostoru:
      • pokud je přítomen místní tajný klíč, odstraňte jej pomocí kubectl delete;
      • pokud místní tajemství není detekováno, neudělá nic.

Jít? Bash! Seznamte se s operátorem shellu (recenze a videoreportáž z KubeCon EU'2020)

Implementace algoritmu v Bash si můžete stáhnout v našem úložiště s příklady.

Tak jsme byli schopni vytvořit jednoduchý ovladač Kubernetes pomocí 35 řádků konfigurace YAML a přibližně stejného množství kódu Bash! Úkolem operátora shellu je propojit je dohromady.

Kopírování tajemství však není jedinou oblastí použití nástroje. Zde je několik dalších příkladů, které ukazují, čeho je schopen.

Příklad 1: Provádění změn v ConfigMap

Podívejme se na Deployment sestávající ze tří modulů. Pody používají ConfigMap k uložení nějaké konfigurace. Když byly moduly spuštěny, ConfigMap byl v určitém stavu (říkejme tomu v.1). V souladu s tím všechny moduly používají tuto konkrétní verzi ConfigMap.

Nyní předpokládejme, že se mapa ConfigMap změnila (v.2). Pody však budou používat předchozí verzi ConfigMap (v.1):

Jít? Bash! Seznamte se s operátorem shellu (recenze a videoreportáž z KubeCon EU'2020)

Jak je mohu přimět k přechodu na novou ConfigMap (v.2)? Odpověď je jednoduchá: použijte šablonu. Do sekce přidáme anotaci kontrolního součtu template Konfigurace nasazení:

Jít? Bash! Seznamte se s operátorem shellu (recenze a videoreportáž z KubeCon EU'2020)

Výsledkem je, že tento kontrolní součet bude registrován ve všech modulech a bude stejný jako u Deploymentu. Nyní stačí aktualizovat anotaci, když se změní ConfigMap. A shell-operátor se v tomto případě hodí. Vše, co musíte udělat, je naprogramovat háček, který se přihlásí k odběru ConfigMap a aktualizuje kontrolní součet.

Pokud uživatel provede změny v ConfigMap, operátor shellu si jich všimne a přepočítá kontrolní součet. Poté vstoupí do hry kouzlo Kubernetes: orchestrátor zabije lusk, vytvoří nový, počká, až se stane Readya přejde na další. V důsledku toho se Deployment synchronizuje a přepne na novou verzi ConfigMap.

Jít? Bash! Seznamte se s operátorem shellu (recenze a videoreportáž z KubeCon EU'2020)

Příklad 2: Práce s vlastními definicemi zdrojů

Jak víte, Kubernetes vám umožňuje vytvářet vlastní typy objektů. Můžete například vytvořit laskavost MysqlDatabase. Řekněme, že tento typ má dva parametry metadat: name и namespace.

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

Máme cluster Kubernetes s různými jmennými prostory, ve kterých můžeme vytvářet databáze MySQL. V tomto případě lze ke sledování zdrojů použít shell-operátor MysqlDatabase, jejich připojení k serveru MySQL a synchronizace požadovaných a pozorovaných stavů clusteru.

Jít? Bash! Seznamte se s operátorem shellu (recenze a videoreportáž z KubeCon EU'2020)

Příklad 3: Sledování sítě clusteru

Jak víte, pomocí pingu je nejjednodušší způsob monitorování sítě. V tomto příkladu si ukážeme, jak takové monitorování implementovat pomocí shell-operator.

Nejprve se budete muset přihlásit k odběru uzlů. Operátor shellu potřebuje jméno a IP adresu každého uzlu. S jejich pomocí bude pingovat tyto uzly.

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

Parametr executeHookOnEvent: [] zabraňuje spuštění háku v reakci na jakoukoli událost (tedy v reakci na změnu, přidání, odstranění uzlů). Nicméně on poběží (a aktualizovat seznam uzlů) Naplánováno - každou minutu, jak předepisuje pole schedule.

Nyní vyvstává otázka, jak přesně víme o problémech, jako je ztráta paketů? Pojďme se podívat na kód:

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
}

Iterujeme seznam uzlů, získáme jejich jména a IP adresy, pingneme na ně a pošleme výsledky společnosti Prometheus. Shell-operátor může exportovat metriky do Prometheus, uložte je do souboru umístěného podle cesty zadané v proměnné prostředí $METRICS_PATH.

takhle můžete vytvořit operátora pro jednoduché monitorování sítě v clusteru.

Mechanismus řazení do fronty

Tento článek by byl neúplný bez popisu dalšího důležitého mechanismu zabudovaného do shell-operátoru. Představte si, že v reakci na událost v clusteru spustí nějaký druh háku.

  • Co se stane, když se zároveň něco stane v shluku? ještě jeden událost?
  • Spustí shell-operátor další instanci háku?
  • Co když se v clusteru stane řekněme pět událostí najednou?
  • Bude je shell-operátor zpracovávat paralelně?
  • A co spotřebované zdroje, jako je paměť a CPU?

Naštěstí má shell-operátor vestavěný mechanismus řazení do fronty. Všechny události jsou zařazeny do fronty a zpracovány postupně.

Pojďme si to ilustrovat na příkladech. Řekněme, že máme dva háčky. První událost jde do prvního háku. Jakmile je zpracování dokončeno, fronta se posune vpřed. Následující tři události jsou přesměrovány na druhý háček - jsou odstraněny z fronty a vloženy do „svazku“. To znamená hook přijímá řadu událostí — nebo přesněji pole závazných kontextů.

Také tyto akce lze spojit do jedné velké. Za to může parametr group v konfiguraci vazby.

Jít? Bash! Seznamte se s operátorem shellu (recenze a videoreportáž z KubeCon EU'2020)

Můžete vytvořit libovolný počet front/háčků a jejich různé kombinace. Například jedna fronta může pracovat se dvěma háčky nebo naopak.

Jít? Bash! Seznamte se s operátorem shellu (recenze a videoreportáž z KubeCon EU'2020)

Vše, co musíte udělat, je odpovídajícím způsobem nakonfigurovat pole queue v konfiguraci vazby. Pokud není zadán název fronty, hák se spustí ve výchozí frontě (default). Tento mechanismus řazení do front vám umožňuje zcela vyřešit všechny problémy se správou zdrojů při práci s háčky.

Závěr

Vysvětlili jsme, co je shell-operátor, ukázali, jak jej lze použít k rychlému a snadnému vytváření operátorů Kubernetes, a uvedli několik příkladů jeho použití.

Podrobné informace o operátorovi shellu, stejně jako rychlý návod, jak jej používat, jsou k dispozici v odpovídajícím úložiště na GitHubu. Neváhejte nás kontaktovat s dotazy: můžete je probrat ve speciálu Skupina telegramů (v ruštině) nebo v toto fórum (v angličtině).

A pokud se vám to líbilo, vždy rádi uvidíme nová čísla/PR/hvězdy na GitHubu, kde mimochodem najdete další zajímavé projekty. Mezi nimi stojí za to zdůraznit addon-operátor, což je velký bratr shell-operátora. Tento nástroj používá Helm diagramy k instalaci doplňků, může dodávat aktualizace a monitorovat různé parametry/hodnoty diagramů, řídí proces instalace diagramů a může je také upravovat v reakci na události v clusteru.

Jít? Bash! Seznamte se s operátorem shellu (recenze a videoreportáž z KubeCon EU'2020)

Videa a diapozitivy

Video z představení (~23 minut):


Prezentace zprávy:

PS

Přečtěte si také na našem blogu:

Zdroj: www.habr.com

Přidat komentář