Me gustaría hablarles sobre la nueva herramienta CLI que escribí para resolver un problema antiguo.
problema
Terraform ha sido durante mucho tiempo un estándar en la comunidad Devops/Cloud/IT. Es muy conveniente y útil para tratar la infraestructura como código. En Terraform hay muchas delicias, así como muchos tenedores, cuchillos afilados y rastrillos.
Con Terraform es muy conveniente crear cosas nuevas y luego administrarlas, cambiarlas o eliminarlas. ¿Qué deben hacer quienes tienen una infraestructura enorme en la nube y no creada a través de Terraform? Reescribir y recrear toda la nube es algo costoso e inseguro.
Encontré este problema en 2 trabajos, el ejemplo más simple es cuando quieres que todo esté en Git en forma de archivos Terraform, pero tienes más de 250 depósitos y es mucho escribirlos en Terraform a mano.
Hay
En general todo es como en la imagen solo de derecha a izquierda.
Advertencias: El autor no vive en Rusia la mitad de su vida y escribe poco en ruso. Cuidado con los errores de ortografía.
Решения
1. Existen soluciones antiguas y listas para usar para AWS
Cómo funciona la terraformación: toma datos del SDK de AWS y genera tf y tfstate a través de una plantilla.
Hay 3 problemas aquí:
1. Siempre habrá un retraso en las actualizaciones.
2. Los archivos tf a veces salen rotos
3. tfstate se recopila por separado de tf y no siempre converge
En general, es difícil obtener un resultado en el que el "plan terraforma" diga que no hay cambios.
2. `terraform import` es un comando integrado en terraform. ¿Como funciona?
Escribe un archivo TF vacío con el nombre y tipo de recurso, luego ejecuta "terraform import" y pasa el ID del recurso. Terraform se pone en contacto con el proveedor, recibe los datos y crea un archivo tfstate.
Hay 3 problemas aquí:
1. Solo obtenemos un archivo tfstate y el tf está vacío, debe escribirlo manualmente o convertirlo desde tfstate
2. Solo puede trabajar con un recurso a la vez y no admite todos los recursos. ¿Y qué debo hacer de nuevo con más de 250 depósitos?
3. Necesita conocer el ID de los recursos; es decir, debe incluirlo en un código que obtenga la lista de recursos.
En general, el resultado es parcial y no escala bien.
Mi decisión
requisitos:
1. Capacidad para crear archivos tf y tfstate para recursos. Por ejemplo, descargue todos los depósitos/grupo de seguridad/equilibrador de carga y ese "plan de terraformación" devolvió que no hay cambios.
2. Necesitas 2 nubes GCP + AWS
3. Solución global que es fácil de actualizar cada vez y no pierde tiempo en cada recurso durante 3 días de trabajo.
4. Hágalo de código abierto: todos tienen el mismo problema
El lenguaje Go es la razón por la que me encanta, y tiene una biblioteca para crear archivos HCL que se usa en terraform + mucho código en terraform que puede ser útil.
Camino
Primer intento
Empecé con una versión sencilla. Contactar con la nube a través del SDK para obtener el recurso requerido y convertirlo en campos para terraform. El intento falló inmediatamente en el grupo de seguridad porque no me gustó el día y medio para convertir solo el grupo de seguridad (y hay muchos recursos). Durante mucho tiempo y luego se pueden cambiar/agregar campos
Segundo intento
Basado en la idea descrita.
Ahora hagamos la pornografía recursiva de escribir un convertidor de tfstate a tf. Para los que nunca han leído tfstate, es JSON, pero especial.
Aquí están sus 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",
Hay:
1. identificación - cadena
2. metadatos: una matriz de tamaño 1 y en ella un objeto con campos que se describe a continuación
3. especificación: hash de tamaño 1 y clave, valor en él
En definitiva, un formato divertido, todo puede tener varios niveles de profundidad.
"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 general, si alguien quiere un problema de programación para una entrevista, simplemente pídale que escriba un analizador para esta tarea :)
Después de muchos intentos de escribir un analizador sin errores, encontré una parte en el código de Terraform y la parte más importante. Y todo parecía funcionar bien
intento tres
Los proveedores de Terraform son archivos binarios que contienen código con todos los recursos y la lógica para trabajar con la API de la nube. Cada nube tiene su propio proveedor y la propia terraform sólo los llama a través de su protocolo RPC entre dos procesos.
Ahora decidí contactar a los proveedores de Terraform directamente mediante llamadas RPC. Resultó hermoso e hizo posible cambiar los proveedores de Terraform por otros más nuevos y obtener nuevas funciones sin cambiar el código. También resulta que no todos los campos en tfstate deberían estar en tf, pero ¿cómo puedes saberlo? Pregúntele a su proveedor sobre esto. Luego comenzó otra pornografía recursiva de ensamblar expresiones regulares, buscando campos dentro de tfstate en todos los niveles en profundidad.
Al final, obtuvimos una herramienta CLI útil que tiene una infraestructura común para todos los proveedores de Terraform y puedes agregar fácilmente una nueva. Además, agregar recursos requiere poco código. Además de todo tipo de ventajas, como conexiones entre recursos. Por supuesto, hubo muchos problemas diferentes que no se pueden describir todos.
Llamé al animal Terrafomer.
Final
Usando Terrafomer, generamos entre 500 y 700 mil líneas de código tf + tfstate a partir de dos nubes. Pudimos tomar cosas heredadas y comenzar a tocarlas solo a través de terraform, como en la mejor infraestructura como ideas de código. Es simplemente mágico cuando tomas una nube enorme y la recibes a través de un equipo en forma de archivos de trabajadores de Terraform. Y luego grep/replace/git y así sucesivamente.
Lo peiné y lo puse en orden, obtuve permiso. Lanzado en GitHub para todos el jueves (02.05.19/XNUMX/XNUMX).
Ya recibí 600 estrellas, 2 solicitudes de extracción para agregar soporte para openstack y kubernetes. Buenos comentarios. En general, el proyecto es útil para las personas.
Aconsejo a todos los que quieran empezar a trabajar con Terraform que no reescriban todo para ello.
Estaré encantado de recibir solicitudes, problemas y estrellas.
Manifestación
Fuente: habr.com