ProHoster > Blog > Uprava > Kaj sem se naučil pri testiranju 200 vrstic infrastrukturne kode
Kaj sem se naučil pri testiranju 200 vrstic infrastrukturne kode
Pristop IaC (Infrastruktura kot koda) ni sestavljena le iz kode, ki je shranjena v repozitoriju, ampak tudi iz ljudi in procesov, ki to kodo obkrožajo. Ali je mogoče ponovno uporabiti pristope od razvoja programske opreme do upravljanja in opisa infrastrukture? Dobro bi bilo, da imate to misel v mislih, medtem ko berete članek.
Recimo, da pridete do novega projekta in vam rečejo: »imamo Infrastruktura kot zakonik". V resnici se izkaže Infrastruktura kot bash zgodovina ali na primer Dokumentacija kot zgodovina bash. To je zelo resnična situacija, podoben primer je na primer opisal Denis Lysenko v govoru Kako zamenjati celotno infrastrukturo in začeti mirno spati, je povedal, kako so iz bash zgodovine dobili skladno infrastrukturo za projekt.
Z nekaj želje lahko rečemo Infrastruktura kot bash zgodovina to je kot koda:
ponovljivost: Lahko vzamete zgodovino bash, zaženete ukaze od tam in mimogrede lahko dobite delujočo konfiguracijo kot izhod.
različic: veste, kdo je vstopil in kaj je naredil, spet ni dejstvo, da vas bo to na izhodu pripeljalo do delujoče konfiguracije.
Zgodovina: zgodba o tem, kdo je kaj naredil. samo če izgubiš strežnik, ga ne boš mogel uporabljati.
Kaj storiti?
Infrastruktura kot zakonik
Tudi tako čuden primer, kot je Infrastruktura kot bash zgodovina lahko ga vlečeš za ušesa Infrastruktura kot zakonik, ko pa želimo narediti nekaj bolj zapletenega od dobrega starega strežnika LAMP, bomo prišli do zaključka, da je treba to kodo nekako modificirati, spremeniti, izboljšati. Nato bi radi razmislili o vzporednicah med Infrastruktura kot zakonik in razvoj programske opreme.
SUHO
Pri projektu razvoja sistema za shranjevanje je obstajala podnaloga občasno konfigurirajte SDS: izdajamo novo izdajo - treba jo je uvesti za nadaljnje testiranje. Naloga je izjemno preprosta:
tukaj se prijavite prek ssh in izvedite ukaz.
kopirajte datoteko tja.
popravi konfiguracijo tukaj.
tam zaženite storitev
...
DOBIČEK!
Za opisano logiko je bash več kot dovolj, sploh v zgodnjih fazah projekta, ko se ta šele začenja. to ni slabo, da uporabljaš bash, vendar se sčasoma pojavijo zahteve za uvedbo nečesa podobnega, a nekoliko drugačnega. Prva stvar, ki pride na misel, je copy-paste. In zdaj že imamo dva zelo podobna skripta, ki delata skoraj isto stvar. Sčasoma je število skript naraslo in soočili smo se z dejstvom, da obstaja določena poslovna logika za postavitev namestitve, ki mora biti sinhronizirana med različnimi skripti, kar je precej zapleteno.
Izkazalo se je, da obstaja takšna praksa, kot je D.R.Y. (Ne ponavljaj se). Ideja je ponovno uporabiti obstoječo kodo. Sliši se preprosto, a do tega nismo prišli takoj. V našem primeru je šlo za banalno idejo: ločiti konfiguracije od skriptov. Tisti. poslovna logika, kako je namestitev nameščena ločeno, konfiguracije ločeno.
S.O.L.I.D. za CFM
Sčasoma je projekt rasel in naravno nadaljevanje je bil nastanek Ansiblea. Glavni razlog za njegov pojav je, da je v ekipi strokovno znanje in da bash ni zasnovan za zapleteno logiko. Ansible je začel vsebovati tudi zapleteno logiko. Da bi preprečili, da bi se kompleksna logika spremenila v kaos, obstajajo načela za organiziranje kode pri razvoju programske opreme TRDNO Tudi Grigory Petrov je na primer v poročilu »Zakaj IT strokovnjak potrebuje osebno blagovno znamko« postavil vprašanje, da je človek zasnovan tako, da mu je lažje delovati z nekaterimi družbenimi entitetami, pri razvoju programske opreme pa ti so predmeti. Če združimo ti dve ideji in ju še naprej razvijamo, bomo opazili, da lahko tudi uporabimo TRDNO da bo lažje vzdrževati in spreminjati to logiko v prihodnosti.
Načelo enotne odgovornosti
Vsak razred opravi samo eno nalogo.
Ni vam treba mešati kode in izdelovati monolitnih božanskih pošasti iz špagetov. Infrastruktura naj bo sestavljena iz preprostih zidakov. Izkazalo se je, da če Ansible Playbook razdelite na majhne koščke, preberete Ansible vloge, jih je lažje vzdrževati.
Odprto zaprto načelo
Odprto/zaprto načelo.
Odprto za razširitev: pomeni, da je mogoče vedenje entitete razširiti z ustvarjanjem novih tipov entitet.
Zaprto za spremembe: zaradi razširitve vedenja entitete se ne sme spreminjati koda, ki uporablja te entitete.
Sprva smo testno infrastrukturo uvedli na virtualnih strojih, vendar smo zaradi dejstva, da je bila poslovna logika uvedbe ločena od implementacije, brez težav dodali uvajanje v baremetall.
Načelo zamenjave Liskova
Nadomestni princip Barbare Liskov. objekte v programu je treba zamenjati s primerki njihovih podtipov, ne da bi spremenili pravilno izvajanje programa
Če pogledate širše, to ni lastnost nekega posebnega projekta, ki bi ga lahko tam uporabili TRDNO, na splošno gre za CFM, na primer pri drugem projektu je treba namestiti aplikacijo Java v škatli na vrhu različnih Jav, aplikacijskih strežnikov, baz podatkov, OS itd. Na tem primeru bom preučil nadaljnja načela TRDNO
V našem primeru obstaja dogovor znotraj skupine za infrastrukturo, da če imamo nameščeno vlogo imbjava ali oraclejava, potem imamo binarno izvršljivo datoteko java. To je potrebno, ker Vloge navzgor so odvisne od tega vedenja; pričakujejo javo. Hkrati nam to omogoča zamenjavo ene implementacije/različice java z drugo brez spreminjanja logike uvajanja aplikacije.
Težava je v tem, da tega ni mogoče implementirati v Ansible, zaradi česar se pojavljajo nekateri dogovori znotraj ekipe.
Načelo ločevanja vmesnika
Načelo ločevanja vmesnikov: »Številni vmesniki, specifični za odjemalce, so boljši od enega splošnega vmesnika.
Sprva smo poskušali vso variabilnost uvajanja aplikacij spraviti v en Ansible playbook, vendar je bilo to težko podpreti in pristop, ko imamo določen zunanji vmesnik (stranka pričakuje vrata 443), nato pa je infrastrukturo mogoče sestaviti iz posameznih opeke za določeno izvedbo.
Načelo inverzije odvisnosti
Načelo inverzije odvisnosti. Moduli na višjih ravneh ne bi smeli biti odvisni od modulov na nižjih ravneh. Obe vrsti modulov morata biti odvisni od abstrakcij. Abstrakcije ne smejo biti odvisne od podrobnosti. Podrobnosti morajo biti odvisne od abstrakcij.
Tu bo primer temeljil na antivzorcu.
Ena od strank je imela zasebni oblak.
Naročili smo virtualne stroje znotraj oblaka.
Toda zaradi narave oblaka je bila uvedba aplikacije vezana na hipervizor, na katerem je bil VM.
Tisti. Logika uvajanja aplikacij na visoki ravni je tekla z odvisnostmi na nižje ravni hipervizorja, kar je pomenilo težave pri ponovni uporabi te logike. Ne delaj tako.
Medsebojno
Pri infrastrukturi kot kodi ne gre le za kodo, ampak tudi za odnos med kodo in ljudmi, za interakcije med razvijalci infrastrukture.
Faktor avtobusa
Predpostavimo, da imate na svojem projektu Vasjo. Vasya ve vse o vaši infrastrukturi, kaj se bo zgodilo, če Vasya nenadoma izgine? To je povsem realna situacija, saj bi ga lahko zbil avtobus. Včasih se zgodi. Če se to zgodi in znanje o kodi, njeni strukturi, delovanju, nastopih in geslih ni porazdeljeno med ekipo, lahko naletite na številne neprijetne situacije. Za zmanjšanje teh tveganj in distribucijo znanja znotraj ekipe lahko uporabite različne pristope
Par Devopsing
Ni všeč kot za šalo, da so admini pili pivo, spreminjali gesla in analogno programiranje v parih. Tisti. dva inženirja se usedeta za en računalnik, eno tipkovnico in začneta skupaj postavljati vašo infrastrukturo: nastavitev strežnika, pisanje vloge Ansible itd. Sliši se lepo, a nam ni uspelo. Toda posebni primeri te prakse so delovali. Pride nov sodelavec, njegov mentor skupaj z njim prevzame pravo nalogo, dela in prenaša znanje.
Drug poseben primer je incidentni klic. Ob težavi se zbere skupina dežurnih in vpletenih, določi se en vodja, ki si deli svoj zaslon in glasno izraža tok misli. Drugi udeleženci sledijo voditeljevim mislim, vohunijo za triki s konzole, preverjajo, ali niso zgrešili vrstice v dnevniku, in se učijo novih stvari o sistemu. Ta pristop je bolj pogosto deloval kot ne.
Pregled kode
Subjektivno je bilo bolj učinkovito razširjati znanje o infrastrukturi in njenem delovanju s pregledom kode:
Infrastruktura je opisana s kodo v repozitoriju.
Spremembe se zgodijo v ločeni veji.
Med zahtevo za združitev lahko vidite delto sprememb v infrastrukturi.
Vrhunec pri tem je bil, da so recenzente izbirali enega za drugim, po urniku, t.j. z določeno stopnjo verjetnosti se boste povzpeli na nov del infrastrukture.
Slog kode
Sčasoma so se med pregledi začeli pojavljati prepiri, ker... recenzenti so imeli svoj slog in rotacija recenzentov jih je zložila z različnimi slogi: 2 presledki ali 4, camelCase ali snake_case. Tega ni bilo mogoče izvesti takoj.
Prva ideja je bila priporočiti uporabo linterja, navsezadnje so vsi inženirji, vsi so pametni. Toda različni urejevalniki, OS, niso priročni
To se je razvilo v bota, ki je pisal v slack za vsako problematično objavo in priložil izhod linterja. Toda v večini primerov je bilo treba opraviti pomembnejše stvari in koda je ostala nepopravljena.
Mojster zelene gradnje
Čas teče in prišli smo do zaključka, da commitov, ki ne prestanejo določenih testov, ni mogoče dovoliti v master. Voila! Izumili smo Green Build Master, ki se že dolgo uporablja v razvoju programske opreme:
Razvoj poteka v ločeni veji.
V tej temi potekajo testi.
Če testi ne uspejo, koda ne bo prišla v glavno kodo.
Ta odločitev je bila zelo boleča, saj... sprožil veliko polemik, a je bilo vredno, saj... Recenzije so začele prejemati zahteve za združitve brez razlik v slogu in sčasoma se je število problematičnih področij začelo zmanjševati.
IaC testiranje
Poleg preverjanja sloga lahko uporabite tudi druge stvari, da na primer preverite, ali se lahko vaša infrastruktura dejansko uvede. Ali preverite, ali spremembe v infrastrukturi ne bodo povzročile izgube denarja. Zakaj je to morda potrebno? Vprašanje je zapleteno in filozofsko, bolje je odgovoriti z zgodbo, da se je nekako pojavil samodejni skalirnik na Powershellu, ki ni preverjal mejnih pogojev => ustvarjenih je bilo več VM-jev, kot je bilo potrebno => stranka je porabila več denarja, kot je bilo načrtovano. To ni zelo prijetno, vendar bi bilo to napako povsem mogoče ujeti v zgodnejših fazah.
Lahko bi se vprašali, zakaj narediti kompleksno infrastrukturo še bolj kompleksno? Pri testih za infrastrukturo, tako kot za kodo, ne gre za poenostavitev, ampak za poznavanje, kako naj vaša infrastruktura deluje.
Piramida testiranja IAC
Testiranje IaC: statična analiza
Če naenkrat namestite celotno infrastrukturo in preverite, ali deluje, boste morda ugotovili, da vzame veliko časa in zahteva veliko časa. Zato mora biti osnova nekaj, kar deluje hitro, tega je veliko in zajema veliko primitivnih mest.
Bash je težaven
Poglejmo trivialen primer. izberite vse datoteke v trenutnem imeniku in jih kopirajte na drugo lokacijo. Prva stvar, ki mi pride na misel:
for i in * ; do
cp $i /some/path/$i.bak
done
Kaj pa, če je v imenu datoteke presledek? No, ok, smo pametni, znamo uporabljati narekovaje:
for i in * ; do cp "$i" "/some/path/$i.bak" ; done
Dobro opravljeno? ne! Kaj pa, če v imeniku ni ničesar, tj. globiranje ne bo delovalo.
find . -type f -exec mv -v {} dst/{}.bak ;
Dobro opravljeno? Ne ... Pozabil sem, kaj lahko piše v imenu datoteke n.
touch x
mv x "$(printf "foonbar")"
find . -type f -print0 | xargs -0 mv -t /path/to/target-dir
Orodja za statično analizo
Težavo iz prejšnjega koraka bi lahko ujeli, ko bi pozabili narekovaje, za to je v naravi veliko rešitev Shellcheck, na splošno jih je veliko in najverjetneje lahko najdete linter za svoj sklad pod svojim IDE.
Kot smo videli iz prejšnjega primera, linterji niso vsemogočni in ne morejo izpostaviti vseh problematičnih področij. Nadalje, po analogiji s testiranjem pri razvoju programske opreme, se lahko spomnimo enotnih testov. Kar takoj pride na misel je shunit, junit, rspec, pytest. Toda kaj storiti z ansibleom, chefom, saltstackom in drugimi podobnimi?
Na samem začetku smo govorili o TRDNO in da bi morala biti naša infrastruktura sestavljena iz majhnih kock. Prišel je njihov čas.
Infrastruktura je razdeljena na majhne kocke, na primer vloge Ansible.
Nameščeno je nekakšno okolje, naj bo to docker ali VM.
Za to testno okolje uporabljamo svojo vlogo Ansible.
Preverimo, ali je vse delovalo, kot smo pričakovali (izvajamo teste).
Odločamo se ok ali ne ok.
Testiranje IaC: orodja za testiranje enot
Vprašanje, kaj so testi za CFM? Lahko preprosto zaženete skript ali pa za to uporabite že pripravljene rešitve:
Primer za testinfra, preverjanje, da uporabniki test1, test2 obstajajo in so v skupini sshusers:
def test_default_users(host):
users = ['test1', 'test2' ]
for login in users:
assert host.user(login).exists
assert 'sshusers' in host.user(login).groups
Kaj izbrati? Vprašanje je zapleteno in dvoumno, tukaj je primer sprememb v projektih na githubu za 2018-2019:
Ogrodja testiranja IAC
Postavlja se vprašanje: kako vse to sestaviti in zagnati? Lahko vzemi in naredi sam če je dovolj inženirjev. Lahko pa vzamete že pripravljene rešitve, čeprav jih ni veliko:
Za 25-35 vlog je delalo 40-70 minut, kar je bilo dolgo.
Naslednji korak je bil prehod na jenkins/docker/ansible/molecule. Idiološko je vse isto
Lint playbooks.
Razporedite vloge.
Izstrelitveni vsebnik
Uporabite Ansible vloge.
Zaženi testinfra.
Preverite idempotenco.
Linting za 40 vlog in testi za ducat so začeli trajati približno 15 minut.
Kaj izbrati, je odvisno od številnih dejavnikov, kot so uporabljeni sklad, strokovnost v ekipi itd. tukaj se vsak sam odloči, kako zapreti vprašanje o testiranju enote
Testiranje IAC: integracijski testi
Naslednji korak v piramidi testiranja infrastrukture bodo integracijski testi. Podobni so testom enote:
Infrastruktura je razdeljena na majhne kocke, na primer vloge Ansible.
Nameščeno je nekakšno okolje, naj bo to docker ali VM.
Za to preskusno okolje velja veliko Anzibilne vloge.
Preverimo, ali je vse delovalo, kot smo pričakovali (izvajamo teste).
Odločamo se ok ali ne ok.
Grobo povedano ne preverjamo delovanja posameznega elementa sistema kot pri enotnih testih, ampak preverjamo, kako je strežnik konfiguriran kot celota.
Testiranje IAC: preizkusi od konca do konca
Na vrhu piramide nas pozdravijo End to End testi. Tisti. Ne preverjamo delovanja ločenega strežnika, ločenega skripta ali ločene opeke naše infrastrukture. Preverjamo, ali je veliko strežnikov povezanih skupaj, naša infrastruktura deluje, kot pričakujemo. Na žalost še nikoli nisem videl pripravljenih rešitev v škatli, verjetno zato, ker ... Infrastruktura je pogosto edinstvena in jo je težko oblikovati in ustvariti okvir za testiranje. Posledično vsak ustvarja svoje rešitve. Povpraševanje je, a ni odgovora. Zato vam bom povedal, kaj obstaja, da bi druge spodbudil k zdravim mislim ali podrgnil nos v dejstvu, da je bilo vse izumljeno že davno pred nami.
Projekt z bogato zgodovino. Uporabljajo ga v velikih organizacijah in verjetno se je že vsak od vas posredno srečal z njim. Aplikacija podpira številne baze podatkov, integracije itd. Vedeti, kakšna bi lahko bila infrastruktura, je veliko datotek za sestavljanje dockerjev, Jenkins pa vedeti, katere teste izvesti v katerem okolju.
Ta shema je delovala precej dolgo, dokler ni bila znotraj okvira Raziskave tega nismo poskušali prenesti v Openshift. Vsebniki ostajajo enaki, vendar se je okolje za zagon spremenilo (spet zdravo D.R.Y.).
Raziskovalna ideja je šla še dlje in v openshiftu so našli nekaj, kot je APB (Ansible Playbook Bundle), ki vam omogoča, da znanje o tem, kako razmestiti infrastrukturo, zapakirate v vsebnik. Tisti. obstaja ponovljiva točka znanja o tem, kako razmestiti infrastrukturo, ki jo je mogoče preizkusiti.
Vse to je zvenelo dobro, dokler nismo naleteli na heterogeno infrastrukturo: za teste smo potrebovali Windows. Posledično je znanje o tem, kaj, kje, kako namestiti in preizkusiti, v jenkinsu.