Ono što sam naučio testiranjem 200 linija infrastrukturnog koda
Pristup IaC (Infrastruktura kao kod) se sastoji ne samo od koda koji je pohranjen u spremištu, već i od ljudi i procesa koji okružuju ovaj kod. Da li je moguće ponovo koristiti pristupe od razvoja softvera do upravljanja infrastrukturom i opisa? Bilo bi dobro da ovu ideju imate na umu dok čitate članak.
Pretpostavimo da dođete na novi projekat, a oni vam kažu: „imamo Infrastruktura kao kod". U stvarnosti se ispostavilo Infrastruktura kao bash istorija ili na primjer Dokumentacija kao bash istorija. Ovo je vrlo realna situacija, na primjer, sličan slučaj opisao je Denis Lysenko u govoru Kako zamijeniti cijelu infrastrukturu i početi mirno spavati, ispričao je kako su dobili koherentnu infrastrukturu za projekat iz bash istorije.
Uz određenu želju, možemo to reći Infrastruktura kao bash istorija ovo je kao kod:
reproduktivnost: Možete uzeti bash historiju, pokrenuti komande odatle, i možda ćete, usput, dobiti radnu konfiguraciju kao izlaz.
verzijama: znate ko je ušao i šta je radio, opet, nije činjenica da će vas ovo dovesti do radne konfiguracije na izlazu.
istorija: priča o tome ko je šta uradio. samo što ga nećete moći koristiti ako izgubite server.
Šta da radim?
Infrastruktura kao kod
Čak i tako čudan slučaj kao Infrastruktura kao bash istorija možete ga povući za uši Infrastruktura kao kod, ali kada želimo da uradimo nešto komplikovanije od dobrog starog LAMP servera, doći ćemo do zaključka da ovaj kod treba nekako modifikovati, promeniti, poboljšati. Zatim bismo željeli razmotriti paralele između Infrastruktura kao kod i razvoj softvera.
DRY
Na projektu razvoja sistema skladištenja, postojao je podzadatak periodično konfigurišite SDS: objavljujemo novo izdanje - potrebno ga je izbaciti radi daljeg testiranja. Zadatak je krajnje jednostavan:
prijavite se ovdje preko ssh-a i izvršite naredbu.
kopirajte datoteku tamo.
ispravite konfiguraciju ovdje.
tamo započnite uslugu
...
PROFIT!
Za opisanu logiku, bash je više nego dovoljan, posebno u ranim fazama projekta, kada tek počinje. Ovo nije loše što koristite bash, ali s vremenom se javljaju zahtjevi da se implementira nešto slično, ali malo drugačije. Prva stvar koja pada na pamet je copy-paste. A sada već imamo dvije vrlo slične skripte koje rade skoro istu stvar. Vremenom je broj skripti rastao, a mi smo se suočili sa činjenicom da postoji određena poslovna logika za postavljanje instalacije koju treba sinhronizovati između različitih skripti, to je prilično komplikovano.
Ispostavilo se da postoji praksa kao što je DRY (Ne ponavljaj se). Ideja je ponovno korištenje postojećeg koda. Zvuči jednostavno, ali nismo odmah došli do ovoga. U našem slučaju, to je bila banalna ideja: odvojiti konfiguracije od skripti. One. poslovna logika kako se instalacija postavlja zasebno, konfiguracije zasebno.
SOLID za CFM
Vremenom je projekat rastao i prirodni nastavak bila je pojava Ansiblea. Glavni razlog njegovog pojavljivanja je što postoji stručnost u timu i što bash nije dizajniran za složenu logiku. Ansible je također počeo sadržavati složenu logiku. Kako bi se spriječilo da se složena logika pretvori u haos, postoje principi za organiziranje koda u razvoju softvera SOLID Takođe, na primer, Grigorij Petrov je u izveštaju „Zašto je IT stručnjaku potreban lični brend“ postavio pitanje da je čovek dizajniran tako da mu je lakše da operiše sa nekim društvenim subjektima, u razvoju softvera ovim su objekti. Ako spojimo ove dvije ideje i nastavimo da ih razvijamo, primijetit ćemo da ih također možemo koristiti SOLID kako bi se olakšalo održavanje i modifikacija ove logike u budućnosti.
Princip jedinstvene odgovornosti
Svaka klasa obavlja samo jedan zadatak.
Nema potrebe za miješanjem koda i pravljenjem monolitnih božanskih špageti čudovišta. Infrastruktura bi se trebala sastojati od jednostavnih cigli. Ispostavilo se da ako podijelite Ansible playbook na male dijelove, pročitate Ansible uloge, onda ih je lakše održavati.
Otvoreno zatvoreno načelo
Otvoreno/zatvoreno princip.
Otvoreno za proširenje: znači da se ponašanje entiteta može proširiti kreiranjem novih tipova entiteta.
Zatvoreno za promjenu: Kao rezultat proširenja ponašanja entiteta, ne bi trebale biti napravljene promjene u kodu koji koristi te entitete.
U početku smo postavili testnu infrastrukturu na virtuelne mašine, ali zbog činjenice da je poslovna logika implementacije bila odvojena od implementacije, dodali smo uvođenje na baremetall bez ikakvih problema.
Princip zamjene Liskov
Princip zamjene Barbare Liskov. objekti u programu moraju biti zamjenjivi instancama njihovih podtipova bez promjene ispravnog izvršavanja programa
Ako pogledate šire, to nije odlika nijednog projekta koji se tu može primijeniti SOLID, generalno se radi o CFM-u, na primjer, na drugom projektu je potrebno postaviti upakiranu Java aplikaciju na razne Jave, aplikacijske servere, baze podataka, OS itd. Koristeći ovaj primjer, razmotrit ću daljnja načela SOLID
U našem slučaju postoji dogovor unutar infrastrukturnog tima da ako smo instalirali ulogu imbjava ili oraclejava, onda imamo java binarnu izvršnu datoteku. Ovo je neophodno jer Upstream uloge ovise o ovom ponašanju; U isto vrijeme, ovo nam omogućava da zamijenimo jednu implementaciju/verziju java s drugom bez promjene logike implementacije aplikacije.
Problem ovdje leži u činjenici da je to nemoguće implementirati u Ansibleu, zbog čega se pojavljuju neki dogovori unutar tima.
Princip segregacije interfejsa
Princip razdvajanja interfejsa: „Mnoga sučelja specifična za klijenta su bolja od jednog interfejsa opšte namene.
U početku smo pokušali da svu varijabilnost implementacije aplikacije stavimo u jedan Ansible playbook, ali to je bilo teško podržati, a pristup kada imamo specificirano vanjsko sučelje (klijent očekuje port 443), onda se infrastruktura može sastaviti od pojedinačnih cigle za konkretnu implementaciju.
Princip inverzije zavisnosti
Princip inverzije zavisnosti. Moduli na višim nivoima ne bi trebali ovisiti o modulima na nižim nivoima. Oba tipa modula moraju zavisiti od apstrakcija. Apstrakcije ne bi trebale zavisiti od detalja. Detalji moraju zavisiti od apstrakcija.
Ovdje će se primjer temeljiti na antiuzorku.
Jedan od kupaca je imao privatni oblak.
Naručili smo virtuelne mašine unutar oblaka.
Ali zbog prirode oblaka, implementacija aplikacije bila je vezana za koji hipervizor je bio na VM.
One. Logika implementacije aplikacije na visokom nivou tekla je sa zavisnostima do nižih nivoa hipervizora, a to je značilo probleme prilikom ponovnog korišćenja ove logike. Nemojte to raditi na ovaj način.
interakcija
Infrastruktura kao kod se ne odnosi samo na kod, već i na odnos između koda i ljudi, na interakcije između infrastrukturnih programera.
Faktor autobusa
Pretpostavimo da imate Vasyu na svom projektu. Vasja zna sve o vašoj infrastrukturi, šta će se dogoditi ako Vasja iznenada nestane? Ovo je sasvim realna situacija, jer bi ga mogao udariti autobus. Ponekad se desi. Ako se to dogodi, a znanje o kodu, njegovoj strukturi, načinu rada, izgledu i lozinkama ne bude distribuirano među timom, tada možete naići na niz neugodnih situacija. Da biste minimizirali ove rizike i distribuirali znanje unutar tima, možete koristiti različite pristupe
Pair Devopsing
To nije kao kao šala, da su admini pili pivo, mijenjali lozinke i analogno programiranju u paru. One. dva inženjera sjednu za jedan računar, jednu tastaturu i zajedno počnu postavljati vašu infrastrukturu: postavljanje servera, pisanje Ansible uloge, itd. Zvuči lijepo, ali nama nije išlo. Ali posebni slučajevi ove prakse su uspjeli. Dolazi novi zaposlenik, njegov mentor zajedno sa njim preuzima pravi zadatak, radi i prenosi znanje.
Još jedan poseban slučaj je incidentni poziv. Tokom problema, okuplja se grupa dežurnih i uključenih, imenuje se jedan vođa, koji dijeli svoj ekran i izgovara tok misli. Ostali učesnici prate misli vođe, špijuniraju trikove sa konzole, proveravaju da nisu propustili red u dnevniku i uče nove stvari o sistemu. Ovaj pristup je djelovao češće nego ne.
Pregled koda
Subjektivno, bilo je efikasnije širiti znanje o infrastrukturi i kako ona funkcionira korištenjem pregleda koda:
Infrastruktura je opisana kodom u spremištu.
Promjene se dešavaju u posebnoj grani.
Tokom zahtjeva za spajanjem, možete vidjeti deltu promjena u infrastrukturi.
Vrhunac je bio da su recenzenti birani jedan po jedan, prema rasporedu, tj. s određenim stepenom vjerovatnoće ćete se popeti u novi dio infrastrukture.
stil koda
Vremenom su se počele pojavljivati svađe tokom recenzija, jer... recenzenti su imali svoj stil i rotacija recenzenata ih je slagala sa različitim stilovima: 2 razmaka ili 4, camelCase ili snake_case. To nije bilo moguće odmah implementirati.
Prva ideja je bila preporučiti korištenje lintera, na kraju krajeva, svi su inženjeri, svi su pametni. Ali različiti uređivači, OS, nisu zgodni
Ovo je evoluiralo u bota koji je pisao u slack za svako problematično urezivanje i priložio izlaz lintera. Ali u većini slučajeva bilo je važnijih stvari koje treba uraditi i kod je ostao neispravljen.
Green Build Master
Vrijeme prolazi, a mi smo došli do zaključka da se commiti koji ne prođu određene testove ne mogu dopustiti u master. Voila! Izmislili smo Green Build Master, koji se već duže vrijeme prakticira u razvoju softvera:
U toku je razvoj u posebnoj grani.
Testovi se izvode na ovoj temi.
Ako testovi ne uspiju, kod neće ući u master.
Donošenje ove odluke bilo je veoma bolno, jer... izazvalo mnogo kontroverzi, ali vredelo je, jer... Recenzije su počele primati zahtjeve za spajanje bez razlike u stilu, a vremenom je broj problematičnih područja počeo da se smanjuje.
IaC Testing
Osim provjere stila, možete koristiti i druge stvari, na primjer, da provjerite da li se vaša infrastruktura zaista može implementirati. Ili provjerite da promjene u infrastrukturi neće dovesti do gubitka novca. Zašto bi ovo moglo biti potrebno? Pitanje je kompleksno i filozofsko, bolje je odgovoriti pričom da je na Powershell-u nekako postojao auto-skaler koji nije provjerio granične uslove => kreirano je više VM-ova nego što je potrebno => klijent je potrošio više novca nego što je planirano. Ovo nije baš ugodno, ali bilo bi sasvim moguće uhvatiti ovu grešku u ranijim fazama.
Moglo bi se zapitati, zašto složenu infrastrukturu činiti još složenijom? Testovi za infrastrukturu, baš kao i za kod, ne odnose se na pojednostavljenje, već na znanje kako bi vaša infrastruktura trebala funkcionirati.
IaC testna piramida
IaC testiranje: statička analiza
Ako smjestite cijelu infrastrukturu odjednom i provjerite da li radi, možda ćete otkriti da je potrebno puno vremena i puno vremena. Dakle, osnova mora biti nešto što brzo radi, toga ima dosta i pokriva dosta primitivnih mjesta.
Bash je lukav
Pogledajmo trivijalan primjer. odaberite sve datoteke u trenutnom direktoriju i kopirajte ih na drugu lokaciju. Prva stvar koja mi pada na pamet:
for i in * ; do
cp $i /some/path/$i.bak
done
Šta ako postoji razmak u imenu datoteke? Pa dobro, mi smo pametni, znamo da koristimo navodnike:
for i in * ; do cp "$i" "/some/path/$i.bak" ; done
Dobro urađeno? Ne! Šta ako nema ništa u imeniku, tj. globiranje neće raditi.
find . -type f -exec mv -v {} dst/{}.bak ;
Dobro urađeno sada? Ne... Zaboravio sam šta može biti u nazivu datoteke n.
touch x
mv x "$(printf "foonbar")"
find . -type f -print0 | xargs -0 mv -t /path/to/target-dir
Alati za statičku analizu
Problem iz prethodnog koraka mogao bi se uhvatiti kada smo zaboravili citate, za to u prirodi postoje mnogi lijekovi Shellcheck, generalno ih ima puno, i najvjerovatnije možete pronaći linter za svoj stek pod vašim IDE.
Kao što smo vidjeli iz prethodnog primjera, linteri nisu svemoćni i ne mogu ukazati na sva problematična područja. Nadalje, po analogiji s testiranjem u razvoju softvera, možemo se prisjetiti jediničnih testova. Ono što mi odmah pada na pamet je shunit, junit, rspec, pytest. Ali šta učiniti sa ansibleom, chefom, saltstackom i drugima sličnim njima?
Na samom početku smo razgovarali SOLID i da se naša infrastruktura sastoji od malih cigli. Njihovo vrijeme je došlo.
Infrastruktura je podijeljena na male cigle, na primjer, Ansible uloge.
Neka vrsta okruženja je raspoređena, bilo da je to docker ili VM.
Primjenjujemo našu Ansible ulogu na ovo testno okruženje.
Provjeravamo da li je sve radilo kako smo očekivali (pokrećemo testove).
Odlučujemo u redu ili ne ok.
IaC testiranje: Alati za testiranje jedinica
Pitanje, šta su testovi za CFM? Možete jednostavno pokrenuti skriptu ili možete koristiti gotova rješenja za ovo:
Primjer za testinfra, provjeravanje korisnika test1, test2 postoje i nalaze se u grupi 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
Šta odabrati? Pitanje je složeno i dvosmisleno, evo primjera promjena u projektima na githubu za 2018-2019:
IaC okviri za testiranje
Postavlja se pitanje: kako sve to spojiti i pokrenuti? Može uzmi i uradi to sam ako postoji dovoljan broj inženjera. Ili možete uzeti gotova rješenja, iako ih nema puno:
Za 25-35 uloga radilo se 40-70 minuta, što je bilo dugo.
Sljedeći korak je bio prelazak na jenkins/docker/ansible/molekule. Idiološki sve je isto
Lint playbooks.
Poravnajte uloge.
Kontejner za lansiranje
Primijenite Ansible uloge.
Pokreni testinfra.
Provjerite idempotenciju.
Linting za 40 uloga i testovi za desetak počeli su trajati oko 15 minuta.
Šta odabrati ovisi o mnogim faktorima, kao što su korišteni stek, stručnost u timu, itd. ovdje svako odlučuje za sebe kako da zatvori pitanje za testiranje jedinice
IaC testiranje: integracijski testovi
Sljedeći korak u piramidi testiranja infrastrukture bit će integracijski testovi. Oni su slični jediničnim testovima:
Infrastruktura je podijeljena na male cigle, na primjer Ansible uloge.
Neka vrsta okruženja je raspoređena, bilo da je to docker ili VM.
Za ovo testno okruženje važi mnogi Ansible role.
Provjeravamo da li je sve radilo kako smo očekivali (pokrećemo testove).
Odlučujemo u redu ili ne ok.
Grubo govoreći, ne provjeravamo performanse pojedinog elementa sistema kao u jediničnim testovima, mi provjeravamo kako je server konfigurisan kao cjelina.
IaC testiranje: Testovi od kraja do kraja
Na vrhu piramide dočekuju nas testovi od kraja do kraja. One. Ne provjeravamo performanse zasebnog servera, zasebne skripte ili zasebne blokove naše infrastrukture. Provjeravamo da li su mnogi serveri povezani zajedno, naša infrastruktura radi kako očekujemo. Nažalost, nikada nisam vidio gotova kutijasta rješenja, vjerovatno zato što... Infrastruktura je često jedinstvena i teško ju je šablonizirati i stvoriti okvir za testiranje. Kao rezultat, svako kreira svoja sopstvena rešenja. Potražnja postoji, ali odgovora nema. Stoga ću vam reći šta postoji da bih natjerao druge na zdrave misli ili trljao nos u činjenici da je sve izmišljeno davno prije nas.
Projekat sa bogatom istorijom. Koristi se u velikim organizacijama i vjerovatno je svako od vas indirektno ukrstio put s njim. Aplikacija podržava mnoge baze podataka, integracije itd. Znati kako bi infrastruktura mogla izgledati je mnogo docker-compose datoteka, a znati koje testove treba pokrenuti u kojem okruženju je Jenkins.
Ova šema je radila dosta dugo, sve do okvira istraživanje nismo pokušali ovo prenijeti na Openshift. Kontejneri ostaju isti, ali okruženje za lansiranje se promijenilo (pozdrav DRY opet).
Ideja istraživanja je otišla dalje i u openshift-u su pronašli nešto poput APB-a (Ansible Playbook Bundle), koji vam omogućava da upakujete znanje o tome kako postaviti infrastrukturu u kontejner. One. postoji ponovljiva, provjerljiva tačka znanja o tome kako postaviti infrastrukturu.
Sve je ovo zvučalo dobro dok nismo naišli na heterogenu infrastrukturu: Windows nam je trebao za testove. Kao rezultat, znanje o tome šta, gdje, kako implementirati i testirati je u jenkinsu.