Mit tanultam, amikor 200 000 sor infrastruktúrakódot teszteltem

Mit tanultam, amikor 200 000 sor infrastruktúrakódot teszteltem

Megközelítés IaC (Infrastructure as Code) nemcsak a kódból áll, amely egy adattárházban tárolódik, hanem az emberekből és folyamatokból is, amelyek körülveszik ezt a kódot. Használhatók-e a szoftverfejlesztésből származó megközelítések az infrastruktúra kezelésében és leírásában? Jó, ha az elméletet szem előtt tartjuk, miközben olvassuk a cikket.

Angol változat

Ez a feljegyzésem a beszéd során Gyorsan emlékezzünk vissza, hogyan működik a moduláris aritmetika. Az óra már egy ismert koncepció. Az órák használata DevopsConf 2019-05-28.

Prezentációk és videók

Infrastructure as bash history

Mit tanultam, amikor 200 000 sor infrastruktúrakódot teszteltem

Tegyük fel, hogy új projektre érkezik, ahol azt mondják: „van nekünk Infrastructure as Code„. A valóságban kiderül, Infrastructure as bash history vagy például Documentation as bash history. Ez egy teljesen valóságos helyzet, például Denis Lysenko egy hasonló esetet ismertetett a Hogyan cserélhetjük le az egész infrastruktúrát és kezdhetünk el nyugodtan aludni, elmondta, hogy a bash history alapján hogyan alakítottak ki egy jól működő infrastruktúrát a projekten.

Az emberi akarattal mondhatjuk, hogy Infrastructure as bash history ez olyan, mint a kód:

  1. az újraindítások során?: kiveheti a bash history-t, végrehajthatja a parancsokat onnan, és valószínűleg egy működő konfigurációt kap a végén.
  2. verziókezelés: tudja, ki lépett be és mit csinált, de nem biztos, hogy ez a végén egy működő konfigurációhoz vezet.
  3. történet: a történet, hogy ki és mit csinált. De nem tudja használni, ha elveszíti a szervert.

Mit tegyünk?

Infrastructure as Code

Mit tanultam, amikor 200 000 sor infrastruktúrakódot teszteltem

Még egy olyan különös eset is, mint Infrastructure as bash history lehet, hogy sokáig húzódik a Infrastructure as Code, de amikor valami bonyolultabb dolgot akarunk létrehozni, mint a régi jól ismert LAMP szerver, akkor arra jutunk, hogy ezt a kódot valamilyen módon módosítani kell, megváltoztatni, fejleszteni. A továbbiakban a párhuzamokat fogjuk vizsgálni az Infrastructure as Code és a szoftverfejlesztés között.

D.R.Y.

Mit tanultam, amikor 200 000 sor infrastruktúrakódot teszteltem

A tárolórendszer fejlesztésénél volt egy alfeladat időszakosan beállítani az SDS-t: új verziót adunk ki - ezt ki kell terjeszteni a további teszteléshez. A feladat rendkívül egyszerű:

  • ikon itt ssh-n keresztül belépni, és hajtson végre egy parancsot.
  • ide másolja a fájlt.
  • itt módosítsa a konfigurációt.
  • ott indítsa el a szolgáltatást.
  • …
  • NYERESÉG!

A leírt logikához teljes mértékben elegendő a bash, különösen a projekt korai szakaszában, amikor éppen csak indul. Ez nem rossz, hogy bash-t használ., de idővel felmerülnek a kérések arra, hogy valami hasonlót, de kicsit másként valósítsunk meg. Az első, ami eszünkbe jut, a másolás-beillesztés. Így már két nagyon hasonló scriptünk van, amelyek szinte ugyanazt csinálják. Idővel a script-ek száma megnőtt, és szembesültünk azzal, hogy van egy bizonyos üzleti logika az installációk kiépítésére, amelyet szinkronizálnunk kell a különböző scriptek között, ami elég bonyolult.

Mit tanultam, amikor 200 000 sor infrastruktúrakódot teszteltem

Kiderült, hogy létezik egy ilyen gyakorlat: D.R.Y. (Ne Ismételd Meg Magad). Az ötlet az, hogy újrahasználjuk a meglévő kódot. Egyszerűen hangzik, de nem jutottunk el ide azonnal. A mi esetünkben ez egy banális ötlet volt: a konfigurációkat külön választani a scriptektől. Tehát az üzleti logika az installáció kiépítése során külön, a konfigurációk külön.

S.O.L.I.D. CFM-re

Mit tanultam, amikor 200 000 sor infrastruktúrakódot teszteltem

Idővel a projekt nőtt, és természetes következménye az Ansible megjelenése lett. Fő oka ennek a csapatban lévő szakértelem, és hogy a bash nem alkalmas bonyolult logikákhoz. Az Ansible is összetett logikát tartalmazott. Ahhoz, hogy a bonyolult logika ne váljon káosszá, a szoftverfejlesztés során léteznek a kód szervezésének alapelvei. S.O.L.I.D. Például Grigory Petrov a "Miért fontos a személyes márka az IT szakembereknek" előadásában felvetette, hogy az ember természete szerint könnyebben bánik valamilyen társadalmi entitásokkal, a szoftverfejlesztésben ezek az objektumok. Ha ezeket az ötleteket ötvözzük és tovább fejlesztjük, észrevehetjük, hogy az infrastruktúra leírásában is S.O.L.I.D. ezáltal könnyebben fenntartható és módosítható logikát jelent.

Az Egyszerűsített Felelősség Elve

Mit tanultam, amikor 200 000 sor infrastruktúrakódot teszteltem

Minden osztály csak egy feladatot lát el.

Ne keverjük a kódot, és ne hozzunk létre monolitikus, isteni makaron monstereket. Az infrastruktúrának egyszerű építőkockákból kell állnia. Kiderült, hogy, ha az Ansible playbook-t kis darabokra törjük, olvasható Ansible szerepekre, akkor könnyebb őket karbantartani.

A Nyitott-Zárt Elv

Mit tanultam, amikor 200 000 sor infrastruktúrakódot teszteltem

A nyitott/zárt elv.

  • Nyitottak az bővítésre: azt jelenti, hogy egy entitás viselkedése új entitástípusok létrehozásával bővíthető.
  • Zártak a módosításra: az entitás viselkedésének bővítése miatt nem szabad változtatni azon a kódon, amely ezeket az entitásokat használja.

Kezdetben tesztinfrastruktúrát indítottunk virtuális gépeken, de mivel az üzleti logika külön volt a megvalósítástól, problémamentesen hozzáadtuk a telepítést bare metal-ra.

A Liskov Helyettesítési Elv

Mit tanultam, amikor 200 000 sor infrastruktúrakódot teszteltem

Barbara Liskov Helyettesítési Elve. A programban található objektumoknak helyettesíthetőknek kell lenniük a típusaik példányaival anélkül, hogy a program helyessége megváltozna.

Ha tágabban nézzük, nem egy specifikus projekt sajátossága, hogy ott alkalmazható. S.O.L.I.D., ez alapvetően a CFM-ről szól, például egy másik projektben dobozos Java alkalmazást kell telepíteni különböző Java, alkalmazás szerverek, adatbázisok, operációs rendszerek fölé, stb. E példán fogom megvizsgálni a további elveket. S.O.L.I.D.

A mi esetünkben az infrastruktúra csapat keretein belül megegyeztünk, hogy ha beállítjuk az imbjava vagy oraclejava szerepet, akkor van egy bináris végrehajtható fájlunk, java. Erre szükség van, mivel a magasabb szintű szerepek függenek ettől a viselkedéstől, elvárják a java meglétét. Ugyanakkor ez lehetővé teszi számunkra, hogy egy java megvalósítást/verziót lecseréljünk anélkül, hogy megváltoztatnánk az alkalmazás telepítési logikáját.

A probléma itt abban rejlik, hogy az Ansible-ben nem lehet megvalósítani ilyen, mint következmény, a csapaton belül megjelennek valamilyen megállapodások.

Az Interfész Megosztási Elv

Mit tanultam, amikor 200 000 sor infrastruktúrakódot teszteltem

Az interfész megosztásának elve: „több interfész, amely kifejezetten az ügyfelek számára készült, jobb, mint egy általános célú interfész.”

Kezdetben megpróbáltuk a teljes variabilitást egy Ansible playbookba sűríteni, de ez nehezen támogatható volt, és a megközelítés, amikor a követelmény specifikált külső interfész (az ügyfél várja a 443-as portot), lehetővé teszi számunkra, hogy a konkrét megvalósításhoz különböző építőelemekből építsük fel az infrastruktúrát.

A Függőségi Inverziós Elv

Mit tanultam, amikor 200 000 sor infrastruktúrakódot teszteltem

A függőségek inverziójának elve. A magasabb szintű moduloknak nem szabad függeniük az alacsonyabb szintű moduloktól. Mindkét modul típusnak az absztrakcióktól kell függenie. Az absztrakcióknak nem szabad függeniük a részletektől. A részleteknek az absztrakcióktól kell függeniük.

Itt egy példa az antidizájnra fog épülni.

  1. Az egyik ügyfelünknél privát felhő állt rendelkezésre.
  2. A felhőn belül virtuális gépeket rendeltünk.
  3. De a felhő sajátosságai miatt az alkalmazás telepítése attól függött, hogy melyik hypervisorra került a VM.

Tehát a magas szintű alkalmazástelepítési logika, a függőségek a hypervisor alacsonyabb szintjein haladtak, ami problémákat jelentett a logika újrahasznosításában. Ezt nem kéne.

Interakció

Mit tanultam, amikor 200 000 sor infrastruktúrakódot teszteltem

A kód infrastruktúra nemcsak a kódra vonatkozik, hanem a kód és az ember közötti kapcsolatokra is, a infrastuktúra fejlesztői közötti interakciókra.

Busz faktor

Mit tanultam, amikor 200 000 sor infrastruktúrakódot teszteltem

Tegyük fel, hogy van egy Vasja a projektben. Vasja mindent tud az infrastruktúrádról, mi történik, ha Vasja egyszer csak eltűnik? Ez egy teljesen valóságos helyzet, hiszen elütheti őt egy busz. Néha előfordul ilyesmi. Ha ez megtörténik, és a kódról, annak struktúrájáról, működéséről, jelszavakról és felhasználónevekről való tudás nincs elosztva a csapatban, akkor számos kellemetlen helyzettel szembesülhetsz. A kockázatok minimalizálása és a tudás csapaton belüli elosztása érdekében különböző megközelítéseket alkalmazhatunk.

Páros Devops

Mit tanultam, amikor 200 000 sor infrastruktúrakódot teszteltem

Ez nem olyan, mint a viccben,, hogy az adminisztrátorok sört isznak, jelszavakat cserélnek, és a páros programozás analógja. Tehát két mérnök ül le egy számítógéphez, egy billentyűzethez, és elkezdik közösen beállítani az infrastruktúrádat: beállítani a szervert, Ansible szerepet írni, stb. Jól hangzik, de nálunk nem működött. Azonban a gyakorlat egyes konkrét esetei működtek. Egy új munkatárs érkezett, a mentora valós feladatot vesz fel vele, dolgozik — átadja a tudást.

Egy másik példája ennek az incident call. Probléma esetén összehívják a felelős csapatokat, és kijelölnek egy vezetőt, aki megosztja a képernyőjét és elmondja a gondolatmenetét. A többi résztvevő követi a vezető gondolatmenetét, megnézi a konzolból származó trükköket, ellenőrzik, hogy nem hagytak-e ki egy sort a naplóból, új dolgokat tudnak meg a rendszerről. Ez a megközelítés inkább működött, mint nem.

Kódellenőrzés

Mit tanultam, amikor 200 000 sor infrastruktúrakódot teszteltem

Szubjektíven, a tudás infrastruktúráról és annak működéséről történő elosztása hatékonyabban zajlott kódellenőrzésen keresztül:

  • Az infrastruktúra kódban van leírva a tárolóban.
  • A módosítások külön ágon történnek.
  • A merge request során látható az infrastruktúra módosításainak delta.

Az érdekessége az volt, hogy a felülvizsgálók sorban, ütemezés szerint lettek kiválasztva, ami azt jelenti, hogy bizonyos valószínűséggel egy új infrastruktúra szakaszba kerülsz.

Kódstílus

Mit tanultam, amikor 200 000 sor infrastruktúrakódot teszteltem

Idővel kezdték el zavarni a revíziók során felmerülő ellentétek, mivel a revíziózóknak saját stílusuk volt, és a rotáció miatt különböző stílusokkal találkoztak: 2 vagy 4 szóköz, camelCase vagy snake_case. Ezt nem könnyen sikerült bevezetni.

  • Az első ötlet az volt, hogy ajánljuk a linter használatát, hiszen végül is mérnökök vagyunk, mindannyian okosak. De különböző szerkesztők és operációs rendszerek miatt ez nem volt kényelmes.
  • Ez egy botra fejlődött, amely minden problémás commit után írt a Slackbe, és csatolta a linter kimenetét. De a legtöbb esetben fontosabb feladatok merültek fel, és a kód javítatlan maradt.

Zöld Build Master

Mit tanultam, amikor 200 000 sor infrastruktúrakódot teszteltem

Idő telik, és arra a következtetésre jutottunk, hogy nem engedhetünk be a masterbe olyan commiteket, amelyek nem teljesítenek bizonyos teszteket. Voila! Feltaláltuk a Zöld Build Master-t, amelyet már régóta alkalmaznak a szoftverfejlesztés során:

  • A fejlesztés külön ágon zajlik.
  • Ezen az ágon futtatták a teszteket.
  • Ha a tesztek nem teljesülnek, a kód nem kerül a masterbe.

A döntés elfogadása elég fájdalmas volt, mivel számos vitát váltott ki, de megérte, mert a revíziókra érkező összevonási kérelmek stílusviták nélkül érkeztek, és idővel a problémás esetek száma csökkent.

IaC Tesztelés

Mit tanultam, amikor 200 000 sor infrastruktúrakódot teszteltem

A stílus ellenőrzésén kívül más dolgokat is használhatunk, például ellenőrizhetjük, hogy az infrastruktúrája valóban telepíthető-e. Vagy megvizsgálhatjuk, hogy az infrastruktúra módosításai nem vezetnek-e pénzveszteséghez. Miért lehet szükség erre? A kérdés bonyolult és filozófikus, legjobban egy mesével tudom illusztrálni, hogy egyszer volt egy auto-scaler Powershell-en, amely nem ellenőrizte a határfeltételeket => több VM jött létre, mint amennyire szükség volt => az ügyfél többet költött, mint tervezett. Nem jó érzés, de ezt a hibát nagyon korai szakaszokban meg lehetett volna fogni.

Megkérdezheti, hogy miért kell még bonyolultabbá tenni a bonyolult infrastruktúrát? Az infrastruktúrára vonatkozó tesztek, akárcsak a kód számára, nem az egyszerűsítésről szólnak, hanem arról, hogy tudjuk, hogyan kell az infrastruktúránknak működnie.

IaC Tesztelési Piramis

Mit tanultam, amikor 200 000 sor infrastruktúrakódot teszteltem

IaC Tesztelés: Statikus Elemzés

Ha az egész infrastruktúrát egyszerre telepítjük és ellenőrizzük, hogy működik, akkor kiderülhet, hogy ez rengeteg időt vesz igénybe, és sok időt követel. Ezért valaminek gyorsan működőnek kell lennie, sok van belőle, és számos primitív helyet lefed.

A Bash nehéz

Nézzünk egy banális példát. Válasszuk ki az összes fájlt a jelenlegi könyvtárból, és másoljuk át egy másik helyre. Az első, ami eszembe jut:

for i in * ; do 
    cp $i /some/path/$i.bak
done

De mi van, ha a fájl nevében szóköz van? Nos, rendben van, okosak vagyunk, tudjuk használni a idézőjeleket:

for i in * ; do cp "$i" "/some/path/$i.bak" ; done

Jól csináltuk? Nem! Mi van, ha a könyvtárban nincs semmi, azaz nem működik a globálás.

find . -type f -exec mv -v {} dst/{}.bak ;

Most jól csináltuk? Nem… Elfelejtettük, hogy a fájl nevében lehet n.

touch x
mv x "$(printf "foonbar")"
find . -type f -print0 | xargs -0 mv -t /path/to/target-dir

Statikus elemző eszközök

A korábbi lépés problémáját észlelhettük, amikor elfelejtettük az idézőjeleket, erre számos eszköz áll rendelkezésre. Shellcheck, valójában sokan vannak, és valószínűleg talál egy lintert a saját IDE-jéhez a technológiai stackjéhez.

Nyelv
Eszköz

bash
Shellcheck

Ruby
RuboCop

python
Pylint

ansible
Ansible Lint

IaC Tesztelés: Egység Tesztek

Mit tanultam, amikor 200 000 sor infrastruktúrakódot teszteltem

Ahogy azt a korábbi példából láttuk, a linerek nem mindenhatóak, és nem tudnak minden problémát kiemelni. A szoftverfejlesztés tesztelésével analóg módon emlékezhetünk az egységtesztekre. Azonnal eszembe jut shunit, junit, rspec, pytest. De mi a helyzet az ansible-lal, chef-fel, saltstack-kel és hasonlókkal?

Kezdetben arról beszéltünk, hogy S.O.L.I.D. és hogy az infrastruktúránknak kis építőelemekből kell állnia. Most elérkezett az idejük.

  1. Az infrastruktúra apró építőelemekre bontható, például Ansible szerepekre.
  2. Egy adott környezetet állítunk fel, legyen az docker vagy virtuális gép.
  3. Ezen a tesztkörnyezeten alkalmazzuk az Ansible szerepünket.
  4. Ellenőrizzük, hogy minden a várakozásaink szerint működött (teszteket futtatunk).
  5. Döntünk, hogy oké vagy nem oké.

IaC Tesztelés: Egység Tesztelő Eszközök

A kérdés az, hogy mik azok a tesztek a CFM-hez? Egyszerűen futtathatunk egy szkriptet, de használhatunk kész megoldásokat is:

CFM
Eszköz

Ansible
Testinfra

Chef
Inspec

Chef
Serverspec

saltstack
Goss

Példa a testinfra-ra, ellenőrizzük, hogy a felhasználók test1, test2 léteznek és a csoport tagjai 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

Mit válasszunk? A kérdés bonyolult és nem egyértelmű, itt van egy példa a github projekteken történt változásokra 2018-2019 között:

Mit tanultam, amikor 200 000 sor infrastruktúrakódot teszteltem

IaC Tesztelő Keretrendszerek

Felmerül a kérdés, hogyan lehet mindezt összegyűjteni és futtatni? Lehet venni és mindent megcsinálni magunknak a megfelelő számú mérnök rendelkezésre állása esetén. Vagy lehet kész megoldásokat választani, bár nem sok van belőlük:

CFM
Eszköz

Ansible
Molecule

Chef
Test Kitchen

Terraform
Terratest

Példa a github projekteken történt változásokra 2018-2019 között:

Mit tanultam, amikor 200 000 sor infrastruktúrakódot teszteltem

Molecule vs. Testkitchen

Mit tanultam, amikor 200 000 sor infrastruktúrakódot teszteltem

Kezdetben mi próbáltuk használni a testkitchen-t:

  1. Hozzunk létre párhuzamosan virtuális gépet.
  2. Alkalmazzuk az Ansible szerepeket.
  3. Futtassuk az Inspec-t.

25-35 szerep esetén 40-70 percet vett igénybe, ami hosszú volt.

Mit tanultam, amikor 200 000 sor infrastruktúrakódot teszteltem

A következő lépés a Jenkins / Docker / Ansible / Molecule átállása volt. Ideológiailag minden ugyanaz.

  1. Linteljük a playbookokat.
  2. Linteljük a szerepeket.
  3. Indítsuk el a konténert.
  4. Alkalmazzuk az Ansible szerepeket.
  5. Futtassuk a Testinfra-t.
  6. Ellenőrizzük az idempotenciát.

Mit tanultam, amikor 200 000 sor infrastruktúrakódot teszteltem

A 40 szerepre vonatkozó lintelés és a tesztek körülbelül 15 percet vettek igénybe.

Mit tanultam, amikor 200 000 sor infrastruktúrakódot teszteltem

A választás sok tényezőtől függ, például a használt stacktől, a csapat szakértelmétől stb. Itt mindenkinek magának kell eldöntenie, hogyan közelíti meg az egységtesztelés kérdését.

IaC Tesztelés: Integrációs Tesztek

Mit tanultam, amikor 200 000 sor infrastruktúrakódot teszteltem

A tesztelési piramis következő szintjén integrációs tesztek jelennek meg. Ezek hasonlítanak az egységtesztekhez:

  1. Az infrastruktúra apró darabokra, például Ansible szerepekre bomlik.
  2. Egy adott környezetet állítunk fel, legyen az docker vagy virtuális gép.
  3. Ezt a tesztkörnyezetet alkalmazzuk több Ansible szerepekkel.
  4. Ellenőrizzük, hogy minden úgy működik, ahogy várjuk (futtatjuk a teszteket).
  5. Döntünk, hogy oké vagy nem oké.

Durván szólva, nem az egyes rendszeralkotók működését ellenőrizzük, mint az egységteszteknél, hanem azt, hogy a szerver összességében hogyan van konfigurálva.

IaC Tesztelés: Végső Tesztek

Mit tanultam, amikor 200 000 sor infrastruktúrakódot teszteltem

A piramis csúcsán végső tesztek várnak ránk. Tehát nem az egyes szerverek, egyes szkriptek, egyes építőelemek működését ellenőrizzük az infrastruktúránkban. Ellenőrizzük, hogy a különböző szerverek, amelyek egy egységes infrastruktúrát alkotnak, úgy működnek, ahogy azt várjuk. Sajnos dobozos megoldásokat eddig nem láttam, valószínűleg azért, mert az infrastruktúrák gyakran egyediek, és nehéz sablonosítani őket és keretrendszert kidolgozni a tesztelésre. Ennek eredményeként mindenki saját megoldásokat alkot. Igény van rá, de válasz nem létezik. Ezért elmondom, mi a helyzet, hogy másokat jó gondolatokra inspiráljak, vagy hogy valaki rávilágítson, hogy ezt már régen kitalálták.

Mit tanultam, amikor 200 000 sor infrastruktúrakódot teszteltem

Egy gazdag történelemmel bíró projekt. Nagy szervezetekben használják, és valószínűleg mindannyian közvetve találkoztunk vele. Az alkalmazás számos adatbázist, integrációt, stb. támogat. Az infrastruktúra megvalósulásának ismerete sok docker-compose fájlt jelent, a tudás pedig azt, hogy milyen teszteket kell futtatni melyik környezetben - ez a Jenkins.

Mit tanultam, amikor 200 000 sor infrastruktúrakódot teszteltem

Ez a séma viszonylag sokáig működött, amíg kutatások meg nem próbáltuk ezt átvinni az Openshiftbe. A konténerek változatlanok maradtak, de a végrehajtási környezet megváltozott (üdvözöljük újra a D.R.Y.-t).

Mit tanultam, amikor 200 000 sor infrastruktúrakódot teszteltem

A kutatás gondolata továbbfejlődött, és az OpenShift-ben egy APB (Ansible Playbook Bundle) nevű dolog került elő, amely lehetővé teszi, hogy tudást csomagoljunk be egy konténerbe az infrastruktúra kiépítésének módjáról. Vagyis van egy reprodukálható, tesztelhető tudáspont arról, hogyan kell kiépíteni az infrastruktúrát.

Mit tanultam, amikor 200 000 sor infrastruktúrakódot teszteltem

Mindez jól hangzott, amíg nem ütköztünk heterogén infrastruktúrába: a tesztekhez Windows-ra volt szükség. Végül a tudás arról, hogy hol, hogyan kell kiépíteni és tesztelni, a Jenkins-ben van.

Következtetés

Mit tanultam, amikor 200 000 sor infrastruktúrakódot teszteltem

Infrastruktúra mint kód

  • Kód a tárolóban.
  • Emberek közötti interakció.
  • Az infrastruktúra tesztelése.

linkek

Forrás: habr.com

Megbízható hosting vásárlása weboldalak számára, DDoS védelemmel, VPS VDS szerverek. 🔥 Megbízható webtárhely vásárlása DDoS védelemmel, VPS VDS szerverek | ProHoster