Terraformer — Infrastruktūra kā kods

Terraformer — Infrastruktūra kā kods
Vēlos stāstīt par jauno CLI rīku, ko esmu uzrakstījis, lai atrisinātu vienu vecu problēmu.

Problēma

Terraform jau sen ir kļuvis par standartu DevOps/Cloud/IT kopienā. Tā ir ļoti ērta un noderīga lieta, lai nodarbotos ar infrastruktūru kā kodu. Ir daudz priekšrocību, kas saistītas ar Terraform, kā arī daudz šķēršļu un problēmu.
Ar Terraform ir ļoti ērti veidot jaunas lietas un pēc tam tām vadīt, mainīt vai dzēst. Bet ko darīt tiem, kam ir milzīga infrastruktūra mākoņos, kas nav izveidota ar Terraform? Visu pārveidot un atkārtoti izveidot būtu gan dārgi, gan nedroši.
Es esmu saskāries ar šādu problēmu divās darbavietās, vienkāršākais piemērs ir tad, kad vēlies, lai viss būtu Git formātā ar Terraform failiem, bet tev ir 250+ kausu, un tos rakstīt Terraformā ar rokām ir pārāk daudz.
Ir problēma Vēl kopš 2014. gada pastāvēja terrafom, ko slēdza 2016. gadā ar cerību, ka būs importēšanas iespēja.

Vispār, viss kā attēlā, tikai no labās uz kreiso.

Brīdinājumi: Autors pusi sava mūža dzīvo nevis Krievijā, un raksta krieviski maz. Uzmanību, ortogrāfijas kļūdas.

Risinājumi

1. Ir gatavi un veci risinājumi AWS. terraforming. Kad es mēģināju caur to iegūt savus 250+ kausus, sapratu, ka tur viss ir slikti. AWS jau sen bija iespraucis daudz jaunu iespēju, un terraforming par tām nezināja un vispār tam ir Ruby. paraugi izskatās skopi.. Pēc 2 vakarā es nosūtīju Pull request , lai pievienotu vairāk iespēju tur un sapratu, ka šāds risinājums vispār nepiestāv.
Kā darbojas terraforming? Tas ņem datus no AWS SDK un ģenerē tf un tfstate, izmantojot paraugu.
Šeit ir 3 problēmas:
1. Vienmēr būs kavēšanās atjauninājumos.
2. tf faili dažreiz iznāk bojāti.
3. tfstate tiek veidots atsevišķi no tf un ne vienmēr sakrīt.
Vispārīgi ir grūti iegūt rezultātu, kur terraform plan saka, ka nav izmaiņu.

2. terraform import — iebūvēta komanda Terraformā. Kā tā darbojas?
Tu uzraksti tukšu TF failu ar resursa nosaukumu un tipu, pēc tam palaidi terraform import un nodod resursa ID. Terraform vēršas pie pakalpojuma sniedzēja, saņem datus un izveido tfstate failu.
Šeit ir 3 problēmas:
1. Mēs saņemam tikai tfstate failu, bet tf ir tukšs, to jāraksta ar rokām vai jākonvertē no tfstate.
2. Tas var strādāt tikai ar vienu resursu katru reizi un neatbalsta visus resursus. Un ko man darīt atkārtoti ar 250+ kausiem?
3. Jāzina resursu ID — tas ir, jāaptver tas kodā, kas izgūst resursu sarakstu.
Vispārīgi rezultāts ir daļējs un neizskatās labi mērogot.

Mans risinājums

Prasības:
1. Iespēja izveidot tf un tfstate failus no resursiem. Piemēram, lejupielādēt visas bucketus/sekuritātes grupas/iebraukšanas slēdzējus un to, ko `terraform plan` atgriež, ka nav izmaiņu.
2. Nepieciešami 2 mākoņi GCP + AWS.
3. Globāls risinājums, ko ir viegli atjaunināt katru reizi un netērēt laiku katram resursam pa 3 dienām.
4. Jāveido Open source — visiem tāda problēma.

Valoda Go — tāpēc man patīk, un tajā ir bibliotēka HCL failu izveidei, kas tiek izmantota terraform + daudz koda terraform, kas var būt noderīgs.

Ceļš.

Pirmais mēģinājums.
Sāku ar vienkāršu variantu. Pieprasījumi uz mākoni caur SDK, lai iegūtu nepieciešamos resursus un pārveidotu tos laukos terraform. Mēģinājums izgāzās uzreiz ar sekurītātes grupu, jo man nepatika pavadīt 1,5 dienas, lai pārveidotu tikai sekurītātes grupu (resursu ir daudz). Ilgi, un vēlāk lauki var mainīties/pievienoties.

Otrs mēģinājums.
Balstīts uz ideju, kas aprakstīta. šeit. Vienkārši paņemt un pārvērst tfstate uz tf. Vis dati tur ir un lauki ir tie paši. Kā iegūt pilnu tfstate daudziem resursiem?? Šeit palīdzēja komanda `terraform refresh`. Terraform ņem visus resursus tfstate un pēc ID iegūst datus par tiem un ieraksta visu tfstate. Tas nozīmē izveidot tukšu tfstate tikai ar nosaukumiem un ID, palaist `terraform refresh`, tad iegūstam pilnu tfstate. Hooray!
Tagad ķersimies pie rekursīvās pornogrāfijas, rakstot konvertoru no tfstate uz tf. Lai tiem, kas nekad nav lasījuši tfstate, tas ir JSON, bet īpašs.
Šeit ir svarīgākā daļa 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",

Šeit ir:
1. id — string.
2. metadata — masīvs ar izmēru 1, un tajā ir objekts ar laukiem, kas aprakstīti zemāk.
3. spec — hashes ar izmēru 1 un tajā key,value.
Īsumā, jautrs formāts, viss var būt dziļi arī vairākos līmeņos.

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

Ja, ja, kas vēlas programmēšanas uzdevumu intervijai, vienkārši lūdziet uzrakstīt parseri par šo 🙂
Pēc daudzkārtējām pūlēm uzrakstīt parseri bez kļūdām, es atradu daļu no tā Terraform kodā, pat vissvarīgāko daļu. Un viss šķita kārtībā.

Mēģinājums trīs
Terraform provider ir binārie faili, kuros ir kods ar visiem resursiem un loģiku API mijiedarbībai ar mākoņiem. Katram mākoņam ir sava provider un pats Terraform vienkārši izsauc tos caur savu RPC protokolu starp divām procesiem.
Tagad es nolēmu tieši izsaukt Terraform providerus caur RPC izsaukumiem. Tas izdevās skaisti un deva iespēju mainīt Terraform providerus uz jaunākiem un gūt jaunas iespējas, nemainot kodu. Turklāt izrādījās, ka ne visi lauki tfstate jāsatur tf, un kā to uzzināt? Tikai pajautājot provideram par to. Pēc tam sākās vēl viena rekursīva murgu sērija par regulāro izteiksmju izveidi, meklējot laukus tfstate visos līmeņos dziļumā.

Beigās izdevās izveidot noderīgu CLI rīku, kuram ir kopīga infrastruktūra visiem Terraform provideriem, un var viegli pievienot jaunus. Arī resursu pievienošana prasa maz kodu. Plus, visādas foršas iespējas, piemēram, savienojumi starp resursiem. Protams, bija daudz dažādu problēmu, kuras nav iespējams aprakstīt.
Nosaucu šo rīku par Terrafomer.

Fināls

Mēs ar Terrafomer palīdzību esam ģenerējuši 500-700 tūkstošus koda rindu tf + tfstate no diviem mākoņiem. Iespējām pārņemt legātos projektus un sākt tos apstrādāt, izmantojot Terraform, kā to paredz ideja par infrastruktūru kā kodu. Tas ir burvīgi, kad paņem milzīgu mākoņu un saņem to komandas veidā kā darba terraform failus. Tad seko grep/replace/git un tā tālāk.

Es izrēķināju un sakārtoju, ieguvu atļaujas. Izlaidu uz GitHub visiem ceturtdienā (02.05.19). github.com/GoogleCloudPlatform/terraformer
Esmu jau ieguvis 600 zvaigžņu, 2 pull requestus ar atbalsta pievienošanu OpenStack un Kubernetes. Labas atsauksmes. Projekts ir patiesi noderīgs cilvēkiem.
Iesaku visiem, kas vēlas sākt strādāt ar Terraform un nevēlas visu pārrakstīt šim nolūkam.
Būšu priecīgs par pull requestiem, problēmām, zvaigznēm.

Demonstrācija
Terraformer — Infrastruktūra kā kods

Avots: habr.com

Iegādājieties uzticamu tīmekļa hostingu ar DDoS aizsardzību, VPS VDS serveriem 🔥 Iegādājieties uzticamu tīmekļa hostingu ar DDoS aizsardzību, VPS VDS serveriem | ProHoster