Wat ik leerde door 200.000 regels infrastructuurcode te testen

Wat ik leerde door 200.000 regels infrastructuurcode te testen

Aanpak IaC (Infrastructure as Code) bestaat niet alleen uit de code die in de repository is opgeslagen, maar ook uit de mensen en processen die deze code omringen. Is het mogelijk om benaderingen uit softwareontwikkeling te hergebruiken voor het beheer en de beschrijving van infrastructuur? Het is nuttig om dit idee in gedachten te houden terwijl u het artikel leest.

Engelse versie

Dit is de transcriptie van mijn de presentatie en een werkende opdracht krijgen. DevopsConf 2019-05-28.

Dia's en video's

Infrastructuur als bash-geschiedenis

Wat ik leerde door 200.000 regels infrastructuurcode te testen

Stel, je komt op een nieuw project en men zegt je: «we hebben Infrastructure as Code». In werkelijkheid blijkt dat Infrastructuur als bash-geschiedenis of bijvoorbeeld Documentatie als bash-geschiedenis. Dit is een heel reële situatie, bijvoorbeeld, zo'n geval beschreef Denis Lysenko in zijn voordracht Hoe je de hele infrastructuur vervangt en weer rustig kunt slapen, hij vertelde hoe ze uit bash-geschiedenis een gestructureerde infrastructuur voor het project hebben ontvangen.

Met enige moeite kan men zeggen dat Infrastructuur als bash-geschiedenis het als code is:

  1. reproduceerbaarheid: je kunt bash-geschiedenis nemen, de commando's daaruit uitvoeren, mogelijk krijg je trouwens een werkende configuratie als resultaat.
  2. versiebeheer: je weet wie er binnenkwam en wat ze deden, maar nogmaals, het is niet zeker dat dit je naar een werkende configuratie leidt.
  3. geschiedenis: de geschiedenis van wie wat deed. Maar je kunt er niet mee werken als je de server verliest.

Wat moeten we nu doen?

Infrastructure as Code

Wat ik leerde door 200.000 regels infrastructuurcode te testen

Zelfs zo'n vreemd geval als Infrastructuur als bash-geschiedenis kan naar het Infrastructure as Codegetrokken worden, maar wanneer we iets complexers willen doen dan de oude vertrouwde LAMP-server, komen we tot de conclusie dat deze code op een bepaalde manier moet worden aangepast, gewijzigd, verder ontwikkeld. Verder willen we de parallellen tussen Infrastructure as Code en softwareontwikkeling bekijken.

D.R.Y.

Wat ik leerde door 200.000 regels infrastructuurcode te testen

Bij een project voor de ontwikkeling van opslagarrays was er een subtaak om periodiek SDS in te stellen.: we brengen een nieuwe release uit - deze moet worden uitgerold voor verdere tests. De taak is uiterst eenvoudig:

  • ga hierheen via ssh en voer de opdracht uit.
  • kopieer het bestand daarheen.
  • corrigeer hier de configuratie.
  • start daar de service.
  • …
  • WINST!

Voor de beschreven logica is bash meer dan voldoende, vooral in de vroege stadia van het project, wanneer het net begint. Het is niet slecht dat je bash gebruikt., maar na verloop van tijd ontstaan er verzoeken om iets soortgelijks uit te breiden, maar net iets anders. Het eerste wat in me opkomt: copy-paste. En daar hebben we al twee heel vergelijkbare scripts die bijna hetzelfde doen. Na verloop van tijd is het aantal scripts toegenomen, en we stuiten op een zekere bedrijfslogica voor de uitrol van de installatie, die gesynchroniseerd moet worden tussen verschillende scripts; dat is best complex.

Wat ik leerde door 200.000 regels infrastructuurcode te testen

Het blijkt dat er een praktijk is genaamd D.R.Y. (Do not Repeat Yourself). Het idee is om bestaande code te hergebruiken. Het klinkt eenvoudig, maar we kwamen daar niet meteen achter. In ons geval was het een banale gedachte: scheid de configuraties van de scripts. Dat wil zeggen, de bedrijfslogica voor het uitrollen van de installatie apart, de configuraties apart.

S.O.L.I.D. voor CFM

Wat ik leerde door 200.000 regels infrastructuurcode te testen

Na verloop van tijd groeide het project en was een natuurlijk gevolg de opkomst van Ansible. De belangrijkste reden voor de opkomst ervan was de aanwezige expertise in het team en dat bash niet bedoeld is voor complexe logica. Ansible bevatte ook complexe logica. Om ervoor te zorgen dat complexe logica niet in chaos verandert, bestaan er in softwareontwikkeling principes voor het organiseren van code. S.O.L.I.D. Ook bijvoorbeeld Grigory Petrov raakte in zijn presentatie "Waarom een IT'er een persoonlijk merk nodig heeft" het onderwerp aan dat mensen zodanig zijn opgebouwd dat het voor hen gemakkelijker is om met sociale entiteiten om te gaan, in softwareontwikkeling zijn dit objecten. Als je deze twee ideeën samenvoegt en verder ontwikkelt, kan je merken dat ook in de beschrijving van infrastructuur S.O.L.I.D. het in de toekomst gemakkelijker zal zijn om deze logica te ondersteunen en te wijzigen.

Het Enkelvoudige Verantwoordelijkheidsprincipe

Wat ik leerde door 200.000 regels infrastructuurcode te testen

Elke klasse voert slechts één taak uit.

Mix geen code en maak geen monolitische goddelijke spaghettimonsters. Infrastructuur moet bestaan uit eenvoudige bouwstenen. Blijkt dat als je een Ansible playbook in kleine stukjes opdeelt, lees Ansible rollen, dat ze gemakkelijker te onderhouden zijn.

Het Open Gesloten Principe

Wat ik leerde door 200.000 regels infrastructuurcode te testen

Het principe van openheid/geslotenheid.

  • Open voor uitbreiding: betekent dat het gedrag van een entiteit kan worden uitgebreid door nieuwe typen entiteiten te creëren.
  • Gesloten voor wijziging: als gevolg van het uitbreiden van het gedrag van een entiteit mogen er geen wijzigingen worden aangebracht in de code die deze entiteiten gebruikt.

Aanvankelijk draaiden we een testinfrastructuur op virtuele machines, maar omdat de zakelijke logica van de implementatie gescheiden was, hebben we zonder problemen een uitrol op bare metal toegevoegd.

Het Liskov-substitutieprincipe

Wat ik leerde door 200.000 regels infrastructuurcode te testen

Het Liskov-substitutieprincipe. Objecten in een programma moeten vervangbaar zijn door instanties van hun subtypen zonder de correctheid van het programma in gevaar te brengen.

Als je breder kijkt, is het geen specifieke eigenschap van een bepaald project dat je daar kunt toepassen. S.O.L.I.D., het gaat in het algemeen om CFM, bijvoorbeeld in een ander project moet je een kant-en-klaar Java-toepassing implementeren bovenop verschillende Java, applicatieservers, databases, besturingssystemen, enz. Op dit voorbeeld zal ik de verdere principes bekijken. S.O.L.I.D.

In ons geval is er binnen het infrastructuurteam een afspraak dat als we de rol imbjava of oraclejava hebben geïnstalleerd, er een uitvoerbaar binair bestand java aanwezig moet zijn. Dit is nodig omdat de bovenliggende rollen van dit gedrag afhankelijk zijn en ze de aanwezigheid van java verwachten. Tegelijkertijd stelt dit ons in staat om de ene implementatie/versie van java door de andere te vervangen zonder de logica van de applicatie-implementatie te veranderen.

Het probleem hier zit in het feit dat je zoiets niet kunt implementeren in Ansible, waardoor er binnen het team bepaalde afspraken ontstaan.

Het Interface-segregatieprincipe

Wat ik leerde door 200.000 regels infrastructuurcode te testen

Het principe van interface-segregatie. "Veel interfaces, speciaal ontworpen voor klanten, zijn beter dan één interface voor algemeen gebruik."

Aanvankelijk probeerden we alle variabiliteit van de applicatie-implementatie in één Ansible-playbook onder te brengen, maar dit was moeilijk te onderhouden. De aanpak waarbij we een gespecificeerd interface naar buiten hebben (de klant verwacht poort 443), stelt ons in staat om de infrastructuur voor een specifieke implementatie uit afzonderlijke bouwstenen samen te stellen.

Het principe van afhankelijkheidsinversie

Wat ik leerde door 200.000 regels infrastructuurcode te testen

Het principe van afhankelijkheidsinversie. Modules op een hoger niveau mogen niet afhankelijk zijn van modules op een lager niveau. Beide soorten modules moeten afhankelijk zijn van abstracties. Abstracties mogen niet afhankelijk zijn van details. Details moeten afhankelijk zijn van abstracties.

Het voorbeeld hier zal gebaseerd zijn op een antipatroon.

  1. Een van onze klanten had een privécloud.
  2. Binnen de cloud vroegen we virtuele machines aan.
  3. Maar vanwege de kenmerken van de cloud was de uitrol van de applicatie gebonden aan de hypervisor waarop de VM terechtkwam.

Dus, de hoog-niveau logica van de applicatieontplooiing, afhankelijkheden, stroomden naar de onderliggende niveaus van de hypervisor, en dit betekende problemen bij het hergebruiken van deze logica. Dat hoef je niet te doen.

Interacties

Wat ik leerde door 200.000 regels infrastructuurcode te testen

Infrastructuur als code gaat niet alleen over code, maar ook over de relaties tussen de code en de mens, over de interacties tussen infrastructuurontwikkelaars.

Busfactor

Wat ik leerde door 200.000 regels infrastructuurcode te testen

Stel dat je iemand op je project hebt, laten we zeggen Vasja. Vasja weet alles over jouw infrastructuur; wat gebeurt er als Vasja plotseling verdwijnt? Dit is een heel reële situatie, want hij kan door een bus overreden worden. Soms gebeurt dat. Als dergelijke kennis over de code, de structuur, hoe het werkt, gebruikersnamen en wachtwoorden niet binnen het team is verdeeld, dan kun je met een aantal vervelende situaties geconfronteerd worden. Om deze risico's te minimaliseren en de kennis binnen het team te verspreiden, kunnen verschillende benaderingen worden gebruikt.

Pair Devopsing

Wat ik leerde door 200.000 regels infrastructuurcode te testen

Dit is niet zoals in de grap, dat admins bier dronken, wachtwoorden wijzigden, en een analoog aan pair programming. Dat wil zeggen, twee ingenieurs zitten achter één computer, één toetsenbord en beginnen samen jouw infrastructuur in te stellen: de server configureren, een Ansible-rol schrijven, enzovoort. Het klinkt mooi, maar bij ons werkte het niet. Maar private gevallen van deze praktijk werkten. Een nieuwe medewerker, zijn mentor neemt samen met hem een echte taak op zich en werkt samen — kennisoverdracht.

Een ander privé geval is de incident call. Tijdens een probleem verzamelt zich een groep van kaderleden en betrokkenen, er wordt één leider aangewezen die zijn scherm deelt en zijn gedachtegang verhaalt. Andere deelnemers volgen de gedachtegang van de leider, kijken naar tricks in de console, controleren wat hij niet in de log heeft gemist, en leren nieuwe dingen over het systeem. Deze aanpak werkte meer dan niet.

Code Review

Wat ik leerde door 200.000 regels infrastructuurcode te testen

Subjectief gezien vond ik de verspreiding van kennis over de infrastructuur en hoe deze is opgebouwd effectiever via code reviews:

  • De infrastructuur is in code beschreven in de repository.
  • Wijzigingen vinden plaats in een aparte tak.
  • Bij de merge-aanvraag kan je de delta van de veranderingen in de infrastructuur zien.

Het opvallende hier was dat de reviewers om de beurt, volgens een schema, werden geselecteerd, dus met een zekere waarschijnlijkheid zou je in een nieuw deel van de infrastructuur kunnen duiken.

Code Stijl

Wat ik leerde door 200.000 regels infrastructuurcode te testen

Naarmate de tijd vorderde, begonnen er discussies te ontstaan tijdens reviews, omdat reviewers hun eigen stijl hadden en de rotatie van reviewers hen in aanraking bracht met verschillende stijlen: 2 spaties of 4, camelCase of snake_case. Het implementeren hiervan lukte niet meteen.

  • Het eerste idee was om aan te bevelen een linter te gebruiken, want tenslotte zijn het allemaal ingenieurs, allemaal slim. Maar verschillende editors, besturingssystemen, niet handig.
  • Dit evolueerde naar een bot die bij elk problematisch commit naar Slack schreef en de uitvoer van de linter toevoegde. Maar in de meeste gevallen waren er belangrijkere zaken en bleef de code ongecorrigeerd.

Green Build Master

Wat ik leerde door 200.000 regels infrastructuurcode te testen

De tijd ging voorbij, en we kwamen tot de conclusie dat commits die niet door bepaalde tests komen, niet in de master mogen worden toegelaten. Voilà! We hebben de Green Build Master uitgevonden, die al geruime tijd in softwareontwikkeling wordt toegepast:

  • De ontwikkeling vindt plaats in een aparte tak.
  • In deze tak worden tests uitgevoerd.
  • Als de tests niet slagen, komt de code niet in de master.

Het nemen van deze beslissing was behoorlijk pijnlijk, omdat het veel discussie veroorzaakte, maar het was het waard, omdat de merge-aanvragen voor reviews zonder stilistische meningsverschillen binnenkwamen en na verloop van tijd het aantal probleemgevallen afnam.

IaC Testing

Wat ik leerde door 200.000 regels infrastructuurcode te testen

Naast stijlcontroles kunnen ook andere zaken worden gebruikt, bijvoorbeeld controleren of uw infrastructuur daadwerkelijk kan worden uitgerold. Of controleren of de wijzigingen in de infrastructuur niet leiden tot verlies van geld. Waarom zou dit nodig zijn? De vraag is complex en filosofisch, het antwoord kan beter met een verhaal worden gegeven: er was eens een auto-scaler op Powershell die geen randvoorwaarden controleerde => er werden meer VM's gemaakt dan nodig was => de klant gaf meer uit dan gepland. Niet leuk, maar deze fout had heel goed in een vroeg stadium kunnen worden opgemerkt.

Men kan zich afvragen, waarom een complexe infrastructuur nog ingewikkelder maken? Tests voor infrastructuur, net als voor code, zijn niet bedoeld om het te vereenvoudigen, maar om te begrijpen hoe uw infrastructuur zou moeten werken.

IaC Testing Pyramid

Wat ik leerde door 200.000 regels infrastructuurcode te testen

IaC Testing: Static Analysis

Als je meteen de volledige infrastructuur uitrolt en controleert of deze werkt, kan het zijn dat dit een hoop tijd en inspanning vergt. Daarom moet er iets zijn dat snel werkt, veel voorkomt, en dat vele primitieve aspecten dekt.

Bash is tricky

Laten we een eenvoudig voorbeeld bekijken. Alle bestanden in de huidige directory selecteren en naar een andere locatie kopiëren. Het eerste dat in me opkomt:

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

Maar wat als er een spatie in de bestandsnaam zit? Nou ja, we zijn slim, we weten hoe we aanhalingstekens moeten gebruiken:

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

Goed gedaan? Nee! Wat als er niets in de directory staat, dat wil zeggen, globbing werkt niet.

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

En nu, goed gedaan? Nee… We zijn vergeten dat er n.

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

Statische analysetools

Het probleem van de vorige stap kon worden opgemerkt toen we de aanhalingstekens vergaten, hiervoor bestaan er veel middelen. Shellcheck, er zijn er veel en waarschijnlijk kun je een linter voor jouw stack vinden voor je IDE.

Taal
Hulpmiddel

bash
Shellcheck

Ruby
RuboCop

python
Pylint

ansible
Ansible Lint

IaC Testing: Unit Tests

Wat ik leerde door 200.000 regels infrastructuurcode te testen

Zoals we uit het vorige voorbeeld hebben gezien, zijn linters niet almachtig en kunnen ze niet alle probleemgebieden aanwijzen. Verderop, in navolging van testen in softwareontwikkeling, kunnen we het hebben over unittests. Hier komen meteen in gedachten: shunit, junit, rspec, pytest. Maar wat doen we met ansible, chef, saltstack en soortgelijke?

Aan het begin spraken we over S.O.L.I.D. en dat onze infrastructuur uit kleine bouwstenen moet bestaan. Het is tijd voor hen.

  1. De infrastructuur wordt opgedeeld in kleine bouwstenen, zoals Ansible-rollen.
  2. Er wordt een bepaalde omgeving opgezet, of dit nu docker of een VM is.
  3. We passen onze Ansible-rol toe op deze testomgeving.
  4. We controleren of alles is uitgevoerd zoals we verwachtten (we voeren de tests uit).
  5. We besluiten of het goed of niet goed is.

IaC Testing: Unit Testing tools

De vraag is, wat zijn tests voor CFM? Je kunt simpelweg een script uitvoeren, maar je kunt ook gebruik maken van kant-en-klare oplossingen hiervoor:

CFM
Hulpmiddel

Ansible
Testinfra

Chef
Inspec

Chef
Serverspec

saltstack
Goss

Voorbeeld voor testinfra, we controleren of de gebruikers test1, test2 bestaan en lid zijn van de groep 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

Wat te kiezen? Een moeilijke en niet eenduidige vraag, hier is een voorbeeld van veranderingen in projecten op GitHub in 2018-2019:

Wat ik leerde door 200.000 regels infrastructuurcode te testen

IaC Testing frameworks

De vraag is hoe dit allemaal samen te brengen en uit te voeren? Je kunt alles zelf doen met voldoende ingenieurs. Of je kunt kant-en-klare oplossingen nemen, maar die zijn er niet veel:

CFM
Hulpmiddel

Ansible
Molecule

Chef
Test Kitchen

Terraform
Terratest

Voorbeeld van veranderingen in projecten op GitHub in 2018-2019:

Wat ik leerde door 200.000 regels infrastructuurcode te testen

Molecule vs. Testkitchen

Wat ik leerde door 200.000 regels infrastructuurcode te testen

In het begin hebben we geprobeerd testkitchen te gebruiken:

  1. Een VM parallel creëren.
  2. Toepassen van Ansible-rollen.
  3. Inspec uitvoeren.

Voor 25-35 rollen duurde het 40-70 minuten, wat lang was.

Wat ik leerde door 200.000 regels infrastructuurcode te testen

De volgende stap was de overstap naar Jenkins / Docker / Ansible / Molecule. Ideologisch is het allemaal hetzelfde.

  1. Playbooks linten.
  2. Rollen linten.
  3. Container starten.
  4. Toepassen van Ansible-rollen.
  5. Testinfra uitvoeren.
  6. Controleer idempotentie.

Wat ik leerde door 200.000 regels infrastructuurcode te testen

Linten voor 40 rollen en tests voor een tiental duurden ongeveer 15 minuten.

Wat ik leerde door 200.000 regels infrastructuurcode te testen

Wat te kiezen hangt af van veel factoren, zoals de gebruikte stack, expertise in het team, enz. Iedereen beslist zelf hoe ze de kwestie van unit testing aanpakken.

IaC Testing: Integratietests.

Wat ik leerde door 200.000 regels infrastructuurcode te testen

In de volgende laag van de piramide voor infrastructuurtesten verschijnen integratietests. Ze lijken op unit tests:

  1. Infrastructuur wordt opgesplitst in kleine blokjes, bijvoorbeeld Ansible-rollen.
  2. Er wordt een bepaalde omgeving opgezet, of dit nu docker of een VM is.
  3. Deze testomgeving wordt toegepast op. veel Ansible-rollen.
  4. We controleren of alles is uitgevoerd zoals we verwachten (we voeren de tests uit).
  5. We besluiten of het goed of niet goed is.

Grofweg gezegd, controleren we niet de functionaliteit van een enkel element van het systeem zoals bij unit tests, maar controleren we hoe de server als geheel is geconfigureerd.

IaC Testing: End-to-End Tests.

Wat ik leerde door 200.000 regels infrastructuurcode te testen

Bovenaan de piramide worden we begroet door end-to-end tests. Dat wil zeggen, we controleren niet de functionaliteit van een enkele server, een enkel script, of een enkele bouwsteen van onze infrastructuur. We controleren of een aantal servers, verenigd als één geheel, onze infrastructuur werkt zoals we verwachten. Helaas heb ik geen kant-en-klare oplossingen gezien, waarschijnlijk omdat infrastructuren vaak uniek zijn en moeilijk te standaardiseren en te kaderen voor testen. Als resultaat maken velen hun eigen oplossingen. Er is vraag, maar geen aanbod. Daarom zal ik vertellen wat er is, om anderen op verstandige gedachten te brengen of om me te wijzen op het feit dat alles al lang voor ons is uitgevonden.

Wat ik leerde door 200.000 regels infrastructuurcode te testen

Project met een rijke geschiedenis. Het wordt gebruikt in grote organisaties en waarschijnlijk heeft elk van jullie er indirect mee te maken gehad. De applicatie ondersteunt veel databases, integraties, enzovoort. Kennis over hoe de infrastructuur eruit kan zien, is een heleboel docker-compose bestanden, en kennis over welke tests in welke omgeving moeten worden uitgevoerd — dat is Jenkins.

Wat ik leerde door 200.000 regels infrastructuurcode te testen

Dit schema heeft relatief lang gewerkt totdat we het op Openshift probeerden te zetten. onderzoeken De containers bleven hetzelfde, maar de uitvoeringsomgeving is veranderd (hallo D.R.Y. weer).

Wat ik leerde door 200.000 regels infrastructuurcode te testen

De gedachtegang van het onderzoek ging verder, en in OpenShift werd er zo'n ding gevonden genaamd APB (Ansible Playbook Bundle), waarmee je de kennis over het implementeren van infrastructuur in een container kunt inpakken. Dat wil zeggen, er is een reproduceerbaar, testbaar kennis punt over hoe de infrastructuur te implementeren.

Wat ik leerde door 200.000 regels infrastructuurcode te testen

Dit klonk allemaal goed, totdat we tegen een heterogene infrastructuur aanliepen: we hebben Windows nodig voor tests. Uiteindelijk bevindt de kennis over wat, waar en hoe te implementeren en te testen zich in Jenkins.

Conclusie

Wat ik leerde door 200.000 regels infrastructuurcode te testen

Infrastructure as Code is

  • Code in de repository.
  • Interacties tussen mensen.
  • Testen van infrastructuur.

links

Bron: habr.com

Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers 🔥 Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers | ProHoster