Vad jag lärde mig av att testa 200 000 rader av infrastrukturkod

Vad jag lärde mig av att testa 200 000 rader av infrastrukturkod

tillvägagångssätt IaC (Infrastructure as Code) består inte bara av koden som är lagrad i förvaret, utan också av de personer och processer som omger denna kod. Är det möjligt att återanvända metoder från mjukvaruutveckling till infrastrukturhantering och beskrivning? Det skulle vara en bra idé att ha denna idé i åtanke när du läser artikeln.

Svensk version

Det här är en utskrift av min föreställningarDevopsConf 2019-05-28.

Bilder och videor

Infrastruktur som bash historia

Vad jag lärde mig av att testa 200 000 rader av infrastrukturkod

Anta att du kommer till ett nytt projekt och de säger till dig: "vi har Infrastruktur som kod". I verkligheten visar det sig Infrastruktur som bash historia eller till exempel Dokumentation som bash historia. Detta är en mycket verklig situation, till exempel beskrevs ett liknande fall av Denis Lysenko i ett tal Hur man byter ut hela infrastrukturen och börjar sova gott, berättade han hur de fick en sammanhängande infrastruktur för projektet från bashhistorien.

Med viss lust kan vi säga det Infrastruktur som bash historia detta är som kod:

  1. reproducerbarhet: Du kan ta bash-historik, köra kommandon därifrån, och du kan förresten få en fungerande konfiguration som en utdata.
  2. versionshantering: du vet vem som kom in och vad de gjorde, igen, det är inte ett faktum att detta kommer att leda dig till en fungerande konfiguration vid utgången.
  3. historia: berättelsen om vem som gjorde vad. bara du kommer inte att kunna använda den om du tappar servern.

Vad göra?

Infrastruktur som kod

Vad jag lärde mig av att testa 200 000 rader av infrastrukturkod

Även ett så konstigt fall som Infrastruktur som bash historia du kan dra den i öronen Infrastruktur som kod, men när vi vill göra något mer komplicerat än den gamla goda LAMP-servern kommer vi till slutsatsen att den här koden på något sätt måste modifieras, ändras, förbättras. Därefter skulle vi vilja överväga parallellerna mellan Infrastruktur som kod och mjukvaruutveckling.

TORR

Vad jag lärde mig av att testa 200 000 rader av infrastrukturkod

På ett utvecklingsprojekt för lagringssystem fanns det en deluppgift konfigurera SDS med jämna mellanrum: vi släpper en ny version - den måste rullas ut för ytterligare testning. Uppgiften är extremt enkel:

  • logga in här via ssh och kör kommandot.
  • kopiera filen dit.
  • korrigera konfigurationen här.
  • starta tjänsten där
  • .
  • VINST!

För den beskrivna logiken är bash mer än tillräckligt, särskilt i de tidiga stadierna av projektet, när det precis har börjat. Detta det är inte dåligt att du använder bash, men med tiden finns det förfrågningar om att distribuera något liknande, men något annorlunda. Det första som kommer att tänka på är copy-paste. Och nu har vi redan två väldigt lika manus som gör nästan samma sak. Med tiden växte antalet skript, och vi ställdes inför det faktum att det finns en viss affärslogik för att distribuera en installation som behöver synkroniseras mellan olika skript, detta är ganska komplicerat.

Vad jag lärde mig av att testa 200 000 rader av infrastrukturkod

Det visar sig att det finns en sådan praxis som DRY (Do not Repeat Yourself). Tanken är att återanvända befintlig kod. Det låter enkelt, men vi kom inte fram till det här direkt. I vårt fall var det en banal idé: att separera konfigurationer från skript. De där. affärslogik för hur installationen distribueras separat, konfigureras separat.

SOLID för CFM

Vad jag lärde mig av att testa 200 000 rader av infrastrukturkod

Med tiden växte projektet och naturlig fortsättning var uppkomsten av Ansible. Den främsta anledningen till dess utseende är att det finns expertis i laget och att bash inte är designad för komplex logik. Ansible började också innehålla komplex logik. För att förhindra att komplex logik förvandlas till kaos finns det principer för att organisera kod i mjukvaruutveckling FAST Till exempel ställde Grigory Petrov också i rapporten "Varför behöver en IT-specialist ett personligt varumärke" frågan om att en person är utformad på ett sådant sätt att det är lättare för honom att arbeta med vissa sociala enheter, inom mjukvaruutveckling dessa är föremål. Om vi ​​kombinerar dessa två idéer och fortsätter att utveckla dem kommer vi att märka att vi också kan använda dem FAST för att göra det lättare att underhålla och modifiera denna logik i framtiden.

Principen om ett enda ansvar

Vad jag lärde mig av att testa 200 000 rader av infrastrukturkod

Varje klass utför bara en uppgift.

Inget behov av att blanda kod och göra monolitiska gudomliga spagettimonster. Infrastrukturen ska bestå av enkla tegelstenar. Det visar sig att om du delar upp Ansible-spelboken i små bitar, läser Ansible-roller, så är de lättare att underhålla.

Den öppna stängda principen

Vad jag lärde mig av att testa 200 000 rader av infrastrukturkod

Öppen/stängd princip.

  • Öppen för förlängning: betyder att beteendet hos en entitet kan utökas genom att skapa nya entitetstyper.
  • Stängd för förändring: Som ett resultat av att en entitets beteende utökas bör inga ändringar göras i koden som använder dessa entiteter.

Inledningsvis distribuerade vi testinfrastrukturen på virtuella maskiner, men på grund av att affärslogiken för implementeringen var skild från implementeringen lade vi till utrullning till baremetall utan problem.

Liskov Substitutionsprincipen

Vad jag lärde mig av att testa 200 000 rader av infrastrukturkod

Barbara Liskovs substitutionsprincip. objekt i ett program måste kunna ersättas med instanser av deras undertyper utan att ändra programmets korrekta exekvering

Om man ser det bredare så är det inte ett inslag i något särskilt projekt som kan tillämpas där FAST, det handlar i allmänhet om CFM, till exempel på ett annat projekt är det nödvändigt att distribuera en boxad Java-applikation ovanpå olika Java, applikationsservrar, databaser, OS, etc. Med hjälp av detta exempel kommer jag att överväga ytterligare principer FAST

I vårt fall finns det en överenskommelse inom infrastrukturteamet att om vi har installerat rollen imbjava eller oraclejava så har vi en binär körbar java. Detta är nödvändigt eftersom Uppströmsroller beror på detta beteende; de ​​förväntar sig java. Samtidigt tillåter detta oss att ersätta en java-implementering/version med en annan utan att ändra logiken för applikationsdistribution.

Problemet här ligger i det faktum att det är omöjligt att implementera detta i Ansible, vilket gör att vissa avtal dyker upp inom teamet.

Gränssnittssegregationsprincipen

Vad jag lärde mig av att testa 200 000 rader av infrastrukturkod

Gränssnittsseparationsprincip: "Många klientspecifika gränssnitt är bättre än ett allmänt gränssnitt.

Inledningsvis försökte vi lägga all variation av applikationsdistribution i en Ansible playbook, men det var svårt att stödja, och tillvägagångssättet när vi har ett externt gränssnitt specificerat (klienten förväntar sig port 443), då kan en infrastruktur sättas ihop från individuella klossar för en specifik implementering.

Beroendeinversionsprincipen

Vad jag lärde mig av att testa 200 000 rader av infrastrukturkod

Principen för beroendeinversion. Moduler på högre nivåer bör inte vara beroende av moduler på lägre nivåer. Båda typerna av moduler måste bero på abstraktioner. Abstraktioner bör inte bero på detaljer. Detaljer måste bero på abstraktioner.

Här kommer exemplet att baseras på ett antimönster.

  1. En av kunderna hade ett privat moln.
  2. Vi beställde virtuella maskiner inne i molnet.
  3. Men på grund av molnets natur var applikationsdistributionen kopplad till vilken hypervisor som den virtuella datorn var på.

De där. Högnivåapplikationsdistributionslogik flödade med beroenden till lägre nivåer av hypervisorn, och detta innebar problem vid återanvändning av denna logik. Gör det inte på det här sättet.

Interaktion

Vad jag lärde mig av att testa 200 000 rader av infrastrukturkod

Infrastruktur som kod handlar inte bara om kod, utan också om relationen mellan kod och människor, om interaktioner mellan infrastrukturutvecklare.

Bussfaktor

Vad jag lärde mig av att testa 200 000 rader av infrastrukturkod

Låt oss anta att du har Vasya på ditt projekt. Vasya vet allt om din infrastruktur, vad händer om Vasya plötsligt försvinner? Det här är en mycket verklig situation, eftersom han kan bli påkörd av en buss. Det händer ibland. Om detta händer och kunskap om koden, dess struktur, hur den fungerar, utseenden och lösenord inte fördelas mellan teamet, kan du stöta på ett antal obehagliga situationer. För att minimera dessa risker och sprida kunskap inom teamet kan du använda dig av olika tillvägagångssätt

Pardevopsing

Vad jag lärde mig av att testa 200 000 rader av infrastrukturkod

Det är inte som som ett skämt, att administratörerna drack öl, bytte lösenord och en analog av parprogrammering. De där. två ingenjörer sätter sig vid en dator, ett tangentbord och börjar sätta upp din infrastruktur tillsammans: konfigurera en server, skriva en Ansible-roll, etc. Det låter trevligt, men det fungerade inte för oss. Men speciella fall av denna praxis fungerade. En ny medarbetare kommer, hans mentor tar sig an en riktig uppgift tillsammans med honom, arbetar och överför kunskap.

Ett annat specialfall är ett incidentsamtal. Under ett problem samlas en grupp av de i tjänst och de inblandade, en ledare utses, som delar sin skärm och uttrycker tankegångarna. Andra deltagare följer ledarens tankar, spionerar på tricks från konsolen, kontrollerar att de inte har missat en rad i loggen och lär sig nya saker om systemet. Detta tillvägagångssätt fungerade oftare än inte.

Kodgranskning

Vad jag lärde mig av att testa 200 000 rader av infrastrukturkod

Subjektivt sett var det mer effektivt att sprida kunskap om infrastrukturen och hur den fungerar med hjälp av kodgranskning:

  • Infrastrukturen beskrivs med kod i förvaret.
  • Förändringar sker i en separat gren.
  • Under en sammanslagningsförfrågan kan du se deltat för ändringar i infrastrukturen.

Höjdpunkten här var att recensenterna valdes ut en efter en, enligt ett schema, d.v.s. med en viss grad av sannolikhet kommer du att klättra in i en ny bit av infrastruktur.

Kodstil

Vad jag lärde mig av att testa 200 000 rader av infrastrukturkod

Med tiden började käbbel dyka upp under recensioner, eftersom... recensenter hade sin egen stil och rotationen av granskare staplade dem med olika stilar: 2 mellanslag eller 4, camelCase eller snake_case. Det gick inte att genomföra detta direkt.

  • Den första tanken var att rekommendera att använda linter, alla är ju ingenjörer, alla är smarta. Men olika redigerare, OS, är inte bekväma
  • Detta utvecklades till en bot som skrev till slack för varje problematisk commit och fäste linter-utgången. Men i de flesta fall fanns det viktigare saker att göra och koden förblev ofixad.

Green Build Master

Vad jag lärde mig av att testa 200 000 rader av infrastrukturkod

Tiden går och vi har kommit fram till att commits som inte klarar vissa test inte kan släppas in i mastern. Voila! Vi uppfann Green Build Master, som har praktiserats inom mjukvaruutveckling under lång tid:

  • Utveckling pågår i en separat gren.
  • Tester pågår i denna tråd.
  • Om testerna misslyckas kommer koden inte in i mastern.

Att fatta detta beslut var väldigt smärtsamt, eftersom... orsakade mycket kontrovers, men det var värt det, för... Recensioner började få förfrågningar om sammanslagningar utan stilskillnader, och med tiden började antalet problemområden minska.

IaC-testning

Vad jag lärde mig av att testa 200 000 rader av infrastrukturkod

Förutom stilkontroll kan du använda andra saker, till exempel för att kontrollera att din infrastruktur faktiskt kan distribueras. Eller kontrollera att förändringar i infrastrukturen inte leder till förlust av pengar. Varför kan detta behövas? Frågan är komplex och filosofisk, det är bättre att svara med en berättelse att det på något sätt fanns en automatisk skalare på Powershell som inte kontrollerade gränsvillkoren => fler virtuella datorer skapades än nödvändigt => klienten spenderade mer pengar än planerat. Detta är inte särskilt trevligt, men det skulle vara fullt möjligt att fånga detta fel i tidigare skeden.

Man kan fråga sig, varför göra komplex infrastruktur ännu mer komplex? Tester för infrastruktur, precis som för kod, handlar inte om förenkling, utan om att veta hur din infrastruktur ska fungera.

IaC-testpyramid

Vad jag lärde mig av att testa 200 000 rader av infrastrukturkod

IaC-testning: Statisk analys

Om du distribuerar hela infrastrukturen på en gång och kontrollerar att den fungerar kan du upptäcka att det tar mycket tid och kräver mycket tid. Därför måste grunden vara något som fungerar snabbt, det finns mycket av det, och det täcker många primitiva platser.

Bash är knepigt

Låt oss titta på ett trivialt exempel. välj alla filer i den aktuella katalogen och kopiera till en annan plats. Det första som kommer att tänka på:

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

Vad händer om det finns ett mellanslag i filnamnet? Okej, vi är smarta, vi vet hur man använder citattecken:

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

Bra gjort? Nej! Tänk om det inte finns något i katalogen, d.v.s. globbing fungerar inte.

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

Bra gjort nu? Nej... Glömde vad som kan stå i filnamnet n.

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

Statiska analysverktyg

Problemet från föregående steg kunde fångas när vi glömde citaten, för detta finns det många botemedel i naturen Shellcheck, i allmänhet finns det många av dem, och troligtvis kan du hitta en linter för din stack under din IDE.

Språk
Verktyget

bash
Shellcheck

Rubin
RuboCop

pytonorm
pylint

ansible
Ansible Lint

IaC-testning: enhetstester

Vad jag lärde mig av att testa 200 000 rader av infrastrukturkod

Som vi såg från föregående exempel är linters inte allsmäktig och kan inte peka ut alla problemområden. Vidare, analogt med testning inom mjukvaruutveckling, kan vi återkalla enhetstester. Det som direkt kommer att tänka på är shunit, juni, rspec, fråga. Men vad ska man göra med ansible, kock, saltstack och andra liknande dem?

I början pratade vi om FAST och att vår infrastruktur ska bestå av små tegelstenar. Deras tid har kommit.

  1. Infrastrukturen är uppdelad i små klossar, till exempel Ansible-roller.
  2. Någon form av miljö är utplacerad, vare sig det är docker eller en virtuell dator.
  3. Vi tillämpar vår Ansible-roll på denna testmiljö.
  4. Vi kontrollerar att allt fungerade som vi förväntade oss (vi kör tester).
  5. Vi bestämmer ok eller inte ok.

IaC-testning: Verktyg för enhetstestning

Fråga, vad är tester för CFM? Du kan helt enkelt köra skriptet, eller så kan du använda färdiga lösningar för detta:

CFM
Verktyget

Ansible
Testinfra

Chef
Inspekte

Chef
Serverspec

saltstack
Goss

Exempel för testinfra, kontrollera att användare test1, test2 finns och är i en grupp 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

Vad ska man välja? Frågan är komplex och tvetydig, här är ett exempel på förändringar i projekt på github för 2018-2019:

Vad jag lärde mig av att testa 200 000 rader av infrastrukturkod

IaC-testramverk

Frågan uppstår: hur man sätter ihop allt och lanserar det? Burk ta det och gör det själv om det finns tillräckligt många ingenjörer. Eller så kan du ta färdiga lösningar, även om det inte finns särskilt många av dem:

CFM
Verktyget

Ansible
molekyl

Chef
Testa köket

Terraform
Terratest

Exempel på ändringar i projekt på github för 2018-2019:

Vad jag lärde mig av att testa 200 000 rader av infrastrukturkod

Molekyl vs. Testkök

Vad jag lärde mig av att testa 200 000 rader av infrastrukturkod

Till en början vi försökte använda testkitchen:

  1. Skapa en virtuell dator parallellt.
  2. Tillämpa Ansible roller.
  3. Kör inspektion.

För 25-35 roller fungerade det 40-70 minuter, vilket var långt.

Vad jag lärde mig av att testa 200 000 rader av infrastrukturkod

Nästa steg var övergången till jenkins/docker/ansible/molekyl. Idiologiskt är allt sig likt

  1. Lint lekböcker.
  2. Rada upp rollerna.
  3. Starta container
  4. Tillämpa Ansible roller.
  5. Kör testinfra.
  6. Kontrollera idempotens.

Vad jag lärde mig av att testa 200 000 rader av infrastrukturkod

Lintning för 40 roller och tester för ett dussin började ta cirka 15 minuter.

Vad jag lärde mig av att testa 200 000 rader av infrastrukturkod

Vad man ska välja beror på många faktorer, såsom den stack som används, expertis i teamet, etc. här bestämmer var och en själv hur man stänger enhetens testfråga

IaC-testning: Integrationstest

Vad jag lärde mig av att testa 200 000 rader av infrastrukturkod

Nästa steg i infrastrukturtestpyramiden kommer att vara integrationstester. De liknar enhetstester:

  1. Infrastrukturen är uppdelad i små klossar, till exempel Ansible roller.
  2. Någon form av miljö är utplacerad, vare sig det är docker eller en virtuell dator.
  3. För denna testmiljö gäller många Ansible roller.
  4. Vi kontrollerar att allt fungerade som vi förväntade oss (vi kör tester).
  5. Vi bestämmer ok eller inte ok.

Grovt sett kontrollerar vi inte prestandan för en enskild del av systemet som i enhetstester, vi kontrollerar hur servern är konfigurerad som helhet.

IaC-testning: Änd-till-änd-tester

Vad jag lärde mig av att testa 200 000 rader av infrastrukturkod

På toppen av pyramiden möts vi av End to End-tester. De där. Vi kontrollerar inte prestandan för en separat server, ett separat skript eller en separat del av vår infrastruktur. Vi kontrollerar att många servrar är sammankopplade, vår infrastruktur fungerar som vi förväntar oss. Tyvärr har jag aldrig sett färdiga boxlösningar, förmodligen för att... Infrastrukturen är ofta unik och svår att malla och skapa ett ramverk för att testa. Som ett resultat skapar alla sina egna lösningar. Det finns en efterfrågan, men det finns inget svar. Därför ska jag berätta vad som finns för att få andra att låta tankar eller gnugga min näsa i det faktum att allt uppfanns för länge sedan före oss.

Vad jag lärde mig av att testa 200 000 rader av infrastrukturkod

Ett projekt med en rik historia. Det används i stora organisationer och förmodligen har var och en av er indirekt korsat vägar med den. Applikationen stöder många databaser, integrationer etc. Att veta hur infrastrukturen kan se ut är många docker-compose-filer och att veta vilka tester som ska köras i vilken miljö är Jenkins.

Vad jag lärde mig av att testa 200 000 rader av infrastrukturkod

Detta upplägg fungerade ganska länge, tills inom ramen forskning vi har inte försökt överföra detta till Openshift. Behållarna förblir desamma, men lanseringsmiljön har förändrats (hej DRY igen).

Vad jag lärde mig av att testa 200 000 rader av infrastrukturkod

Forskningsidéen gick längre, och i openshift hittade de något som APB (Ansible Playbook Bundle), som låter dig packa kunskap om hur man distribuerar infrastruktur i en container. De där. det finns en repeterbar, testbar kunskapspunkt om hur man distribuerar infrastrukturen.

Vad jag lärde mig av att testa 200 000 rader av infrastrukturkod

Allt detta lät bra tills vi stötte på en heterogen infrastruktur: vi behövde Windows för tester. Som ett resultat finns kunskapen om vad, var, hur man distribuerar och testar i jenkins.

Slutsats

Vad jag lärde mig av att testa 200 000 rader av infrastrukturkod

Infrastruktur som kod är

  • Kod i förvaret.
  • Mänsklig interaktion.
  • Infrastrukturtestning.

länkar

Källa: will.com

Lägg en kommentar