<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Automatización on Adur</title><link>https://adurrr.github.io/tags/automatizaci%C3%B3n/</link><description>Recent content in Automatización on Adur</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Mon, 20 Oct 2025 00:00:00 +0000</lastBuildDate><atom:link href="https://adurrr.github.io/tags/automatizaci%C3%B3n/index.xml" rel="self" type="application/rss+xml"/><item><title>Lecciones aprendidas en DevSecOps</title><link>https://adurrr.github.io/p/lecciones-aprendidas-en-devsecops/</link><pubDate>Mon, 20 Oct 2025 00:00:00 +0000</pubDate><guid>https://adurrr.github.io/p/lecciones-aprendidas-en-devsecops/</guid><description>&lt;p&gt;DevSecOps se usa mucho en ofertas de trabajo y charlas. Pero detrás del buzzword hay lecciones reales que solo vienen de hacer el trabajo. De construir pipelines que se rompen cuando añades seguridad, de ver equipos ignorar herramientas que pasaste meses desplegando, hasta finalmente encontrar qué funciona.&lt;/p&gt;
&lt;p&gt;Estas son lecciones que aprendimos a base de golpes. Son opiniones fundamentadas, prácticas, moldeadas por experiencia real.&lt;/p&gt;
&lt;h2 id="la-seguridad-es-responsabilidad-de-todos"&gt;La seguridad es responsabilidad de todos
&lt;/h2&gt;&lt;p&gt;Suena a póster, pero es la lección más importante. Si la seguridad es solo del equipo de seguridad, ya perdiste.&lt;/p&gt;
&lt;p&gt;Los desarrolladores toman decisiones de seguridad cada vez que escriben código, lo sepan o no. Cómo validan entrada. Cómo manejan secretos. Cómo configuran acceso de red. Cada PR es un evento de seguridad.&lt;/p&gt;
&lt;p&gt;Lo que funciona: haz seguridad parte del flujo de desarrollo normal, no una puerta al final. Los desarrolladores aprenden cuando reciben feedback rápido sobre problemas de seguridad en su PR. Lo resientan cuando se enteran tres semanas después de un auditor.&lt;/p&gt;
&lt;p&gt;Lo hemos visto repetidamente: equipos que tratan seguridad como responsabilidad compartida encuentran menos vulnerabilidades críticas. Los que la aíslan las encuentran en las noticias.&lt;/p&gt;
&lt;h2 id="automatiza-todo-lo-que-puedas"&gt;Automatiza todo lo que puedas
&lt;/h2&gt;&lt;p&gt;Los procesos de seguridad manuales no escalan. Punto. Si tu revisión de seguridad es un humano leyendo una checklist, se saltará bajo presión de plazos, se aplicará de forma inconsistente y será odiada por todos los involucrados.&lt;/p&gt;
&lt;p&gt;Automatiza las cosas que se pueden automatizar:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Escaneo de dependencias&lt;/strong&gt; en cada build de CI (Dependabot, Snyk, Trivy)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Análisis estático&lt;/strong&gt; en cada pull request (Semgrep, SonarQube)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Detección de secretos&lt;/strong&gt; como pre-commit hook y check de CI (gitleaks, detect-secrets)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Escaneo de imágenes de contenedores&lt;/strong&gt; antes del despliegue (Trivy, Grype)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Escaneo de Infrastructure as Code&lt;/strong&gt; (tfsec, Checkov, KICS)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Compliance as Code&lt;/strong&gt; para cumplimiento de políticas en runtime (OPA, Kyverno)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;El objetivo no es capturarlo todo automáticamente. El objetivo es capturar lo fácil automáticamente para que los revisores humanos puedan centrarse en lo difícil: fallos en la lógica de negocio, problemas de seguridad a nivel de diseño, modelado de amenazas.&lt;/p&gt;
&lt;h2 id="empieza-pequeño"&gt;Empieza pequeño
&lt;/h2&gt;&lt;p&gt;Uno de los mayores errores que hemos cometido es intentar asegurar todo de golpe. Despliegas SAST, DAST, SCA, escaneo de contenedores, escaneo de IaC y protección en runtime en un trimestre. El resultado: fatiga de alertas, rebelión de los desarrolladores y un muro de hallazgos sin resolver que nadie mira.&lt;/p&gt;
&lt;p&gt;Empieza con una herramienta, un pipeline, un equipo. Haz que funcione bien. Que los desarrolladores se sientan cómodos con ello. Resuelve los falsos positivos. Ajusta las reglas. Después expande.&lt;/p&gt;
&lt;p&gt;Una progresión práctica:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Mes 1&lt;/strong&gt;: Detección de secretos en pre-commit hooks y CI. Esto es poco controvertido y captura problemas reales.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mes 2&lt;/strong&gt;: Escaneo de dependencias con creación automatizada de PRs para actualizaciones. Los desarrolladores ven el valor inmediatamente.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mes 3&lt;/strong&gt;: Escaneo de imágenes de contenedores bloqueando despliegues con vulnerabilidades críticas/altas.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mes 4+&lt;/strong&gt;: Análisis estático, expandiendo conjuntos de reglas gradualmente.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Cada paso debe ser estable antes de pasar al siguiente. Ir con prisas crea ruido, y el ruido enseña a la gente a ignorar alertas.&lt;/p&gt;
&lt;h2 id="la-cultura-blameless-importa"&gt;La cultura blameless importa
&lt;/h2&gt;&lt;p&gt;Cuando ocurre un incidente de seguridad porque alguien subió un secreto a un repo público, o porque una vulnerabilidad no se parcheó a tiempo, la respuesta importa más que el propio incidente.&lt;/p&gt;
&lt;p&gt;Si se culpa a la gente, ocultan cosas. No reportan casi-incidentes. Tapan errores. Y el siguiente incidente será peor porque nadie compartió las lecciones del anterior.&lt;/p&gt;
&lt;p&gt;Las postmortems blameless no consisten en librar a la gente de responsabilidad. Consisten en entender fallos sistémicos. Por qué fue posible subir un secreto? Por qué no había escaneo? Por qué el proceso de parcheo era lento? Arregla el sistema, no a la persona.&lt;/p&gt;
&lt;p&gt;Hemos comprobado que los equipos con culturas genuinamente blameless tienen posturas de seguridad significativamente mejores. La gente reporta cosas sospechosas. Piden ayuda pronto. Señalan riesgos antes de que se conviertan en incidentes.&lt;/p&gt;
&lt;h2 id="las-herramientas-no-bastan-sin-cambio-cultural"&gt;Las herramientas no bastan sin cambio cultural
&lt;/h2&gt;&lt;p&gt;Una vez desplegamos un pipeline de escaneo de seguridad completo con dashboards bonitos, notificaciones de Slack, creación de tickets en Jira, todo el paquete. Seis meses después, había 3.000 hallazgos sin resolver y el canal de Slack estaba silenciado por todos los desarrolladores.&lt;/p&gt;
&lt;p&gt;Las herramientas estaban bien. La cultura no estaba preparada.&lt;/p&gt;
&lt;p&gt;Antes de desplegar herramientas, invierte en:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Formación&lt;/strong&gt;: Los desarrolladores necesitan entender por qué existe la herramienta y cómo actuar sobre sus hallazgos.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ownership&lt;/strong&gt;: Alguien necesita ser dueño del backlog de hallazgos y hacer triaje. Si nadie es dueño, nadie lo hace.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SLAs&lt;/strong&gt;: Define plazos claros para remediar hallazgos por severidad. Críticos en 48 horas. Altos en una semana. Medios en un sprint. Bajos en un trimestre.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bucles de feedback&lt;/strong&gt;: Cuando una herramienta produce un falso positivo, debe haber una forma fácil de reportarlo y que se ajuste la regla. De lo contrario, los desarrolladores aprenden a ignorar todo.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="invierte-en-la-experiencia-de-desarrollador-de-las-herramientas-de-seguridad"&gt;Invierte en la experiencia de desarrollador de las herramientas de seguridad
&lt;/h2&gt;&lt;p&gt;Si tu herramienta de seguridad hace la vida de los desarrolladores más difícil, encontrarán la forma de esquivarla. Esto no es un defecto de carácter. Es naturaleza humana y buen instinto de ingeniería: eliminar obstáculos para entregar.&lt;/p&gt;
&lt;p&gt;Las herramientas de seguridad que se adoptan son las que:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Ejecutan rápido&lt;/strong&gt;: Un escaneo SAST que tarda 20 minutos será esquivado. Uno que tarda 30 segundos será tolerado.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Se integran nativamente&lt;/strong&gt;: Muestra resultados en la PR, no en un portal separado. Nadie quiere hacer login en otro dashboard.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tienen baja tasa de falsos positivos&lt;/strong&gt;: Cada falso positivo erosiona la confianza. Invierte tiempo en el ajuste.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Proporcionan guía accionable&lt;/strong&gt;: &amp;ldquo;Vulnerabilidad de SQL injection en la línea 42&amp;rdquo; es inútil sin &amp;ldquo;así es como se arregla.&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fallan de forma elegante&lt;/strong&gt;: Si el escáner está caído, el pipeline debe avisar, no bloquear. La disponibilidad del pipeline de desarrollo no es negociable.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Lo pensamos así: si un desarrollador tiene que cambiar su flujo de trabajo para acomodar una herramienta de seguridad, la herramienta ha fallado. Las mejores herramientas de seguridad son invisibles.&lt;/p&gt;
&lt;h2 id="monitorización-y-observabilidad-no-son-negociables"&gt;Monitorización y observabilidad no son negociables
&lt;/h2&gt;&lt;p&gt;No puedes asegurar lo que no puedes ver. La monitorización de seguridad no es opcional, y no es algo que se añade después.&lt;/p&gt;
&lt;p&gt;Qué significa esto en la práctica:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Logging centralizado&lt;/strong&gt;: Todos los logs de aplicación, infraestructura y herramientas de seguridad en un solo lugar. Si tienes que hacer SSH a una máquina para leer logs, ya vas por detrás.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Audit trails&lt;/strong&gt;: Quién hizo qué, cuándo y desde dónde. Cada despliegue, cada cambio de configuración, cada solicitud de acceso.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Alertas sobre anomalías&lt;/strong&gt;: No solo &amp;ldquo;está el servicio arriba?&amp;rdquo; sino &amp;ldquo;es este patrón de acceso normal?&amp;rdquo; Volúmenes inusuales de llamadas a API, accesos desde nuevas ubicaciones, escalaciones de privilegios.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Seguridad en runtime&lt;/strong&gt;: Herramientas como Falco para monitorización de runtime de contenedores. Saber cuándo algo inesperado ocurre en producción.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;La monitorización también es cómo demuestras a auditores y clientes que tus controles de seguridad funcionan. &amp;ldquo;Confía en nosotros&amp;rdquo; no es una estrategia de cumplimiento.&lt;/p&gt;
&lt;h2 id="el-open-source-es-tu-aliado"&gt;El open source es tu aliado
&lt;/h2&gt;&lt;p&gt;Algunas de las mejores herramientas de seguridad disponibles son open source. Trivy, Falco, OPA, Semgrep, gitleaks, cosign, KICS, Checkov. El ecosistema es rico y madura rápidamente.&lt;/p&gt;
&lt;p&gt;Beneficios de las herramientas de seguridad open source:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Transparencia&lt;/strong&gt;: Puedes leer las reglas y entender exactamente qué se está comprobando.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Comunidad&lt;/strong&gt;: Miles de contribuidores encontrando casos límite y añadiendo reglas de detección.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sin vendor lock-in&lt;/strong&gt;: Puedes cambiar de herramienta sin renegociar un contrato.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Coste&lt;/strong&gt;: Empieza gratis, escala según necesites.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Esto no significa que las herramientas comerciales no tengan su lugar. Algunas proporcionan agregación, gestión y soporte valiosos. Pero puedes construir un pipeline de seguridad muy sólido solo con herramientas open source, y creemos que todos los equipos deberían empezar por ahí.&lt;/p&gt;
&lt;h2 id="el-aprendizaje-continuo-es-esencial"&gt;El aprendizaje continuo es esencial
&lt;/h2&gt;&lt;p&gt;El panorama de amenazas cambia constantemente. Las herramientas cambian. Las mejores prácticas evolucionan. Lo que se consideraba seguro hace dos años puede tener un CVE hoy.&lt;/p&gt;
&lt;p&gt;Lo que hacemos para mantenernos al día:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Dedicar tiempo al aprendizaje&lt;/strong&gt;: Al menos unas horas por sprint para que el equipo lea sobre nuevas vulnerabilidades, herramientas y técnicas. Esto no es un nice-to-have. Es un requisito profesional.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Organizar CTFs internos y ejercicios de mesa&lt;/strong&gt;: Nada enseña seguridad como intentar romper cosas. Los ejercicios regulares mantienen las habilidades afiladas y revelan brechas en tus defensas.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Participar en la comunidad&lt;/strong&gt;: Asistir a meetups, contribuir a open source, leer advisories. La comunidad de seguridad es generosa con el conocimiento. Aprovéchalo.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Revisar y actualizar&lt;/strong&gt;: Revisiones trimestrales de tu tooling de seguridad, políticas y procedimientos de respuesta a incidentes. Lo que funcionó el trimestre pasado puede no funcionar el próximo.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="reflexiones-finales"&gt;Reflexiones finales
&lt;/h2&gt;&lt;p&gt;DevSecOps no es un destino. No hay un punto donde digas &amp;ldquo;terminamos, somos seguros.&amp;rdquo; Es una práctica continua de reducir riesgo, mejorar visibilidad, construir una cultura donde seguridad sea tan natural como escribir tests.&lt;/p&gt;
&lt;p&gt;La lección más importante: lo perfecto es enemigo de lo bueno. Un pipeline básico que los desarrolladores usan de verdad vale infinitamente más que uno completo que esquivan. Empieza donde estás, mejora iterativamente, nunca pares.&lt;/p&gt;</description></item><item><title>LLMOps: integrando LLMs en flujos de trabajo DevOps</title><link>https://adurrr.github.io/p/llmops-integrando-llms-en-flujos-de-trabajo-devops/</link><pubDate>Sun, 15 Jun 2025 00:00:00 +0000</pubDate><guid>https://adurrr.github.io/p/llmops-integrando-llms-en-flujos-de-trabajo-devops/</guid><description>&lt;p&gt;Los LLMs han ido más allá de chatbots. Ahora se integran en flujos de trabajo de ingeniería donde automatizan tareas tediosas, aceleran respuesta a incidentes y potencian productividad. Pero desplegar un LLM en un pipeline de DevOps en producción es fundamentalmente diferente a usar ChatGPT en un navegador.&lt;/p&gt;
&lt;p&gt;Esta guía cubre qué significa LLMOps en la práctica, dónde encajan los LLMs en DevOps, patrones de arquitectura que funcionan y trampas que debes evitar.&lt;/p&gt;
&lt;h2 id="qué-es-llmops"&gt;Qué es LLMOps
&lt;/h2&gt;&lt;p&gt;LLMOps es el conjunto de prácticas, herramientas e infraestructura necesarios para operacionalizar LLMs. Extiende MLOps pero aborda desafíos únicos de los modelos de lenguaje:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Selección de modelo vs. entrenamiento de modelo&lt;/strong&gt;: La mayoría de equipos consumen modelos pre-entrenados (mediante APIs o inferencia auto-alojada) en lugar de entrenar desde cero. El foco operacional se desplaza hacia prompt engineering, fine-tuning y generación aumentada por recuperación (RAG).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Gestión de costes&lt;/strong&gt;: La inferencia con LLMs es cara. La tarificación por tokens significa que los costes escalan con el uso de formas más difíciles de predecir que el cómputo tradicional.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No determinismo&lt;/strong&gt;: Los LLMs producen salidas variables para la misma entrada, lo que complica las pruebas, la validación y la reproducibilidad.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Latencia&lt;/strong&gt;: Tiempos de respuesta de segundos (no milisegundos) requieren patrones arquitectónicos diferentes a los microservicios tradicionales.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;LLMOps no es una disciplina separada. Es una extensión de tus prácticas existentes de DevOps y MLOps, adaptada a las características operacionales específicas de los modelos de lenguaje.&lt;/p&gt;
&lt;h2 id="casos-de-uso-prácticos-en-devops"&gt;Casos de uso prácticos en DevOps
&lt;/h2&gt;&lt;p&gt;Aquí es donde los LLMs están aportando valor real en flujos de trabajo DevOps hoy en día:&lt;/p&gt;
&lt;h3 id="revisión-automatizada-de-código"&gt;Revisión automatizada de código
&lt;/h3&gt;&lt;p&gt;Los LLMs pueden proporcionar una primera pasada de revisión de pull requests, detectando problemas comunes como manejo de errores ausente, anti-patrones de seguridad, nomenclatura inconsistente o tests faltantes. No reemplazan a los revisores humanos, pero reducen la carga del feedback repetitivo.&lt;/p&gt;
&lt;h3 id="resumen-de-incidentes"&gt;Resumen de incidentes
&lt;/h3&gt;&lt;p&gt;Cuando un incidente salta a las 3 de la mañana, la persona de guardia necesita contexto rápido. Un LLM puede ingerir datos de alertas, logs de despliegues recientes, runbooks relacionados e informes de incidentes anteriores para producir un resumen conciso de lo que probablemente está fallando y qué se hizo la última vez.&lt;/p&gt;
&lt;h3 id="análisis-de-logs"&gt;Análisis de logs
&lt;/h3&gt;&lt;p&gt;Los LLMs son sorprendentemente efectivos en el reconocimiento de patrones en datos de logs no estructurados. Aliméntalos con un bloque de logs de error y pueden identificar la causa raíz más rápido que sesiones manuales de grep, especialmente para sistemas con los que no estás familiarizado.&lt;/p&gt;
&lt;h3 id="generación-de-documentación"&gt;Generación de documentación
&lt;/h3&gt;&lt;p&gt;Generar borradores de documentación a partir de código, esquemas de API o módulos de Terraform. El resultado necesita revisión humana, pero elimina el problema de la página en blanco y mantiene la documentación más cercana al estado actual.&lt;/p&gt;
&lt;h3 id="generación-de-infrastructure-as-code"&gt;Generación de Infrastructure as Code
&lt;/h3&gt;&lt;p&gt;Dada una descripción en lenguaje natural de la infraestructura deseada, los LLMs pueden generar manifiestos de Terraform, Ansible o Kubernetes como punto de partida. Útil para scaffolding, no para código listo para producción sin revisión.&lt;/p&gt;
&lt;h2 id="patrones-de-arquitectura-para-integración-de-llms"&gt;Patrones de arquitectura para integración de LLMs
&lt;/h2&gt;&lt;h3 id="patrón-1-api-gateway-a-llm-externo"&gt;Patrón 1: API gateway a LLM externo
&lt;/h3&gt;&lt;p&gt;El enfoque más simple. Tu aplicación llama a una API de LLM externa (OpenAI, Anthropic, etc.) a través de un gateway centralizado que gestiona autenticación, rate limiting, logging y seguimiento de costes.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[Pipeline CI/CD] --&amp;gt; [API Gateway] --&amp;gt; [API LLM Externa]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; |
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; [Logging y Métricas]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; |
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; [Seguimiento de Costes]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;: Sin infraestructura que gestionar, acceso a los modelos más capaces, rápido de implementar.
&lt;strong&gt;Contras&lt;/strong&gt;: Los datos salen de tu red, dependencia del proveedor, latencia variable, costes continuos de API.&lt;/p&gt;
&lt;h3 id="patrón-2-inferencia-auto-alojada"&gt;Patrón 2: Inferencia auto-alojada
&lt;/h3&gt;&lt;p&gt;Ejecutar modelos de pesos abiertos (Llama, Mistral, etc.) en tu propia infraestructura usando servidores de inferencia como vLLM u Ollama.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[Pipeline CI/CD] --&amp;gt; [Load Balancer] --&amp;gt; [Instancia(s) vLLM / Ollama]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; |
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; [Pool de Nodos GPU]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;: Los datos permanecen internos, costes predecibles a escala, sin dependencia de proveedor, control total sobre versiones del modelo.
&lt;strong&gt;Contras&lt;/strong&gt;: Requiere infraestructura GPU, sobrecarga operacional, modelos más pequeños pueden ser menos capaces.&lt;/p&gt;
&lt;h3 id="patrón-3-pipeline-mejorado-con-rag"&gt;Patrón 3: Pipeline mejorado con RAG
&lt;/h3&gt;&lt;p&gt;Combinar un LLM con un sistema de recuperación que proporciona contexto relevante de tu propia base de conocimiento (runbooks, documentación, incidentes pasados). Esto mejora drásticamente la calidad de las respuestas para tareas específicas del dominio.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[Consulta] --&amp;gt; [Modelo Embedding] --&amp;gt; [Búsqueda Vector DB] --&amp;gt; [Contexto + Consulta] --&amp;gt; [LLM] --&amp;gt; [Respuesta]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; |
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; [Tu Base de Conocimiento]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; (runbooks, docs, etc.)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Este patrón es particularmente potente para respuesta a incidentes y tareas de documentación donde el LLM necesita el contexto específico de tu organización.&lt;/p&gt;
&lt;h2 id="consideraciones-clave"&gt;Consideraciones clave
&lt;/h2&gt;&lt;h3 id="coste"&gt;Coste
&lt;/h3&gt;&lt;p&gt;Los costes de API de LLMs pueden sorprender. Un pipeline de revisión de código que procesa 50 PRs al día con diffs grandes puede fácilmente alcanzar cientos de dólares al mes. Estrategias para controlar costes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Establecer límites de tokens por petición&lt;/li&gt;
&lt;li&gt;Cachear consultas y respuestas comunes&lt;/li&gt;
&lt;li&gt;Usar modelos más pequeños para tareas simples (triaje con un modelo pequeño, escalar a uno mayor)&lt;/li&gt;
&lt;li&gt;Monitorizar el uso de tokens por pipeline y configurar alertas&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="latencia"&gt;Latencia
&lt;/h3&gt;&lt;p&gt;Las respuestas de LLMs tardan segundos, no milisegundos. Diseña tus integraciones como procesos asíncronos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Publicar comentarios de revisión de código después del hecho, no bloquear la PR&lt;/li&gt;
&lt;li&gt;Procesar datos de incidentes en segundo plano, enviar resultados a un canal de Slack&lt;/li&gt;
&lt;li&gt;Usar streaming de respuestas donde sea posible para mejorar el rendimiento percibido&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="alucinaciones"&gt;Alucinaciones
&lt;/h3&gt;&lt;p&gt;Los LLMs generarán con confianza información que suena plausible pero es incorrecta. Esta es una preocupación crítica para tareas de DevOps donde un mal consejo puede causar caídas.&lt;/p&gt;
&lt;p&gt;Mitigaciones:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Siempre presentar la salida del LLM como sugerencias, nunca como acciones autoritativas&lt;/li&gt;
&lt;li&gt;Requerir aprobación humana antes de aplicar cualquier cambio generado por LLM&lt;/li&gt;
&lt;li&gt;Usar RAG para anclar las respuestas en documentación verificada&lt;/li&gt;
&lt;li&gt;Implementar validación de salida (por ejemplo, lint del IaC generado antes de presentarlo)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="seguridad"&gt;Seguridad
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Exposición de datos&lt;/strong&gt;: Cualquier cosa que envíes a una API de LLM externa puede ser usada para entrenamiento o almacenada. Nunca envíes secretos, credenciales o datos sensibles de clientes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Prompt injection&lt;/strong&gt;: Contenido malicioso en código, logs o entrada de usuario puede manipular el comportamiento del LLM. Sanitiza las entradas y valida las salidas.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cadena de suministro&lt;/strong&gt;: El código generado por LLM puede introducir vulnerabilidades. Pasa todo el código generado por tu pipeline de escaneo de seguridad existente.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="herramientas-y-plataformas"&gt;Herramientas y plataformas
&lt;/h2&gt;&lt;h3 id="langchain"&gt;LangChain
&lt;/h3&gt;&lt;p&gt;Un framework para construir aplicaciones potenciadas por LLMs. Útil para orquestar cadenas de múltiples pasos (por ejemplo, recuperar contexto, formatear prompt, llamar al LLM, parsear la salida). Soporta muchos proveedores de LLMs y tiene buen tooling para pipelines RAG.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;langchain.chat_models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ChatOpenAI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;langchain.prompts&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ChatPromptTemplate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ChatPromptTemplate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Review this code diff for security issues and suggest fixes:&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="si"&gt;{diff}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;chain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;ChatOpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;gpt-4o&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chain&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;diff&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;code_diff&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="vllm"&gt;vLLM
&lt;/h3&gt;&lt;p&gt;Un motor de inferencia de alto rendimiento para modelos auto-alojados. Soporta PagedAttention para gestión eficiente de memoria y continuous batching para alto throughput.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Iniciar un servidor vLLM&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;python -m vllm.entrypoints.openai.api_server &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --model mistralai/Mistral-7B-Instruct-v0.2 &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --port &lt;span class="m"&gt;8000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Expone una API compatible con OpenAI, así que puedes cambiar entre APIs auto-alojadas y externas con cambios mínimos de código.&lt;/p&gt;
&lt;h3 id="ollama"&gt;Ollama
&lt;/h3&gt;&lt;p&gt;La forma más fácil de ejecutar LLMs localmente para desarrollo y pruebas. Ideal para prototipar pipelines antes de comprometerte con infraestructura.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Descargar y ejecutar un modelo&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ollama pull llama3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ollama run llama3 &lt;span class="s2"&gt;&amp;#34;Summarize this error log: [paste log]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Servir como API&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ollama serve
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Luego llamar a http://localhost:11434/api/generate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="ejemplo-pipeline-de-revisión-automatizada-de-prs"&gt;Ejemplo: Pipeline de revisión automatizada de PRs
&lt;/h2&gt;&lt;p&gt;Aquí tienes un pipeline conceptual para revisión automatizada de PRs usando un LLM:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;span class="lnt"&gt;29
&lt;/span&gt;&lt;span class="lnt"&gt;30
&lt;/span&gt;&lt;span class="lnt"&gt;31
&lt;/span&gt;&lt;span class="lnt"&gt;32
&lt;/span&gt;&lt;span class="lnt"&gt;33
&lt;/span&gt;&lt;span class="lnt"&gt;34
&lt;/span&gt;&lt;span class="lnt"&gt;35
&lt;/span&gt;&lt;span class="lnt"&gt;36
&lt;/span&gt;&lt;span class="lnt"&gt;37
&lt;/span&gt;&lt;span class="lnt"&gt;38
&lt;/span&gt;&lt;span class="lnt"&gt;39
&lt;/span&gt;&lt;span class="lnt"&gt;40
&lt;/span&gt;&lt;span class="lnt"&gt;41
&lt;/span&gt;&lt;span class="lnt"&gt;42
&lt;/span&gt;&lt;span class="lnt"&gt;43
&lt;/span&gt;&lt;span class="lnt"&gt;44
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# .github/workflows/llm-review.yml&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;LLM Code Review&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;pull_request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;types&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="l"&gt;opened, synchronize]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;llm-review&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Checkout&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/checkout@v4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;fetch-depth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Get diff&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;diff&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="sd"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; git diff origin/${{ github.base_ref }}...HEAD &amp;gt; diff.txt&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Run LLM review&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;LLM_API_KEY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${{ secrets.LLM_API_KEY }}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="sd"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; python scripts/llm_review.py \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; --diff diff.txt \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; --model gpt-4o \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; --max-tokens 2000 \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; --output review.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Post review comments&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/github-script@v7&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="sd"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; const review = require(&amp;#39;./review.json&amp;#39;);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; await github.rest.pulls.createReview({
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; owner: context.repo.owner,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; repo: context.repo.repo,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; pull_number: context.issue.number,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; body: review.summary,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; event: &amp;#39;COMMENT&amp;#39;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; comments: review.line_comments
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; });&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;El script de revisión:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Lee el diff&lt;/li&gt;
&lt;li&gt;Divide diffs grandes en fragmentos que quepan en la ventana de contexto del modelo&lt;/li&gt;
&lt;li&gt;Para cada fragmento, construye un prompt pidiendo problemas de seguridad, bugs y problemas de estilo&lt;/li&gt;
&lt;li&gt;Agrega resultados y formatea como comentarios de revisión de GitHub&lt;/li&gt;
&lt;li&gt;Incluye puntuaciones de confianza y siempre marca la salida como generada por IA&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="guardrails-y-uso-responsable"&gt;Guardrails y uso responsable
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Etiqueta claramente toda la salida del LLM&lt;/strong&gt; como generada por IA. Los ingenieros deben saber cuándo están leyendo salida de una máquina.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Nunca auto-mergees ni auto-apliques&lt;/strong&gt; sugerencias del LLM. Mantén un humano en el bucle para todos los cambios.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Registra todos los prompts y respuestas&lt;/strong&gt; para depuración y auditoría.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Establece límites de gasto&lt;/strong&gt; y alertas sobre el uso de API de LLMs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Revisa las plantillas de prompts regularmente&lt;/strong&gt; para asegurarte de que no filtran información sensible.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Prueba sesgos y errores&lt;/strong&gt; con muestras representativas antes de desplegar en flujos de trabajo de producción.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="recomendaciones-para-empezar"&gt;Recomendaciones para empezar
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Elige un caso de uso&lt;/strong&gt; - No intentes habilitar LLMs en todo. Empieza bajo riesgo: borradores, sugerencias de commits.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Empieza con API externa&lt;/strong&gt; - No inviertas en GPU hasta validar el caso. Usa OpenAI o Anthropic para prototipar.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mide todo&lt;/strong&gt; - Registra coste por invocación, latencia, satisfacción, tasas de error desde el primer día.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Construye un framework&lt;/strong&gt; - Crea un suite de tests con entradas y salidas conocidas. Ejecútalo contra cada cambio de prompt o modelo.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Planifica tu estrategia de datos&lt;/strong&gt; - Decide qué datos enviarás a APIs externas. Documéntalo.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Itera en prompts&lt;/strong&gt; - El prompt engineering es iterativo. Versiona prompts, trátalos como código.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Los LLMs son una herramienta potente para DevOps, pero son exactamente eso: una herramienta. Funcionan mejor cuando se integran de forma reflexiva en flujos existentes, con límites claros sobre qué pueden y no pueden hacer autonomamente.&lt;/p&gt;</description></item><item><title>Modelo de madurez de DevSecOps</title><link>https://adurrr.github.io/p/modelo-de-madurez-de-devsecops/</link><pubDate>Sun, 08 Oct 2023 10:00:00 +0100</pubDate><guid>https://adurrr.github.io/p/modelo-de-madurez-de-devsecops/</guid><description>&lt;h2 id="por-qué-un-modelo-de-madurez-ayuda"&gt;Por qué un modelo de madurez ayuda
&lt;/h2&gt;&lt;p&gt;La mayoría de los equipos saben que deberían &amp;ldquo;desplazar la seguridad a la izquierda&amp;rdquo;, pero saber por dónde empezar es la parte difícil. Un modelo de madurez proporciona una forma estructurada de evaluar el estado actual, identificar brechas y planificar una hoja de ruta realista para mejorar.&lt;/p&gt;
&lt;p&gt;Sin un modelo, las mejoras de seguridad tienden a ser reactivas (desencadenadas por incidentes o hallazgos de auditoría en lugar de por una planificación deliberada). Un modelo de madurez convierte la seguridad de un simulacro de incendio en una disciplina de ingeniería con progreso medible.&lt;/p&gt;
&lt;p&gt;El modelo descrito aquí tiene cinco niveles. El objetivo no es correr al nivel más alto, sino hacer un progreso constante y sostenible. Cada nivel se construye sobre el anterior.&lt;/p&gt;
&lt;h2 id="los-cinco-niveles-de-madurez"&gt;Los cinco niveles de madurez
&lt;/h2&gt;&lt;h3 id="nivel-1-ad-hoc"&gt;Nivel 1: Ad-Hoc
&lt;/h3&gt;&lt;p&gt;En este nivel, la seguridad es algo secundario. No existen procesos formales y las actividades de seguridad ocurren de forma esporádica, si es que ocurren.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cómo se ve:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sin pruebas de seguridad en los pipelines de CI/CD.&lt;/li&gt;
&lt;li&gt;Las vulnerabilidades se descubren en producción o por terceros.&lt;/li&gt;
&lt;li&gt;Sin herramientas de seguridad dedicadas.&lt;/li&gt;
&lt;li&gt;Los desarrolladores tienen poca o ninguna formación en seguridad.&lt;/li&gt;
&lt;li&gt;La respuesta a incidentes es improvisada.&lt;/li&gt;
&lt;li&gt;El cumplimiento normativo se aborda manualmente antes de las auditorías.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Herramientas típicas:&lt;/strong&gt; Ninguna específica de seguridad. Quizás un firewall y un antivirus.&lt;/p&gt;
&lt;h3 id="nivel-2-reactivo"&gt;Nivel 2: Reactivo
&lt;/h3&gt;&lt;p&gt;La seguridad se reconoce como importante, pero el enfoque es reactivo. El equipo responde a vulnerabilidades e incidentes pero no los previene de manera proactiva.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cómo se ve:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;El análisis estático básico (SAST) se ejecuta ocasionalmente, pero los hallazgos no siempre se abordan.&lt;/li&gt;
&lt;li&gt;El escaneo de dependencias se hace de forma manual o ad-hoc.&lt;/li&gt;
&lt;li&gt;Hay documentación de seguridad, pero está desactualizada.&lt;/li&gt;
&lt;li&gt;La respuesta a incidentes existe como un proceso documentado, aunque se practica raramente.&lt;/li&gt;
&lt;li&gt;Las revisiones de seguridad ocurren tarde en el ciclo de desarrollo (justo antes del lanzamiento).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Herramientas típicas:&lt;/strong&gt; SonarQube (reglas básicas), OWASP Dependency-Check, pruebas de penetración manuales.&lt;/p&gt;
&lt;h3 id="nivel-3-proactivo"&gt;Nivel 3: Proactivo
&lt;/h3&gt;&lt;p&gt;La seguridad está integrada en el flujo de trabajo de desarrollo. El equipo busca activamente prevenir vulnerabilidades en lugar de solo reaccionar ante ellas.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cómo se ve:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SAST y DAST se ejecutan automáticamente en los pipelines de CI/CD.&lt;/li&gt;
&lt;li&gt;Escaneo de dependencias con alertas automáticas para vulnerabilidades conocidas.&lt;/li&gt;
&lt;li&gt;Escaneo de imágenes de contenedores antes del despliegue (Trivy, Grype).&lt;/li&gt;
&lt;li&gt;La Infrastructure as Code se escanea en busca de configuraciones incorrectas (Checkov, tfsec).&lt;/li&gt;
&lt;li&gt;Se realiza threat modeling para nuevas funcionalidades y cambios de arquitectura.&lt;/li&gt;
&lt;li&gt;Existen security champions dentro de los equipos de desarrollo.&lt;/li&gt;
&lt;li&gt;Se realizan postmortems sin culpa después de incidentes de seguridad.&lt;/li&gt;
&lt;li&gt;Formación regular en seguridad para desarrolladores.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Herramientas típicas:&lt;/strong&gt; Semgrep, Trivy, Checkov, OWASP ZAP, HashiCorp Vault, Falco.&lt;/p&gt;
&lt;h3 id="nivel-4-optimizado"&gt;Nivel 4: Optimizado
&lt;/h3&gt;&lt;p&gt;La seguridad está profundamente integrada en cada etapa del ciclo de vida del software. Las métricas guían las decisiones y el equipo mejora continuamente basándose en datos.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cómo se ve:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Puertas de seguridad en los pipelines que bloquean el despliegue si se encuentran problemas críticos.&lt;/li&gt;
&lt;li&gt;El tiempo medio de remediación (MTTR) se rastrea y se reduce continuamente.&lt;/li&gt;
&lt;li&gt;Se genera un Software Bill of Materials (SBOM) para cada release.&lt;/li&gt;
&lt;li&gt;Artefactos firmados y cadena de suministro verificada.&lt;/li&gt;
&lt;li&gt;Comprobaciones de cumplimiento automatizadas mapeadas a frameworks (SOC2, ISO 27001, PCI-DSS).&lt;/li&gt;
&lt;li&gt;Monitorización de seguridad en runtime con respuesta automatizada (Falco + reglas personalizadas).&lt;/li&gt;
&lt;li&gt;Ejercicios regulares de red team y chaos engineering para seguridad.&lt;/li&gt;
&lt;li&gt;Las métricas de seguridad forman parte de los dashboards de ingeniería.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Herramientas típicas:&lt;/strong&gt; Sigstore/cosign, OPA/Gatekeeper, Kyverno, integración con SIEM, plataformas de cumplimiento automatizado.&lt;/p&gt;
&lt;h3 id="nivel-5-innovador"&gt;Nivel 5: Innovador
&lt;/h3&gt;&lt;p&gt;La seguridad es una ventaja competitiva. El equipo contribuye a la comunidad de seguridad en general y empuja el estado del arte.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cómo se ve:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Programas de bug bounty gestionados activamente.&lt;/li&gt;
&lt;li&gt;Herramientas de seguridad personalizadas desarrolladas para riesgos específicos de la organización.&lt;/li&gt;
&lt;li&gt;Machine learning aplicado a detección de anomalías y threat hunting.&lt;/li&gt;
&lt;li&gt;La seguridad es una característica que se vende a los clientes (certificaciones, informes de transparencia).&lt;/li&gt;
&lt;li&gt;Participación activa en proyectos de seguridad open-source.&lt;/li&gt;
&lt;li&gt;Arquitectura zero-trust completamente implementada.&lt;/li&gt;
&lt;li&gt;Policy as code gobierna toda la seguridad de infraestructura y aplicaciones.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Herramientas típicas:&lt;/strong&gt; Plataformas construidas a medida, herramientas de seguridad basadas en eBPF, SIEM avanzado con ML, service mesh zero-trust.&lt;/p&gt;
&lt;h2 id="dimensiones-clave"&gt;Dimensiones clave
&lt;/h2&gt;&lt;p&gt;Un modelo de madurez no es unidimensional. Evalúa tu organización en estas dimensiones, ya que el progreso rara vez es parejo:&lt;/p&gt;
&lt;h3 id="seguridad-del-código"&gt;Seguridad del código
&lt;/h3&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Nivel&lt;/th&gt;
 &lt;th&gt;Prácticas&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Ad-Hoc&lt;/td&gt;
 &lt;td&gt;Sin escaneo de código&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Reactivo&lt;/td&gt;
 &lt;td&gt;SAST ocasional, revisiones de código manuales orientadas a seguridad&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Proactivo&lt;/td&gt;
 &lt;td&gt;SAST/DAST automatizado en CI, directrices de revisión de código enfocadas en seguridad&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Optimizado&lt;/td&gt;
 &lt;td&gt;Reglas personalizadas para patrones específicos de la organización, MTTR rastreado&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Innovador&lt;/td&gt;
 &lt;td&gt;Revisión de código asistida por IA, sugerencias automáticas de corrección&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="seguridad-de-la-infraestructura"&gt;Seguridad de la infraestructura
&lt;/h3&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Nivel&lt;/th&gt;
 &lt;th&gt;Prácticas&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Ad-Hoc&lt;/td&gt;
 &lt;td&gt;Configuración manual de servidores, sin estándares de hardening&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Reactivo&lt;/td&gt;
 &lt;td&gt;Checklists básicas de hardening, auditorías ocasionales&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Proactivo&lt;/td&gt;
 &lt;td&gt;Escaneo de IaC, hardening automatizado, CIS benchmarks&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Optimizado&lt;/td&gt;
 &lt;td&gt;Policy as code (OPA), detección de drift, remediación automatizada&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Innovador&lt;/td&gt;
 &lt;td&gt;Infraestructura auto-reparable, redes zero-trust&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="monitorización-y-detección"&gt;Monitorización y detección
&lt;/h3&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Nivel&lt;/th&gt;
 &lt;th&gt;Prácticas&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Ad-Hoc&lt;/td&gt;
 &lt;td&gt;Sin monitorización de seguridad&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Reactivo&lt;/td&gt;
 &lt;td&gt;Recopilación básica de logs, revisión manual después de incidentes&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Proactivo&lt;/td&gt;
 &lt;td&gt;Logging centralizado, alertas sobre patrones conocidos, monitorización en runtime&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Optimizado&lt;/td&gt;
 &lt;td&gt;SIEM con reglas de correlación, playbooks de respuesta automatizada&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Innovador&lt;/td&gt;
 &lt;td&gt;Detección de anomalías basada en ML, programas de threat hunting&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="respuesta-a-incidentes"&gt;Respuesta a incidentes
&lt;/h3&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Nivel&lt;/th&gt;
 &lt;th&gt;Prácticas&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Ad-Hoc&lt;/td&gt;
 &lt;td&gt;Sin proceso, respuesta improvisada&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Reactivo&lt;/td&gt;
 &lt;td&gt;Runbooks documentados, raramente probados&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Proactivo&lt;/td&gt;
 &lt;td&gt;Ejercicios regulares de simulación, postmortems sin culpa, rotación de guardia&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Optimizado&lt;/td&gt;
 &lt;td&gt;Clasificación automatizada de incidentes, tiempos de respuesta basados en SLA&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Innovador&lt;/td&gt;
 &lt;td&gt;Chaos engineering para seguridad, contención automatizada&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="cumplimiento-normativo"&gt;Cumplimiento normativo
&lt;/h3&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Nivel&lt;/th&gt;
 &lt;th&gt;Prácticas&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Ad-Hoc&lt;/td&gt;
 &lt;td&gt;Recopilación manual de evidencias antes de auditorías&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Reactivo&lt;/td&gt;
 &lt;td&gt;Seguimiento en hojas de cálculo, revisiones periódicas&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Proactivo&lt;/td&gt;
 &lt;td&gt;Recopilación automatizada de evidencias, monitorización continua&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Optimizado&lt;/td&gt;
 &lt;td&gt;Compliance as code, dashboards en tiempo real, informes automatizados&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Innovador&lt;/td&gt;
 &lt;td&gt;Certificación continua, informes públicos de transparencia&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="checklist-de-autoevaluación"&gt;Checklist de autoevaluación
&lt;/h2&gt;&lt;p&gt;Califica tu organización en cada punto (Sí / Parcial / No):&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fase de build:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; SAST se ejecuta automáticamente en cada pull request.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; El escaneo de dependencias alerta sobre CVEs conocidos.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Las imágenes de contenedores se escanean antes de publicarse en un registry.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Las plantillas de IaC se escanean en busca de configuraciones incorrectas.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; La detección de secretos impide que se hagan commit de credenciales.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Fase de despliegue:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Las puertas de seguridad pueden bloquear el despliegue por hallazgos críticos.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Los artefactos están firmados y las firmas se verifican.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Se genera un SBOM para cada release.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Los cambios de infraestructura pasan por validación de policy-as-code.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Fase de ejecución:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; La monitorización de seguridad en runtime está activa (Falco, Sysdig, etc.).&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Logging centralizado con alertas relevantes para seguridad.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; La segmentación de red limita el radio de impacto.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Los secretos se gestionan a través de un vault dedicado.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Cultura y procesos:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Los desarrolladores reciben formación regular en seguridad.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Hay security champions integrados en los equipos de desarrollo.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Se realizan postmortems sin culpa después de los incidentes.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; El threat modeling es parte del proceso de diseño de nuevas funcionalidades.&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Las métricas de seguridad se rastrean y revisan regularmente.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="hoja-de-ruta-para-la-progresión"&gt;Hoja de ruta para la progresión
&lt;/h2&gt;&lt;p&gt;Subir de nivel de madurez no ocurre de la noche a la mañana. Aquí tienes una hoja de ruta práctica:&lt;/p&gt;
&lt;h3 id="de-ad-hoc-a-reactivo-3-6-meses"&gt;De Ad-Hoc a Reactivo (3-6 meses)
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;Añade una herramienta SAST a tu pipeline de CI (empieza con Semgrep, tiene buenos valores por defecto y es rápido).&lt;/li&gt;
&lt;li&gt;Habilita el escaneo de dependencias (GitHub Dependabot, o &lt;code&gt;trivy fs&lt;/code&gt; en CI).&lt;/li&gt;
&lt;li&gt;Documenta tu proceso de respuesta a incidentes, aunque sea básico.&lt;/li&gt;
&lt;li&gt;Realiza una sesión de formación en seguridad para el equipo.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="de-reactivo-a-proactivo-6-12-meses"&gt;De Reactivo a Proactivo (6-12 meses)
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;Añade escaneo de imágenes de contenedores y escaneo de IaC a los pipelines.&lt;/li&gt;
&lt;li&gt;Implementa detección de secretos en pre-commit hooks (&lt;code&gt;gitleaks&lt;/code&gt;, &lt;code&gt;detect-secrets&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Nombra security champions en cada equipo.&lt;/li&gt;
&lt;li&gt;Comienza a hacer threat modeling para funcionalidades importantes.&lt;/li&gt;
&lt;li&gt;Realiza tu primer postmortem sin culpa después de un incidente.&lt;/li&gt;
&lt;li&gt;Despliega monitorización en runtime (Falco).&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="de-proactivo-a-optimizado-12-18-meses"&gt;De Proactivo a Optimizado (12-18 meses)
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;Implementa puertas de seguridad que puedan bloquear despliegues.&lt;/li&gt;
&lt;li&gt;Rastrea el MTTR y establece objetivos de reducción.&lt;/li&gt;
&lt;li&gt;Genera SBOMs y firma los artefactos.&lt;/li&gt;
&lt;li&gt;Implementa policy-as-code para infraestructura (OPA/Gatekeeper).&lt;/li&gt;
&lt;li&gt;Mapea las comprobaciones automatizadas a frameworks de cumplimiento.&lt;/li&gt;
&lt;li&gt;Integra las métricas de seguridad en los dashboards de ingeniería.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="de-optimizado-a-innovador-18-meses"&gt;De Optimizado a Innovador (18+ meses)
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;Lanza un programa de bug bounty.&lt;/li&gt;
&lt;li&gt;Construye herramientas de seguridad personalizadas para riesgos específicos de la organización.&lt;/li&gt;
&lt;li&gt;Implementa arquitectura zero-trust.&lt;/li&gt;
&lt;li&gt;Realiza ejercicios regulares de red team.&lt;/li&gt;
&lt;li&gt;Contribuye a proyectos de seguridad open-source.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="aspectos-culturales"&gt;Aspectos culturales
&lt;/h2&gt;&lt;p&gt;Las herramientas y los procesos son necesarios pero insuficientes. La cultura determina si las prácticas de seguridad realmente se mantienen.&lt;/p&gt;
&lt;h3 id="postmortems-sin-culpa"&gt;Postmortems sin culpa
&lt;/h3&gt;&lt;p&gt;Cuando ocurre un incidente de seguridad, el instinto suele ser buscar a alguien a quien culpar. Esto lleva a la gente a ocultar errores y encubrir casi-incidentes. Los postmortems sin culpa le dan la vuelta a esto: se centran en los fallos sistémicos y las mejoras de procesos en lugar de la responsabilidad individual. La pregunta cambia de &amp;ldquo;quién cometió este error&amp;rdquo; a &amp;ldquo;qué permitió que este error ocurriera y cómo lo prevenimos&amp;rdquo;.&lt;/p&gt;
&lt;h3 id="security-champions"&gt;Security Champions
&lt;/h3&gt;&lt;p&gt;Un security champion es un desarrollador que asume responsabilidad adicional en materia de seguridad dentro de su equipo. No son ingenieros de seguridad a tiempo completo &amp;mdash; son desarrolladores que actúan como puente entre el equipo de seguridad y el equipo de desarrollo. Su papel incluye:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Revisar pull requests relevantes para seguridad.&lt;/li&gt;
&lt;li&gt;Mantenerse al día en temas de seguridad y compartir conocimiento.&lt;/li&gt;
&lt;li&gt;Participar en sesiones de threat modeling.&lt;/li&gt;
&lt;li&gt;Ser el primer punto de contacto para preguntas de seguridad.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Este modelo escala mucho mejor que tener un equipo central de seguridad revisando todo.&lt;/p&gt;
&lt;h3 id="hacer-la-seguridad-fácil"&gt;Hacer la seguridad fácil
&lt;/h3&gt;&lt;p&gt;Si las prácticas de seguridad son dolorosas, la gente buscará atajos. El objetivo es hacer que la seguridad sea el camino más fácil:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Proporciona plantillas seguras y proyectos de inicio.&lt;/li&gt;
&lt;li&gt;Automatiza tanto como sea posible para que los desarrolladores no tengan que recordar pasos manuales.&lt;/li&gt;
&lt;li&gt;Da feedback rápido. Un escaneo SAST que tarda 30 minutos será ignorado; uno que tarda 30 segundos será utilizado.&lt;/li&gt;
&lt;li&gt;Celebra las mejoras de seguridad igual que celebras la entrega de funcionalidades.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="conclusión"&gt;Conclusión
&lt;/h2&gt;&lt;p&gt;Un modelo de madurez DevSecOps es una brújula, no un destino. El valor viene de una autoevaluación honesta, establecer objetivos realistas y hacer un progreso constante. Empieza donde estás, elige la dimensión donde la mejora tendrá mayor impacto y construye a partir de ahí. La seguridad es un deporte de equipo. Las mejores culturas de seguridad se construyen de forma incremental, una práctica a la vez.&lt;/p&gt;</description></item><item><title>Introducción a AIOps: operaciones de TI inteligentes</title><link>https://adurrr.github.io/p/introducci%C3%B3n-a-aiops-operaciones-de-ti-inteligentes/</link><pubDate>Mon, 05 Dec 2022 00:00:00 +0000</pubDate><guid>https://adurrr.github.io/p/introducci%C3%B3n-a-aiops-operaciones-de-ti-inteligentes/</guid><description>&lt;h2 id="qué-es-aiops"&gt;¿Qué es AIOps?
&lt;/h2&gt;&lt;p&gt;AIOps (Artificial Intelligence for IT Operations) aplica machine learning y analítica de datos a los datos operativos (logs, métricas, eventos, trazas) para automatizar y mejorar flujos de trabajo. Gartner acuñó el término en 2017, pero la idea es simple: usar algoritmos para gestionar el volumen y la complejidad que los humanos no pueden manejar manualmente.&lt;/p&gt;
&lt;p&gt;En términos prácticos, las plataformas AIOps ingieren datos de herramientas de monitorización, sistemas APM, agregadores de logs y fuentes de eventos. Aplican modelos de ML para detectar anomalías, correlacionar eventos, identificar causas raíz y, en algunos casos, desencadenar remediación automatizada. El objetivo es reducir el tiempo medio de detección (MTTD) y el tiempo medio de resolución (MTTR) mientras se libera a los equipos de operaciones de la fatiga por alertas.&lt;/p&gt;
&lt;h2 id="por-qué-la-monitorización-tradicional-se-queda-corta"&gt;Por qué la monitorización tradicional se queda corta
&lt;/h2&gt;&lt;p&gt;La monitorización funcionaba bien cuando los sistemas eran simples. Tenías pocos servidores, unas pocas apps y un número limitado de métricas. Un umbral estático de CPU o un regex en logs era suficiente.&lt;/p&gt;
&lt;p&gt;La infraestructura moderna rompió ese modelo:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Escala&lt;/strong&gt;: Un clúster de Kubernetes genera millones de métricas y logs por minuto. No puedes vigilar dashboards a esa escala.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Complejidad&lt;/strong&gt;: Los microservicios crean dependencias enredadas. Una petición puede atravesar docenas de servicios. Encontrar qué causó una latencia significa correlacionar datos entre todos.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Entornos dinámicos&lt;/strong&gt;: Auto-scaling, contenedores efímeros, serverless. Las baselines cambian constantemente y los umbrales estáticos explotan con falsos positivos.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fatiga por alertas&lt;/strong&gt;: Los equipos se hunden en alertas. Cuando el 90% es ruido, ese crítico 10% desaparece. Los ingenieros empiezan a ignorar todo.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AIOps no reemplaza la monitorización. Se sitúa encima de lo que ya tienes y lo hace más inteligente.&lt;/p&gt;
&lt;h2 id="capacidades-clave"&gt;Capacidades clave
&lt;/h2&gt;&lt;h3 id="1-detección-de-anomalías"&gt;1. Detección de anomalías
&lt;/h3&gt;&lt;p&gt;En lugar de umbrales estáticos, AIOps usa modelos de ML (frecuentemente análisis de series temporales, clustering o autoencoders) para aprender qué aspecto tiene lo &amp;ldquo;normal&amp;rdquo; para cada métrica y servicio. Cuando el comportamiento se desvía significativamente de la línea base aprendida, se marca una anomalía.&lt;/p&gt;
&lt;p&gt;Esto maneja el problema de la línea base dinámica. Si tu aplicación normalmente ve un pico de tráfico cada lunes a las 9 de la mañana, el modelo aprende ese patrón y no alerta por ello. Pero un pico inesperado a las 3 de la madrugada de un miércoles sí se marca.&lt;/p&gt;
&lt;h3 id="2-correlación-de-eventos"&gt;2. Correlación de eventos
&lt;/h3&gt;&lt;p&gt;Un único problema de infraestructura puede generar cientos o miles de alertas relacionadas en diferentes herramientas de monitorización. AIOps correlaciona estos eventos — agrupándolos por tiempo, topología y relaciones causales — para presentar un único incidente en lugar de un muro de alertas.&lt;/p&gt;
&lt;p&gt;Por ejemplo, un fallo en un switch de red podría disparar alertas en: el propio switch, todos los servidores conectados (conectividad perdida), todas las aplicaciones en esos servidores (fallos en health checks), y servicios downstream (errores de timeout). Una plataforma AIOps correlaciona todos estos en un incidente: &amp;ldquo;Switch de red X ha fallado.&amp;rdquo;&lt;/p&gt;
&lt;h3 id="3-análisis-de-causa-raíz"&gt;3. Análisis de causa raíz
&lt;/h3&gt;&lt;p&gt;Más allá de la correlación, AIOps intenta identificar la causa raíz de un incidente. Al comprender la topología de tu infraestructura y la cadena causal de eventos, puede sugerir que el fallo del switch de red es la causa raíz, en lugar de presentar el timeout de la aplicación como un problema independiente.&lt;/p&gt;
&lt;p&gt;Aquí es donde el valor se vuelve tangible. En lugar de que un ingeniero de guardia pase 30 minutos rastreando a través de dashboards y logs, la plataforma muestra la causa raíz probable inmediatamente.&lt;/p&gt;
&lt;h3 id="4-auto-remediación"&gt;4. Auto-remediación
&lt;/h3&gt;&lt;p&gt;Las implementaciones más maduras de AIOps cierran el ciclo disparando acciones de remediación automatizadas. Si se detecta un patrón conocido (disco llenándose, un pod en CrashLoopBackOff, un proceso descontrolado consumiendo memoria), la plataforma puede ejecutar runbooks predefinidos automáticamente.&lt;/p&gt;
&lt;p&gt;Ejemplos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reiniciar un pod o servicio caído.&lt;/li&gt;
&lt;li&gt;Escalar un deployment cuando se detecta carga anómala.&lt;/li&gt;
&lt;li&gt;Limpiar un directorio de logs cuando el uso de disco supera un umbral dinámico.&lt;/li&gt;
&lt;li&gt;Disparar un failover cuando una base de datos primaria deja de responder.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;La auto-remediación requiere un diseño cuidadoso. Empieza con acciones de bajo riesgo y amplía conforme crece la confianza.&lt;/p&gt;
&lt;h2 id="plataformas-y-herramientas-comunes"&gt;Plataformas y herramientas comunes
&lt;/h2&gt;&lt;p&gt;El panorama de AIOps incluye tanto plataformas comerciales como bloques de construcción open-source:&lt;/p&gt;
&lt;h3 id="plataformas-comerciales"&gt;Plataformas comerciales
&lt;/h3&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Plataforma&lt;/th&gt;
 &lt;th&gt;Fortalezas&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Dynatrace&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Auto-descubrimiento robusto, motor de IA (Davis), observabilidad full-stack&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Datadog&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Monitorización unificada + alertas con ML, detección de anomalías Watchdog&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Splunk ITSI&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Analítica de logs potente + toolkit de ML, bueno para correlación de eventos&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Moogsoft&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Pionero en el espacio AIOps, fuerte correlación de eventos y reducción de ruido&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;BigPanda&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Enfocado en correlación de eventos y automatización, se integra con herramientas existentes&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;PagerDuty&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Gestión de incidentes con reducción de ruido por ML y agrupación inteligente&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="bloques-de-construcción-open-source"&gt;Bloques de construcción open-source
&lt;/h3&gt;&lt;p&gt;Puedes ensamblar un stack similar a AIOps con componentes open-source:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Recolección de datos&lt;/strong&gt;: Prometheus, Grafana Agent, OpenTelemetry Collector, Fluentd/Fluent Bit.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Almacenamiento de datos&lt;/strong&gt;: Prometheus (métricas), Elasticsearch/OpenSearch (logs), Jaeger/Tempo (trazas).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Detección de anomalías&lt;/strong&gt;: Facebook Prophet, Isolation Forest (scikit-learn), luminol, Grafana ML.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Correlación de eventos&lt;/strong&gt;: Lógica personalizada sobre streams de eventos, o StackStorm para automatización dirigida por eventos.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Alertas y automatización&lt;/strong&gt;: Alertmanager, Grafana OnCall, StackStorm, Rundeck.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Construir un stack AIOps personalizado es significativamente más trabajo que usar una plataforma comercial, pero te da control total y evita el vendor lock-in. Un punto medio razonable es usar una plataforma comercial para las capacidades core de AIOps mientras mantienes tu pipeline de datos en open-source.&lt;/p&gt;
&lt;h2 id="casos-de-uso-prácticos"&gt;Casos de uso prácticos
&lt;/h2&gt;&lt;h3 id="reducción-de-ruido-en-gestión-de-alertas"&gt;Reducción de ruido en gestión de alertas
&lt;/h3&gt;&lt;p&gt;Un equipo que recibe más de 500 alertas al día implementa correlación de eventos AIOps. Las alertas relacionadas se agrupan en incidentes, los duplicados se suprimen y las alertas fluctuantes se silencian. El volumen de alertas baja un 80%, y el ingeniero de guardia puede enfocarse en incidentes reales.&lt;/p&gt;
&lt;h3 id="planificación-proactiva-de-capacidad"&gt;Planificación proactiva de capacidad
&lt;/h3&gt;&lt;p&gt;Los modelos AIOps analizan tendencias históricas de uso de recursos y predicen cuándo se alcanzarán los límites de capacidad. En lugar de reaccionar a una alerta de disco lleno a las 2 de la madrugada, la plataforma predice el problema con dos semanas de antelación y crea un ticket para que el equipo lo aborde en horario laboral.&lt;/p&gt;
&lt;h3 id="respuesta-a-incidentes-más-rápida"&gt;Respuesta a incidentes más rápida
&lt;/h3&gt;&lt;p&gt;Durante una caída de producción, la plataforma AIOps correlaciona alertas de todo el stack de monitorización, identifica la causa raíz (un despliegue reciente que introdujo una fuga de memoria) y muestra el commit del despliegue relevante. El MTTR baja de 45 minutos a 10 minutos.&lt;/p&gt;
&lt;h3 id="escalado-automático"&gt;Escalado automático
&lt;/h3&gt;&lt;p&gt;La plataforma detecta patrones de tráfico anómalos que se desvían de la línea base aprendida. En lugar de esperar a que la CPU alcance el 80% (el umbral estático), dispara una acción de scale-up basada en la tasa de cambio, asegurando que la capacidad está lista antes de que los usuarios experimenten degradación.&lt;/p&gt;
&lt;h2 id="cómo-encaja-aiops-en-los-flujos-de-trabajo-devops"&gt;Cómo encaja AIOps en los flujos de trabajo DevOps
&lt;/h2&gt;&lt;p&gt;AIOps no es un reemplazo de las prácticas DevOps. Es una capa de mejora:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Código&lt;/span&gt; &lt;span class="err"&gt;──&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;CI&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;CD&lt;/span&gt; &lt;span class="n"&gt;Pipeline&lt;/span&gt; &lt;span class="err"&gt;──&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Deploy&lt;/span&gt; &lt;span class="err"&gt;──&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Observar&lt;/span&gt; &lt;span class="err"&gt;──&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Capa&lt;/span&gt; &lt;span class="n"&gt;AIOps&lt;/span&gt; &lt;span class="err"&gt;──&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Actuar&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="err"&gt;│&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Monitoring&lt;/span&gt; &lt;span class="n"&gt;Stack&lt;/span&gt; &lt;span class="n"&gt;Modelos&lt;/span&gt; &lt;span class="n"&gt;ML&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;métricas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;logs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;detección&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;anomalías&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;trazas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;eventos&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;correlación&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RCA&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;Los &lt;strong&gt;desarrolladores&lt;/strong&gt; se benefician de una identificación más rápida de la causa raíz cuando su código causa problemas en producción.&lt;/li&gt;
&lt;li&gt;Los equipos de &lt;strong&gt;operaciones&lt;/strong&gt; se benefician de la reducción de ruido, remediación automatizada y alertas proactivas.&lt;/li&gt;
&lt;li&gt;Los equipos &lt;strong&gt;SRE&lt;/strong&gt; se benefician del seguimiento de SLOs basado en datos y el análisis de tasa de consumo del error budget.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AIOps funciona mejor cuando tu base de observabilidad es sólida. Si no estás recolectando buenos datos (logs estructurados, métricas significativas, trazas distribuidas), los modelos de ML no producirán insights significativos. Arregla primero tu observabilidad, luego añade AIOps encima.&lt;/p&gt;
&lt;h2 id="primeros-pasos-un-camino-pragmático"&gt;Primeros pasos: Un camino pragmático
&lt;/h2&gt;&lt;p&gt;Si estás considerando AIOps, aquí tienes un enfoque práctico:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Audita tu stack de observabilidad actual.&lt;/strong&gt; ¿Qué datos estás recolectando? ¿Los logs están estructurados? ¿Las métricas están etiquetadas de forma consistente? ¿Las trazas se propagan entre servicios? AIOps es tan bueno como los datos que ingiere.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Empieza con la reducción de ruido.&lt;/strong&gt; Esta es la fruta que cuelga más baja. Implementa agrupación y deduplicación de alertas. Incluso una correlación básica basada en reglas (antes de cualquier ML) reducirá la fatiga por alertas significativamente.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Añade detección de anomalías a métricas clave.&lt;/strong&gt; Elige 3-5 métricas críticas de negocio e infraestructura. Aplica un modelo de detección de anomalías de series temporales. Facebook Prophet o recording rules de Prometheus con ajustes estacionales son buenos puntos de partida.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Implementa remediación automatizada para problemas conocidos.&lt;/strong&gt; Identifica los 5 incidentes recurrentes principales. Escribe runbooks para ellos. Automatiza los runbooks usando StackStorm, Rundeck o el motor de automatización de tu plataforma.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Evalúa una plataforma comercial cuando la complejidad lo requiera.&lt;/strong&gt; Si tienes cientos de servicios, múltiples herramientas de monitorización y un equipo de operaciones creciente, la inversión en una plataforma AIOps comercial puede justificarse solo por la reducción en MTTR.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Mide el impacto.&lt;/strong&gt; Sigue MTTD, MTTR, ratio alerta-a-incidente y tasa de falsos positivos. Sin métricas, no puedes probar que AIOps vale la pena.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;AIOps no es magia. Es un conjunto de técnicas que, aplicadas a buenos datos operativos, pueden reducir la carga sobre los equipos y mejorar la fiabilidad. Empieza pequeño, mide todo, y escala lo que funcione.&lt;/p&gt;</description></item><item><title>Infraestructura como código con Terraform: guía práctica</title><link>https://adurrr.github.io/p/infraestructura-como-c%C3%B3digo-con-terraform-gu%C3%ADa-pr%C3%A1ctica/</link><pubDate>Sat, 10 Sep 2022 00:00:00 +0000</pubDate><guid>https://adurrr.github.io/p/infraestructura-como-c%C3%B3digo-con-terraform-gu%C3%ADa-pr%C3%A1ctica/</guid><description>&lt;h2 id="por-qué-importa-la-infraestructura-como-código"&gt;Por qué importa la infraestructura como código
&lt;/h2&gt;&lt;p&gt;Gestionar infraestructura manualmente a través de consolas web o scripts ad-hoc crea problemas que se acumulan con el tiempo: entornos inconsistentes, cambios sin documentar, rollbacks imposibles y el clásico &amp;ldquo;funciona en mi máquina&amp;rdquo; extendido a servidores enteros.&lt;/p&gt;
&lt;p&gt;La Infraestructura como Código (IaC) resuelve esto tratando la infraestructura como el código de aplicación: se escribe, versiona, revisa, prueba y aplica mediante flujos de trabajo automatizados. Los beneficios llegan rápidamente:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Reproducibilidad&lt;/strong&gt;: Levanta entornos idénticos en minutos, no en días.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Control de versiones&lt;/strong&gt;: Cada cambio de infraestructura pasa por un PR con revisión de código.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Documentación por defecto&lt;/strong&gt;: El código &lt;em&gt;es&lt;/em&gt; la documentación de cómo es tu infraestructura.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Recuperación ante desastres&lt;/strong&gt;: Reconstruye todo desde código si una región cae.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Visibilidad de costes&lt;/strong&gt;: Revisa los cambios de infraestructura antes de aplicarlos (y antes de que empiecen a costar dinero).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="terraform-vs-otras-herramientas"&gt;Terraform vs otras herramientas
&lt;/h2&gt;&lt;p&gt;Existen varias herramientas de IaC. Así es como Terraform se compara con las principales alternativas:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Característica&lt;/th&gt;
 &lt;th&gt;Terraform&lt;/th&gt;
 &lt;th&gt;Pulumi&lt;/th&gt;
 &lt;th&gt;CloudFormation&lt;/th&gt;
 &lt;th&gt;Ansible&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Lenguaje&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;HCL (declarativo)&lt;/td&gt;
 &lt;td&gt;Python, TypeScript, Go, etc.&lt;/td&gt;
 &lt;td&gt;JSON/YAML&lt;/td&gt;
 &lt;td&gt;YAML (procedural)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Soporte cloud&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Multi-cloud&lt;/td&gt;
 &lt;td&gt;Multi-cloud&lt;/td&gt;
 &lt;td&gt;Solo AWS&lt;/td&gt;
 &lt;td&gt;Multi-cloud (vía módulos)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Gestión de estado&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Fichero de estado explícito&lt;/td&gt;
 &lt;td&gt;Gestionado por servicio Pulumi&lt;/td&gt;
 &lt;td&gt;Gestionado por AWS&lt;/td&gt;
 &lt;td&gt;Sin estado&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Curva de aprendizaje&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Moderada&lt;/td&gt;
 &lt;td&gt;Varía según lenguaje&lt;/td&gt;
 &lt;td&gt;Moderada&lt;/td&gt;
 &lt;td&gt;Baja&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Ecosistema&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Enorme ecosistema de providers&lt;/td&gt;
 &lt;td&gt;En crecimiento&lt;/td&gt;
 &lt;td&gt;Solo AWS pero profundo&lt;/td&gt;
 &lt;td&gt;Enorme ecosistema de roles&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Ideal para&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Infra multi-cloud&lt;/td&gt;
 &lt;td&gt;Equipos que prefieren lenguajes de propósito general&lt;/td&gt;
 &lt;td&gt;Entornos solo AWS&lt;/td&gt;
 &lt;td&gt;Gestión de configuración&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;El punto fuerte de Terraform es el aprovisionamiento de infraestructura multi-cloud con un enfoque declarativo. Si estás solo en AWS y quieres integración estrecha, CloudFormation es razonable. Si tu equipo prefiere escribir Python en lugar de HCL, Pulumi merece una mirada. Pero para la mayoría de equipos que gestionan infraestructura entre distintos proveedores, Terraform es la elección pragmática.&lt;/p&gt;
&lt;h2 id="conceptos-fundamentales"&gt;Conceptos fundamentales
&lt;/h2&gt;&lt;h3 id="providers"&gt;Providers
&lt;/h3&gt;&lt;p&gt;Los providers son plugins que permiten a Terraform interactuar con APIs — AWS, Azure, GCP, Kubernetes, GitHub, Cloudflare y cientos más.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-hcl" data-lang="hcl"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;terraform&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;required_providers&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; aws&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;hashicorp/aws&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;~&amp;gt; 5.0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;aws&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; region&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;eu-west-1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="resources"&gt;Resources
&lt;/h3&gt;&lt;p&gt;Los resources son los bloques de construcción fundamentales. Cada bloque resource describe un objeto de infraestructura.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-hcl" data-lang="hcl"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;aws_instance&amp;#34; &amp;#34;web&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; ami&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;ami-0c55b159cbfafe1f0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; instance_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;t3.micro&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; Name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;web-server&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="state"&gt;State
&lt;/h3&gt;&lt;p&gt;Terraform mantiene un &lt;strong&gt;fichero de estado&lt;/strong&gt; que mapea tu configuración a recursos del mundo real. Así es como Terraform sabe qué existe, qué necesita cambiar y qué destruir. El fichero de estado es crítico. Perderlo significa que Terraform pierde la pista de tu infraestructura.&lt;/p&gt;
&lt;h3 id="modules"&gt;Modules
&lt;/h3&gt;&lt;p&gt;Los modules son paquetes reutilizables de configuración Terraform. Piensa en ellos como funciones: reciben entradas (variables), crean recursos y producen salidas.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-hcl" data-lang="hcl"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;vpc&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;terraform-aws-modules/vpc/aws&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;5.1.0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;my-vpc&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; cidr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;10.0.0.0/16&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; azs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;eu-west-1a&amp;#34;, &amp;#34;eu-west-1b&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; private_subnets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;10.0.1.0/24&amp;#34;, &amp;#34;10.0.2.0/24&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; public_subnets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;10.0.101.0/24&amp;#34;, &amp;#34;10.0.102.0/24&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; enable_nat_gateway&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="ejemplo-práctico-vpc--ec2"&gt;Ejemplo práctico: VPC + EC2
&lt;/h2&gt;&lt;p&gt;Aquí hay un ejemplo completo que aprovisiona una VPC con una subred pública y una instancia EC2:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt; 10
&lt;/span&gt;&lt;span class="lnt"&gt; 11
&lt;/span&gt;&lt;span class="lnt"&gt; 12
&lt;/span&gt;&lt;span class="lnt"&gt; 13
&lt;/span&gt;&lt;span class="lnt"&gt; 14
&lt;/span&gt;&lt;span class="lnt"&gt; 15
&lt;/span&gt;&lt;span class="lnt"&gt; 16
&lt;/span&gt;&lt;span class="lnt"&gt; 17
&lt;/span&gt;&lt;span class="lnt"&gt; 18
&lt;/span&gt;&lt;span class="lnt"&gt; 19
&lt;/span&gt;&lt;span class="lnt"&gt; 20
&lt;/span&gt;&lt;span class="lnt"&gt; 21
&lt;/span&gt;&lt;span class="lnt"&gt; 22
&lt;/span&gt;&lt;span class="lnt"&gt; 23
&lt;/span&gt;&lt;span class="lnt"&gt; 24
&lt;/span&gt;&lt;span class="lnt"&gt; 25
&lt;/span&gt;&lt;span class="lnt"&gt; 26
&lt;/span&gt;&lt;span class="lnt"&gt; 27
&lt;/span&gt;&lt;span class="lnt"&gt; 28
&lt;/span&gt;&lt;span class="lnt"&gt; 29
&lt;/span&gt;&lt;span class="lnt"&gt; 30
&lt;/span&gt;&lt;span class="lnt"&gt; 31
&lt;/span&gt;&lt;span class="lnt"&gt; 32
&lt;/span&gt;&lt;span class="lnt"&gt; 33
&lt;/span&gt;&lt;span class="lnt"&gt; 34
&lt;/span&gt;&lt;span class="lnt"&gt; 35
&lt;/span&gt;&lt;span class="lnt"&gt; 36
&lt;/span&gt;&lt;span class="lnt"&gt; 37
&lt;/span&gt;&lt;span class="lnt"&gt; 38
&lt;/span&gt;&lt;span class="lnt"&gt; 39
&lt;/span&gt;&lt;span class="lnt"&gt; 40
&lt;/span&gt;&lt;span class="lnt"&gt; 41
&lt;/span&gt;&lt;span class="lnt"&gt; 42
&lt;/span&gt;&lt;span class="lnt"&gt; 43
&lt;/span&gt;&lt;span class="lnt"&gt; 44
&lt;/span&gt;&lt;span class="lnt"&gt; 45
&lt;/span&gt;&lt;span class="lnt"&gt; 46
&lt;/span&gt;&lt;span class="lnt"&gt; 47
&lt;/span&gt;&lt;span class="lnt"&gt; 48
&lt;/span&gt;&lt;span class="lnt"&gt; 49
&lt;/span&gt;&lt;span class="lnt"&gt; 50
&lt;/span&gt;&lt;span class="lnt"&gt; 51
&lt;/span&gt;&lt;span class="lnt"&gt; 52
&lt;/span&gt;&lt;span class="lnt"&gt; 53
&lt;/span&gt;&lt;span class="lnt"&gt; 54
&lt;/span&gt;&lt;span class="lnt"&gt; 55
&lt;/span&gt;&lt;span class="lnt"&gt; 56
&lt;/span&gt;&lt;span class="lnt"&gt; 57
&lt;/span&gt;&lt;span class="lnt"&gt; 58
&lt;/span&gt;&lt;span class="lnt"&gt; 59
&lt;/span&gt;&lt;span class="lnt"&gt; 60
&lt;/span&gt;&lt;span class="lnt"&gt; 61
&lt;/span&gt;&lt;span class="lnt"&gt; 62
&lt;/span&gt;&lt;span class="lnt"&gt; 63
&lt;/span&gt;&lt;span class="lnt"&gt; 64
&lt;/span&gt;&lt;span class="lnt"&gt; 65
&lt;/span&gt;&lt;span class="lnt"&gt; 66
&lt;/span&gt;&lt;span class="lnt"&gt; 67
&lt;/span&gt;&lt;span class="lnt"&gt; 68
&lt;/span&gt;&lt;span class="lnt"&gt; 69
&lt;/span&gt;&lt;span class="lnt"&gt; 70
&lt;/span&gt;&lt;span class="lnt"&gt; 71
&lt;/span&gt;&lt;span class="lnt"&gt; 72
&lt;/span&gt;&lt;span class="lnt"&gt; 73
&lt;/span&gt;&lt;span class="lnt"&gt; 74
&lt;/span&gt;&lt;span class="lnt"&gt; 75
&lt;/span&gt;&lt;span class="lnt"&gt; 76
&lt;/span&gt;&lt;span class="lnt"&gt; 77
&lt;/span&gt;&lt;span class="lnt"&gt; 78
&lt;/span&gt;&lt;span class="lnt"&gt; 79
&lt;/span&gt;&lt;span class="lnt"&gt; 80
&lt;/span&gt;&lt;span class="lnt"&gt; 81
&lt;/span&gt;&lt;span class="lnt"&gt; 82
&lt;/span&gt;&lt;span class="lnt"&gt; 83
&lt;/span&gt;&lt;span class="lnt"&gt; 84
&lt;/span&gt;&lt;span class="lnt"&gt; 85
&lt;/span&gt;&lt;span class="lnt"&gt; 86
&lt;/span&gt;&lt;span class="lnt"&gt; 87
&lt;/span&gt;&lt;span class="lnt"&gt; 88
&lt;/span&gt;&lt;span class="lnt"&gt; 89
&lt;/span&gt;&lt;span class="lnt"&gt; 90
&lt;/span&gt;&lt;span class="lnt"&gt; 91
&lt;/span&gt;&lt;span class="lnt"&gt; 92
&lt;/span&gt;&lt;span class="lnt"&gt; 93
&lt;/span&gt;&lt;span class="lnt"&gt; 94
&lt;/span&gt;&lt;span class="lnt"&gt; 95
&lt;/span&gt;&lt;span class="lnt"&gt; 96
&lt;/span&gt;&lt;span class="lnt"&gt; 97
&lt;/span&gt;&lt;span class="lnt"&gt; 98
&lt;/span&gt;&lt;span class="lnt"&gt; 99
&lt;/span&gt;&lt;span class="lnt"&gt;100
&lt;/span&gt;&lt;span class="lnt"&gt;101
&lt;/span&gt;&lt;span class="lnt"&gt;102
&lt;/span&gt;&lt;span class="lnt"&gt;103
&lt;/span&gt;&lt;span class="lnt"&gt;104
&lt;/span&gt;&lt;span class="lnt"&gt;105
&lt;/span&gt;&lt;span class="lnt"&gt;106
&lt;/span&gt;&lt;span class="lnt"&gt;107
&lt;/span&gt;&lt;span class="lnt"&gt;108
&lt;/span&gt;&lt;span class="lnt"&gt;109
&lt;/span&gt;&lt;span class="lnt"&gt;110
&lt;/span&gt;&lt;span class="lnt"&gt;111
&lt;/span&gt;&lt;span class="lnt"&gt;112
&lt;/span&gt;&lt;span class="lnt"&gt;113
&lt;/span&gt;&lt;span class="lnt"&gt;114
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-hcl" data-lang="hcl"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;terraform&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; required_version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt; &amp;#34;&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="err"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;required_providers&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; aws&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;hashicorp/aws&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;~&amp;gt; 5.0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;aws&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; region&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;eu-west-1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}&lt;span class="c1"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# --- Networking ---
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;aws_vpc&amp;#34; &amp;#34;main&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; cidr_block&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;10.0.0.0/16&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; enable_dns_support&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; enable_dns_hostnames&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; Name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;main-vpc&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;aws_subnet&amp;#34; &amp;#34;public&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; vpc_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;aws_vpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;id&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; cidr_block&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;10.0.1.0/24&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; availability_zone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;eu-west-1a&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; map_public_ip_on_launch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; Name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;public-subnet&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;aws_internet_gateway&amp;#34; &amp;#34;gw&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; vpc_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;aws_vpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;id&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; Name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;main-igw&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;aws_route_table&amp;#34; &amp;#34;public&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; vpc_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;aws_vpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;id&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;route&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; cidr_block&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;0.0.0.0/0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; gateway_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;aws_internet_gateway&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;gw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;id&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; Name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;public-rt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;aws_route_table_association&amp;#34; &amp;#34;public&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; subnet_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;aws_subnet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;id&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; route_table_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;aws_route_table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;id&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}&lt;span class="c1"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# --- Security Group ---
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;aws_security_group&amp;#34; &amp;#34;web&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;web-sg&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Allow HTTP and SSH&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; vpc_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;aws_vpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;id&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;ingress&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; from_port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; to_port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; protocol&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;tcp&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; cidr_blocks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;0.0.0.0/0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;ingress&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; from_port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;22&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; to_port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;22&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; protocol&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;tcp&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; cidr_blocks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;YOUR_IP/32&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="c1"&gt; # Restringir a tu IP
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;egress&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; from_port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; to_port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; protocol&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;-1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; cidr_blocks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;0.0.0.0/0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}&lt;span class="c1"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# --- EC2 Instance ---
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;aws_instance&amp;#34; &amp;#34;web&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; ami&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;ami-0c55b159cbfafe1f0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; instance_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;t3.micro&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; subnet_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;aws_subnet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;id&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; vpc_security_group_ids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;aws_security_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;web&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; Name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;web-server&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}&lt;span class="c1"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# --- Outputs ---
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;instance_public_ip&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;aws_instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;web&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;public_ip&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;vpc_id&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;aws_vpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;id&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="el-flujo-planapply"&gt;El flujo plan/apply
&lt;/h2&gt;&lt;p&gt;Terraform sigue un flujo de trabajo predecible:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1. Inicializar - descargar providers y modules&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;terraform init
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2. Formatear - asegurar estilo de código consistente&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;terraform fmt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 3. Validar - comprobar sintaxis y configuración&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;terraform validate
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 4. Plan - previsualizar qué cambiará (¡paso crítico!)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;terraform plan -out&lt;span class="o"&gt;=&lt;/span&gt;tfplan
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 5. Apply - ejecutar el plan&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;terraform apply tfplan
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 6. Destroy - destruir todos los recursos (cuando sea necesario)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;terraform destroy
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;El paso &lt;code&gt;terraform plan&lt;/code&gt; es el más importante. Nunca te lo saltes. Siempre revisa la salida del plan antes de aplicar, especialmente en producción. El plan te muestra exactamente qué se creará, modificará o destruirá.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Ejemplo de salida del plan&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Plan: &lt;span class="m"&gt;6&lt;/span&gt; to add, &lt;span class="m"&gt;0&lt;/span&gt; to change, &lt;span class="m"&gt;0&lt;/span&gt; to destroy.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;En pipelines CI/CD, guarda el plan en un fichero (&lt;code&gt;-out=tfplan&lt;/code&gt;) y aplica ese plan exacto. Esto previene condiciones de carrera donde la infraestructura cambia entre el plan y el paso de apply.&lt;/p&gt;
&lt;h2 id="buenas-prácticas-de-gestión-de-estado"&gt;Buenas prácticas de gestión de estado
&lt;/h2&gt;&lt;p&gt;La gestión de estado es donde se originan la mayoría de problemas con Terraform. Sigue estas prácticas:&lt;/p&gt;
&lt;h3 id="usa-un-backend-remoto"&gt;Usa un backend remoto
&lt;/h3&gt;&lt;p&gt;Nunca almacenes el estado localmente o en Git. Usa un backend remoto con cifrado y bloqueo:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;span class="lnt"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-hcl" data-lang="hcl"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;terraform&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;backend&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;s3&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;my-terraform-state&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;prod/networking/terraform.tfstate&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; region&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;eu-west-1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; encrypt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; dynamodb_table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;terraform-locks&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;La tabla DynamoDB proporciona &lt;strong&gt;bloqueo de estado&lt;/strong&gt;. Esto previene que dos personas o pipelines modifiquen la misma infraestructura al mismo tiempo.&lt;/p&gt;
&lt;h3 id="organiza-el-estado-por-componente"&gt;Organiza el estado por componente
&lt;/h3&gt;&lt;p&gt;No pongas toda tu infraestructura en un solo fichero de estado. Divídela por componente o equipo:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;environments&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;prod&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;networking&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="c1"&gt;# VPC, subnets, routes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="c1"&gt;# EC2, ASGs, load balancers&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="c1"&gt;# Instancias RDS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;monitoring&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="c1"&gt;# CloudWatch, alertas&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;staging&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;networking&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;compute&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Ficheros de estado más pequeños significan planes más rápidos, menor radio de explosión y menos equipos compitiendo por los bloqueos.&lt;/p&gt;
&lt;h3 id="usa-terraform_remote_state-con-moderación"&gt;Usa &lt;code&gt;terraform_remote_state&lt;/code&gt; con moderación
&lt;/h3&gt;&lt;p&gt;Puedes referenciar outputs de otros ficheros de estado, pero úsalo con cuidado. El uso excesivo de remote state crea acoplamiento fuerte entre componentes. Prefiere pasar valores a través de variables o un parameter store.&lt;/p&gt;
&lt;h2 id="consejos-para-uso-en-producción"&gt;Consejos para uso en producción
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Fija las versiones de los providers.&lt;/strong&gt; Usa restricciones &lt;code&gt;~&amp;gt;&lt;/code&gt; para permitir actualizaciones de parche pero prevenir cambios incompatibles: &lt;code&gt;version = &amp;quot;~&amp;gt; 5.0&amp;quot;&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Usa workspaces con cuidado.&lt;/strong&gt; Los workspaces son útiles para separación simple de entornos pero se vuelven confusos a escala. Directorios separados por entorno suele ser más claro.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Implementa un pipeline CI/CD para Terraform.&lt;/strong&gt; Ejecuta &lt;code&gt;terraform plan&lt;/code&gt; en PRs y publica la salida como comentario en el PR. Ejecuta &lt;code&gt;terraform apply&lt;/code&gt; solo después del merge y la aprobación.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Usa &lt;code&gt;prevent_destroy&lt;/code&gt; para recursos críticos.&lt;/strong&gt; Esta regla de lifecycle evita la destrucción accidental de bases de datos o almacenamiento persistente:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-hcl" data-lang="hcl"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;aws_db_instance&amp;#34; &amp;#34;main&amp;#34;&lt;/span&gt; {&lt;span class="c1"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt; # ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;lifecycle&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt; prevent_destroy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Etiqueta todo.&lt;/strong&gt; Usa un bloque &lt;code&gt;default_tags&lt;/code&gt; en el provider para asegurar que cada recurso recibe tags estándar (entorno, equipo, proyecto).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Usa &lt;code&gt;tflint&lt;/code&gt; y &lt;code&gt;checkov&lt;/code&gt;.&lt;/strong&gt; Haz lint de tu código Terraform y escanea en busca de configuraciones inseguras antes de aplicar.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tflint --init
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tflint
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;checkov -d .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Importa recursos existentes.&lt;/strong&gt; Si tienes infraestructura creada manualmente, usa &lt;code&gt;terraform import&lt;/code&gt; para traerla bajo gestión en lugar de recrearla.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Revisa el diff del plan cuidadosamente.&lt;/strong&gt; Un recurso que muestra &amp;ldquo;destroy and recreate&amp;rdquo; puede causar tiempo de inactividad. Entiende qué cambios son in-place versus destructivos.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Terraform es una de esas herramientas que recompensa la disciplina. Cuanto más consistentemente sigas estas prácticas, con más confianza gestionará tu equipo la infraestructura a escala.&lt;/p&gt;</description></item></channel></rss>