
TillvÀgagÄngssÀtt IaC (Infrastructure as Code) bestÄr inte bara av koden som lagras i ett rep, utan ocksÄ av mÀnniskorna och processerna som omger den koden. Kan vi ÄteranvÀnda metoder frÄn mjukvaruutveckling i hantering och beskrivning av infrastruktur? Det Àr bra att hÄlla denna idé i Ätanke nÀr du lÀser artikeln.
Detta Àr en avkodning av min till .
Presentationer och videor
- Torrkörning 2019-04-24
Infrastruktur som bash-historik

Anta att du kommer till ett nytt projekt, och de sÀger till dig: «vi har Infrastructure as Code«. I verkligheten visar det sig att Infrastruktur som bash-historik eller till exempel Dokumentation som bash-historik. Detta Àr en helt realistisk situation, till exempel, en liknande historia beskrev Denis Lysenko i sin presentation , han berÀttade hur de fick en strukturerad infrastruktur frÄn bash-historik pÄ projektet.
Med lite vilja kan man sÀga att Infrastruktur som bash-historik det Àr som kod:
- Äterproducibility: du kan ta bash-historiken, utföra kommandona dÀrifrÄn, och kanske fÄr du en fungerande konfiguration som resultat.
- versionshantering: du vet vem som loggade in och vad de gjorde, men det Àr Äterigen inte sÀkert att detta leder till en fungerande konfiguration som resultat.
- with the VPN provider UFO, which had a publicly accessible Elasticsearch database of 894GB. The provider positioned itself as caring about user privacy and not keeping logs. Contrary to the claim, the exposed database contained logs, including information about IP addresses, session bindings to time, user location tags, information about the operating system and user device, and lists of domains for ad placement in unprotected HTTP traffic. Moreover, the database contained access passwords in plain text and session keys that allowed the decryption of intercepted sessions.: historik över vem som gjorde vad. men du kan inte anvÀnda den om du förlorar servern.
Vad ska vi göra?
Infrastructure as Code

Ăven ett sĂ„ konstigt fall som Infrastruktur som bash-historik kan dras med vĂ„ld till Infrastructure as Code, men nĂ€r vi vill göra nĂ„got mer komplicerat Ă€n en gammal god LAMP-server, kommer vi till den punkten att denna kod mĂ„ste modifieras pĂ„ nĂ„got sĂ€tt, förĂ€ndras, förbĂ€ttras. Vidare kommer vi att betrakta paralleller mellan Infrastructure as Code och mjukvaruutveckling.
D.R.Y.

PĂ„ ett projekt för utveckling av lagringssystem, fanns det en deluppgift : vi slĂ€pper en ny release â den mĂ„ste rullas ut för vidare testning. Uppgiften Ă€r överraskande enkel:
- gÄ in hÀr via ssh och kör kommandot.
- kopiera filen dit.
- justera 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 startat. Det Àr , men med tiden uppstÄr önskemÄl om att utveckla nÄgot liknande men med smÄ avvikelser. Det första som kommer att tÀnka pÄ: copy-paste. Och nu har vi redan tvÄ mycket lika skript som gör nÀstan samma sak. Med tiden har antalet skript ökat, och vi har stött pÄ att det finns en viss affÀrslogik för att distribuera installationen som mÄste synkroniseras mellan olika skript, vilket Àr ganska komplicerat.

Det visar sig att det finns en sÄdan praxis som D.R.Y. (Do not Repeat Yourself). Idén Àr att ÄteranvÀnda befintlig kod. Det lÄter enkelt, men vi kom inte fram till det omedelbart. I vÄrt fall var det en banal idé: att separera konfigurationerna frÄn skripten. Det vill sÀga affÀrslogiken för hur installationen distribueras Àr separat, konfigurationerna Àr separata.
S.O.L.I.D. för CFM

Med tiden vÀxte projektet och var framvÀxten av Ansible. HuvudskÀlet till dess tillkomst var expertisen i teamet och att bash inte Àr avsett för komplex logik. Ansible började ocksÄ innehÄlla komplex logik. För att förhindra att den komplexa logiken förvandlas till kaos, finns det principer för kodorganisation inom mjukvaruutveckling. S.O.L.I.D. Dessutom nÀmnde Grigory Petrov i sin presentation "Varför IT-specialister behöver ett personligt varumÀrke" att mÀnniskan Àr utformad sÄ att det Àr lÀttare för henne att hantera sociala enheter, och inom mjukvaruutveckling handlar det om objekt. Om man kombinerar dessa tvÄ idéer och fortsÀtter att utveckla dem, kan man lÀgga mÀrke till att beskrivningen av infrastrukturen ocksÄ kan anvÀnda S.O.L.I.D. sÄ att det i framtiden blir enklare att stödja och modifiera denna logik.
Single Responsibility Principle

Varje klass utför endast en uppgift.
Man ska inte blanda kod och skapa monolitiska, gudomliga makaronmonster. Infrastrukturen ska bestÄ av enkla byggstenar. Det visar sig att om man bryter ner Ansible playbook i smÄ bitar, lÀs Ansible roller, sÄ Àr de lÀttare att underhÄlla.
Open Closed Principle

Ăppen/StĂ€ngd princip.
- Ăppna för utvidgning: innebĂ€r att en vĂ€sendes beteende kan utvidgas genom att skapa nya typer av vĂ€sen.
- StÀngda för förÀndringar: som ett resultat av utvidgningen av ett vÀsendes beteende fÄr inga Àndringar göras i koden som anvÀnder dessa vÀsen.
Till en början rullade vi ut testinfrastruktur pÄ virtuella maskiner, men eftersom affÀrslogiken för utrullningen var separat frÄn implementationen, kunde vi enkelt lÀgga till distributionen pÄ baremetal.
Liskov Substitution Principle

Liskovsubstitutionsprincipen. Objekt i programmet ska kunna ersÀttas med instanser av deras underklasser utan att Àndra programmets korrekthet.
Om man ser bredare Àr det inte en specifik egenskap hos nÄgot sÀrskilt projekt, utan nÄgot som kan tillÀmpas. S.O.L.I.D., det handlar generellt om CFM, till exempel i ett annat projekt behövs det att rulla ut ett boxat Java-program ovanpÄ olika Java-servrar, applikationsservrar, databaser, operativsystem, etc. PÄ detta exempel kommer jag att betrakta vidare principer. S.O.L.I.D.
I vÄrt fall finns det en överenskommelse inom infrastrukturen att om vi installerar rollen imbjava eller oraclejava, sÄ har vi en binÀr körbar fil för java. Detta Àr nödvÀndigt eftersom de överordnade rollerna Àr beroende av detta beteende, de förvÀntar sig att java finns. Samtidigt gör det att vi kan byta ut en implementation/version av java mot en annan utan att Àndra logiken för applikationens distribution.
Problemet hÀr ligger i att det i Ansible inte gÄr att implementera sÄdant, vilket leder till att det uppstÄr vissa överenskommelser inom teamet.
Interface Segregation Principle

Principen för grÀnssnittssegregering "flera grÀnssnitt som Àr speciellt designade för kunder Àr bÀttre Àn ett allmÀnt grÀnssnitt."
Till en början försökte vi samla all variabilitet för applikationsdistribution i en enda Ansible-playbook, men det var svÄrt att underhÄlla, och med tillvÀgagÄngssÀttet dÀr vi har specificerat grÀnssnittet utÄt (klienten förvÀntar sig port 443) kan infrastrukturen för en specifik implementation byggas upp av separata byggstenar.
Dependency Inversion Principle

Principen för beroendeinversion. Moduler av högre nivÄer ska inte bero pÄ moduler av lÀgre nivÄer. BÄda typerna av moduler ska bero pÄ abstraktioner. Abstraktioner ska inte bero pÄ detaljer. Detaljer ska bero pÄ abstraktioner.
HÀr kommer exemplet att baseras pÄ ett antipattern.
- En av vÄra kunder hade en privat moln.
- Inuti molnet bestÀllde vi virtuella maskiner.
- Men pÄ grund av sÀrdragen hos molnet var distributionen av applikationen knuten till vilken hypervisor den virtuella maskinen hamnade pÄ.
D.v.s. den högnivÄlogik som anvÀnds för att distribuera applikationen och dess beroenden flöt ner till de underliggande nivÄerna av hypervisorn, vilket skapade problem med att ÄteranvÀnda denna logik. Det behövs inte.
Interaktion

Infrastruktur som kod handlar inte bara om kod, utan Àven om relationen mellan kod och mÀnniska, samt interaktionen mellan infrastrukturutvecklare.
Busfaktor

Anta att du har en person i ditt projekt som heter Vanya. Vanya vet allt om din infrastruktur, vad hÀnder om Vanya plötsligt försvinner? Det Àr en verklig situation, eftersom han kan bli överkörd av en buss. SÄdana saker hÀnder ibland. Om dessa kunskaper om koden, dess struktur, hur den fungerar, anvÀndarnamn och lösenord inte Àr fördelade inom teamet, kan det leda till en rad obehagliga situationer. För att minimera dessa risker och fördela kunskapen inom teamet kan olika metoder anvÀndas.
Par DevOps

Det Ă€r inte som , dĂ€r administratörer dricker öl, byter lösenord, och det Ă€r en analog av parprogrammering. D.v.s. tvĂ„ ingenjörer sĂ€tter sig vid en dator, en tangentbord och börjar tillsammans konfigurera din infrastruktur: stĂ€lla in servrar, skriva Ansible-roll, etc. Det lĂ„ter bra, men det fungerade inte för oss. Men privata fall av denna praktik har fungerat. En ny anstĂ€lld kom, hans mentor tar tillsammans med honom en verklig uppgift, arbetar â överför kunskapen.
Ett annat privatfall Àr incidentanropet. Under ett problem samlas en grupp jourpersonal och berörda parter, en ledare utses som delar sin skÀrm och redogör för sitt tÀnkande. Andra deltagare följer ledarens tankegÄngar, ser tricks frÄn konsolen, kontrollerar om en rad i loggen har missats, lÀr sig nya saker om systemet. Denna metod fungerade oftare Àn den inte gjorde.
Kodgranskning

Subjektivt sett var spridningen av kunskaper om infrastrukturen och hur den var uppbyggd mer effektiv genom kodgranskning:
- Infrastrukturen beskrivs i kod i ett repository.
- Ăndringar görs i en separat gren.
- Vid en merge-förfrÄgan kan man se skillnaden i infrastrukturen.
Det som var unikt hÀr var att granskare valdes pÄ tur, enligt schema, vilket innebÀr att med viss sannolikhet skulle du fÄ reda pÄ en ny del av infrastrukturen.
Kodstil

Med tiden började det uppstÄ konflikter under granskningar, eftersom granskare hade sina egna stilar och deras rotationer ledde dem till olika stilar: 2 mellanslag eller 4, camelCase eller snake_case. Att införa detta gick inte direkt.
- Den första idén var att rekommendera anvÀndning av en linter, eftersom ingenjörerna ÀndÄ Àr smarta. Men olika redigerare och operativsystem gjorde det besvÀrligt.
- Detta utvecklades till en bot som vid varje problematiskt commit skrev i Slack och bifogade linterutgÄngen. Men i de flesta fall fanns det viktigare uppgifter och koden förblev oÄtgÀrdad.
Green Build Master

Tiden gick, och vi kom fram till att vi inte kunde lÄta commits gÄ in i master som inte passerade vissa tester. Voilà ! vi inventerade Green Build Master som redan lÀnge har praktiserats inom programvaruutveckling:
- Utvecklingen sker i en separat gren.
- Tester körs pÄ denna gren.
- Om testerna misslyckas, kommer koden inte att hamna i master.
Att fatta detta beslut var ganska smÀrtsamt, eftersom det orsakade mÄnga diskussioner, men det var vÀrt det, eftersom förfrÄgningar om sammanslagning började komma utan stilkonflikter, och med tiden minskade antalet problematiska omrÄden.
IaC Testing

Förutom stilkontroll kan man anvÀnda andra metoder, till exempel verifiera att er infrastruktur verkligen kan distribueras. Eller kontrollera att förÀndringar i infrastrukturen inte leder till förluster. Varför kan detta vara nödvÀndigt? FrÄgan Àr komplex och filosofisk; det Àr bÀttre att svara med en historia om att det fanns en auto-scaler pÄ Powershell som inte kontrollerade grÀnsvillkoren => det skapades fler VM Àn nödvÀndigt => kunden spenderade mer pengar Àn planerat. Inte sÄ trevligt, men det skulle verkligen ha varit möjligt att fÄnga detta misstag i ett tidigare skede.
Man kan frÄga sig varför man ska göra en komplex infrastruktur Ànnu mer komplex? Tester för infrastruktur, precis som för kod, handlar inte om förenkling, utan om att veta hur er infrastruktur ska fungera.
IaC Testing Pyramid

IaC Testing: Static Analysis
Om man direkt distribuerar hela infrastrukturen och kontrollerar att den fungerar kan det visa sig ta mycket tid och krÀva en massa resurser. DÀrför bör det finnas nÄgot som fungerar snabbt, som Àr omfattande och tÀcker mÄnga primitiva omrÄden.
Bash Àr knepigt
LÄt oss titta pÄ ett enkelt exempel. VÀlj alla filer i den aktuella katalogen och kopiera dem till en annan plats. Det första som kommer att tÀnka pÄ:
for i in * ; do
cp $i /some/path/$i.bak
doneMen vad hÀnder om det finns ett mellanslag i filnamnet? Okej, vi Àr ju smarta, vi kan anvÀnda citattecken:
for i in * ; do cp "$i" "/some/path/$i.bak" ; doneBra jobbat? Nej! Vad hÀnder om det inte finns nÄgot i katalogen, dvs. globbing fungerar inte.
find . -type f -exec mv -v {} dst/{}.bak ;Ăr vi bra nu? Nej... Vi glömde att filnamnet kan innehĂ„lla n.
touch x
mv x "$(printf "foonbar")"
find . -type f -print0 | xargs -0 mv -t /path/to/target-dirStatisk analysverktyg
Problemet frÄn föregÄende steg kunde ha fÄngats nÀr vi glömde citattecken, för detta finns det mÄnga verktyg. , det finns mÄnga av dem, och ni kan sÀkert hitta en linter för er IDE och er stack.
SprÄk
Verktyg
bash
Ruby
python
ansible
IaC-testning: Enhetstester

Som vi sÄg i det föregÄende exemplet Àr inte linters allvetande och kan inte peka pÄ alla problem. Vidare kan vi tÀnka pÄ enhetstester, som vi ser i mjukvaruutveckling. , , , . Men vad ska vi göra med ansible, chef, saltstack och liknande?
I början pratade vi om S.O.L.I.D. och att vÄr infrastruktur bör bestÄ av smÄ block. Nu Àr det deras tid.
- Infrastrukturen bryts ner i smÄ block, till exempel Ansible-roller.
- Ett visst miljö sÀtts upp, oavsett om det Àr docker eller VM.
- Vi tillÀmpar vÄr Ansible-roll pÄ denna testmiljö.
- Vi kontrollerar att allt har fungerat som förvÀntat (kör tester).
- Vi bestÀmmer om det Àr okej eller inte.
IaC-testning: Verktyg för enhetstestning
FrÄgan Àr, vad Àr tester för CFM? Du kan enkelt köra ett skript, men det finns ocksÄ fÀrdiga lösningar för det:
CFM
Verktyg
Ansible
Chef
Chef
saltstack
Exempel för testinfra, vi kontrollerar att anvÀndarna test1, test2 finns och tillhör gruppen sshusers:
def test_default_users(host):
users = ['test1', 'test2']
for login in users:
assert host.user(login).exists
assert 'sshusers' in host.user(login).groupsVad ska man vÀlja? En svÄr och otydlig frÄga, hÀr Àr ett exempel pÄ förÀndringar i projekt pÄ github under 2018-2019:

IaC-testningsramverk
FrÄgan Àr hur man samlar allt detta och kör det? Man kan med tillrÀckligt mÄnga ingenjörer. Men man kan ocksÄ anvÀnda fÀrdiga lösningar, som inte Àr sÄ mÄnga:
CFM
Verktyg
Ansible
Chef
Terraform
Exempel pÄ förÀndringar i projekt pÄ github under 2018-2019:

Molecule vs. Testkitchen

Vi försökte först anvÀnda testkitchen :
- ĐĄĐŸĐ·ĐŽĐ°ŃŃ ĐĐ ĐČ ĐżĐ°ŃаллДлŃ.
- TillÀmpa Ansible-roller.
- Kör inspec.
För 25-35 roller tog det 40-70 minuter, vilket var lÀnge.

NÀsta steg blev att gÄ över till Jenkins / Docker / Ansible / Molecule. Ideologiskt Àr allt detsamma.
- Linta playbooks.
- Linta roller.
- Starta behÄllare.
- TillÀmpa Ansible-roller.
- Kör testinfra.
- Kontrollera idempotens.

Lintning för 40 roller och tester för ett dussin tog omkring 15 minuter.

Vad man vÀljer beror pÄ mÄnga faktorer, som den anvÀnda teknologin, expertisen i teamet osv. HÀr bestÀmmer var och en sjÀlv hur man löser frÄgan om enhetstestning.
IaC-testning: Integrationstester.

PÄ nÀsta steg i pyramidens testning av infrastrukturen dyker integrations tester upp. De liknar enhetstester:
- Infrastrukturen delas upp i smÄ bitar, till exempel Ansible-roller.
- Ett visst miljö sÀtts upp, oavsett om det Àr docker eller VM.
- Detta testmiljö tillÀmpas. mÄnga Ansible-roller.
- Vi kontrollerar att allt har fungerat som vi förvÀntar oss (kör tester).
- Vi bestÀmmer om det Àr okej eller inte.
Grovt sett, vi kontrollerar inte funktionaliteten hos enskilda systemelement som i enhetstester, vi kontrollerar hur servern Àr konfigurerad i sin helhet.
IaC-testning: End to End-tester.

PÄ toppen av pyramiden möter vi End to End-tester. Det vill sÀga, vi kontrollerar inte funktionaliteten för enskilda servrar, enskilda skript, eller enskilda delar av vÄr infrastruktur. Vi kontrollerar att en mÀngd servrar, sammanslagna till en helhet, fungerar som vi förvÀntar oss. TyvÀrr har jag inte sett nÄgra fÀrdiga lösningar, antagligen eftersom infrastruktur ofta Àr unik och det Àr svÄrt att standardisera och skapa ett ramverk för testning av den. Som ett resultat skapar alla sina egna lösningar. Det finns en efterfrÄgan, men inget svar. SÄ jag kommer att berÀtta vad som finns, för att inspirera andra till kloka tankar eller pÄminna mig om att allt redan Àr uppfunnet.

Projekt med en rik historia. AnvÀnds i stora organisationer och förmodligen har var och en av er indirekt varit i kontakt med det. Applikationen stöder mÄnga databaser, integrationer osv. Kunskapen om hur infrastrukturen kan se ut Àr mÄnga docker-compose-filer, och kunskapen om vilka tester som ska köras i vilken miljö Àr Jenkins.

Denna schemat fungerade lĂ€nge, tills vi försökte flytta det till Openshift. BehĂ„llarna förblev desamma, men körningsmiljön Ă€ndrades (hej D.R.Y. igen). ĐŒŃ ĐœĐ” ĐżĐŸĐżŃĐŸĐ±ĐŸĐČалО ŃŃĐŸ пДŃĐ”ĐœĐ”ŃŃĐž ĐČ Openshift. ĐĐŸĐœŃĐ”ĐčĐœĐ”ŃŃ ĐŸŃŃалОŃŃ ŃДжД, а ĐČĐŸŃ ŃŃДЎа запŃŃĐșа ŃĐŒĐ”ĐœĐžĐ»Đ°ŃŃ (ĐżŃĐžĐČĐ”Ń D.R.Y. ĐŸĐżŃŃŃ).

Forskningsidén gick lÀngre, och i OpenShift hittades nÄgot som kallas APB (Ansible Playbook Bundle), vilket möjliggör att packa in kunskapen om hur man distribuerar infrastrukturen i en container. Det vill sÀga, det finns en reproducerbar, testbar kunskapspunkt om hur man distribuerar infrastrukturen.

Allt detta lÀt bra, tills vi stötte pÄ en heterogen infrastruktur: vi behövde Windows för tester. Slutligen sitter kunskapen om vad, var, hur man distribuerar och testar i Jenkins.
Slutsats

Infrastruktur som kod Àr
- Kod i ett repository.
- Interaktion mellan mÀnniskor.
- Testning av infrastrukturen.
lÀnkar
- Torrkörning 2019-04-24
- &
KĂ€lla: habr.com
