Terraformer - Infrastruktur å kode

Terraformer - Infrastruktur å kode
Jeg vil gjerne fortelle deg om det nye CLI-verktøyet som jeg skrev for å løse et gammelt problem.

problem

Terraform har lenge vært en standard i Devops/Cloud/IT-miljøet. Tingen er veldig praktisk og nyttig for å håndtere infrastruktur som kode. Det er mange herligheter i Terraform i tillegg til mange gafler, skarpe kniver og river.
Med Terraform er det veldig praktisk å lage nye ting og deretter administrere, endre eller slette dem. Hva skal de som har en enorm infrastruktur i skyen og ikke opprettet gjennom Terraform gjøre? Å omskrive og gjenskape hele skyen er på en eller annen måte dyrt og utrygt.
Jeg støtt på dette problemet ved 2 jobber, det enkleste eksemplet er når du vil at alt skal være i Git i form av terraform-filer, men du har 250+ bøtter og det er mye å skrive dem i terraform for hånd.
Det er utstedelse siden 2014 i terrafom som ble stengt i 2016 med håp om at det blir import.

Generelt er alt som på bildet bare fra høyre til venstre

Advarsler: Forfatteren bor ikke halve livet i Russland og skriver lite på russisk. Pass på stavefeil.

Løsninger

1. Det finnes ferdige og gamle løsninger for AWS terrorforming. Da jeg prøvde å få mine 250+ bøtter gjennom den, skjønte jeg at alt var dårlig der. AWS har lenge introdusert mange nye alternativer, men terraforming vet ikke om dem, og generelt er det rubin malen ser sparsom ut. Etter 2 på kvelden sendte jeg Trekk forespørsel å legge til flere funksjoner der og innså at en slik løsning ikke er egnet i det hele tatt.
Hvordan terraforming fungerer: det tar data fra AWS SDK og genererer tf og tfstate gjennom en mal.
Det er 3 problemer her:
1. Det vil alltid være etterslep i oppdateringer
2. tf filer noen ganger kommer ut ødelagt
3. tfstate samles separat fra tf og konvergerer ikke alltid
Generelt er det vanskelig å få et resultat hvor `terraformplan` sier at det ikke er endringer

2. `terraform import` er en innebygd kommando i terraform. Hvordan virker det?
Du skriver en tom TF-fil med navn og type ressurs, kjører deretter `terraform import` og sender ressurs-IDen. terraform kontakter leverandøren, mottar dataene og lager en tfstate-fil.
Det er 3 problemer her:
1. Vi får bare en tfstate-fil, og tf-en er tom, du må skrive den manuelt eller konvertere den fra tfstate
2. Kan kun jobbe med én ressurs om gangen og støtter ikke alle ressursene. Og hva skal jeg gjøre igjen med 250+ bøtter?
3. Du må kjenne IDen til ressursene - det vil si at du må pakke den inn i kode som henter listen over ressurser
Generelt er resultatet delvis og skalerer ikke godt

Mitt valg

krav:
1. Evne til å lage tf- og tfstate-filer for ressurser. For eksempel, last ned alle bøttene/sikkerhetsgruppen/lastbalanseren og at `terraform-planen` returnerte at det ikke er noen endringer
2. Du trenger 2 GCP + AWS-skyer
3. Global løsning som er enkel å oppdatere hver gang og som ikke kaster bort tid på hver ressurs for 3 dagers arbeid
4. Gjør det åpen kildekode - alle har det samme problemet

Go-språket er grunnen til at jeg elsker det, og det har et bibliotek for å lage HCL-filer som brukes i terraform + mye kode i terraform som kan være nyttig

Sti

Første forsøk
Jeg startet med en enkel versjon. Kontakt skyen via SDK for den nødvendige ressursen og konverter den til felt for terraform. Forsøket døde umiddelbart på sikkerhetsgruppen fordi jeg ikke likte de 1.5 dagene for å konvertere bare sikkerhetsgruppen (og det er mange ressurser). I lang tid og så kan felt endres/legges til

Andre forsøk
Basert på ideen beskrevet her. Bare ta og konverter tfstate til tf. Alle dataene er der og feltene er de samme. Hvordan få full tfstate for mange ressurser?? Det var her `terraform refresh`-kommandoen kom til unnsetning. terraform tar alle ressurser i tfstate og, ved ID, trekker ut data om dem og skriver alt til tfstate. Det vil si, lag en tom tfstate med kun navn og IDer, kjør `terraform refresh` og så får vi fulle tfstater. Hurra!
La oss nå gjøre den rekursive pornografien med å skrive en konverter for tfstate til tf. For de som aldri har lest tfstate, er det JSON, men spesielt.
Her er dens viktige delegenskaper

 "attributes": {
                            "id": "default/backend-logging-load-deployment",
                            "metadata.#": "1",
                            "metadata.0.annotations.%": "0",
                            "metadata.0.generate_name": "",
                            "metadata.0.generation": "24",
                            "metadata.0.labels.%": "1",
                            "metadata.0.labels.app": "backend-logging",
                            "metadata.0.name": "backend-logging-load-deployment",
                            "metadata.0.namespace": "default",
                            "metadata.0.resource_version": "109317427",
                            "metadata.0.self_link": "/apis/apps/v1/namespaces/default/deployments/backend-logging-load-deployment",
                            "metadata.0.uid": "300ecda1-4138-11e9-9d5d-42010a8400b5",
                            "spec.#": "1",
                            "spec.0.min_ready_seconds": "0",
                            "spec.0.paused": "false",
                            "spec.0.progress_deadline_seconds": "600",
                            "spec.0.replicas": "1",
                            "spec.0.revision_history_limit": "10",
                            "spec.0.selector.#": "1",

Det er:
1. id - streng
2. metadata - en matrise av størrelse 1 og i den et objekt med felt som er beskrevet nedenfor
3. spec - hash av størrelse 1 og nøkkel, verdi i den
Kort sagt, et morsomt format, alt kan være flere nivåer dypt

                   "spec.#": "1",
                            "spec.0.min_ready_seconds": "0",
                            "spec.0.paused": "false",
                            "spec.0.progress_deadline_seconds": "600",
                            "spec.0.replicas": "1",
                            "spec.0.revision_history_limit": "10",
                            "spec.0.selector.#": "1",
                            "spec.0.selector.0.match_expressions.#": "0",
                            "spec.0.selector.0.match_labels.%": "1",
                            "spec.0.selector.0.match_labels.app": "backend-logging-load",
                            "spec.0.strategy.#": "0",
                            "spec.0.template.#": "1",
                            "spec.0.template.0.metadata.#": "1",
                            "spec.0.template.0.metadata.0.annotations.%": "0",
                            "spec.0.template.0.metadata.0.generate_name": "",
                            "spec.0.template.0.metadata.0.generation": "0",
                            "spec.0.template.0.metadata.0.labels.%": "1",
                            "spec.0.template.0.metadata.0.labels.app": "backend-logging-load",
                            "spec.0.template.0.metadata.0.name": "",
                            "spec.0.template.0.metadata.0.namespace": "",
                            "spec.0.template.0.metadata.0.resource_version": "",
                            "spec.0.template.0.metadata.0.self_link": "",
                            "spec.0.template.0.metadata.0.uid": "",
                            "spec.0.template.0.spec.#": "1",
                            "spec.0.template.0.spec.0.active_deadline_seconds": "0",
                            "spec.0.template.0.spec.0.container.#": "1",
                            "spec.0.template.0.spec.0.container.0.args.#": "3",

Generelt, hvis noen vil ha et programmeringsproblem for et intervju, bare be dem skrive en parser for denne oppgaven :)
Etter mange forsøk på å skrive en parser uten feil, fant jeg en del av den i terraform-koden, og den viktigste delen. Og alt så ut til å fungere bra

Forsøk tre
terraform-leverandører er binære filer som inneholder kode med alle ressursene og logikken for å jobbe med cloud API. Hver sky har sin egen leverandør og terraform selv kaller dem kun gjennom sin RPC-protokoll mellom to prosesser.
Nå bestemte jeg meg for å kontakte terraform-leverandører direkte via RPC-anrop. Det ble vakkert og gjorde det mulig å bytte terraform-leverandører til nyere og få nye funksjoner uten å endre koden. Det viser seg også at ikke alle felt i tfstate skal være i tf, men hvordan kan du finne det ut? Bare spør leverandøren din om dette. Så begynte en annen rekursiv pornografi med å sette sammen regulære uttrykk, og søkte etter felt inne i tfstate på alle nivåer i dybden.

Til slutt fikk vi et nyttig CLI-verktøy som har en felles infrastruktur for alle terraform-leverandører og du kan enkelt legge til en ny. Dessuten krever det lite kode å legge til ressurser. Pluss alle slags godsaker som forbindelser mellom ressurser. Selvfølgelig var det mange forskjellige problemer som ikke kan beskrives alle.
Jeg kalte dyret Terrafomer.

finale

Ved å bruke Terrafomer genererte vi 500-700 tusen linjer med tf + tfstate-kode fra to skyer. Vi var i stand til å ta eldre ting og begynne å berøre dem bare gjennom terraform, som i den beste infrastrukturen som kodeideer. Det er bare magi når du tar en enorm sky og mottar den gjennom et team i form av terraform-arbeiderfiler. Og så grep/replace/git og så videre.

Jeg gredde den ut og satte den i stand, fikk tillatelse. Utgitt på GitHub for alle torsdag (02.05.19). github.com/GoogleCloudPlatform/terraformer
Har allerede mottatt 600 stjerner, 2 pull-forespørsler for å legge til støtte for openstack og kubernetes. Gode ​​tilbakemeldinger. Generelt sett er prosjektet nyttig for folk
Jeg anbefaler alle som ønsker å begynne å jobbe med Terraform og ikke skrive om alt for dette.
Jeg vil gjerne trekke forespørsler, problemer, stjerner.

demo
Terraformer - Infrastruktur å kode

Kilde: www.habr.com

Legg til en kommentar