Terraformer: infrastruttura da codificare

Terraformer: infrastruttura da codificare
Vorrei parlarvi del nuovo strumento CLI che ho scritto per risolvere un vecchio problema.

Problema

Terraform è da tempo uno standard nella comunità Devops/Cloud/IT. La cosa è molto comoda e utile per gestire l'infrastruttura come codice. Ci sono molte delizie in Terraform così come molte forchette, coltelli affilati e rastrelli.
Con Terraform è molto comodo creare nuove cose e poi gestirle, modificarle o eliminarle. Cosa dovrebbe fare chi ha una infrastruttura enorme in cloud e non realizzata tramite Terraform? Riscrivere e ricreare l'intero cloud è in qualche modo costoso e pericoloso.
Ho riscontrato questo problema in 2 lavori, l'esempio più semplice è quando vuoi che tutto sia in Git sotto forma di file terraform, ma hai più di 250 bucket ed è molto complicato scriverli a mano in terraform.
C'è problema dal 2014 in terrafom che è stato chiuso nel 2016 con la speranza che ci sia importazione.

In generale, tutto è come nella foto solo da destra a sinistra

Avvertenze: L'autore non vive in Russia per metà della sua vita e scrive poco in russo. Attenzione agli errori di ortografia.

Soluzioni

1. Esistono soluzioni vecchie e già pronte per AWS terraformazione. Quando ho provato a far passare i miei oltre 250 secchi, mi sono reso conto che lì andava tutto male. AWS ha introdotto da tempo molte nuove opzioni, ma terraforming non le conosce e in generale è rubino il modello sembra scarno. Dopo le 2 di sera ho inviato Pull richiesta per aggiungere più funzionalità e mi sono reso conto che una soluzione del genere non è affatto adatta.
Come funziona la terraformazione: prende i dati dall'SDK AWS e genera tf e tfstate tramite un modello.
Qui ci sono 3 problemi:
1. Ci sarà sempre un ritardo negli aggiornamenti
2. I file tf a volte escono danneggiati
3. tfstate viene raccolto separatamente da tf e non sempre converge
In generale, è difficile ottenere un risultato in cui il "piano terraform" affermi che non ci sono cambiamenti

2. "terraform import" è un comando integrato in terraform. Come funziona?
Scrivi un file TF vuoto con il nome e il tipo di risorsa, quindi esegui "terraform import" e passi l'ID della risorsa. terraform contatta il provider, riceve i dati e crea un file tfstate.
Qui ci sono 3 problemi:
1. Otteniamo solo un file tfstate e tf è vuoto, devi scriverlo manualmente o convertirlo da tfstate
2. Può funzionare solo con una risorsa alla volta e non supporta tutte le risorse. E cosa dovrei fare di nuovo con oltre 250 bucket?
3. Devi conoscere l'ID delle risorse, ovvero devi inserirlo nel codice che ottiene l'elenco delle risorse
In generale, il risultato è parziale e non si adatta bene

La mia decisione

requisiti:
1. Possibilità di creare file tf e tfstate per le risorse. Ad esempio, scarica tutti i bucket/gruppi di sicurezza/bilanciatore del carico e il "piano terraform" restituisce che non sono presenti modifiche
2. Sono necessari 2 cloud GCP + AWS
3. Soluzione globale facile da aggiornare ogni volta e che non fa perdere tempo su ciascuna risorsa per 3 giorni di lavoro
4. Rendetelo Open Source: tutti hanno lo stesso problema

Il linguaggio Go è il motivo per cui lo adoro e ha una libreria per la creazione di file HCL utilizzata in terraform + molto codice in terraform che può essere utile

Strada

Primo tentativo
Ho iniziato con una versione semplice. Contattando il cloud tramite l'SDK per la risorsa richiesta e convertendola in campi per terraform. Il tentativo è fallito immediatamente sul gruppo di sicurezza perché non mi piaceva il tempo di 1.5 giorni per convertire solo il gruppo di sicurezza (e ci sono molte risorse). Per molto tempo e poi i campi possono essere modificati/aggiunti

Secondo tentativo
Basato sull'idea descritta qui. Basta prendere e convertire tfstate in tf. Tutti i dati sono lì e i campi sono gli stessi. Come ottenere il tfstate completo per molte risorse?? È qui che il comando "terraform refresh" è venuto in soccorso. terraform prende tutte le risorse in tfstate e, in base all'ID, estrae i dati su di esse e scrive tutto su tfstate. Cioè, crea un tfstate vuoto con solo nomi e ID, esegui `terraform refresh` e poi otterremo tfstate completi. Evviva!
Ora eseguiamo la pornografia ricorsiva scrivendo un convertitore da tfstate a tf. Per chi non ha mai letto tfstate, è JSON, ma speciale.
Ecco i suoi attributi di parte importanti

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

C'è:
1. id - stringa
2. metadati - un array di dimensione 1 e in esso un oggetto con campi descritti di seguito
3. spec - hash di dimensione 1 e chiave, valore in esso contenuto
In breve, un formato divertente, tutto può essere profondo diversi livelli

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

In generale, se qualcuno vuole un problema di programmazione per un'intervista, chiedigli semplicemente di scrivere un parser per questo compito :)
Dopo molti tentativi di scrivere un parser senza bug, ne ho trovato una parte nel codice terraform, e la parte più importante. E tutto sembrava funzionare bene

Tentativo tre
I fornitori di terraform sono file binari che contengono codice con tutte le risorse e la logica per lavorare con l'API cloud. Ogni cloud ha il proprio provider e terraform stesso li chiama solo tramite il suo protocollo RPC tra due processi.
Ora ho deciso di contattare direttamente i fornitori di terraform tramite chiamate RPC. Il risultato è stato fantastico e ha permesso di cambiare i fornitori di terraform con quelli più recenti e ottenere nuove funzionalità senza modificare il codice. Si scopre anche che non tutti i campi in tfstate dovrebbero essere in tf, ma come puoi scoprirlo? Chiedi informazioni al tuo fornitore. Poi è iniziata un'altra pornografia ricorsiva di assemblaggio di espressioni regolari, alla ricerca di campi all'interno di tfstate a tutti i livelli di profondità.

Alla fine, abbiamo ottenuto un utile strumento CLI che dispone di un'infrastruttura comune per tutti i fornitori di terraform e puoi facilmente aggiungerne una nuova. Inoltre, l'aggiunta di risorse richiede poco codice. Inoltre ogni sorta di chicche come le connessioni tra le risorse. Naturalmente c'erano molti problemi diversi che non possono essere descritti tutti.
Ho chiamato l'animale Terrafomer.

Finale

Utilizzando Terrafomer, abbiamo generato 500-700mila righe di codice tf + tfstate da due cloud. Siamo stati in grado di prendere cose legacy e iniziare a toccarle solo attraverso la terraformazione, come nelle migliori infrastrutture come idee di codice. È semplicemente magico quando prendi un'enorme nuvola e la ricevi attraverso un team sotto forma di file di lavoro terraform. E poi grep/replace/git e così via.

L'ho pettinato e messo in ordine, ho ottenuto il permesso. Rilasciato su GitHub per tutti giovedì (02.05.19/XNUMX/XNUMX). github.com/GoogleCloudPlatform/terraformer
Già ricevute 600 stelle, 2 richieste pull per l'aggiunta del supporto per openstack e kubernetes. Buon feedback. In generale, il progetto è utile per le persone
Consiglio a tutti coloro che vogliono iniziare a lavorare con Terraform e di non riscrivere tutto per questo.
Sarò felice di attirare richieste, problemi, stelle.

Demo
Terraformer: infrastruttura da codificare

Fonte: habr.com

Aggiungi un commento