Hvad jeg lærte af at teste 200 linjer med infrastrukturkode

Hvad jeg lærte af at teste 200 linjer med infrastrukturkode

tilgang IaC (Infrastructure as Code) består ikke kun af den kode, der er gemt i depotet, men også af de mennesker og processer, der omgiver denne kode. Er det muligt at genbruge tilgange fra softwareudvikling til infrastrukturstyring og beskrivelse? Det ville være en god idé at have denne idé i tankerne, mens du læser artiklen.

engelsk version

Dette er en udskrift af min forestillingerDevopsConf 2019-05-28.

Slides og videoer

Infrastruktur som bash-historie

Hvad jeg lærte af at teste 200 linjer med infrastrukturkode

Antag, at du kommer til et nyt projekt, og de siger til dig: "det har vi Infrastruktur som kode". I virkeligheden viser det sig Infrastruktur som bash-historie eller f.eks Dokumentation som bash-historie. Dette er en meget reel situation, for eksempel blev en lignende sag beskrevet af Denis Lysenko i en tale Sådan udskifter du hele infrastrukturen og begynder at sove roligt, fortalte han, hvordan de fik en sammenhængende infrastruktur til projektet fra bash-historien.

Med en vis lyst kan vi sige det Infrastruktur som bash-historie dette er som kode:

  1. reproducerbarhed: Du kan tage bash-historikken, køre kommandoerne derfra, og du kan forresten få en fungerende konfiguration som output.
  2. versionering: du ved, hvem der kom ind, og hvad de gjorde, igen, det er ikke et faktum, at dette vil føre dig til en fungerende konfiguration ved udgangen.
  3. historie: historien om, hvem der gjorde hvad. kun du ikke kan bruge det, hvis du mister serveren.

Hvad skal jeg gøre?

Infrastruktur som kode

Hvad jeg lærte af at teste 200 linjer med infrastrukturkode

Selv sådan en mærkelig sag som Infrastruktur som bash-historie du kan trække den i ørerne Infrastruktur som kode, men når vi vil gøre noget mere kompliceret end den gode gamle LAMP-server, kommer vi til den konklusion, at denne kode på en eller anden måde skal modificeres, ændres, forbedres. Dernæst vil vi gerne overveje parallellerne mellem Infrastruktur som kode og softwareudvikling.

TØR

Hvad jeg lærte af at teste 200 linjer med infrastrukturkode

På et lagersystemudviklingsprojekt var der en underopgave konfigurer SDS med jævne mellemrum: vi udgiver en ny udgivelse - den skal rulles ud til yderligere test. Opgaven er meget enkel:

  • log ind her via ssh og udfør kommandoen.
  • kopiere filen der.
  • ret konfigurationen her.
  • starte tjenesten der
  • ...
  • PROFIT!

For den beskrevne logik er bash mere end nok, især i de tidlige stadier af projektet, hvor det lige er startet. Det her det er ikke dårligt, at du bruger bash, men over tid er der anmodninger om at implementere noget lignende, men lidt anderledes. Det første, der kommer til at tænke på, er copy-paste. Og nu har vi allerede to meget ens scripts, der gør næsten det samme. Med tiden voksede antallet af scripts, og vi stod over for, at der er en vis forretningslogik for at implementere en installation, der skal synkroniseres mellem forskellige scripts, det er ret kompliceret.

Hvad jeg lærte af at teste 200 linjer med infrastrukturkode

Det viser sig, at der er sådan en praksis som DRY (Gentag ikke dig selv). Tanken er at genbruge eksisterende kode. Det lyder enkelt, men vi kom ikke til dette med det samme. I vores tilfælde var det en banal idé: at adskille konfigurationer fra scripts. De der. forretningslogik for, hvordan installationen implementeres separat, konfigureres separat.

SOLID til CFM

Hvad jeg lærte af at teste 200 linjer med infrastrukturkode

Med tiden voksede projektet og naturlig fortsættelse var fremkomsten af ​​Ansible. Hovedårsagen til dets udseende er, at der er ekspertise på holdet, og at bash ikke er designet til kompleks logik. Ansible begyndte også at indeholde kompleks logik. For at forhindre kompleks logik i at blive til kaos, er der principper for organisering af kode i softwareudvikling SOLID For eksempel rejste Grigory Petrov også i rapporten "Hvorfor har en it-specialist et personligt brand" spørgsmålet om, at en person er designet på en sådan måde, at det er lettere for ham at arbejde med nogle sociale enheder, i softwareudvikling disse er genstande. Hvis vi kombinerer disse to ideer og fortsætter med at udvikle dem, vil vi bemærke, at vi også kan bruge dem SOLID for at gøre det lettere at vedligeholde og ændre denne logik i fremtiden.

Det fælles ansvarsprincip

Hvad jeg lærte af at teste 200 linjer med infrastrukturkode

Hver klasse udfører kun én opgave.

Ingen grund til at blande kode og lave monolitiske guddommelige spaghettimonstre. Infrastrukturen skal bestå af simple mursten. Det viser sig, at hvis du deler Ansible-spillebogen op i små stykker, læser Ansible-roller, så er de nemmere at vedligeholde.

Det åbne lukkede princip

Hvad jeg lærte af at teste 200 linjer med infrastrukturkode

Åbent/lukket princip.

  • Åben for udvidelse: betyder, at en enheds adfærd kan udvides ved at oprette nye entitetstyper.
  • Lukket for ændring: Som et resultat af en udvidelse af en enheds adfærd, bør der ikke foretages ændringer i den kode, der bruger disse entiteter.

Til at begynde med implementerede vi testinfrastrukturen på virtuelle maskiner, men på grund af det faktum, at forretningslogikken i implementeringen var adskilt fra implementeringen, tilføjede vi udrulning til baremetall uden problemer.

Liskov Substitutionsprincippet

Hvad jeg lærte af at teste 200 linjer med infrastrukturkode

Barbara Liskovs substitutionsprincip. objekter i et program skal kunne udskiftes med forekomster af deres undertyper uden at ændre den korrekte udførelse af programmet

Hvis man ser mere bredt på det, er det ikke et træk ved et bestemt projekt, der kan anvendes der SOLID, det handler generelt om CFM, for eksempel på et andet projekt er det nødvendigt at implementere en boxed Java-applikation oven på diverse Java, applikationsservere, databaser, OS osv. Ved at bruge dette eksempel vil jeg overveje yderligere principper SOLID

I vores tilfælde er der en aftale i infrastrukturteamet om, at hvis vi har installeret imbjava- eller oraclejava-rollen, så har vi en java binær eksekverbar. Dette er nødvendigt pga Opstrømsroller afhænger af denne adfærd; de forventer java. Samtidig giver dette os mulighed for at erstatte en java-implementering/-version med en anden uden at ændre logikken for applikationsimplementering.

Problemet her ligger i, at det er umuligt at implementere dette i Ansible, som følge af, at der opstår nogle aftaler inden for teamet.

Interfacesegregationsprincippet

Hvad jeg lærte af at teste 200 linjer med infrastrukturkode

Interfaceadskillelsesprincip: "Mange klientspecifikke grænseflader er bedre end en generel grænseflade.

Til at begynde med forsøgte vi at lægge al variabiliteten af ​​applikationsimplementering i én Ansible playbook, men det var svært at understøtte, og tilgangen, når vi har en ekstern grænseflade specificeret (klienten forventer port 443), så kan en infrastruktur samles fra individuelle mursten til en specifik implementering.

Afhængighedsinversionsprincippet

Hvad jeg lærte af at teste 200 linjer med infrastrukturkode

Princippet om afhængighedsinversion. Moduler på højere niveauer bør ikke afhænge af moduler på lavere niveauer. Begge typer moduler skal afhænge af abstraktioner. Abstraktioner bør ikke afhænge af detaljer. Detaljer må afhænge af abstraktioner.

Her vil eksemplet være baseret på et antimønster.

  1. En af kunderne havde en privat sky.
  2. Vi bestilte virtuelle maskiner inde i skyen.
  3. Men på grund af skyens natur var applikationsimplementering bundet til, hvilken hypervisor VM'en var på.

De der. Applikationsimplementeringslogik på højt niveau flød med afhængigheder til lavere niveauer af hypervisoren, og det betød problemer ved genbrug af denne logik. Gør det ikke på denne måde.

Interaktion

Hvad jeg lærte af at teste 200 linjer med infrastrukturkode

Infrastruktur som kode handler ikke kun om kode, men også om forholdet mellem kode og mennesker, om interaktioner mellem infrastrukturudviklere.

Bus faktor

Hvad jeg lærte af at teste 200 linjer med infrastrukturkode

Lad os antage, at du har Vasya på dit projekt. Vasya ved alt om din infrastruktur, hvad vil der ske, hvis Vasya pludselig forsvinder? Det er en meget reel situation, for han kan blive ramt af en bus. Nogle gange sker det. Hvis dette sker, og viden om koden, dens struktur, hvordan den fungerer, udseende og adgangskoder ikke er fordelt på teamet, kan du støde på en række ubehagelige situationer. For at minimere disse risici og distribuere viden inden for teamet, kan du bruge forskellige tilgange

Par Devopsing

Hvad jeg lærte af at teste 200 linjer med infrastrukturkode

Det er ikke sådan som en joke, at administratorerne drak øl, ændrede adgangskoder og en analog af parprogrammering. De der. to ingeniører sætter sig ved én computer, ét tastatur og begynder at opsætte jeres infrastruktur sammen: opsætning af en server, skrivning af en Ansible-rolle osv. Det lyder godt, men det virkede ikke for os. Men særlige tilfælde af denne praksis virkede. En ny medarbejder kommer, hans mentor påtager sig en rigtig opgave sammen med ham, arbejder og overfører viden.

Et andet særligt tilfælde er et hændelsesopkald. Under et problem samles en gruppe af vagthavende og de involverede, en leder udpeges, som deler sin skærm og giver udtryk for tankerækken. Andre deltagere følger lederens tanker, spionerer på tricks fra konsollen, kontrollerer, at de ikke har misset en linje i loggen, og lærer nye ting om systemet. Denne tilgang virkede oftere end ikke.

Kode gennemgang

Hvad jeg lærte af at teste 200 linjer med infrastrukturkode

Subjektivt var det mere effektivt at formidle viden om infrastrukturen og hvordan den fungerer ved hjælp af kodegennemgang:

  • Infrastrukturen er beskrevet med kode i depotet.
  • Ændringer sker i en separat gren.
  • Under en fletningsanmodning kan du se deltaet af ændringer i infrastrukturen.

Højdepunktet her var, at anmelderne blev udvalgt én efter én, efter et skema, dvs. med en vis grad af sandsynlighed vil du klatre ind i et nyt stykke infrastruktur.

Kode stil

Hvad jeg lærte af at teste 200 linjer med infrastrukturkode

Med tiden begyndte skænderier at dukke op under anmeldelser, fordi... anmeldere havde deres egen stil, og rotationen af ​​anmeldere stablede dem med forskellige stilarter: 2 mellemrum eller 4, camelCase eller snake_case. Det var ikke muligt at implementere dette med det samme.

  • Den første idé var at anbefale at bruge linter, alle er jo ingeniører, alle er smarte. Men forskellige editorer, OS, er ikke praktiske
  • Dette udviklede sig til en bot, der skrev til slack for hver problematisk commit og vedhæftede linter-outputtet. Men i de fleste tilfælde var der vigtigere ting at gøre, og koden forblev ufikset.

Green Build Master

Hvad jeg lærte af at teste 200 linjer med infrastrukturkode

Tiden går, og vi er nået til den konklusion, at commits, der ikke består visse prøver, ikke kan slippes ind i masteren. Voila! Vi opfandt Green Build Master, som har været praktiseret i softwareudvikling i lang tid:

  • Udvikling er i gang i en særskilt afdeling.
  • Der kører test på denne tråd.
  • Hvis testene mislykkes, kommer koden ikke ind i masteren.

At træffe denne beslutning var meget smertefuldt, fordi... skabte en masse kontrovers, men det var det værd, fordi... Anmeldelser begyndte at modtage anmodninger om fusioner uden forskelle i stil, og med tiden begyndte antallet af problemområder at falde.

IaC test

Hvad jeg lærte af at teste 200 linjer med infrastrukturkode

Udover stiltjek kan du bruge andre ting, for eksempel til at kontrollere, at din infrastruktur rent faktisk kan implementeres. Eller tjek, at ændringer i infrastrukturen ikke vil føre til tab af penge. Hvorfor kan dette være nødvendigt? Spørgsmålet er komplekst og filosofisk, det er bedre at svare med en historie om, at der på en eller anden måde var en auto-scaler på Powershell, der ikke kontrollerede grænsebetingelserne => flere VM'er blev oprettet end nødvendigt => klienten brugte flere penge end planlagt. Dette er ikke særlig behageligt, men det ville være meget muligt at fange denne fejl på tidligere stadier.

Man kan spørge, hvorfor gøre kompleks infrastruktur endnu mere kompleks? Tests for infrastruktur, ligesom for kode, handler ikke om forenkling, men om at vide, hvordan din infrastruktur skal fungere.

IaC testpyramide

Hvad jeg lærte af at teste 200 linjer med infrastrukturkode

IaC-test: Statisk analyse

Hvis du implementerer hele infrastrukturen på én gang og tjekker, at den virker, kan du opleve, at det tager meget tid og kræver meget tid. Derfor skal grundlaget være noget, der virker hurtigt, det er der meget af, og det dækker over mange primitive steder.

Bash er vanskelig

Lad os se på et trivielt eksempel. vælg alle filer i den aktuelle mappe og kopier til en anden placering. Det første der kommer til at tænke på:

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

Hvad hvis der er et mellemrum i filnavnet? Nå, ok, vi er smarte, vi ved, hvordan man bruger citater:

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

Godt klaret? Ingen! Hvad hvis der ikke er noget i mappen, dvs. globbing virker ikke.

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

Godt gået nu? Nej... Glemt hvad der kan stå i filnavnet n.

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

Statiske analyseværktøjer

Problemet fra det forrige trin kunne fanges, da vi glemte citaterne, for dette er der mange midler i naturen Shellcheck, generelt er der mange af dem, og højst sandsynligt kan du finde en linter til din stack under din IDE.

Sprog
Værktøj

bash
Shellcheck

Rubin
RuboCop

python
pylint

ansible
Ansible Lint

IaC-test: Enhedstest

Hvad jeg lærte af at teste 200 linjer med infrastrukturkode

Som vi så fra det foregående eksempel, er linters ikke almægtige og kan ikke pege på alle problemområderne. Yderligere, analogt med test i softwareudvikling, kan vi huske enhedstests. Hvad der umiddelbart kommer til at tænke på er shunit, junit, rspec, spørgsmål. Men hvad skal man gøre med ansible, kok, saltstack og andre som dem?

Allerede i begyndelsen talte vi om SOLID og at vores infrastruktur skal bestå af små mursten. Deres tid er kommet.

  1. Infrastrukturen er opdelt i små klodser, for eksempel Ansible roller.
  2. En eller anden form for miljø er implementeret, det være sig docker eller en VM.
  3. Vi anvender vores Ansible-rolle i dette testmiljø.
  4. Vi tjekker at alt fungerede som vi forventede (vi kører test).
  5. Vi beslutter os for ok eller ikke ok.

IaC-test: Værktøjer til enhedstest

Spørgsmål, hvad er test for CFM? Du kan blot køre scriptet, eller du kan bruge færdige løsninger til dette:

CFM
Værktøj

Ansible
Testinfra

Kok
Inspec

Kok
Serverspec

saltstabel
Goss

Eksempel på testinfra, kontrol af, at brugere test1, test2 eksisterer og er i en gruppe 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

Hvad skal man vælge? Spørgsmålet er komplekst og tvetydigt, her er et eksempel på ændringer i projekter på github for 2018-2019:

Hvad jeg lærte af at teste 200 linjer med infrastrukturkode

IaC-testrammer

Spørgsmålet opstår: hvordan sætter man det hele sammen og starter det? Kan tag det og gør det selv hvis der er et tilstrækkeligt antal ingeniører. Eller du kan tage færdige løsninger, selvom der ikke er ret mange af dem:

CFM
Værktøj

Ansible
Molecule

Kok
Test køkken

terraform
Terratest

Eksempel på ændringer i projekter på github for 2018-2019:

Hvad jeg lærte af at teste 200 linjer med infrastrukturkode

Molekyle vs. Testkøkken

Hvad jeg lærte af at teste 200 linjer med infrastrukturkode

I første omgang vi prøvet at bruge testkitchen:

  1. Opret en VM parallelt.
  2. Anvend Ansible roller.
  3. Kør inspektion.

I 25-35 roller arbejdede det 40-70 minutter, hvilket var langt.

Hvad jeg lærte af at teste 200 linjer med infrastrukturkode

Næste trin var overgangen til jenkins/docker/ansible/molekyle. Idiologisk er alt det samme

  1. Lint spillebøger.
  2. Stil rollerne op.
  3. Start container
  4. Anvend Ansible roller.
  5. Kør testinfra.
  6. Tjek idempotens.

Hvad jeg lærte af at teste 200 linjer med infrastrukturkode

Linting for 40 roller og test for et dusin begyndte at tage omkring 15 minutter.

Hvad jeg lærte af at teste 200 linjer med infrastrukturkode

Hvad man skal vælge afhænger af mange faktorer, såsom den anvendte stak, ekspertise i teamet osv. her bestemmer alle selv, hvordan spørgsmålet om enhedstest skal lukkes

IaC-test: Integrationstest

Hvad jeg lærte af at teste 200 linjer med infrastrukturkode

Det næste trin i infrastrukturtestpyramiden vil være integrationstest. De ligner enhedstests:

  1. Infrastrukturen er opdelt i små klodser, for eksempel Ansible roller.
  2. En eller anden form for miljø er implementeret, det være sig docker eller en VM.
  3. For dette testmiljø gælder mange Ansible roller.
  4. Vi tjekker at alt fungerede som vi forventede (vi kører test).
  5. Vi beslutter os for ok eller ikke ok.

Groft sagt kontrollerer vi ikke ydelsen af ​​et enkelt element i systemet som i enhedstests, vi tjekker hvordan serveren er konfigureret som helhed.

IaC-test: ende til ende-test

Hvad jeg lærte af at teste 200 linjer med infrastrukturkode

I toppen af ​​pyramiden bliver vi mødt af End to End-tests. De der. Vi kontrollerer ikke ydeevnen af ​​en separat server, et separat script eller en separat klods af vores infrastruktur. Vi tjekker at mange servere er forbundet sammen, vores infrastruktur fungerer som vi forventer. Desværre har jeg aldrig set færdige kasseløsninger, sandsynligvis fordi... Infrastrukturen er ofte unik og svær at skabe en ramme for test. Som et resultat skaber alle deres egne løsninger. Der er en efterspørgsel, men der er intet svar. Derfor vil jeg fortælle dig, hvad der er for at skubbe andre til at lyde tanker eller gnide min næse ind i, at alt blev opfundet for længe siden før os.

Hvad jeg lærte af at teste 200 linjer med infrastrukturkode

Et projekt med en rig historie. Det bruges i store organisationer og sandsynligvis har I hver især indirekte krydset veje med det. Applikationen understøtter mange databaser, integrationer mv. At vide, hvordan infrastrukturen kan se ud, er en masse docker-compose-filer, og at vide, hvilke tests der skal køres i hvilket miljø Jenkins er.

Hvad jeg lærte af at teste 200 linjer med infrastrukturkode

Denne ordning fungerede i ret lang tid, indtil inden for rammerne forskning vi har ikke forsøgt at overføre dette til Openshift. Containerne forbliver de samme, men lanceringsmiljøet er ændret (hej DRY igen).

Hvad jeg lærte af at teste 200 linjer med infrastrukturkode

Forskningsideen gik videre, og i openshift fandt de sådan noget som APB (Ansible Playbook Bundle), som giver dig mulighed for at pakke viden om, hvordan du implementerer infrastruktur i en container. De der. der er en gentagelig, testbar viden om, hvordan man implementerer infrastrukturen.

Hvad jeg lærte af at teste 200 linjer med infrastrukturkode

Alt dette lød godt, indtil vi løb ind i en heterogen infrastruktur: vi havde brug for Windows til test. Som et resultat er viden om hvad, hvor, hvordan man implementerer og tester i jenkins.

Konklusion

Hvad jeg lærte af at teste 200 linjer med infrastrukturkode

Infrastruktur som kode er

  • Kode i depotet.
  • Menneskelig interaktion.
  • Infrastruktur test.

links

Kilde: www.habr.com

Tilføj en kommentar