Espansione è cumplementarii Kubernetes (revisione è video rapportu)
8 d'aprile à a cunferenza Saint HighLoad++ 2019, cum'è parte di a sezione "DevOps and Operations", un rapportu "Espandendu è cumplementari Kubernetes" hè statu datu, in a creazione di quale hà participatu trè impiegati di a cumpagnia Flant. In questu, parlemu di parechje situazioni in quale vulemu espansione è cumplementarii e capacità di Kubernetes, ma per quale ùn avemu micca truvatu una suluzione pronta è simplice. Avemu e suluzioni necessarii in forma di prughjetti Open Source, è stu discorsu hè ancu dedicatu à elli.
Per tradizione, avemu piacè di prisentà video di u rapportu (50 minuti, assai più informativu chè l'articulu) è u riassuntu principale in forma di testu. Vai !
Core è aghjunte in K8s
Kubernetes cambia l'industria è l'approcciu di l'amministrazione chì sò longu stabiliti:
Grazie à ellu astrazioni, ùn avemu più operatu cù cuncetti cum'è a creazione di una cunfigurazione o eseguisce un cumandamentu (Chef, Ansible...), ma aduprate raggruppamenti di cuntenituri, servizii, etc.
Pudemu preparà applicazioni senza pensà à e sfumature di u situ specificu, nantu à quale serà lanciatu: bare metal, nuvola di unu di i fornituri, etc.
Cù K8 ùn avete mai statu più accessibile e migliori pratiche nantu à l'urganizazione di l'infrastruttura: tecniche di scaling, self-healing, fault tolerance, etc.
Tuttavia, sicuru, tuttu ùn hè micca cusì liscia: Kubernetes hà ancu purtatu i so sfidi novi.
Kubernetes ùn hè una combinazione chì risolve tutti i prublemi di tutti l'utilizatori. Core Kubernetes hè rispunsevule solu per un inseme di e funzioni minimu necessarii chì sò prisenti in ogni cluster:
U core di Kubernetes definisce un inseme basicu di primitivi per raggruppà cuntenituri, gestisce u trafficu, è cusì. Avemu parlatu di elli in più detail in rapportu 2 anni fà.
Per d 'altra banda, K8s offre grandi opportunità per espansione e funzioni dispunibili, chì aiutanu à chjude l'altri - specifichi - bisogni di l'utilizatori. L'addizioni à Kubernetes sò a rispunsabilità di l'amministratori di cluster, chì devenu installà è cunfigurà tuttu ciò chì hè necessariu per uttene u so cluster "in a forma curretta" [per risolve i so prublemi specifichi]. Chì tippu di aghjunte sò questi? Fighjemu qualchi esempii.
Esempii di add-ons
Dopu avè installatu Kubernetes, pudemu esse surprised chì a rete chì hè cusì necessaria per l'interazzione di pods sia in un node sia trà i nodi ùn funziona micca da sè stessu. U kernel Kubernetes ùn guarantisci micca e cunnessione necessarie; invece, determina a reta interfaccia (CNI) per add-ons di terze parti. Avemu da installà unu di sti add-ons, chì serà rispunsevule per a cunfigurazione di a rete.
Un esempiu vicinu hè e soluzioni di almacenamiento di dati (discu lucale, dispositivu di bloccu di rete, Ceph ...). In principiu eranu in u core, ma cù l'avventu CSI a situazione cambia à qualcosa simili à quellu chì hè digià descrittu: l'interfaccia hè in Kubernetes, è a so implementazione hè in moduli di terzu.
Operators hè una classa sana di add-ons (chì include u certificat-manager mintuatu), definiscenu primitive (s) è controller (s). A logica di u so travagliu hè limitata solu da a nostra imaginazione è ci permette di trasfurmà i cumpunenti di l'infrastruttura pronta (per esempiu, un DBMS) in primitivi, chì sò assai più faciuli di travaglià cù (ch'è cù un set di cuntenituri è i so paràmetri). Un gran numaru di operatori sò stati scritti - ancu s'è parechji ùn sò micca pronti per a produzzione, hè solu questione di tempu:
Metriche - un'altra illustrazione di cumu Kubernetes hà separatu l'interfaccia (Metrics API) da l'implementazione (add-ons di terze parti cum'è l'adattatore Prometheus, l'agente di cluster Datadog...).
di surviglianza è statistiche, induve in pratica ùn sò micca solu bisognu Prometheus è Grafana, ma ancu kube-state-metrics, node-exporter, etc.
È questu ùn hè micca una lista cumpleta di l'aghjunghje... Per esempiu, à a cumpagnia Flant chì avemu installatu oghje 29 add-ons (tutti chì creanu un totale di 249 oggetti Kubernetes). Simply put, ùn pudemu micca vede a vita di un cluster senza aghjunte.
L'automatizazione
L'operatori sò pensati per automatizà e operazioni di rutina chì scontru ogni ghjornu. Eccu esempi di a vita reale per quale scrive un operatore seria una soluzione eccellente:
Ci hè un registru privatu (vale à dì chì richiede un login) cù l'imaghjini per l'applicazione. Si assume chì ogni pod hè assignatu un sicretu speciale chì permette l'autentificazione in u registru. U nostru compitu hè di assicurà chì stu sicretu si trova in u namespace per chì i pods ponu scaricà l'imaghjini. Ci ponu esse assai appricazzioni (ognuna di e quali hà bisognu di un sicretu), è hè utile per aghjurnà i sicreti stessi regularmente, cusì l'opzione di mette i sicreti cù a manu hè eliminata. Hè quì chì l'operatore vene à u salvamentu: creemu un controller chì aspittà chì u spaziu di nome apparisce è, basatu annantu à questu avvenimentu, aghjunghje un sicretu à u spaziu di nome.
Permette l'accessu predeterminatu da pods à Internet hè pruibitu. Ma qualchì volta pò esse dumandatu: hè logicu chì u mecanismu di permessu d'accessu per travaglià simpliciamente, senza bisognu di cumpetenze specifiche, per esempiu, da a presenza di una certa etichetta in u namespace. Cumu l'operatore ci pò aiutà quì? Un controller hè creatu chì aspetta chì l'etichetta apparisce in u namespace è aghjunghje a pulitica approprita per l'accessu à Internet.
Una situazione simile: supponi chì avemu bisognu di aghjunghje un certu macchia, s'ellu hà una etichetta simile (cù qualchì prefissu). L'azzioni cù l'operatore sò evidenti ...
In ogni cluster, i travaglii di rutina deve esse risolti, è dirittu questu pò esse fattu cù l'operatori.
Riassuntu tutte e storie descritte, avemu ghjuntu à a cunclusione chì per u travagliu còmode in Kubernetes avete bisognu: A) installà add-ons, b) sviluppà operatori (per risolve i travaglii di amministrazione di ogni ghjornu).
Cumu scrive una dichjarazione per Kubernetes?
In generale, u schema hè simplice:
... ma poi risulta chì :
L'API Kubernetes hè una cosa piuttostu micca triviale chì piglia assai tempu per maestru;
A prugrammazione ùn hè ancu per tutti (a lingua Go hè stata scelta cum'è a lingua preferita perchè ci hè un quadru speciale per questu - Operatore SDK);
A situazione hè simile à u quadru stessu.
ligna di fondu: per scrive un controller (operatore) hà da spende risorse significative per studià u materiale. Questu seria ghjustificatu per l'operatori "grandi" - per dì, per u DBMS MySQL. Ma s'ellu ci ricurdamu di l'esempii descritti sopra (spiegamentu di sicreti, accessu à pods à Internet...), chì vulemu ancu fà bè, allora capiremu chì u sforzu spesu sopra u risultatu chì avemu bisognu avà :
In generale, un dilema nasce: spende assai risorse è truvate l'uttellu adattatu per scrive dichjarazioni, o fate a manera antica (ma rapidamente). Per risolve - per truvà un cumprumissu trà questi estremi - avemu creatu u nostru propiu prughjettu: shell-operatore(vede ancu u so annunziu recente nant'à u hub).
Shell-operatore
Cumu travaglia ? U cluster hà un pod chì cuntene un Go binariu cù un shell-operatore. Accantu à ellu hè un set di ganci(più dettagli nantu à elli - vede quì sottu). U shell-operatore stessu abbona à certi avvenimenti in l'API Kubernetes, à l'occurrence di quale lancia i ganci currispondenti.
Cumu l'operatore di shell sapi quali ganci chjamà nantu à quale avvenimenti? Sta infurmazione hè trasmessa à l'operatore di shell da i ganci stessi, è facenu assai simplicemente.
Un ganciu hè un script Bash o qualsiasi altru schedariu eseguibile chì accetta un argumentu unicu --config è risponde cù JSON. L'ultime determina chì l'uggetti sò d'interessu per ellu è chì avvenimenti (per questi ogetti) deve esse rispostu:
Illustreraghju l'implementazione nantu à l'operatore di cunchiglia di unu di i nostri esempi - sicreti di descomposizione per accede à un registru privatu cù l'imaghjini di l'applicazione. Hè custituitu di dui tappe.
Pràtica : 1. Scrivite un ganciu
Prima di tuttu, in u ganciu avemu da prucessu --config, chì indicanu chì avemu interessatu in namespaces, è specificamente, u mumentu di a so creazione:
U primu passu hè di sapè quale spaziu di nomi hè statu creatu, è u sicondu hè di creà l'usu kubectl sicretu per questu namespace.
Pràtica : 2. Assembla l'imaghjini
Tuttu ciò chì resta hè di passà u ganciu creatu à l'operatore di shell - cumu fà questu? U shell-operatore stessu vene cum'è una maghjina Docker, cusì u nostru compitu hè di aghjunghje u ganciu à un repertoriu speciale in questa maghjina:
FROM flant/shell-operator:v1.0.0-beta.1
ADD my-handler.sh /hooks
Questu hè un cumpunente di u sistema chì (à u minimu) hà bisognu di diritti per subscribe à l'avvenimenti in Kubernetes è per attribuisce sicreti à spazii di nomi, cusì creamu un ServiceAccount (è un settore di regule) per u ganciu.
Risultatu - avemu risoltu u nostru prublema parenti per Kubernetes in una manera chì crea un operatore per a descomposizione di i secreti.
Altre caratteristiche di l'operatore di shell
Per limità l'uggetti di u vostru tipu sceltu chì u ganciu hà da travaglià, ponu esse filtrati, selezziunate secondu certi etichette (o usendu matchExpressions):
Fornitu mecanismu di deduplicazione, chì - utilizendu un filtru jq - permette di cunvertisce l'uggetti JSON grandi in chjuchi, induve solu quessi paràmetri restanu chì vulemu monitorà per i cambiamenti.
Quandu un ganciu hè chjamatu, l'operatore di shell passa dati di l'ughjettu, chì pò esse usatu per ogni bisognu.
L'avvenimenti chì attivanu i ganci ùn sò micca limitati à l'avvenimenti Kubernetes: l'operatore di shell furnisce supportu per chjamà ganci da u tempu (simile à crontab in un scheduler tradiziunale), è ancu un avvenimentu speciale onStartup. Tutti questi avvenimenti ponu esse cumminati è assignati à u stessu ganciu.
È duie altre caratteristiche di l'operatore di shell:
Funziona in modu asincronu. Siccomu un avvenimentu Kubernetes (cum'è un ughjettu chì hè creatu) hè statu ricevutu, altri avvenimenti (cum'è u stessu ughjettu chì hè sguassatu) puderia esse accadutu in u cluster, è i ganci anu bisognu di cuntà per questu. Se u ganciu hè statu eseguitu cù un errore, da automaticamente serà richiamà finu à a fine di successu (questu cumpurtamentu pò esse cambiatu).
Esporta metrica per Prometheus, cù quale pudete capisce se l'operatore di shell hè travagliatu, scopre u numeru di errori per ogni ganciu è a dimensione attuale di a fila.
Per sintetizà sta parte di u rapportu:
Install Add-ons
Per u travagliu còmode cù Kubernetes, a necessità di installà add-ons hè statu ancu mintuatu. Vi cuntaraghju cù l'esempiu di a strada di a nostra cumpagnia per cumu fà avà.
Avemu cuminciatu à travaglià cù Kubernetes cù parechji clusters, l'unicu aghjuntu à quale era Ingress. Ci vole à esse installatu in modu diversu in ogni cluster, è avemu fattu parechje cunfigurazioni YAML per ambienti differenti: bare metal, AWS...
Cume ci era più clusters, ci era più cunfigurazioni. Inoltre, avemu migliuratu sti cunfigurazioni stessi, per via di quale sò diventati abbastanza eterogenei:
Per mette tuttu in ordine, avemu principiatu cù un script (install-ingress.sh), chì hà pigliatu cum'è un argumentu u tipu di cluster à quale avemu da implementà, hà generatu a cunfigurazione YAML necessaria è l'hà purtatu à Kubernetes.
In breve, u nostru percorsu ulteriore è u ragiunamentu assuciatu cù questu era u seguitu:
per travaglià cù cunfigurazioni YAML, un mutore di mudellu hè necessariu (à i primi tappe questu hè simplice sed);
cù l'aumentu di u nùmeru di clusters, hè vinutu a necessità di l'aghjurnamentu automaticu (a prima suluzione era di mette u script in Git, aghjurnà cù cron è eseguisce);
un script simile era necessariu per Prometheus (install-prometheus.sh), in ogni modu, hè notu per u fattu chì esige assai più dati di input, è ancu u so almacenamentu (in un bonu modu - centralizatu è in un cluster), è certi dati (password) puderanu esse generati automaticamente:
u risicu di sparghje qualcosa di sbagliatu à un numeru crescente di clusters era in constantemente crescente, cusì avemu capitu chì l'installatori (vale à dì dui script: per Ingress è Prometheus) staging era necessariu (parechji rami in Git, parechji crons per aghjurnà in u currispundente: clusters stabili o teste);
с kubectl apply hè diventatu difficiuli di travaglià perchè ùn hè micca dichjarazione è pò creà solu l'uggetti, ma micca piglià decisioni nantu à u so status / sguassate;
Ci mancava alcune funzioni chì ùn avemu micca implementatu in tuttu à quellu tempu:
cuntrollu tutale di u risultatu di l'aghjurnamenti di u cluster,
determinazione automatica di certi paràmetri (input per script d'installazione) basatu nantu à dati chì ponu esse ottenuti da u cluster (scuperta),
u so sviluppu logicu in forma di scuperta cuntinua.
Avemu implementatu tutta sta sperienza accumulata in u quadru di u nostru altru prughjettu - addun-operatore.
Addon-operatore
Hè basatu annantu à l'operatore di shell digià citatu. Tuttu u sistema s'assumiglia cusì:
U seguente hè aghjuntu à i ganci di l'operatore di shell:
almacenamentu di valori,
Graficu di Helm,
cumpunente chì monitoreghja u magazinu di valori è - in casu di qualsiasi cambiamenti - dumanda à Helm di ritruvà a carta.
Cusì, pudemu reagisce à un avvenimentu in Kubernetes, lanciate un ganciu, è da questu ganciu pudemu fà cambiamenti à l'almacenamiento, dopu chì u graficu serà scaricatu di novu. In u diagramma resultanti, separemu u settore di ganci è u graficu in un cumpunente, chì chjamemu modulu:
Ci ponu esse parechji moduli, è à elli aghjunghjemu ganci glubale, una tenda di valori globale, è un cumpunente chì monitoreghja sta tenda globale.
Avà, quandu qualcosa succede in Kubernetes, pudemu reagisce cù un ganciu globale è cambià qualcosa in a tenda globale. Stu cambiamentu serà nutatu è pruvucarà tutti i moduli in u cluster per esse lanciati:
Stu schema risponde à tutti i requisiti per installà add-ons chì sò stati dichjarati sopra:
Helm hè rispunsevuli di mudelli è di dichjarazione.
U prublema di l'aghjurnamentu automaticu hè stata risolta cù un ganciu globale, chì và à u registru nantu à un calendariu è, se vede una nova maghjina di u sistema, u rollu fora (vale à dì "ellu stessu").
L'almacenamentu di e paràmetri in u cluster hè implementatu usendu ConfigMap, chì cuntene i dati primari per i magazzini (à l'iniziu sò caricati in i magazzini).
I prublemi cù a generazione di password, a scuperta è a scuperta cuntinua sò stati risolti cù ganci.
A messa in scena hè ottenuta grazia à i tags, chì Docker sustene fora di a scatula.
U risultatu hè monitoratu cù metrica per quale pudemu capisce u statutu.
Stu sistema sanu hè implementatu in a forma di un solu binariu in Go, chì hè chjamatu addon-operatore. Questu rende u diagramma più simplice:
U cumpunente principale in stu schema hè un inseme di moduli (evidenziatu in grisgiu sottu). Avà pudemu scrive un modulu per l'add-on necessariu cun un pocu sforzu è assicuratevi chì serà stallatu in ogni cluster, serà aghjurnatu è risponde à l'avvenimenti chì hà bisognu in u cluster.
"Flant" usa addun-operatore nantu à 70+ clusters Kubernetes. Statu attuale - versione alfa. Avà preparamu a documentazione per liberà a beta, ma per avà in u repository esempi dispunibuli, nantu à a basa di quale pudete creà u vostru propiu addon.
Induve possu uttene i moduli per l'operatore addon? A publicazione di a nostra biblioteca hè a prossima tappa per noi; pensamu di fà questu in l'estiu.