<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: LIANN MELANNY</title>
    <description>The latest articles on Forem by LIANN MELANNY (@liannmelannyhuamancunyas).</description>
    <link>https://forem.com/liannmelannyhuamancunyas</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1156818%2F19ae4623-71e0-40b1-9c6f-5c3602f139e5.jpg</url>
      <title>Forem: LIANN MELANNY</title>
      <link>https://forem.com/liannmelannyhuamancunyas</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/liannmelannyhuamancunyas"/>
    <language>en</language>
    <item>
      <title>Flujo GitOps para Despliegue de Aplicaciones Web en GCP (Terraform + Argo CD + Kubernetes + Helm + GitHub Actions + Docker)</title>
      <dc:creator>LIANN MELANNY</dc:creator>
      <pubDate>Fri, 25 Apr 2025 20:03:19 +0000</pubDate>
      <link>https://forem.com/liannmelannyhuamancunyas/flujo-gitops-para-despliegue-de-aplicaciones-web-en-gcp-terraform-argo-cd-kubernetes-helm--52o</link>
      <guid>https://forem.com/liannmelannyhuamancunyas/flujo-gitops-para-despliegue-de-aplicaciones-web-en-gcp-terraform-argo-cd-kubernetes-helm--52o</guid>
      <description>&lt;h2&gt;
  
  
  🚀 Automatiza tus despliegues como un profesional y duerme tranquilo 😎
&lt;/h2&gt;

&lt;p&gt;Guía paso a paso para implementar un flujo CI/CD robusto con herramientas enterprise de código abierto.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcrf87cabd732lmt6nzug.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcrf87cabd732lmt6nzug.png" alt="Flujo de trabajo CI/CD: Diagrama que ilustra un proceso automatizado de integración y despliegue continuo, incluyendo herramientas como Terraform, Kubernetes, Argo CD y GitHub Actions para la gestión de infraestructura y despliegues." width="800" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Con esta guía, te llevaré de la mano para configurar un flujo de trabajo automatizado que garantiza un ciclo de integración y despliegue (CI/CD) eficiente, desde la infraestructura hasta la aplicación.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔥 ¿Por qué esta arquitectura?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;GitOps&lt;/strong&gt; es una filosofía que lleva el enfoque DevOps un paso más allá, basándose en la idea de que el repositorio Git es la "fuente de verdad". A diferencia de DevOps tradicional, GitOps automatiza todo el ciclo de vida de despliegue directamente desde Git.&lt;br&gt;&lt;br&gt;
Con &lt;strong&gt;GitOps&lt;/strong&gt;, los cambios en el repositorio Git se reflejan de manera automática en el clúster de Kubernetes, asegurando consistencia, trazabilidad y una recuperación ante desastres mucho más rápida.&lt;/p&gt;

&lt;p&gt;Esta arquitectura resuelve problemas comunes como:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Despliegues manuales propensos a errores&lt;/li&gt;
&lt;li&gt;Configuraciones inconsistentes entre entornos&lt;/li&gt;
&lt;li&gt;Ambientes difíciles de replicar&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Además, uno de los beneficios clave es la facilidad para realizar &lt;strong&gt;rollback&lt;/strong&gt; a una versión anterior de la infraestructura o de la aplicación. Como todos los cambios están versionados en Git, puedes revertir rápidamente cualquier cambio simplemente volviendo a un commit anterior y permitiendo que &lt;strong&gt;Argo CD&lt;/strong&gt; sincronice el estado del clúster con esa versión.&lt;/p&gt;

&lt;p&gt;Con esta combinación, los despliegues se vuelven predecibles, auditables y completamente automatizados, mejorando la eficiencia y seguridad en todo el ciclo de vida del software.&lt;/p&gt;
&lt;h2&gt;
  
  
  Herramientas clave del ecosistema:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Terraform&lt;/strong&gt;: Infraestructura como código (IaC) en GCP para gestionar recursos de manera declarativa.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kubernetes (GKE)&lt;/strong&gt;: Orquestación de contenedores a gran escala.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Argo CD&lt;/strong&gt;: Implementa GitOps para sincronizar automáticamente el estado de tu repositorio con el clúster Kubernetes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Helm&lt;/strong&gt;: Facilita la gestión y despliegue de aplicaciones en Kubernetes mediante charts reutilizables.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Actions&lt;/strong&gt;: CI/CD integrado que automatiza el ciclo completo desde el código hasta el despliegue, asegurando actualizaciones automáticas de Argo CD en Kubernetes.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Resultado:
&lt;/h2&gt;

&lt;p&gt;Despliegues predecibles, auditoría completa de cambios y recuperación ante desastres en minutos. ✨&lt;/p&gt;
&lt;h2&gt;
  
  
  🛠 Pasos Clave: Arquitectura y Flujo del Proyecto
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. Estructura del Proyecto: Claridad ante todo
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── docker/                 # Configuraciones de contenedores
│   ├── mysql/
│   ├── nginx/
│   ├── php/
│   └── php-fpm/
├── infra/                  # Infraestructura como código
│   └── gcp/
│       ├── modules/        # Módulos Terraform
│       └── main.tf         # Configuración principal
├── kubernetes/             # Manifiestos para Argo CD
│   ├── argocd/
│   └── manifests/
└── laravel/                # Código fuente de la app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  🧠 ¿Por qué importa tener un proyecto bien estructurado?
&lt;/h2&gt;
&lt;h3&gt;
  
  
  ✅ Separación clara entre infraestructura, aplicación y configuración
&lt;/h3&gt;

&lt;p&gt;GitOps permite manejar cada parte de forma desacoplada y versionada:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Infraestructura&lt;/strong&gt;: Terraform&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configuración&lt;/strong&gt;: Helm o manifiestos YAML&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Código de la aplicación&lt;/strong&gt;: Laravel&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  🔁 Módulos reutilizables para distintos entornos (dev/prod)
&lt;/h3&gt;

&lt;p&gt;Con Terraform y Helm, puedes definir módulos genéricos reutilizables con variables para cada entorno (desarrollo, staging, producción), manteniendo consistencia entre ambientes.&lt;/p&gt;
&lt;h3&gt;
  
  
  ⚙️ Configuraciones específicas por servicio
&lt;/h3&gt;

&lt;p&gt;Cada componente tiene su propia configuración declarativa:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PHP-FPM&lt;/strong&gt;: variables de entorno para rendimiento y workers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nginx&lt;/strong&gt;: configurado con reglas de Ingress Controller.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MySQL (Cloud SQL)&lt;/strong&gt;: seguridad reforzada mediante conexión privada y secretos.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;📌 Esta estructura modular mejora la trazabilidad, la seguridad y la automatización de tu arquitectura de despliegue.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  2. ⚙️ Configuración Docker: Optimización para tu código
&lt;/h2&gt;

&lt;p&gt;En este proyecto estamos usando PHP con el framework Laravel, y para ello se diseñó un &lt;strong&gt;Dockerfile multi-etapa&lt;/strong&gt; que optimiza la construcción de la imagen final y separa responsabilidades claramente entre dependencias de PHP, assets de frontend y entorno de ejecución.&lt;/p&gt;
&lt;h3&gt;
  
  
  🐳 Dockerfile Multi-etapa (PHP-FPM + Nginx)
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Stage 1: Instalación de dependencias&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;composer:latest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;composer_deps&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;composer &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--no-dev&lt;/span&gt; &lt;span class="nt"&gt;--optimize-autoloader&lt;/span&gt;

&lt;span class="c"&gt;# Stage 2: Build de assets&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;node:20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;node_deps&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm ci &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm run build

&lt;span class="c"&gt;# Stage 3: Imagen final&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; php:8.3-fpm&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /var/www&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=composer_deps /app/vendor ./vendor&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=node_deps /app/public/build ./public/build&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; docker/nginx/default.conf /etc/nginx/conf.d/default.conf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  ✅ Puntos clave
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;🔽 &lt;strong&gt;Reduce el tamaño final de la imagen&lt;/strong&gt;
Las etapas de instalación y build no se incluyen en la imagen de producción.&lt;/li&gt;
&lt;li&gt;⚙️ &lt;strong&gt;Configuración específica para PHP-FPM y Nginx&lt;/strong&gt;
Permite controlar cada servicio según las necesidades del proyecto.&lt;/li&gt;
&lt;li&gt;🔒 &lt;strong&gt;Uso de usuario no-root (&lt;code&gt;appuser&lt;/code&gt;)&lt;/strong&gt;
Mejora la seguridad del contenedor en producción.&lt;/li&gt;
&lt;li&gt;📦 &lt;strong&gt;Separación de responsabilidades&lt;/strong&gt;
Composer y Node manejan sus dependencias por separado, haciendo el build más limpio y controlado.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;🧠 &lt;strong&gt;Esta estructura es ideal para producción:&lt;/strong&gt; ligera, segura y desacoplada. También permite integración perfecta con GitOps y pipelines CI/CD.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  3. ☁️ Autenticación en GCP: Prepárate para la nube
&lt;/h2&gt;

&lt;p&gt;Antes de desplegar cualquier recurso en &lt;strong&gt;Google Cloud Platform (GCP)&lt;/strong&gt;, es fundamental configurar correctamente la autenticación y el proyecto donde vamos a trabajar.&lt;/p&gt;
&lt;h3&gt;
  
  
  📥 Instalación de gcloud CLI
&lt;/h3&gt;

&lt;p&gt;Primero, instalamos la herramienta de línea de comandos oficial de GCP (&lt;strong&gt;gcloud&lt;/strong&gt;) para poder interactuar con los servicios de Google desde nuestra terminal.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://cloud.google.com/sdk/docs/install" rel="noopener noreferrer"&gt;Documentación oficial aquí&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  🔐 Autenticación y configuración básica
&lt;/h3&gt;

&lt;p&gt;Una vez instalado &lt;code&gt;gcloud&lt;/code&gt;, autenticamos nuestro usuario y seleccionamos el proyecto de trabajo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Inicia sesión en tu cuenta de Google&lt;/span&gt;
gcloud auth login

&lt;span class="c"&gt;# Define el proyecto donde se desplegarán los recursos&lt;/span&gt;
gcloud config &lt;span class="nb"&gt;set &lt;/span&gt;project &lt;span class="o"&gt;{&lt;/span&gt;nombredelproyecto-id&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# Establece las credenciales por defecto para las aplicaciones&lt;/span&gt;
gcloud auth application-default login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; El comando &lt;code&gt;gcloud auth application-default login&lt;/code&gt; es esencial cuando usas herramientas que requieren autenticación explícita con &lt;em&gt;Application Default Credentials (ADC)&lt;/em&gt;, como &lt;strong&gt;Terraform de GCP&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  🛡️ Permisos (IAM) necesarios
&lt;/h3&gt;

&lt;p&gt;Para realizar despliegues de infraestructura y gestionar servicios como &lt;strong&gt;Kubernetes&lt;/strong&gt;, &lt;strong&gt;Cloud SQL&lt;/strong&gt; y &lt;strong&gt;Storage&lt;/strong&gt;, el usuario debe tener asignados los siguientes roles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;roles/owner&lt;/code&gt; — Permisos completos sobre el proyecto (útil para desarrollo y pruebas).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;roles/cloudsql.admin&lt;/code&gt; — Permite crear y administrar instancias de &lt;strong&gt;Cloud SQL&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;roles/storage.admin&lt;/code&gt; — Control total sobre &lt;strong&gt;buckets de almacenamiento&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;roles/container.admin&lt;/code&gt; — Administración de clústeres de &lt;strong&gt;Kubernetes (GKE)&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Importante:&lt;/strong&gt; Si trabajás en entornos de producción, es recomendable aplicar el principio de &lt;strong&gt;mínimos privilegios&lt;/strong&gt; y asignar únicamente los roles estrictamente necesarios para cada tarea.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  4. ⚙️ Infraestructura como código con Terraform
&lt;/h3&gt;

&lt;p&gt;En este proyecto usamos Terraform para definir y desplegar infraestructura en GCP de forma declarativa. Todo está dividido en módulos reutilizables, lo que facilita el mantenimiento, la escalabilidad y la organización.&lt;/p&gt;

&lt;h3&gt;
  
  
  🗂️ Estructura de módulos
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;modules/
├── cloud-sql/          # MySQL gestionado por GCP (Cloud SQL)
├── gke-cluster/        # Clúster de Kubernetes (GKE)
└── helm-deploy/        # Instalación de Argo CD vía Helm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cada módulo contiene su propio &lt;code&gt;main.tf&lt;/code&gt;, &lt;code&gt;variables.tf&lt;/code&gt; y &lt;code&gt;outputs.tf&lt;/code&gt;, lo cual permite una reutilización limpia y controlada de recursos.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;✅ &lt;strong&gt;Recomendación:&lt;/strong&gt;&lt;br&gt;
Siempre que puedas, divide tu infraestructura en módulos separados por responsabilidad.&lt;br&gt;
Eso mejora la trazabilidad y facilita el trabajo en equipo.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  📄 &lt;code&gt;main.tf&lt;/code&gt; (Configuración principal)
&lt;/h3&gt;

&lt;p&gt;Ejemplo de cómo se instancian los módulos en el archivo raíz del proyecto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;required_version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;gt;= 1.0"&lt;/span&gt;
  &lt;span class="nx"&gt;required_providers&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;google&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hashicorp/google"&lt;/span&gt;
      &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 5.0"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;kubernetes&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hashicorp/kubernetes"&lt;/span&gt;
      &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 2.0"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;helm&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hashicorp/helm"&lt;/span&gt;
      &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 2.0"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;backend&lt;/span&gt; &lt;span class="s2"&gt;"gcs"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;bucket&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"my-tfstate-bucket"&lt;/span&gt;
    &lt;span class="nx"&gt;prefix&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"terraform/state"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"google"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;project&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;project_id&lt;/span&gt;
  &lt;span class="nx"&gt;region&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;region&lt;/span&gt;
  &lt;span class="nx"&gt;zone&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;zone&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"google_client_config"&lt;/span&gt; &lt;span class="s2"&gt;"default"&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"gke_cluster"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;source&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"./modules/gke-cluster"&lt;/span&gt;
  &lt;span class="nx"&gt;cluster_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ftrick-cluster"&lt;/span&gt;
  &lt;span class="nx"&gt;machine_type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"e2-medium"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"cloud_sql"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;source&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"./modules/cloud-sql"&lt;/span&gt;
  &lt;span class="nx"&gt;instance_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ftrick-db"&lt;/span&gt;
  &lt;span class="nx"&gt;db_password&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db_password&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;🔐 &lt;strong&gt;Importante:&lt;/strong&gt;&lt;br&gt;
Recuerda definir tus variables sensibles como &lt;code&gt;db_password&lt;/code&gt; en archivos &lt;code&gt;.tfvars&lt;/code&gt; o con Terraform Cloud/Workspaces para evitar exponer credenciales.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  🧙 Comandos mágicos
&lt;/h3&gt;

&lt;p&gt;Una vez definido todo, se utilizan los siguientes comandos para desplegar tu infraestructura:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Inicializa los proveedores, backends y módulos&lt;/span&gt;
terraform init

&lt;span class="c"&gt;# Muestra un plan de ejecución (simulación de cambios)&lt;/span&gt;
terraform plan

&lt;span class="c"&gt;# Aplica la infraestructura (¡despliegue real!)&lt;/span&gt;
terraform apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;🛠️ &lt;strong&gt;Consejo útil:&lt;/strong&gt;&lt;br&gt;
Usa &lt;code&gt;terraform apply -auto-approve&lt;/code&gt;solo en entornos de desarrollo o pruebas.&lt;br&gt;
En producción, siempre revisa el plan antes de aplicar.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  🔁 Reutilización en distintos entornos
&lt;/h3&gt;

&lt;p&gt;Puedes reutilizar los mismos módulos para múltiples entornos (&lt;code&gt;dev&lt;/code&gt;, &lt;code&gt;staging&lt;/code&gt;, &lt;code&gt;prod&lt;/code&gt;) simplemente usando diferentes archivos de variables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform apply &lt;span class="nt"&gt;-var-file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"envs/dev.tfvars"&lt;/span&gt;
terraform apply &lt;span class="nt"&gt;-var-file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"envs/prod.tfvars"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;🎯 &lt;strong&gt;Mejora continua:&lt;/strong&gt;&lt;br&gt;
Usa Workspaces de Terraform o CI/CD (como GitHub Actions + Argo CD) para automatizar y separar despliegues por entorno.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  5. ☸️ Configuración Kubernetes: El corazón del despliegue
&lt;/h3&gt;

&lt;p&gt;Una vez que la infraestructura está lista, toca orquestar los componentes de tu aplicación en Kubernetes. Esto se hace a través de manifiestos YAML que definen cómo se comportan tus contenedores, servicios, accesos y configuraciones.&lt;/p&gt;

&lt;h3&gt;
  
  
  📦 &lt;code&gt;laravel-deployment.yaml&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Este archivo define cómo se ejecuta tu contenedor Laravel dentro del clúster:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;laravel-deployment&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;laravel&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;laravel&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;laravel&lt;/span&gt;
          &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;us-central1-docker.pkg.dev/ftrick-455901/ftrick-laravel:latest&lt;/span&gt;
          &lt;span class="na"&gt;envFrom&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;secretRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;laravel-env&lt;/span&gt;
          &lt;span class="na"&gt;volumeMounts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx-config&lt;/span&gt;
              &lt;span class="na"&gt;mountPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/etc/nginx/nginx.conf&lt;/span&gt;
              &lt;span class="na"&gt;subPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx.conf&lt;/span&gt;
      &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx-config&lt;/span&gt;
          &lt;span class="na"&gt;configMap&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx-config&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;✅ &lt;strong&gt;Consejo:&lt;/strong&gt;&lt;br&gt;
Usa &lt;code&gt;envFrom.secretRef&lt;/code&gt; para cargar tus variables de entorno sensibles.&lt;br&gt;
De esta manera no quedan expuestas en tus archivos YAML.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  📡 Archivos clave adicionales
&lt;/h3&gt;

&lt;h4&gt;
  
  
  📁 &lt;code&gt;laravel-service.yaml&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;Define un servicio interno que expone tu deployment en el clúster (&lt;code&gt;ClusterIP&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;laravel-service&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;laravel&lt;/span&gt;
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&lt;/span&gt;
      &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
      &lt;span class="na"&gt;targetPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterIP&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;🔁 &lt;strong&gt;Recomendación:&lt;/strong&gt;&lt;br&gt;
Usa este servicio como punto de entrada para tu Ingress o para otros servicios internos como base de datos o Redis.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  🌐 &lt;code&gt;laravel-ingress.yaml&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;Permite el acceso público a tu aplicación a través de HTTP(S):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;networking.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Ingress&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;laravel-ingress&lt;/span&gt;
  &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;nginx.ingress.kubernetes.io/rewrite-target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;laravel.example.com&lt;/span&gt;
      &lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt;
            &lt;span class="na"&gt;pathType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Prefix&lt;/span&gt;
            &lt;span class="na"&gt;backend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;laravel-service&lt;/span&gt;
                &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                  &lt;span class="na"&gt;number&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;🌍 &lt;strong&gt;Importante:&lt;/strong&gt;&lt;br&gt;
Configura correctamente tu dominio y certificados si vas a exponer la app a internet (puedes usar &lt;strong&gt;cert-manager&lt;/strong&gt; para certificados SSL automáticos).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  ⚙️ &lt;code&gt;nginx-config.yaml&lt;/code&gt; (ConfigMap)
&lt;/h4&gt;

&lt;p&gt;Configura detalles específicos de Nginx en tu contenedor Laravel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ConfigMap&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx-config&lt;/span&gt;
&lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;nginx.conf&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;server {&lt;/span&gt;
      &lt;span class="s"&gt;listen 80;&lt;/span&gt;
      &lt;span class="s"&gt;index index.php index.html;&lt;/span&gt;
      &lt;span class="s"&gt;root /var/www/public;&lt;/span&gt;

      &lt;span class="s"&gt;location / {&lt;/span&gt;
        &lt;span class="s"&gt;try_files $uri $uri/ /index.php?$query_string;&lt;/span&gt;
      &lt;span class="s"&gt;}&lt;/span&gt;

      &lt;span class="s"&gt;location ~ \.php$ {&lt;/span&gt;
        &lt;span class="s"&gt;fastcgi_pass 127.0.0.1:9000;&lt;/span&gt;
        &lt;span class="s"&gt;fastcgi_index index.php;&lt;/span&gt;
        &lt;span class="s"&gt;include fastcgi_params;&lt;/span&gt;
        &lt;span class="s"&gt;fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;&lt;/span&gt;
      &lt;span class="s"&gt;}&lt;/span&gt;
    &lt;span class="s"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Tip extra:&lt;/strong&gt;&lt;br&gt;
Usa &lt;strong&gt;ConfigMaps&lt;/strong&gt; para separar tu lógica de configuración del código.&lt;br&gt;
Esto mejora el mantenimiento y evita tener que reconstruir la imagen cada vez que cambie un ajuste de Nginx.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  6. 🔄 GitOps con Argo CD: Sincronización automática
&lt;/h3&gt;

&lt;p&gt;Con Argo CD, llevamos la filosofía GitOps a otro nivel: tu repositorio Git se convierte en la fuente de verdad, y Argo CD se encarga de sincronizar automáticamente los manifiestos con el estado real de tu clúster Kubernetes.&lt;/p&gt;

&lt;p&gt;📦 &lt;strong&gt;Application Manifest:&lt;/strong&gt; &lt;code&gt;argocd-app.yaml&lt;/code&gt;&lt;br&gt;&lt;br&gt;
Define una aplicación gestionada por Argo CD, especificando el repositorio Git y la ruta donde están los manifiestos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;argoproj.io/v1alpha1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Application&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;laravel-app&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;argocd&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;project&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt;
  &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;repoURL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://github.com/tu-user/repo'&lt;/span&gt;
    &lt;span class="na"&gt;targetRevision&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;HEAD&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kubernetes/manifests&lt;/span&gt;
  &lt;span class="na"&gt;destination&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://kubernetes.default.svc'&lt;/span&gt;
    &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt;
  &lt;span class="na"&gt;syncPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;automated&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;prune&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;        &lt;span class="c1"&gt;# Elimina recursos que ya no están en el repo&lt;/span&gt;
      &lt;span class="na"&gt;selfHeal&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;     &lt;span class="c1"&gt;# Repara diferencias automáticamente&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;📁 &lt;strong&gt;Ruta path:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Asegúrate de que esta ruta dentro del repo contenga todos tus YAMLs (Deployment, Service, Ingress, etc.).&lt;/p&gt;

&lt;p&gt;🌐 &lt;strong&gt;Exponer Argo CD con LoadBalancer&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Para acceder a la interfaz web de Argo CD desde fuera del clúster, expón el servicio &lt;code&gt;argocd-server&lt;/code&gt; con tipo &lt;code&gt;LoadBalancer&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl patch svc argocd-server &lt;span class="nt"&gt;-n&lt;/span&gt; argocd &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s1"&gt;'{"spec": {"type": "LoadBalancer"}}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔧 &lt;strong&gt;Importante:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Asegúrate de que los puertos 80 y 443 estén abiertos en el firewall de tu GCP para que el LoadBalancer pueda recibir tráfico HTTP/HTTPS.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Puedes verificar la IP externa asignada con:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get svc argocd-server &lt;span class="nt"&gt;-n&lt;/span&gt; argocd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🔐 Obtener contraseña de acceso inicial
&lt;/h3&gt;

&lt;p&gt;Una vez desplegado Argo CD, el usuario por defecto es admin. Para obtener la contraseña inicial (auto-generada):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get secret argocd-initial-admin-secret &lt;span class="nt"&gt;-n&lt;/span&gt; argocd &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"{.data.password}"&lt;/span&gt; | &lt;span class="nb"&gt;base64&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ✅ Acceder a Argo CD
&lt;/h3&gt;

&lt;p&gt;Abre tu navegador y entra a:  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://&amp;lt;IP-del-LoadBalancer" rel="noopener noreferrer"&gt;https://&amp;lt;IP-del-LoadBalancer&amp;gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Usa el usuario admin y la contraseña obtenida.&lt;br&gt;&lt;br&gt;
Desde ahí podrás visualizar, sincronizar y administrar todas tus aplicaciones GitOps 🚀&lt;/p&gt;
&lt;h3&gt;
  
  
  7. ⚙️ CI/CD con GitHub Actions: Automatización total
&lt;/h3&gt;

&lt;p&gt;Con &lt;strong&gt;GitHub Actions&lt;/strong&gt; automatizamos todo el ciclo de integración y despliegue de nuestra aplicación Laravel. Cada vez que haces un push, se construye una nueva imagen Docker y se sincroniza automáticamente con &lt;strong&gt;Argo CD&lt;/strong&gt; en &lt;strong&gt;Kubernetes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;📄 &lt;strong&gt;GitHub Actions Workflow:&lt;/strong&gt; &lt;code&gt;.github/workflows/deploy.yml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build &amp;amp; Deploy&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;

&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;GCP_REGION&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;us-central1&lt;/span&gt;
  &lt;span class="na"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;project_id&lt;/span&gt;
  &lt;span class="na"&gt;IMAGE_NAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;image_name&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout repo&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Docker auth&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;echo ${{ secrets.GCP_CREDENTIALS }} &amp;gt; gcp-key.json&lt;/span&gt;
        &lt;span class="s"&gt;gcloud auth activate-service-account --key-file=gcp-key.json&lt;/span&gt;
        &lt;span class="s"&gt;gcloud auth configure-docker $GCP_REGION-docker.pkg.dev&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build &amp;amp; Push Docker image&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;docker build -t $GCP_REGION-docker.pkg.dev/$PROJECT_ID/$IMAGE_NAME:$GITHUB_SHA .&lt;/span&gt;
        &lt;span class="s"&gt;docker push $GCP_REGION-docker.pkg.dev/$PROJECT_ID/$IMAGE_NAME:$GITHUB_SHA&lt;/span&gt;

  &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;needs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Argo CD Sync&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;curl -k -X POST https://$ARGOCD_SERVER/api/v1/applications/ftrick-app/sync \&lt;/span&gt;
          &lt;span class="s"&gt;-H "Authorization: Bearer $ARGOCD_TOKEN"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  🔐 Secretos necesarios
&lt;/h4&gt;

&lt;p&gt;Debes configurar estos secretos en tu repositorio (Settings &amp;gt; Secrets &amp;gt; Actions):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Nombre&lt;/th&gt;
&lt;th&gt;Descripción&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GCP_CREDENTIALS&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Archivo JSON con credenciales del service account con permisos de push&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ARGOCD_TOKEN&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Token de autenticación de Argo CD (admin o token con permisos de sincronizar)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ARGOCD_SERVER&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Dirección pública (o interna) del servidor de Argo CD, sin https://&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  🧠 Recomendaciones
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Usa la rama &lt;code&gt;main&lt;/code&gt; o crea un workflow diferente para &lt;code&gt;dev&lt;/code&gt; si necesitas entornos separados.&lt;/li&gt;
&lt;li&gt;Usa &lt;code&gt;:latest&lt;/code&gt; como etiqueta solo en desarrollo. En producción, usar &lt;code&gt;:$GITHUB_SHA&lt;/code&gt; permite versionar cada build.&lt;/li&gt;
&lt;li&gt;Asegúrate de que el &lt;strong&gt;Service Account&lt;/strong&gt; usado en &lt;code&gt;GCP_CREDENTIALS&lt;/code&gt; tenga permisos &lt;code&gt;roles/artifactregistry.writer&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  🧪 Resultado
&lt;/h4&gt;

&lt;p&gt;Este pipeline:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Construye y sube tu imagen Docker a &lt;strong&gt;Artifact Registry&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Notifica a &lt;strong&gt;Argo CD&lt;/strong&gt;, quien se encarga de actualizar &lt;strong&gt;Kubernetes&lt;/strong&gt; si detecta un cambio.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwpunys48d6m7g5w4sq97.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwpunys48d6m7g5w4sq97.png" alt="Pipeline de Argo CD: Diagrama que muestra el flujo de trabajo de despliegue continuo utilizando Argo CD, incluyendo la sincronización automática entre el repositorio Git y el clúster de Kubernetes para implementar aplicaciones siguiendo el enfoque GitOps." width="800" height="522"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;🚀 ¡Haz el push final y mira cómo se despliega mágicamente!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Deploy automático con GitOps 🚀"&lt;/span&gt;
git push origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; En 5 minutos tendrás tu aplicación accesible vía la IP del LoadBalancer. ¡Así de simple! 💥&lt;/p&gt;

</description>
      <category>devops</category>
      <category>kubernetes</category>
      <category>gcp</category>
      <category>gitops</category>
    </item>
  </channel>
</rss>
