Från och med den andra commit, blir vilken kod som helst legacy, eftersom initiala idéer börjar avvika från den hårda verkligheten. Det här är varken bra eller dåligt, det är en given given som är svår att argumentera med och måste levas med. En del av denna process är refaktorering. Refaktorering av infrastruktur som kod. Låt historien börja om hur man refaktorerar Ansible om ett år och inte blir galen.
Arvets födelse
Dag #1: Patient Zero
Det var en gång i tiden ett villkorligt projekt. Den hade ett utvecklingsteam och Ops-ingenjörer. De löste samma problem: hur man distribuerar servrar och kör en applikation. Problemet var att varje lag löste detta problem på sitt eget sätt. Vid projektet beslutades det att använda Ansible för att synkronisera kunskap mellan Dev- och Ops-teamen.
Dag #89: Arvets födelse
Utan att själva märka det ville de göra det så bra som möjligt, men det visade sig vara arv. Hur går det till?
Vi har en brådskande uppgift här, låt oss göra ett smutsigt hack och sedan fixa det.
Du behöver inte skriva dokumentation och allt är klart vad som händer här.
Jag vet Ansible/Python/Bash/Terraform! Titta hur jag kan smita!
Jag är en Full Stack Overflow-utvecklare och kopierade detta från stackoverflow, jag vet inte hur det fungerar, men det ser coolt ut och löser problemet.
Som ett resultat kan du få en obegriplig typ av kod som det inte finns någon dokumentation för, det är inte klart vad den gör, om den behövs, men problemet är att du behöver utveckla den, modifiera den, lägga till kryckor och stöd. vilket gör situationen ännu värre.
Den initialt uttänkta och implementerade IaC-modellen uppfyller inte längre kraven från användare / företag / andra team, och tiden för att göra ändringar i infrastrukturen slutar att vara acceptabel. I detta ögonblick kommer förståelsen att det är dags att vidta åtgärder.
IaC-refaktorering
Dag #139: Behöver du verkligen refaktorering?
Innan du rusar till refactor måste du svara på ett antal viktiga frågor:
Varför behöver du allt detta?
Har du tid?
Räcker kunskap?
Om du inte vet hur du ska svara på frågorna, så kommer refaktoreringen att sluta innan den ens har börjat, eller så kan det bara bli värre. Därför att hade erfarenhet ( Vad jag lärde mig av att testa 200 000 rader av infrastrukturkod), sedan fick projektet en förfrågan om hjälp att fixa rollerna och täcka dem med tester.
Dag #149: Förberedelse av omstruktureringen
Det första är att förbereda. Bestäm vad vi ska göra. För att göra detta kommunicerar vi, hittar problemområden och tar reda på sätt att lösa dem. Vi registrerar de resulterande begreppen på något sätt, till exempel en artikel i sammanflöde, så att när frågan uppstår "vad är bäst?" eller "vilket är korrekt?" Vi har inte gått vilse. I vårt fall höll vi fast vid idén söndra och härska: vi bryter upp infrastrukturen i små bitar/tegelstenar. Detta tillvägagångssätt låter dig ta en isolerad del av infrastrukturen, förstå vad den gör, täcka den med tester och ändra den utan rädsla för att gå sönder något.
Det visar sig att infrastrukturtestning blir hörnstenen och här är det värt att nämna infrastrukturtestpyramiden. Exakt samma idé som är under utveckling, men för infrastruktur: vi går från billiga snabba tester som kontrollerar enkla saker, som indrag, till dyra fullfjädrade tester som distribuerar hela infrastrukturen.
Ansible testförsök
Innan vi går för att beskriva hur vi täckte Ansible-tester på projektet kommer jag att beskriva de försök och tillvägagångssätt som jag hade möjlighet att använda tidigare för att förstå sammanhanget för de beslut som fattades.
Dag nr -997: Säkerhetsdatablad
Första gången jag testade Ansible var på ett projekt för att utveckla SDS (Software Defined Storage). Det finns en separat artikel om detta ämne Hur man bryter cyklar över kryckor när man testar sin distribution, men kort sagt, vi slutade med en inverterad testpyramid och testning spenderade vi 60-90 minuter på en roll, vilket är lång tid. Grunden var e2e-tester, d.v.s. vi distribuerade en fullfjädrad installation och testade den sedan. Vad som var ännu mer försvårande var uppfinningen av hans egen cykel. Men jag måste erkänna att den här lösningen fungerade och möjliggjorde en stabil release.
Dag # -701: Ansible och provkök
Utvecklingen av Ansible-testidén var användningen av färdiga verktyg, nämligen testkök/kök-ci och inspec. Valet bestämdes av kunskap om Ruby (för mer information, se artikeln om Habré: Drömmer YML-programmerare om att testa Ansible?) arbetade snabbare, cirka 40 minuter för 10 roller. Vi skapade ett paket med virtuella maskiner och körde tester inuti.
I allmänhet fungerade lösningen, men det fanns en del sediment på grund av heterogenitet. När antalet personer som testades ökades till 13 basroller och 2 metaroller som kombinerade mindre roller, så började plötsligt testerna pågå i 70 minuter, vilket är nästan 2 gånger längre. Det var svårt att prata om XP (extrem programmering) praxis eftersom... ingen vill vänta 70 minuter. Detta var anledningen till att ändra inställningen
Dag # -601: Ansible och molekyl
Konceptuellt liknar detta testkitchen, bara vi flyttade rolltestning till docker och ändrade stacken. Som ett resultat minskade tiden till stabila 20-25 minuter för 7 roller.
Genom att öka antalet testade roller till 17 och lindra 45 roller körde vi detta på 28 minuter på 2 jenkins-slavar.
Dag #167: Lägga till Ansible-tester till projektet
Troligtvis kommer det inte att vara möjligt att göra omstruktureringsuppgiften i all hast. Uppgiften ska vara mätbar så att du kan bryta den i små bitar och äta elefanten bit för bit med en tesked. Det måste finnas en förståelse för om du rör dig i rätt riktning, hur lång tid det ska gå.
Generellt sett spelar det ingen roll hur det kommer att göras, du kan skriva på ett papper, du kan sätta klistermärken på garderoben, du kan skapa uppgifter i Jira, eller så kan du öppna Google Docs och skriva ner aktuell status där. Benen växer av att processen inte är omedelbar, den blir lång och tråkig. Det är osannolikt att någon vill att du ska brinna ut på idéer, tröttna och bli överväldigad under omstruktureringen.
Refaktoreringen är enkel:
Äta.
Sova.
Koda.
IaC-test.
Upprepa
och vi upprepar detta tills vi når det avsedda målet.
Det kanske inte går att börja testa allt direkt, så vår första uppgift var att börja med linting och kolla syntaxen.
Dag #181: Green Build Master
Linting är ett litet första steg mot Green Build Master. Detta kommer inte att bryta nästan vad som helst, men det kommer att tillåta dig att felsöka processer och göra gröna builds i Jenkins. Tanken är att utveckla vanor bland teamet:
Röda tester är dåliga.
Jag kom för att fixa något och samtidigt göra koden lite bättre än den var innan dig.
Dag #193: Från ludd till enhetstester
Efter att ha byggt in processen för att få in koden i mastern kan du börja processen med steg-för-steg förbättring - ersätt linting med lanseringsroller, du kan till och med göra det utan idempotens. Du måste förstå hur man tillämpar roller och hur de fungerar.
Dag #211: Från enhet till integrationstester
När de flesta roller är täckta med enhetstester och allt är ludd kan du gå vidare till att lägga till integrationstester. De där. testar inte en enda sten i infrastrukturen, utan en kombination av dem, till exempel en fullständig instanskonfiguration.
Med hjälp av jenkins genererade vi många stadier som raderade roller/spelböcker parallellt, sedan enhetstester i behållare och slutligen integrationstester.
Jenkins + Docker + Ansible = Tester
Kassa repo och generera byggstadier.
Kör lint playbook stadier parallellt.
Kör lintrollsteg parallellt.
Kör syntaxkontrollrollsteg parallellt.
Kör testrollssteg parallellt.
Lint roll.
Kontrollera beroendet av andra roller.
Kontrollera syntaxen.
Skapa docker-instans
Kör molecule/default/playbook.yml.
Kontrollera idempotens.
Kör integrationstester
Finish
Dag #271: Bussfaktor
Till en början utfördes omfaktorisering av en liten grupp på två eller tre personer. De granskade koden i mastern. Med tiden utvecklade teamet kunskap om hur man skriver kod och kodgranskning bidrog till kunskapsspridningen om infrastrukturen och hur den fungerar. 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.
Och det ska vara bekvämt här. Det är bekvämt att göra en genomgång, se inom ramen för vilken uppgift det gjordes och diskussionernas historia. Vi har integrerat jenkins + bitbucket + jira.
Men som sådan är en recension inte ett universalmedel; på något sätt kom vi in i masterkoden, vilket fick oss att flopptesta:
Med tiden blev det fler tester, byggen gick långsammare, upp till en timme i värsta fall. På en av retroerna fanns en fras som "det är bra att det finns tester, men de är långsamma." Som ett resultat övergav vi integrationstester på virtuella maskiner och anpassade dem för Docker för att göra det snabbare. Vi ersatte även testinfra med en möjlig verifierare för att minska antalet verktyg som används.
Strängt taget fanns det en uppsättning åtgärder:
Byt till docker.
Ta bort rolltestning, som dupliceras på grund av beroenden.
Öka antalet slavar.
Provkörningsordning.
Förmåga att luda ALLT lokalt med ett kommando.
Som ett resultat förenades också Pipeline på jenkins
Skapa byggstadier.
Ludd allt parallellt.
Kör testrollssteg parallellt.
Finish.
Lärdomar
Undvik globala variabler
Ansible använder globala variabler, det finns en delvis lösning i formuläret privat_roll_vars, men detta är inget universalmedel.
Låt mig ge dig ett exempel. Låt oss ha role_a и role_b
Det roliga är att resultatet av playbooks kommer att bero på saker som inte alltid är uppenbara, till exempel i vilken ordning rollerna listas. Tyvärr är detta Ansibles natur och det bästa som kan göras är att använda någon form av överenskommelse, till exempel inom en roll, använd endast variabeln som beskrivs i denna roll.
BRA: I roller för variabler, använd variabler med prefixet rollnamnet; detta, genom att titta på inventering, kommer att göra det lättare att förstå vad som händer.
Vi gick med på att använda variabla prefix; det skulle inte vara överflödigt att kontrollera att de är definierade som vi förväntar oss och till exempel inte åsidosattes av ett tomt värde
BRA: Kontrollera variabler.
- name: "Verify that required string variables are defined"
assert:
that: ahs_var is defined and ahs_var | length > 0 and ahs_var != None
fail_msg: "{{ ahs_var }} needs to be set for the role to work "
success_msg: "Required variables {{ ahs_var }} is defined"
loop_control:
loop_var: ahs_var
with_items:
- ahs_item1
- ahs_item2
- ahs_item3
Undvik hash-ordböcker, använd platt struktur
Om en roll förväntar sig en hash/ordbok i en av dess parametrar, om vi vill ändra en av de underordnade parametrarna, måste vi åsidosätta hela hash/ordboken, vilket kommer att öka konfigurationskomplexiteten.
Roller och spelböcker måste vara idempotenta, eftersom minskar konfigurationsdrift och rädsla för att gå sönder något. Men om du använder molekyler är detta standardbeteendet.
Undvik att använda kommandoskalsmoduler
Att använda en skalmodul resulterar i ett imperativt beskrivningsparadigm, istället för det deklarativa, som är kärnan i Ansible.
Testa dina roller via molekyl
Molekyl är en mycket flexibel sak, låt oss titta på några scenarier.
Molekyl Flera instanser
В molecule.yml i avsnitt platforms du kan beskriva många värdar som du kan distribuera.
I molekyl är det möjligt att använda ansible för att kontrollera att instansen har konfigurerats korrekt, dessutom har detta varit standard sedan release 3. Det är inte lika flexibelt som testinfra/inspec, men vi kan kontrollera att innehållet i filen matchar våra förväntningar:
Eller distribuera tjänsten, vänta tills den blir tillgänglig och gör ett röktest:
---
- name: Verify
hosts: solr
tasks:
- command: /blah/solr/bin/solr start -s /solr_home -p 8983 -force
- uri:
url: http://127.0.0.1:8983/solr
method: GET
status_code: 200
register: uri_result
until: uri_result is not failed
retries: 12
delay: 10
- name: Post documents to solr
command: /blah/solr/bin/post -c master /exampledocs/books.csv
Sätt in komplex logik i moduler och plugins
Ansible förespråkar ett deklarativt tillvägagångssätt, så när du gör kodförgrening, datatransformation, skalmoduler blir koden svår att läsa. För att bekämpa detta och hålla det enkelt att förstå, skulle det inte vara överflödigt att bekämpa denna komplexitet genom att skapa dina egna moduler.
Sammanfatta tips och tricks
Undvik globala variabler.
Prefix rollvariabler.
Använd loopkontrollvariabel.
Kontrollera indatavariabler.
Undvik hash-ordböcker, använd platt struktur.
Skapa idempotenta spelböcker och roller.
Undvik att använda kommandoskalsmoduler.
Testa dina roller via molekyl.
Sätt in komplex logik i moduler och plugins.
Slutsats
Du kan inte bara gå och omstrukturera infrastrukturen i ett projekt, även om du har IaC. Detta är en lång process som kräver tålamod, tid och kunskap.
UPD1 2020.05.01 20:30 — För primär profilering av spelböcker kan du använda callback_whitelist = profile_tasks att förstå vad som fungerar under lång tid. Sedan går vi igenom Ansible accelerationsklassiker. Du kan också prova mitogen UPD2 2020.05.03 16:34 - Svensk version