ProHoster > Blog > administratë > Shkoni? Bash! Takoni operatorin e guaskës (rishikim dhe raport video nga KubeCon EU'2020)
Shkoni? Bash! Takoni operatorin e guaskës (rishikim dhe raport video nga KubeCon EU'2020)
Këtë vit, konferenca kryesore evropiane e Kubernetes - KubeCon + CloudNativeCon Europe 2020 - ishte virtuale. Megjithatë, një ndryshim i tillë në format nuk na pengoi të dorëzonim raportin tonë të planifikuar prej kohësh “Shko? Bash! Njihuni me operatorin Shell” kushtuar projektit tonë me kod të hapur shell-operator.
Ky artikull, i frymëzuar nga fjalimi, paraqet një qasje për thjeshtimin e procesit të krijimit të operatorëve për Kubernetes dhe tregon se si mund ta bëni vetë me përpjekje minimale duke përdorur një operator guaskë.
duke prezantuar video e raportit (~23 minuta në anglisht, dukshëm më informues se artikulli) dhe ekstrakti kryesor prej tij në formë teksti. Shkoni!
Në Flant ne vazhdimisht optimizojmë dhe automatizojmë gjithçka. Sot do të flasim për një koncept tjetër emocionues. Takohen: skriptimi i guaskës së brendshme në renë kompjuterike!
Megjithatë, le të fillojmë me kontekstin në të cilin ndodh e gjithë kjo: Kubernetes.
Kubernetes API dhe kontrollorët
API në Kubernetes mund të përfaqësohet si një lloj serveri skedarësh me direktori për çdo lloj objekti. Objektet (burimet) në këtë server përfaqësohen nga skedarët YAML. Përveç kësaj, serveri ka një API bazë që ju lejon të bëni tre gjëra:
marr burimi sipas llojit dhe emrit të tij;
ndryshim burimi (në këtë rast, serveri ruan vetëm objekte "korrekte" - të gjitha ato të formuara gabimisht ose të destinuara për drejtoritë e tjera janë hedhur poshtë);
udhë për burimin (në këtë rast, përdoruesi merr menjëherë versionin e tij aktual/të përditësuar).
Kështu, Kubernetes vepron si një lloj serveri skedarësh (për manifestet YAML) me tre metoda themelore (po, në fakt ka të tjera, por ne do t'i heqim ato për momentin).
Problemi është se serveri mund të ruajë vetëm informacione. Për ta bërë atë të funksionojë ju duhet kontrollues - koncepti i dytë më i rëndësishëm dhe themelor në botën e Kubernetes.
Ekzistojnë dy lloje kryesore të kontrolluesve. I pari merr informacion nga Kubernetes, e përpunon atë sipas logjikës së mbivendosur dhe e kthen atë në K8. E dyta merr informacion nga Kubernetes, por, ndryshe nga lloji i parë, ndryshon gjendjen e disa burimeve të jashtme.
Le të hedhim një vështrim më të afërt në procesin e krijimit të një vendosjeje në Kubernetes:
Kontrolluesi i vendosjes (përfshirë në kube-controller-manager) merr informacion në lidhje me Deployment dhe krijon një ReplicaSet.
ReplicaSet krijon dy kopje (dy pods) bazuar në këtë informacion, por këto pods nuk janë planifikuar ende.
Planifikuesi planifikon pods dhe shton informacionin e nyjeve në YAML-të e tyre.
Kubelets bëjnë ndryshime në një burim të jashtëm (të themi Docker).
Pastaj e gjithë kjo sekuencë përsëritet në rend të kundërt: kubelet kontrollon kontejnerët, llogarit statusin e pod dhe e kthen atë. Kontrolluesi ReplicaSet merr statusin dhe përditëson gjendjen e grupit të kopjeve. E njëjta gjë ndodh me Deployment Controller dhe përdoruesi më në fund merr statusin e përditësuar (aktual).
Shell-operator
Rezulton se Kubernetes bazohet në punën e përbashkët të kontrolluesve të ndryshëm (operatorët Kubernetes janë gjithashtu kontrollues). Shtrohet pyetja, si të krijoni operatorin tuaj me përpjekje minimale? Dhe këtu vjen në shpëtim ai që kemi zhvilluar shell-operator. Ai i lejon administratorët e sistemit të krijojnë deklaratat e tyre duke përdorur metoda të njohura.
Shembull i thjeshtë: kopjimi i sekreteve
Le të shohim një shembull të thjeshtë.
Le të themi se kemi një grup Kubernetes. Ka një hapësirë emri default me disa sekrete mysecret. Përveç kësaj, ka hapësira të tjera emrash në grup. Disa prej tyre kanë një etiketë specifike të bashkangjitur me to. Qëllimi ynë është të kopjojmë Sekretin në hapësirat e emrave me një etiketë.
Detyra është e ndërlikuar nga fakti se hapësirat e reja të emrave mund të shfaqen në grup, dhe disa prej tyre mund të kenë këtë etiketë. Nga ana tjetër, kur etiketa fshihet, Sekreti gjithashtu duhet të fshihet. Përveç kësaj, vetë Sekreti mund të ndryshojë gjithashtu: në këtë rast, Sekreti i ri duhet të kopjohet në të gjitha hapësirat e emrave me etiketa. Nëse Sekreti fshihet aksidentalisht në ndonjë hapësirë emri, operatori ynë duhet ta rivendosë atë menjëherë.
Tani që detyra është formuluar, është koha për të filluar zbatimin e saj duke përdorur operatorin shell. Por së pari ia vlen të thuash disa fjalë për vetë operatorin e guaskës.
Si funksionon operatori i guaskës
Ashtu si ngarkesat e tjera të punës në Kubernetes, operatori i guaskës funksionon në podin e vet. Në këtë pod në drejtori /hooks skedarët e ekzekutueshëm ruhen. Këto mund të jenë skripta në Bash, Python, Ruby, etj. Ne i quajmë skedarë të tillë të ekzekutueshëm grepa (grepa).
Operatori i Shell abonohet në ngjarjet e Kubernetes dhe i drejton këto grepa në përgjigje të atyre ngjarjeve që na duhen.
Si e di operatori i guaskës se cilin grep duhet të ekzekutojë dhe kur? Çështja është se çdo goditje ka dy faza. Gjatë nisjes, operatori i guaskës ekzekuton të gjitha grepa me një argument --config Kjo është faza e konfigurimit. Dhe pas saj, grepa lëshohen në mënyrën normale - në përgjigje të ngjarjeve të cilave u janë bashkangjitur. Në rastin e fundit, grepi merr kontekstin lidhës (kontekst detyrues) - të dhëna në format JSON, për të cilat do të flasim më në detaje më poshtë.
Bërja e një operatori në Bash
Tani jemi gati për zbatim. Për ta bërë këtë, ne duhet të shkruajmë dy funksione (nga rruga, ne rekomandojmë biblioteka shell_lib, e cila thjeshton shumë shkrimin e grepave në Bash):
e para është e nevojshme për fazën e konfigurimit - shfaq kontekstin e lidhjes;
e dyta përmban logjikën kryesore të grepit.
#!/bin/bash
source /shell_lib.sh
function __config__() {
cat << EOF
configVersion: v1
# BINDING CONFIGURATION
EOF
}
function __main__() {
# THE LOGIC
}
hook::run "$@"
Hapi tjetër është të vendosim se cilat objekte na duhen. Në rastin tonë, duhet të gjurmojmë:
sekret burim për ndryshime;
të gjitha hapësirat e emrave në grup, në mënyrë që të dini se cilat prej tyre kanë një etiketë të bashkangjitur;
synoni sekretet për të siguruar që ato të jenë të gjitha në sinkron me sekretin burimor.
Regjistrohu në burimin sekret
Konfigurimi i lidhjes për të është mjaft i thjeshtë. Ne tregojmë se jemi të interesuar për Secret me emrin mysecret në hapësirën e emrave default:
Siç mund ta shihni, një fushë e re është shfaqur në konfigurim me emrin jqFilter. Siç sugjeron edhe emri i tij, jqFilter filtron të gjitha informacionet e panevojshme dhe krijon një objekt të ri JSON me fushat që janë me interes për ne. Një goditje me një konfigurim të ngjashëm do të marrë kontekstin e mëposhtëm lidhës:
Ai përmban një grup filterResults për çdo hapësirë emri në grup. Variabli Boolean hasLabel tregon nëse një emërtim është i bashkangjitur në një hapësirë të caktuar emri. Përzgjedhësi keepFullObjectsInMemory: false tregon se nuk ka nevojë të mbahen objekte të plota në kujtesë.
Ndjekja e sekreteve të objektivit
Ne abonojmë të gjitha Sekretet që kanë një shënim të specifikuar managed-secret: "yes" (këto janë objektivi ynë dst_secrets):
Në këtë rast, jqFilter filtron të gjithë informacionin përveç hapësirës së emrave dhe parametrit resourceVersion. Parametri i fundit iu kalua shënimit kur krijoni sekretin: ju lejon të krahasoni versionet e sekreteve dhe t'i mbani ato të përditësuara.
Një goditje e konfiguruar në këtë mënyrë, kur të ekzekutohet, do të marrë tre kontekstet lidhëse të përshkruara më sipër. Ato mund të mendohen si një lloj fotografie (fotografi i çastit) grumbull.
Bazuar në të gjitha këto informacione, mund të zhvillohet një algoritëm bazë. Ai përsëritet në të gjitha hapësirat e emrave dhe:
nëse hasLabel çështjet true për hapësirën aktuale të emrave:
krahason sekretin global me atë lokal:
nëse janë të njëjta, nuk bën asgjë;
nëse ndryshojnë - ekzekuton kubectl replace ose create;
nëse hasLabel çështjet false për hapësirën aktuale të emrave:
sigurohet që Sekreti nuk është në hapësirën e emrit të dhënë:
nëse sekreti lokal është i pranishëm, fshijeni atë duke përdorur kubectl delete;
nëse sekreti lokal nuk zbulohet, ai nuk bën asgjë.
Kështu mundëm të krijonim një kontrollues të thjeshtë Kubernetes duke përdorur 35 rreshta të konfigurimit YAML dhe afërsisht të njëjtën sasi të kodit Bash! Detyra e operatorit të guaskës është t'i lidhë ato së bashku.
Sidoqoftë, kopjimi i sekreteve nuk është fusha e vetme e aplikimit të shërbimit. Këtu janë disa shembuj të tjerë për të treguar se çfarë është ai i aftë.
Shembulli 1: Bërja e ndryshimeve në ConfigMap
Le të shohim një vendosje të përbërë nga tre pods. Pods përdorin ConfigMap për të ruajtur disa konfigurime. Kur podet u lansuan, ConfigMap ishte në një gjendje të caktuar (le ta quajmë v.1). Prandaj, të gjitha pods përdorin këtë version të veçantë të ConfigMap.
Tani le të supozojmë se ConfigMap ka ndryshuar (v.2). Megjithatë, pods do të përdorin versionin e mëparshëm të ConfigMap (v.1):
Si mund t'i bëj ata të kalojnë në ConfigMap-in e ri (v.2)? Përgjigja është e thjeshtë: përdorni një shabllon. Le të shtojmë një shënim kontrolli në seksion template Konfigurimet e vendosjes:
Si rezultat, kjo shumë kontrolli do të regjistrohet në të gjitha pods dhe do të jetë e njëjtë me atë të Deployment. Tani ju vetëm duhet të përditësoni shënimin kur ndryshon ConfigMap. Dhe operatori i guaskës është i dobishëm në këtë rast. E tëra çfarë ju duhet të bëni është të programoni një goditje që do të regjistrohet në ConfigMap dhe do të përditësojë kontrollin.
Nëse përdoruesi bën ndryshime në ConfigMap, operatori i guaskës do t'i vërejë ato dhe do të rillogarisë shumën e kontrollit. Pas së cilës magjia e Kubernetes do të hyjë në lojë: orkestratori do të vrasë podin, do të krijojë një të re, do të presë që ajo të bëhet Ready, dhe kalon në tjetrin. Si rezultat, Deployment do të sinkronizohet dhe do të kalojë në versionin e ri të ConfigMap.
Shembulli 2: Puna me përkufizimet e burimeve të personalizuara
Siç e dini, Kubernetes ju lejon të krijoni lloje të personalizuara të objekteve. Për shembull, ju mund të krijoni lloj MysqlDatabase. Le të themi se ky lloj ka dy parametra të meta të dhënave: name и namespace.
apiVersion: example.com/v1alpha1
kind: MysqlDatabase
metadata:
name: foo
namespace: bar
Ne kemi një grup Kubernetes me hapësira të ndryshme emrash në të cilat mund të krijojmë baza të të dhënave MySQL. Në këtë rast shell-operator mund të përdoret për të gjurmuar burimet MysqlDatabase, duke i lidhur ato me serverin MySQL dhe duke sinkronizuar gjendjet e dëshiruara dhe të vëzhguara të grupit.
Shembulli 3: Monitorimi i Rrjetit Cluster
Siç e dini, përdorimi i ping është mënyra më e thjeshtë për të monitoruar një rrjet. Në këtë shembull do të tregojmë se si të zbatohet një monitorim i tillë duke përdorur operatorin e guaskës.
Para së gjithash, do t'ju duhet të abonoheni në nyjet. Operatori shell ka nevojë për emrin dhe adresën IP të secilës nyje. Me ndihmën e tyre, ai do t'i pingojë këto nyje.
Parametër executeHookOnEvent: [] parandalon funksionimin e grepit në përgjigje të ndonjë ngjarjeje (d.m.th., në përgjigje të ndryshimit, shtimit, fshirjes së nyjeve). Megjithatë, ai do të kandidojë (dhe përditësoni listën e nyjeve) I planifikuar - çdo minutë, siç përcaktohet nga fusha schedule.
Tani lind pyetja, si i dimë saktësisht problemet si humbja e paketave? Le t'i hedhim një sy kodit:
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
}
Ne përsërisim listën e nyjeve, marrim emrat e tyre dhe adresat IP, i bëjmë ping dhe i dërgojmë rezultatet te Prometheus. Operatori Shell mund të eksportojë metrikë te Prometheus, duke i ruajtur ato në një skedar të vendosur sipas shtegut të specifikuar në variablin e mjedisit $METRICS_PATH.
Ja kështu ju mund të krijoni një operator për monitorim të thjeshtë të rrjetit në një grup.
Mekanizmi i radhës
Ky artikull do të ishte i paplotë pa përshkruar një mekanizëm tjetër të rëndësishëm të integruar në operatorin e guaskës. Imagjinoni që ai ekzekuton një lloj goditjeje në përgjigje të një ngjarjeje në grup.
Çfarë ndodh nëse, në të njëjtën kohë, ndodh diçka në grup? nje me shume ngjarje?
A do të ekzekutojë operatori i guaskës një shembull tjetër të goditjes?
Po sikur, të themi, pesë ngjarje të ndodhin në grup menjëherë?
A do t'i përpunojë ato paralelisht operatori i guaskës?
Po në lidhje me burimet e konsumuara si memoria dhe CPU?
Për fat të mirë, operatori i guaskës ka një mekanizëm të integruar të radhës. Të gjitha ngjarjet janë në radhë dhe përpunohen në mënyrë sekuenciale.
Le ta ilustrojmë këtë me shembuj. Le të themi se kemi dy grepa. Ngjarja e parë shkon në goditjen e parë. Pasi të përfundojë përpunimi i tij, radha shkon përpara. Tre ngjarjet e ardhshme ridrejtohen në grepin e dytë - ato hiqen nga radha dhe futen në të në një "pako". Kjo eshte hook merr një sërë ngjarjesh - ose, më saktë, një sërë kontekstesh të detyrueshme.
Edhe këto ngjarjet mund të kombinohen në një të madhe. Parametri është përgjegjës për këtë group në konfigurimin e lidhjes.
Ju mund të krijoni çdo numër radhësh/grepash dhe kombinime të ndryshme të tyre. Për shembull, një radhë mund të funksionojë me dy grepa, ose anasjelltas.
E tëra çfarë ju duhet të bëni është të konfiguroni fushën në përputhje me rrethanat queue në konfigurimin e lidhjes. Nëse emri i radhës nuk është specifikuar, grepa funksionon në radhën e paracaktuar (default). Ky mekanizëm i radhës ju lejon të zgjidhni plotësisht të gjitha problemet e menaxhimit të burimeve kur punoni me grepa.
Përfundim
Ne shpjeguam se çfarë është një operator guaskë, treguam se si mund të përdoret për të krijuar shpejt dhe pa mundim operatorë Kubernetes dhe dhamë disa shembuj të përdorimit të tij.
Informacioni i detajuar rreth operatorit të guaskës, si dhe një tutorial i shpejtë se si ta përdorni atë, janë në dispozicion në përkatësin depo në GitHub. Mos hezitoni të na kontaktoni me pyetje: ju mund t'i diskutoni ato në një speciale Grupi i telegramit (në rusisht) ose në ky forum (në Anglisht).
Dhe nëse ju pëlqeu, ne jemi gjithmonë të lumtur të shohim çështje të reja/PR/yje në GitHub, ku, meqë ra fjala, mund të gjeni të tjera projekte interesante. Midis tyre vlen të theksohet shtesë-operator, i cili është vëllai i madh i operatorit të guaskës. Ky mjet përdor diagramet Helm për të instaluar shtesa, mund të japë përditësime dhe të monitorojë parametra/vlera të ndryshme të grafikut, kontrollon procesin e instalimit të grafikëve dhe gjithashtu mund t'i modifikojë ato në përgjigje të ngjarjeve në grup.