Este disponibilă oficial lansarea sistemului deschis

Este disponibilă oficial lansarea sistemului deschis
Aș dori să vă povestesc despre un nou tool CLI pe care l-am scris pentru a rezolva o problemă veche.

Problema

Terraform a devenit deja standard în cadrul comunității DevOps/Cloud/IT. Este un instrument foarte convenabil și util pentru a gestiona infrastructura ca și cod. Există multe beneficii în Terraform, dar și multe capcane, cuțite ascuțite și obstacole.
Cu Terraform este foarte eficient să creezi lucruri noi și să le gestionezi, să le modifici sau să le ștergi. Dar ce fac cei care au o infrastructură imensă în cloud care nu a fost creată prin Terraform? Să o rescrie și să o recreeze ar fi destul de costisitor și nesigur.
Am întâmpinat o astfel de problemă la două locuri de muncă, cel mai simplu exemplu fiind când vrei ca totul să fie în git în formă de fișiere Terraform, iar tu ai 250+ de bucket-uri iar a le scrie manual pentru Terraform ar fi foarte laborios.
Există issue Încă din 2014 exista terraform care a fost închis în 2016 cu speranța că va exista import.

În general, totul este ca în imagine, doar că de la dreapta la stânga.

Avertisment: Autorul trăiește de o jumătate de viață în afară și scrie puțin în limba rusă. Atenție la greșelile de ortografie.

Soluții

1. Există soluții vechi și gata făcute pentru AWS. terraforming. Când am încercat să obțin cele 250+ de bucket-uri prin intermediul acestuia, am realizat că situația este destul de tristă. AWS a adăugat deja multe opțiuni noi, dar terraforming nu le știe și în plus folosește ruby. Templetele arată destul de sărăcăcios.. După ora 2, am trimis Pull request pentru a adăuga mai multe funcționalități acolo și am realizat că o astfel de soluție nu este deloc potrivită.
Cum funcționează terraforming? Acesta ia date de la SDK-ul AWS și generează fișiere tf și tfstate prin intermediul template-urilor.
Sunt 3 probleme:
1. Va exista întotdeauna o întârziere în actualizări.
2. Fișierele tf uneori sunt deteriorate.
3. fișierul tfstate este generat separat de tf și nu corespund întotdeauna.
În general, este dificil să obții un rezultat în care `terraform plan` să spună că nu există modificări.

2. `terraform import` — este comanda încorporată în terraform. Cum funcționează aceasta?
Scrii un fișier TF gol cu numele și tipul resursei, apoi rulezi `terraform import` și îi transmiți ID-ul resursei. Terraform se adresează furnizorului, obține datele și generează fișierul tfstate.
Sunt 3 probleme:
1. Obținem doar fișierul tfstate, iar tf este gol, trebuie să-l scriem manual sau să-l convertim din tfstate.
2. Poate lucra doar cu o singură resursă de fiecare dată și nu acceptă toate resursele. Și ce ar trebui să fac din nou cu cele 250+ bucket-uri?
3. Trebuie să știi ID-urile resurselor — adică trebuie să îl înfășori în cod care extrage lista resurselor.
În general, rezultatul este parțial și nu se scalează bine.

Soluția mea

Cerințe:
1. Posibilitatea de a crea fișiere tf și tfstate pe baza resurselor. De exemplu, descărcarea tuturor bărcilor / grupurilor de securitate / load balancer și ceea ce `terraform plan` a returnat că nu sunt modificări.
2. Necesare 2 cloud-uri GCP + AWS.
3. O soluție globală care să fie ușor de actualizat de fiecare dată și să nu pierzi timp cu fiecare resursă timp de 3 zile de muncă.
4. Să facem Open source — toată lumea are aceeași problemă.

Limbajul Go — de aceea îmi place, și există o bibliotecă pentru crearea fișierelor HCL care este utilizată în terraform + multe coduri în terraform care pot fi utile.

Calea

Încercarea întâi
Am început cu o variantă simplă. Interacțiunea cu cloud-ul prin SDK pentru obținerea resursei necesare și conversia acesteia în câmpuri pentru terraform. Încercarea a eșuat imediat la grupul de securitate deoarece nu mi-a plăcut să convertesc timp de 1.5 zile doar grupul de securitate (iar resursele sunt multe). E prea mult și apoi câmpurile pot să se schimbe / să se adauge.

Încercarea a doua
Se bazează pe ideea descrisă aici. Pur și simplu a lua și a converti tfstate în tf. Toate datele sunt acolo și câmpurile sunt aceleași. Cum obții un tfstate complet pentru multe resurse?? Aici a intervenit comanda `terraform refresh`. terraform ia toate resursele din tfstate și, după ID, extrage datele despre ele și le scrie în tfstate. Adică să creezi un tfstate gol doar cu numele și ID-urile, să rulezi `terraform refresh` și obții tfstate complete. Ura!
Acum să ne ocupăm de scrierea unui converter recursiv pentru tfstate în tf. Pentru cei care nu au citit niciodată tfstate, este JSON, dar special.
Iată partea sa importantă, attributes

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

Aici avem:
1. id — string
2. metadata — un array de dimensiune 1 și în el un obiect cu câmpurile descrise mai jos
3. spec — hash de dimensiune 1 și în el key,value
Pe scurt, un format interesant, totul poate fi la adâncimi și pe mai multe niveluri.

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

În general, cine vrea o provocare de programare pentru interviu, să ceară pur și simplu scrierea unui parser pentru asta 🙂
După încercări îndelungate de a scrie un parser fără erori, am găsit o parte din cod în terraform, și anume partea cea mai importantă. Și totul părea să funcționeze bine.

Încercarea trei
Providerul terraform este un binar care conține cod cu toate resursele și logica pentru a lucra cu API-urile cloud. Fiecare cloud are propriul provider, iar terraform pur și simplu le cheamă prin protocolele sale RPC între cele două procese.
Acum am decis să mă adresez direct providerelor terraform prin apeluri RPC. Așa a ieșit frumos și mi-a dat posibilitatea de a schimba providerii terraform cu unele mai noi și de a obține noi funcționalități fără a schimba codul. De asemenea, s-a dovedit că nu toate câmpurile din tfstate trebuie să fie în tf, dar cum am aflat asta? Numai întrebând providerul despre asta. Apoi, a început o altă pornografie recursivă în construirea expresiilor regulate cu căutarea câmpurilor în tfstate la toate nivelurile adânc.

La final, a rezultat un instrument CLI util, care are o infrastructură comună pentru toate providerii terraform, fiind ușor să adăugi un nou provider. De asemenea, adăugarea resurselor necesită puțin cod. Plus diverse avantaje, cum ar fi interconexiunile între resurse. Desigur, au fost multe probleme diferite care nu pot fi toate descrise.
Am numit creatura Terrafomer.

Finala

Am generat între 500-700 de mii de linii de cod tf + tfstate cu ajutorul Terrafomer în două clouduri. Am reușit să preluăm lucruri legate de legatură și să începem să le modificăm doar prin terraform, așa cum este în cele mai bune idei despre infrastructura ca cod. Este pură magie când iei un cloud uriaș și îl obții printr-o comandă sub formă de fișiere terraform funcționale. Iar apoi grep/replace/git și așa mai departe.

Am calculat și am adus în ordine, am obținut permisiunile. L-am lansat pe GitHub pentru toți joi (02.05.19). github.com/GoogleCloudPlatform/terraformer
Am obținut deja 600 de stele, 2 cereri de pull pentru adăugarea suportului pentru openstack și kubernetes. Recenzii bune. În general, proiectul este util pentru oameni.
Îi recomand tuturor celor care doresc să înceapă să lucreze cu Terraform și să nu rescrie totul pentru asta.
Aș fi bucuros să primesc cereri de pull, probleme, stele.

Demo
Este disponibilă oficial lansarea sistemului deschis

Sursa: habr.com

Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS 🔥 Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS | ProHoster