
8. dubna na konferenci , v rámci sekce „DevOps and Operations“ zazněla zpráva „Rozšiřování a doplňování Kubernetes“, na jejímž vzniku se podíleli tři zaměstnanci společnosti Flant. Hovoříme v něm o četných situacích, ve kterých jsme chtěli rozšířit a doplnit možnosti Kubernetes, ale pro které jsme nenašli hotové a jednoduché řešení. Máme potřebná řešení v podobě Open Source projektů a právě jim je věnován tento projev.
Tradičně rádi představujeme (50 minut, mnohem informativnější než článek) a hlavní shrnutí v textové podobě. Jít!
Jádro a doplňky v K8s
Kubernetes mění odvětví a přístupy k administraci, které jsou již dlouho zavedené:
- Jeho díky abstrakce, již neoperujeme s pojmy jako nastavení konfigurace nebo spuštění příkazu (Chef, Ansible...), ale využíváme seskupování kontejnerů, služeb atp.
- Můžeme připravit aplikace, aniž bychom přemýšleli o nuancích konkrétní místo, na kterém bude spuštěn: bare metal, cloud jednoho z poskytovatelů atp.
- S K8 jste nikdy nebyli dostupnější osvědčené postupy o organizaci infrastruktury: škálovací techniky, samoléčení, odolnost proti chybám atd.
Všechno však samozřejmě není tak hladké: Kubernetes také přinesl své vlastní nové výzvy.
Kubernetes ne je kombajn, který řeší všechny problémy všech uživatelů. Core Kubernetes je zodpovědný pouze za sadu minimálních nezbytných funkcí, které jsou přítomné v každý shluk:

Jádro Kubernetes definuje základní sadu primitiv pro seskupování kontejnerů, správu provozu a tak dále. Podrobněji jsme o nich hovořili v .
Na druhou stranu K8s nabízí skvělé možnosti rozšíření dostupných funkcí, které pomáhají zavřít ostatní - charakteristický — potřeby uživatelů. Za přidání do Kubernetes zodpovídají správci clusteru, kteří musí nainstalovat a nakonfigurovat vše potřebné, aby se jejich cluster dostal „do správného tvaru“ [k vyřešení jejich specifických problémů]. O jaké doplňky se jedná? Podívejme se na několik příkladů.
Příklady doplňků
Po instalaci Kubernetes nás možná překvapí, že síť, která je tak nezbytná pro interakci podů jak v rámci uzlu, tak mezi uzly, nefunguje sama o sobě. Jádro Kubernetes nezaručuje potřebná připojení, místo toho určuje síť Rozhraní () pro doplňky třetích stran. Musíme nainstalovat jeden z těchto doplňků, který bude zodpovědný za konfiguraci sítě.

Blízkým příkladem jsou řešení pro ukládání dat (lokální disk, síťové blokové zařízení, Ceph...). Zpočátku byly v jádru, ale s příchodem situace se změní na něco podobného, co již bylo popsáno: rozhraní je v Kubernetes a jeho implementace je v modulech třetích stran.
Mezi další příklady patří:
- Ingress-ovladače (viz jejich recenze v ).
- :

- je celá třída doplňků (která zahrnuje zmíněný cert-manager), definují primitiv(a) a controller(y). Logika jejich práce je omezena pouze naší představivostí a umožňuje nám z hotových komponent infrastruktury (například DBMS) udělat primitiva, se kterými se pracuje mnohem snadněji (než se sadou kontejnerů a jejich nastavením). Bylo napsáno velké množství operátorů – i když mnoho z nich ještě není připraveno k výrobě, je to jen otázka času:

- Metriky - další ilustrace toho, jak Kubernetes oddělil rozhraní (Metrics API) od implementace (doplňky třetích stran, jako je adaptér Prometheus, agent clusteru Datadog...).
- pro sledování a statistiky, kde jsou v praxi nejen potřeba , ale také kube-state-metrics, node-exporter atd.
A to není úplný výčet doplňků... Například u firmy Flant, kterou aktuálně instalujeme 29 přírůstků (všechny vytvářejí celkem 249 objektů Kubernetes). Jednoduše řečeno, nemůžeme vidět život shluku bez přídavků.
Automatizace
Operátory jsou navrženy tak, aby automatizovaly rutinní operace, se kterými se setkáváme každý den. Zde jsou příklady ze skutečného života, pro které by bylo psaní operátoru vynikajícím řešením:
- Existuje soukromý registr (tj. vyžadující přihlášení) s obrázky pro aplikaci. Předpokládá se, že každému modulu je přiřazen speciální tajný klíč, který umožňuje ověření v registru. Naším úkolem je zajistit, aby bylo toto tajemství nalezeno ve jmenném prostoru, aby moduly mohly stahovat obrázky. Aplikací může být mnoho (každá z nich potřebuje tajemství) a samotné tajenky je užitečné pravidelně aktualizovat, takže odpadá možnost vykládat tajenky ručně. Zde přichází na pomoc operátor: vytvoříme ovladač, který bude čekat, až se jmenný prostor objeví, a na základě této události do jmenného prostoru přidá tajemství.
- Povolit ve výchozím nastavení přístup z modulů na internet je zakázán. Ale někdy to může být vyžadováno: je logické, aby mechanismus povolení přístupu fungoval jednoduše, aniž by vyžadoval specifické dovednosti, například přítomností určitého štítku ve jmenném prostoru. Jak nám zde může operátor pomoci? Je vytvořen řadič, který čeká, až se štítek objeví v oboru názvů, a přidá příslušné zásady pro přístup k internetu.
- Podobná situace: předpokládejme, že potřebujeme přidat určité , pokud má podobný štítek (s nějakou předponou). Jednání s operátorem je zřejmé...
V každém clusteru musí být vyřešeny rutinní úkoly a správně to lze provést pomocí operátorů.
Shrnutím všech popsaných příběhů jsme došli k závěru, že pro pohodlnou práci v Kubernetes potřebujete: a) nainstalovat doplňky, b) rozvíjet operátory (pro řešení každodenních administrativních úkolů).
Jak napsat prohlášení pro Kubernetes?
Obecně je schéma jednoduché:

...ale pak se ukáže, že:
- Kubernetes API je poměrně netriviální věc, jejíž zvládnutí zabere spoustu času;
- programování také není pro každého (jazyk Go byl vybrán jako preferovaný jazyk, protože pro něj existuje speciální framework - );
- Podobná situace je se samotným rámcem.
Sečteno a podtrženo: napsat ovladač (operátor) musí vynakládat značné prostředky studovat materiál. To by bylo oprávněné pro „velké“ operátory – řekněme pro MySQL DBMS. Pokud si ale vzpomeneme na výše popsané příklady (odhalení tajemství, zpřístupnění podů na internet...), které chceme také dělat správně, pak pochopíme, že vynaložené úsilí převáží výsledek, který nyní potřebujeme:

Obecně nastává dilema: utratit spoustu prostředků a najít ten správný nástroj pro psaní prohlášení, nebo to udělat staromódním způsobem (ale rychle). Abychom to vyřešili – abychom našli kompromis mezi těmito extrémy – vytvořili jsme vlastní projekt: (viz také jeho na hubu).
Shell-operátor
Jak pracuje? Cluster má modul obsahující binární soubor Go s operátorem shellu. Vedle něj je sada háčky (více podrobností o nich - viz níže). Sám operátor shellu se přihlásí k určitým vývoj v Kubernetes API, při jehož výskytu spustí odpovídající háky.
Jak operátor shellu ví, které háky má volat na které události? Tyto informace jsou přenášeny k operátorovi shellu samotnými háky a dělají to velmi jednoduše.
Hák je Bash skript nebo jakýkoli jiný spustitelný soubor, který přijímá jeden argument --config a odpoví pomocí JSON. Ten určuje, které objekty jsou pro něj zajímavé a na které události (u těchto objektů) by se mělo reagovat:

Implementaci jednoho z našich příkladů ilustruji na operátorovi shellu – rozkládání tajných klíčů pro přístup k soukromému registru s obrázky aplikací. Skládá se ze dvou etap.
Cvičení: 1. Napište háček
Za prvé, v háku zpracujeme --config, což naznačuje, že nás zajímají jmenné prostory a konkrétně okamžik jejich vytvoření:
[[ $1 == "--config" ]] ; then
cat << EOF
{
"onKubernetesEvent": [
{
"kind": "namespace",
"event": ["add"]
}
]
}
EOF
…Jak by vypadala logika? Také docela jednoduché:
…
else
createdNamespace=$(jq -r '.[0].resourceName' $BINDING_CONTEXT_PATH)
kubectl create -n ${createdNamespace} -f - << EOF
Kind: Secret
...
EOF
fi Prvním krokem je zjistit, který jmenný prostor byl vytvořen, a druhým je jeho vytvoření pomocí kubectl tajemství pro tento jmenný prostor.
Cvičení: 2. Sestavení obrazu
Zbývá pouze předat vytvořený hák shell-operátorovi - jak na to? Samotný shell-operátor přichází jako obrázek Dockeru, takže naším úkolem je přidat hák do speciálního adresáře v tomto obrázku:
FROM flant/shell-operator:v1.0.0-beta.1
ADD my-handler.sh /hooksZbývá jen sestavit a zatlačit:
$ docker build -t registry.example.com/my-operator:v1 .
$ docker push registry.example.com/my-operator:v1Posledním krokem je nasazení obrazu do clusteru. Chcete-li to udělat, napište Rozvinutí:
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 # 2Je třeba věnovat pozornost dvěma bodům:
- označení nově vytvořeného obrázku;
- Toto je systémová komponenta, která (minimálně) potřebuje práva k odběru událostí v Kubernetes a přidělování tajných klíčů jmenným prostorům, takže pro hák vytvoříme ServiceAccount (a sadu pravidel).
Výsledek – vyřešili jsme náš problém příbuzným pro Kubernetes způsobem, který vytváří operátor pro rozklad tajemství.
Další funkce operátora shellu
Chcete-li omezit objekty vámi zvoleného typu, se kterými bude háček pracovat, dají se filtrovat, výběrem podle určitých štítků (nebo pomocí matchExpressions):
"onKubernetesEvent": [
{
"selector": {
"matchLabels": {
"foo": "bar",
},
"matchExpressions": [
{
"key": "allow",
"operation": "In",
"values": ["wan", "warehouse"],
},
],
}
…
}
]Pokud deduplikační mechanismus, který – pomocí jq filtru – umožňuje převádět velké objekty JSON na malé, kde zbývají pouze ty parametry, které chceme sledovat kvůli změnám.
Když je zavolán hák, operátor shellu jej předá objektová data, který lze použít pro jakoukoli potřebu.
Události, které spouštějí zavěšení, nejsou omezeny na události Kubernetes: podporu poskytuje operátor shellu volání háčků podle času (podobně jako crontab v tradičním plánovači), stejně jako speciální událost na začátku. Všechny tyto události lze kombinovat a přiřadit ke stejnému háku.
A další dvě funkce shell-operátora:
- pracuje asynchronně. Vzhledem k tomu, že byla přijata událost Kubernetes (například vytvářený objekt), mohlo dojít v clusteru k jiným událostem (například k odstranění stejného objektu) a s tím musí počítat háky. Pokud byl hák proveden s chybou, pak bude ve výchozím nastavení odvolání až do úspěšného dokončení (toto chování lze změnit).
- Vyváží se metriky pro Prometheus, pomocí kterého můžete pochopit, zda funguje operátor shellu, zjistit počet chyb pro každý háček a aktuální velikost fronty.
Shrnutí této části zprávy:

Instalace doplňků
Pro pohodlnou práci s Kubernetes byla zmíněna i nutnost instalace doplňků. Řeknu vám o tom na příkladu cesty naší společnosti k tomu, jak to děláme nyní.
S Kubernetes jsme začali pracovat s několika clustery, jejichž jediným doplňkem byl Ingress. V každém clusteru to bylo potřeba nainstalovat jinak a udělali jsme několik konfigurací YAML pro různá prostředí: holý kov, AWS...
Čím více clusterů, tím více konfigurací. Kromě toho jsme vylepšili tyto konfigurace samotné, v důsledku čehož se staly značně heterogenními:

Abychom dali vše do pořádku, začali jsme se skriptem (install-ingress.sh), který vzal jako argument typ clusteru, do kterého nasadíme, vygeneroval potřebnou konfiguraci YAML a zavedl ji do Kubernetes.
Stručně řečeno, naše další cesta a úvahy s ní spojené byly následující:
- pro práci s konfiguracemi YAML je vyžadován šablonový engine (v prvních fázích je to jednoduché);
- s nárůstem počtu clusterů přišla potřeba automatické aktualizace (nejranějším řešením bylo umístit skript do Gitu, aktualizovat jej pomocí cronu a spustit);
- podobný skript byl vyžadován pro Prometheus (
install-prometheus.sh), je však pozoruhodný tím, že vyžaduje mnohem více vstupních dat a také jejich ukládání (v dobrém slova smyslu - centralizované a v clusteru) a některá data (hesla) by mohla být generována automaticky:
- riziko zavedení něčeho špatného do rostoucího počtu clusterů neustále rostlo, takže jsme si uvědomili, že instalátoři (tj. dva skripty: pro Ingress a Prometheus) bylo potřeba staging (několik větví v Gitu, několik cronů k jejich aktualizaci v odpovídajících: stabilních nebo testovacích clusterech);
- с
kubectl applyje obtížné s ním pracovat, protože není deklarativní a může pouze vytvářet objekty, ale nemůže rozhodovat o jejich stavu / je mazat; - Chyběly nám některé funkce, které jsme v té době vůbec neimplementovali:
- plnou kontrolu nad výsledkem aktualizací clusteru,
- automatické určení některých parametrů (vstup pro instalační skripty) na základě dat, která lze získat z clusteru (discovery),
- jeho logický vývoj v podobě neustálého objevování.
Všechny tyto nasbírané zkušenosti jsme realizovali v rámci našeho dalšího projektu - .
Operátor doplňků
Vychází z již zmíněného shell-operátora. Celý systém vypadá takto:
K háčkům operátora shellu je přidáno následující:
- ukládání hodnot,
- Tabulka kormidla,
- komponent, který sleduje ukládání hodnot a - v případě jakýchkoli změn - požádá Helma, aby přetočil graf.

Můžeme tedy reagovat na událost v Kubernetes, spustit hák a z tohoto háku provést změny v úložišti, po kterých se graf znovu stáhne. Ve výsledném diagramu oddělíme sadu háčků a graf do jedné komponenty, kterou nazýváme modul:

Modulů může být mnoho a k nim přidáme globální háčky, globální úložiště hodnot a komponentu, která tento globální obchod monitoruje.
Nyní, když se něco stane v Kubernetes, můžeme na to reagovat pomocí globálního háku a něco změnit v globálním obchodě. Tato změna bude zaznamenána a způsobí, že budou spuštěny všechny moduly v clusteru:

Toto schéma splňuje všechny požadavky pro instalaci doplňků, které byly uvedeny výše:
- Helm je zodpovědný za šablonování a deklarativnost.
- Problém s automatickou aktualizací byl vyřešen pomocí globálního háku, který jde do registru podle plánu a pokud tam uvidí nový obraz systému, spustí jej (tj. „sám“).
- Ukládání nastavení do clusteru je realizováno pomocí Konfigurační mapa, který obsahuje primární data pro úložiště (při spuštění se načítají do úložišť).
- Problémy s generováním hesla, zjišťováním a průběžným zjišťováním byly řešeny pomocí háčků.
- Stagingu je dosaženo díky tagům, které Docker podporuje hned po vybalení.
- Výsledek je sledován pomocí metrik, pomocí kterých můžeme porozumět stavu.
Celý tento systém je v Go implementován ve formě jediné binárky, která se nazývá addon-operator. Díky tomu schéma vypadá jednodušeji:

Hlavní komponentou v tomto diagramu je sada modulů (dole zvýrazněno šedou barvou). Nyní můžeme s trochou snahy napsat modul pro požadovaný doplněk a mít jistotu, že bude nainstalován v každém clusteru, bude aktualizován a reagovat na události, které v clusteru potřebuje.
"Ploché" použití na 70+ clusterech Kubernetes. Aktuální stav - alfa verze. Nyní připravujeme dokumentaci k vydání beta verze, ale zatím v úložišti , na jehož základě si můžete vytvořit svůj vlastní addon.
Kde mohu získat moduly pro addon-operátora? Vydání naší knihovny je pro nás další etapou, plánujeme to v létě.
Videa a diapozitivy
Video z představení (~50 minut):

Prezentace zprávy:
PS
Další zprávy na našem blogu:
- «"; (Dmitry Stolyarov; 8. listopadu 2018 na HighLoad++);
- «"; (Dmitry Stolyarov; 28. května 2018 na RootConf);
- «"; (Dmitry Stolyarov; 7. listopadu 2017 na HighLoad++);
- «"; (Dmitry Stolyarov; 6. června 2017 na RootConf).
Také by vás mohly zajímat následující publikace:
- «".
Zdroj: www.habr.com



