Terraformer - Infrastruktur til at kode

Terraformer - Infrastruktur til at kode
Jeg vil gerne fortælle dig om det nye CLI-værktøj, som jeg skrev for at løse et gammelt problem.

problem

Terraform har længe været en standard i Devops/Cloud/IT-fællesskabet. Tingen er meget praktisk og nyttig til at håndtere infrastruktur som kode. Der er mange lækkerier i Terraform samt mange gafler, skarpe knive og river.
Med Terraform er det meget praktisk at skabe nye ting og derefter administrere, ændre eller slette dem. Hvad skal de, der har en enorm infrastruktur i skyen og ikke er skabt gennem Terraform, gøre? Omskrivning og genskabelse af hele skyen er på en eller anden måde dyrt og usikkert.
Jeg stødte på dette problem ved 2 job, det enkleste eksempel er, når du ønsker, at alt skal være i Git i form af terraform-filer, men du har 250+ buckets, og det er meget at skrive dem i terraform i hånden.
Der er spørgsmål siden 2014 i terrafom som blev lukket i 2016 med håb om at der kommer import.

Generelt er alt som på billedet kun fra højre mod venstre

Advarsler: Forfatteren bor ikke i Rusland i halvdelen af ​​sit liv og skriver lidt på russisk. Pas på stavefejl.

Решения

1. Der findes en færdiglavet og gammel løsning til AWS terraforming. Da jeg prøvede at få mine 250+ spande igennem det, indså jeg, at alt var dårligt der. AWS har længe introduceret en masse nye muligheder, men terraforming kender ikke til dem, og generelt er det rubin skabelonen ser sparsom ud. Efter 2 om aftenen sendte jeg Træk anmodning at tilføje flere funktioner der og indså, at en sådan løsning slet ikke er egnet.
Sådan fungerer terraforming: det tager data fra AWS SDK og genererer tf og tfstate gennem en skabelon.
Der er 3 problemer her:
1. Der vil altid være en forsinkelse i opdateringer
2. tf-filer kommer nogle gange i stykker
3. tfstate opsamles separat fra tf og konvergerer ikke altid
Generelt er det svært at få et resultat, hvor `terraformplan` siger, at der ikke er ændringer

2. `terraform import` er en indbygget kommando i terraform. Hvordan virker det?
Du skriver en tom TF-fil med navnet og typen af ​​ressource, kører derefter `terraform import` og sender ressource-id'et. terraform kontakter udbyderen, modtager dataene og laver en tfstate-fil.
Der er 3 problemer her:
1. Vi får kun en tfstate-fil, og tf'en er tom, du skal skrive den manuelt eller konvertere den fra tfstate
2. Kan kun arbejde med én ressource ad gangen og understøtter ikke alle ressourcer. Og hvad skal jeg gøre igen med 250+ spande?
3. Du skal kende ressourcernes ID - det vil sige, du skal pakke det ind i kode, der henter listen over ressourcer
Generelt er resultatet delvist og skalerer ikke godt

Min beslutning

Krav:
1. Mulighed for at oprette tf- og tfstate-filer til ressourcer. Download f.eks. alle buckets/sikkerhedsgruppen/load balancer, og den `terraform-plan` returnerede, at der ikke er nogen ændringer
2. Du skal bruge 2 GCP + AWS-skyer
3. Global løsning, der er nem at opdatere hver gang og ikke spilder tid på hver ressource i 3 dages arbejde
4. Gør det til Open Source - alle har det samme problem

Go-sproget er grunden til, at jeg elsker det, og det har et bibliotek til at lave HCL-filer, der bruges i terraform + en masse kode i terraform, der kan være nyttigt

Sti

Første forsøg
Jeg startede med en simpel version. Kontakt skyen via SDK'et for den nødvendige ressource og konverter den til felter til terraform. Forsøget døde med det samme på sikkerhedsgruppen, fordi jeg ikke kunne lide de 1.5 dage til kun at konvertere sikkerhedsgruppen (og der er mange ressourcer). I lang tid og så kan felter ændres/tilføjes

Andet forsøg
Baseret på den beskrevne idé her. Bare tag og konverter tfstate til tf. Alle data er der, og felterne er de samme. Hvordan får man fuld tfstate for mange ressourcer?? Det var her kommandoen `terraform refresh` kom til undsætning. terraform tager alle ressourcer i tfstate og trækker data ud på dem og skriver alt til tfstate. Det vil sige, opret en tom tfstate med kun navne og ID'er, kør `terraform refresh` og så får vi fulde tfstates. Hurra!
Lad os nu lave den rekursive pornografi med at skrive en konverter til tfstate til tf. For dem, der aldrig har læst tfstate, er det JSON, men specielt.
Her er dens vigtige delegenskaber

 "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",

Der er:
1. id - streng
2. metadata - et array af størrelse 1 og deri et objekt med felter, som er beskrevet nedenfor
3. spec - hash af størrelse 1 og nøgle, værdi i den
Kort sagt et sjovt format, alt kan være flere niveauer dybt

                   "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 nogen vil have et programmeringsproblem til et interview, skal du bare bede dem om at skrive en parser til denne opgave :)
Efter mange forsøg på at skrive en parser uden fejl, fandt jeg en del af den i terraform-koden, og den vigtigste del. Og alt så ud til at fungere fint

Forsøg tre
terraform-udbydere er binære filer, der indeholder kode med alle ressourcer og logik til at arbejde med cloud API. Hver sky har sin egen udbyder og terraform selv kalder dem kun gennem sin RPC-protokol mellem to processer.
Nu besluttede jeg at kontakte terraform-udbydere direkte via RPC-opkald. Det blev smukt og gjorde det muligt at skifte terraform-udbydere til nyere og få nye funktioner uden at ændre koden. Det viser sig også, at ikke alle felter i tfstate skal være i tf, men hvordan kan du finde ud af det? Bare spørg din udbyder om dette. Så begyndte endnu en rekursiv pornografi med at samle regulære udtryk, der søgte efter felter inde i tfstate på alle niveauer i dybden.

Til sidst fik vi et nyttigt CLI-værktøj, der har en fælles infrastruktur for alle terraform-udbydere, og du kan nemt tilføje et nyt. Desuden kræver det lidt kode at tilføje ressourcer. Plus alle mulige godbidder såsom forbindelser mellem ressourcer. Selvfølgelig var der mange forskellige problemer, som ikke kan beskrives alle.
Jeg kaldte dyret Terrafomer.

finale

Ved at bruge Terrafomer genererede vi 500-700 tusind linjer med tf + tfstate kode fra to skyer. Vi var i stand til at tage ældre ting og begynde at røre ved dem kun gennem terraform, som i den bedste infrastruktur som kodeideer. Det er bare magi, når du tager en enorm sky og modtager den gennem et team i form af terraform-arbejderfiler. Og så grep/replace/git og så videre.

Jeg finkæmmede den ud og satte den i stand, fik tilladelse. Udgivet på GitHub for alle torsdag (02.05.19/XNUMX/XNUMX). github.com/GoogleCloudPlatform/terraformer
Allerede modtaget 600 stjerner, 2 pull-anmodninger om tilføjelse af support til openstack og kubernetes. God feedback. Generelt er projektet nyttigt for mennesker
Jeg råder alle, der ønsker at begynde at arbejde med Terraform og ikke omskrive alt til dette.
Jeg vil med glæde trække anmodninger, problemer, stjerner.

Демо
Terraformer - Infrastruktur til at kode

Kilde: www.habr.com

Tilføj en kommentar