Terraformer - Infraestructura para codificar

Terraformer - Infraestructura para codificar
Gustaríame falarvos da nova ferramenta CLI que escribín para resolver un problema antigo.

problema

Terraform foi durante moito tempo un estándar na comunidade Devops/Cloud/IT. A cousa é moi cómoda e útil para tratar a infraestrutura como código. Terraform ten moitas delicias, así como moitos garfos, coitelos afiados e anciños.
Con Terraform é moi cómodo crear cousas novas e despois xestionalas, cambialas ou eliminalas. Que deberían facer aqueles que teñen unha enorme infraestrutura na nube e non se crean a través de Terraform? Reescribir e recrear toda a nube é dalgún xeito caro e inseguro.
Atopei este problema en 2 traballos, o exemplo máis sinxelo é cando queres que todo estea en Git en forma de ficheiros terraform, pero tes máis de 250 baldes e é moito escribilos en terraform a man.
Ten cuestión dende 2014 en terrafom que se pechou en 2016 coa esperanza de que haxa importación.

En xeral, todo é como na imaxe só de dereita a esquerda

Avisos: o autor non vive en Rusia durante a metade da súa vida e escribe pouco en ruso. Coidado coas faltas de ortografía.

Solucións

1. Hai unha solución antiga e preparada para AWS terraformación. Cando tentei pasar os meus máis de 250 baldes, decateime de que alí todo estaba mal. AWS leva moito tempo introducindo moitas opcións novas, pero a terraformación non sabe delas e, en xeral, é rubí o modelo parece escaso. Despois das 2 da noite enviei Solicitude de extracción para engadir máis funcións alí e decatouse de que tal solución non é adecuada para nada.
Como funciona a terraformación: toma datos do SDK de AWS e xera tf e tfstate a través dun modelo.
Aquí hai 3 problemas:
1. Sempre haberá un atraso nas actualizacións
2. Os ficheiros tf ás veces saen rotos
3. tfstate recóllese por separado de tf e non sempre converxe
En xeral, é difícil conseguir un resultado no que `plan terraform` diga que non hai cambios

2. `terraform import` é un comando incorporado en terraform. Como funciona?
Escribe un ficheiro TF baleiro co nome e tipo de recurso, despois executa "terraform import" e pasa o ID do recurso. terraform contacta co provedor, recibe os datos e crea un ficheiro tfstate.
Aquí hai 3 problemas:
1. Só recibimos un ficheiro tfstate e o tf está baleiro, cómpre escribilo manualmente ou convertelo desde tfstate
2. Só pode traballar cun recurso á vez e non admite todos os recursos. E que debo facer de novo con máis de 250 baldes?
3. Debes coñecer o ID dos recursos, é dicir, tes que envolvelo nun código que obtén a lista de recursos
En xeral, o resultado é parcial e non se escala ben

A miña decisión

Requisitos:
1. Capacidade de crear ficheiros tf e tfstate para recursos. Por exemplo, descarga todos os depósitos/grupo de seguridade/equilibrador de carga e ese `plan terraform` devolveu que non hai cambios
2. Necesitas 2 nubes GCP + AWS
3. Solución global que é fácil de actualizar cada vez e que non perda tempo en cada recurso durante 3 días de traballo
4. Fai que sexa de código aberto: todos teñen o mesmo problema

A linguaxe Go é polo que me encanta, e ten unha biblioteca para crear ficheiros HCL que se usa en terraform + moito código en terraform que pode ser útil

Camiño

Intento primeiro
Comecei cunha versión sinxela. Contactar coa nube a través do SDK para obter o recurso necesario e convertelo en campos para terraform. O intento morreu inmediatamente no grupo de seguridade porque non me gustaron os días 1.5 para converter só o grupo de seguridade (e hai moitos recursos). Durante moito tempo e despois os campos pódense cambiar/engadir

Segundo intento
Baseado na idea descrita aquí. Basta tomar e converter tfstate en tf. Todos os datos están alí e os campos son os mesmos. Como obter tfstate completo para moitos recursos? Aquí é onde o comando `terraform refresh` chegou ao rescate. terraform toma todos os recursos en tfstate e, por ID, extrae datos neles e escribe todo en tfstate. É dicir, crear un tfstate baleiro con só nomes e ID, executar `terraform refresh` e despois obteremos tfstates completos. Hurra!
Agora imos facer a pornografía recursiva de escribir un conversor de tfstate a tf. Para aqueles que nunca leron tfstate, é JSON, pero especial.
Aquí están os seus atributos de parte importante

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

Ahí está:
1. id - cadea
2. metadatos: unha matriz de tamaño 1 e nela un obxecto con campos que se describe a continuación
3. spec - hash de tamaño 1 e clave, valor nel
En definitiva, un formato divertido, todo pode ter varios niveis de profundidade

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

En xeral, se alguén quere un problema de programación para unha entrevista, só pídelle que escriba un analizador para esta tarefa :)
Despois de moitos intentos de escribir un analizador sen erros, atopei parte del no código terraform, e a parte máis importante. E todo parecía funcionar ben

Intento tres
Os provedores de terraform son binarios que conteñen código con todos os recursos e a lóxica para traballar coa API da nube. Cada nube ten o seu propio provedor e terraform só os chama a través do seu protocolo RPC entre dous procesos.
Agora decidín contactar directamente cos provedores de terraform mediante chamadas RPC. Resultou moi ben e permitiu cambiar os provedores de terraform por outros máis novos e obter novas funcións sen cambiar o código. Tamén resulta que non todos os campos en tfstate deberían estar en tf, pero como podes averiguarlo? Pregúntalle ao teu provedor sobre isto. Entón comezou outra pornografía recursiva de ensamblar expresións regulares, buscando campos dentro de tfstate a todos os niveis en profundidade.

Ao final, conseguimos unha ferramenta CLI útil que ten unha infraestrutura común para todos os provedores de terraform e pode engadir facilmente unha nova. Ademais, engadir recursos leva pouco código. Ademais de todo tipo de golosinas, como conexións entre recursos. Por suposto, houbo moitos problemas diferentes que non se poden describir todos.
Chamei ao animal Terrafomer.

Final

Usando Terrafomer, xeramos 500-700 mil liñas de código tf + tfstate a partir de dúas nubes. Puidemos tomar cousas legais e comezar a tocalas só a través de terraform, como na mellor infraestrutura como ideas de código. É só maxia cando colles unha nube enorme e a recibes a través dun equipo en forma de ficheiros de traballadores de terraform. E despois grep/replace/git e así por diante.

Peiteino e púxeno en orde, conseguín permiso. Lanzado en GitHub para todos o xoves (02.05.19/XNUMX/XNUMX). github.com/GoogleCloudPlatform/terraformer
Xa recibiu 600 estrelas, 2 solicitudes de extracción para engadir compatibilidade con openstack e kubernetes. Bos comentarios. En xeral, o proxecto é útil para as persoas
Aconsello a todos os que queiran comezar a traballar con Terraform e non reescribir todo para isto.
Estarei encantado de sacar solicitudes, problemas, estrelas.

Demostración
Terraformer - Infraestructura para codificar

Fonte: www.habr.com

Engadir un comentario