Fra den anden commit bliver enhver kode legacy, fordi oprindelige ideer begynder at afvige fra den barske virkelighed. Dette er hverken godt eller dårligt, det er en given given, som er svær at argumentere med og skal leves med. En del af denne proces er refaktorering. Refaktorering af infrastruktur som kode. Lad historien begynde om, hvordan man refaktorerer Ansible om et år og ikke bliver skør.
Arvens fødsel
Dag #1: Patient Zero
Der var engang et betinget projekt. Det havde et udviklingsteam og Ops-ingeniører. De løste det samme problem: hvordan man installerer servere og kører en applikation. Problemet var, at hvert hold løste dette problem på sin egen måde. På projektet blev det besluttet at bruge Ansible til at synkronisere viden mellem Dev- og Ops-teamet.
Dag #89: Arvens fødsel
Uden selv at bemærke det, ville de gøre det bedst muligt, men det viste sig at være arv. Hvordan sker dette?
Vi har en presserende opgave her, lad os lave et beskidt hack og så ordne det.
Du behøver ikke at skrive dokumentation, og alt er klart, hvad der foregår her.
Jeg kender Ansible/Python/Bash/Terraform! Se hvordan jeg kan undvige!
Jeg er en Full Stack Overflow-udvikler og kopierede dette fra stackoverflow, jeg ved ikke hvordan det virker, men det ser cool ud og løser problemet.
Som et resultat kan du få en uforståelig type kode, som der ikke er dokumentation for, det er ikke klart, hvad det gør, om det er nødvendigt, men problemet er, at du skal udvikle det, ændre det, tilføje krykker og understøtter , hvilket gør situationen endnu værre.
Den oprindeligt udtænkte og implementerede IaC-model opfylder ikke længere kravene fra brugere/virksomheder/andre teams, og tiden til at foretage ændringer i infrastrukturen holder op med at være acceptabel. I dette øjeblik kommer forståelsen af, at det er tid til at handle.
IaC refactoring
Dag #139: Har du virkelig brug for refactoring?
Прежде чем кидаться рефакторить вы должны ответить на ряд важных вопросов:
Hvorfor har du brug for alt dette?
Har du tid?
Er viden nok?
Hvis du ikke ved, hvordan du skal besvare spørgsmålene, slutter refaktoreringen, før den overhovedet begynder, ellers bliver den måske kun værre. Fordi havde erfaring ( Hvad jeg lærte af at teste 200 linjer med infrastrukturkode), så modtog projektet en anmodning om hjælp til at fikse rollerne og dække dem med test.
Dag #149: Forberedelse af refactoring
Den første ting er at forberede. Beslut hvad vi vil gøre. For at gøre dette kommunikerer vi, finder problemområder og finder ud af måder at løse dem på. Vi registrerer de resulterende begreber på en eller anden måde, for eksempel en artikel i sammenløb, så når spørgsmålet opstår "hvad er bedst?" eller "hvilket er korrekt?" Vi er ikke gået vild. I vores tilfælde holdt vi fast i ideen del og hersk: vi deler infrastrukturen op i små stykker/klodser. Denne tilgang giver dig mulighed for at tage et isoleret stykke infrastruktur, forstå, hvad det gør, dække det med test og ændre det uden frygt for at bryde noget.
Det viser sig, at infrastrukturtest bliver hjørnestenen, og her er det værd at nævne infrastrukturtestpyramiden. Præcis den samme idé, som er under udvikling, men for infrastruktur: Vi bevæger os fra billige hurtige test, der tjekker simple ting, såsom indrykning, til dyre fuldgyldige test, der implementerer hele infrastrukturen.
Ansible testforsøg
Før vi går i gang med at beskrive, hvordan vi dækkede Ansible-tests på projektet, vil jeg beskrive de forsøg og tilgange, som jeg havde mulighed for at bruge tidligere for at forstå sammenhængen i de beslutninger, der blev truffet.
Dag nr. -997: SDS-bestemmelse
Første gang jeg testede Ansible var på et projekt om at udvikle SDS (Software Defined Storage). Der er en separat artikel om dette emne Sådan knækker du cykler over krykker, når du tester din distribution, men kort fortalt endte vi med en omvendt testpyramide og testning brugte vi 60-90 minutter på én rolle, hvilket er lang tid. Grundlaget var e2e tests, dvs. vi implementerede en fuldgyldig installation og testede den derefter. Hvad der var endnu mere skærpende var opfindelsen af hans egen cykel. Men jeg må indrømme, at denne løsning fungerede og muliggjorde en stabil udgivelse.
Dag # -701: Ansible og testkøkken
Udviklingen af Ansible-testideen var brugen af færdige værktøjer, nemlig testkøkken/køkken-ci og inspec. Valget blev bestemt af viden om Ruby (for flere detaljer, se artiklen om Habré: Мечтают ли YML программисты о тестировании ansible?) arbejdede hurtigere, omkring 40 minutter for 10 roller. Vi lavede en pakke virtuelle maskiner og kørte test indeni.
Generelt virkede løsningen, men der var noget sediment på grund af heterogenitet. Da antallet af testede personer blev øget til 13 basisroller og 2 metaroller, der kombinerede mindre roller, så begyndte testene pludselig at køre i 70 minutter, hvilket er næsten 2 gange længere. Det var svært at tale om XP (ekstrem programmering) praksis, fordi... ingen ønsker at vente 70 minutter. Dette var grunden til at ændre tilgangen
Dag # -601: Ansible og molekyle
Konceptuelt ligner dette testkitchen, kun vi flyttede rolletest til docker og ændrede stakken. Som et resultat blev tiden reduceret til stabile 20-25 minutter for 7 roller.
Ved at øge antallet af testede roller til 17 og lining af 45 roller kørte vi dette på 28 minutter på 2 jenkins-slaver.
Dag #167: Tilføjelse af Ansible-tests til projektet
Mest sandsynligt vil det ikke være muligt at udføre refaktoriseringsopgaven i en fart. Opgaven skal være målbar, så du kan brække den i små stykker og spise elefanten stykke for stykke med en teske. Der skal være en forståelse for, om du bevæger dig i den rigtige retning, hvor lang tid endnu.
Generelt er det lige meget, hvordan det bliver gjort, du kan skrive på et stykke papir, du kan sætte klistermærker på skabet, du kan oprette opgaver i Jira, eller du kan åbne Google Docs og skrive den aktuelle status ned. der. Benene vokser af, at processen ikke er øjeblikkelig, den bliver lang og trættende. Det er usandsynligt, at nogen ønsker, at du brænder ud af ideer, bliver træt og bliver overvældet under refactoring.
Refaktoreringen er enkel:
Spise.
Sleep.
Kode.
IaC test.
Gentag
og vi gentager dette, indtil vi når det tilsigtede mål.
Det er måske ikke muligt at begynde at teste alt med det samme, så vores første opgave var at starte med linting og tjekke syntaksen.
Dag #181: Green Build Master
Linting er et lille første skridt mod Green Build Master. Dette vil ikke bryde næsten noget, men det vil give dig mulighed for at fejlsøge processer og lave grønne builds i Jenkins. Idéen er at udvikle vaner blandt teamet:
Røde tests er dårlige.
Jeg kom for at ordne noget og samtidig gøre koden lidt bedre, end den var før dig.
Dag #193: Fra fnug til enhedstest
Efter at have bygget processen med at få koden ind i masteren, kan du begynde processen med trin-for-trin forbedring - udskiftning af linting med lanceringsroller, du kan endda gøre det uden idempotens. Du skal forstå, hvordan du anvender roller, og hvordan de fungerer.
Dag #211: Fra enhed til integrationstest
Når de fleste roller er dækket af enhedstest, og alt er fnug, kan du gå videre til at tilføje integrationstest. De der. tester ikke en enkelt klods i infrastrukturen, men en kombination af dem, for eksempel en fuld instanskonfiguration.
Ved at bruge jenkins genererede vi mange stadier, der foret roller/playbooks parallelt, derefter enhedstests i containere og til sidst integrationstests.
Jenkins + Docker + Ansible = Tests
Check ud repo og generer byggefaser.
Kør fnug-playbook-stadier parallelt.
Kør fnugrolletrin parallelt.
Kør syntakskontrolrolletrin parallelt.
Kør testrollefaser parallelt.
Lint rolle.
Tjek afhængighed af andre roller.
Tjek syntaks.
Opret docker-instans
Kør molecule/default/playbook.yml.
Tjek idempotens.
Kør integrationstest
Finish
Dag #271: Busfaktor
Til at begynde med blev refactoring udført af en lille gruppe på to eller tre personer. De gennemgik koden i masteren. Med tiden udviklede teamet viden om, hvordan man skriver kode, og kodegennemgang bidrog til formidlingen af viden om infrastrukturen og hvordan den fungerer. 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.
Og det skal være behageligt her. Det er praktisk at lave en gennemgang, se inden for rammerne af, hvilken opgave det blev udført, og historien om diskussioner. Vi har integreret jenkins + bitbucket + jira.
Men som sådan er en anmeldelse ikke et vidundermiddel; på en eller anden måde kom vi ind i masterkoden, som fik os til at floptests:
Med tiden var der flere tests, builds kørte langsommere, op til en time i værste fald. På en af retroerne var der en sætning som "det er godt, at der er tests, men de er langsomme." Som følge heraf opgav vi integrationstest på virtuelle maskiner og tilpassede dem til Docker for at gøre det hurtigere. Vi erstattede også testinfra med en mulig verifikator for at reducere antallet af brugte værktøjer.
Strengt taget var der en række foranstaltninger:
Skift til docker.
Fjern rolletest, som duplikeres på grund af afhængigheder.
Øg antallet af slaver.
Prøvekørselsrækkefølge.
Evne til at fnug ALLE lokalt med én kommando.
Som et resultat blev Pipeline på jenkins også samlet
Generer byggefaser.
Fnug alt sammen parallelt.
Kør testrollefaser parallelt.
Afslut.
Erfaringer
Undgå globale variabler
Ansible bruger globale variabler, der er en delvis løsning i formularen private_rolle_vars, men dette er ikke et vidundermiddel.
Lad mig give dig et eksempel. Lad os have role_a и role_b
Det sjove er, at resultatet af playbooks vil afhænge af ting, der ikke altid er indlysende, såsom den rækkefølge, rollerne er opført i. Desværre er dette Ansibles natur, og det bedste, der kan gøres, er at bruge en form for aftale, for eksempel inden for en rolle, brug kun den variabel, der er beskrevet i denne rolle.
Vi blev enige om at bruge variable præfikser; det ville ikke være overflødigt at kontrollere, at de er defineret, som vi forventer, og for eksempel ikke blev tilsidesat af en tom værdi
GOD: Tjek 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
Undgå hash-ordbøger, brug flad struktur
Hvis en rolle forventer en hash/ordbog i en af dens parametre, så hvis vi vil ændre en af de underordnede parametre, bliver vi nødt til at tilsidesætte hele hash/ordbogen, hvilket vil øge konfigurationskompleksiteten.
Roller og spillebøger skal være idempotente, fordi reducerer konfigurationsdrift og frygt for at bryde noget. Men hvis du bruger molekyle, så er dette standardadfærden.
Undgå at bruge kommandoskalmoduler
Brug af et shell-modul resulterer i et imperativt beskrivelsesparadigme i stedet for det deklarative, som er kernen i Ansible.
Test dine roller via molekyle
Molekyle er en meget fleksibel ting, lad os se på et par scenarier.
Molekyle Flere tilfælde
В molecule.yml i afsnit platforms du kan beskrive mange værter, som du kan implementere.
I molekyle er det muligt at bruge ansible til at kontrollere, at instansen er konfigureret korrekt, desuden har dette været standard siden release 3. Det er ikke så fleksibelt som testinfra/inspec, men vi kan kontrollere, at indholdet af filen matcher vores forventninger:
Eller implementer tjenesten, vent på, at den bliver tilgængelig, og lav en røgtest:
---
- 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æt kompleks logik i moduler og plugins
Ansible går ind for en deklarativ tilgang, så når du laver kodeforgrening, datatransformation, shell-moduler, bliver koden svær at læse. For at bekæmpe dette og holde det nemt at forstå, ville det ikke være overflødigt at bekæmpe denne kompleksitet ved at oprette dine egne moduler.
Opsummer tips og tricks
Undgå globale variabler.
Præfiks rollevariabler.
Brug sløjfekontrolvariabel.
Tjek inputvariabler.
Undgå hash-ordbøger, brug flad struktur.
Skab idempotente spillebøger og roller.
Undgå at bruge kommandoskalmoduler.
Test dine roller via molekyle.
Sæt kompleks logik i moduler og plugins.
Konklusion
Du kan ikke bare gå og refaktorere infrastrukturen på et projekt, selvom du har IaC. Dette er en lang proces, der kræver tålmodighed, tid og viden.
UPD1 2020.05.01 20:30 — Til primær profilering af spillebøger kan du bruge callback_whitelist = profile_tasks at forstå, hvad der præcist virker i lang tid. Så går vi igennem Ansible accelerationsklassikere. Du kan også prøve mitogen UPD2 2020.05.03 16:34 — engelsk version