<?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>DEV Community: Israel Oña Ordoñez 🚀</title>
    <description>The latest articles on DEV Community by Israel Oña Ordoñez 🚀 (@israoo).</description>
    <link>https://dev.to/israoo</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%2F2578323%2Ff22caffa-d6d6-420d-9b73-638ca0e99022.png</url>
      <title>DEV Community: Israel Oña Ordoñez 🚀</title>
      <link>https://dev.to/israoo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/israoo"/>
    <language>en</language>
    <item>
      <title>Everything as Code: La evolución de la infraestructura</title>
      <dc:creator>Israel Oña Ordoñez 🚀</dc:creator>
      <pubDate>Thu, 06 Feb 2025 23:55:26 +0000</pubDate>
      <link>https://dev.to/israoo/everything-as-code-la-evolucion-de-la-infraestructura-4d3e</link>
      <guid>https://dev.to/israoo/everything-as-code-la-evolucion-de-la-infraestructura-4d3e</guid>
      <description>&lt;h2&gt;
  
  
  📝 TL;DR
&lt;/h2&gt;

&lt;p&gt;Everything as Code (EaC) es un enfoque donde todo elemento de la infraestructura, desde la configuración de la red hasta la configuración de la aplicación, se define y gestiona como código. Este enfoque permite mayor automatización, control y reproducibilidad en los entornos de TI. En este artículo aprenderás qué es EaC, sus beneficios y cómo implementarlo en tu organización.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  🏗️ Todo como código
&lt;/h2&gt;

&lt;p&gt;En los entornos de TI modernos, la infraestructura y la configuración de las aplicaciones se gestionan cada vez más como código. Este enfoque, conocido como &lt;strong&gt;Everything as Code (EaC)&lt;/strong&gt;, permite definir y gestionar todos los elementos de la infraestructura y la aplicación como código, lo que facilita la automatización, el control y la seguridad en los entornos de TI.&lt;/p&gt;

&lt;p&gt;Existen varios tipos de "código" en el contexto de EaC:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Infrastructure as Code (IaC)&lt;/strong&gt;: Define y gestiona la infraestructura de TI como código para crear y gestionar recursos en la nube (Terraform).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configuration as Code (CaC)&lt;/strong&gt;: Define y gestiona la configuración de la aplicación como código para instalar y configurar aplicaciones (Ansible).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Policy as Code (PaC)&lt;/strong&gt;: Define y gestiona las políticas de cumplimiento como código para validar y hacer cumplir las políticas de seguridad (OPA).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security as Code (SaC)&lt;/strong&gt;: Define y gestiona la seguridad de la aplicación como código para identificar y corregir vulnerabilidades (Snyk).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitOps&lt;/strong&gt;: Define y gestiona la infraestructura y las aplicaciones a través de Git para automatizar despliegues y operaciones (Argo CD).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  🔧 Ejemplo: Creando infraestructura con EaC
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Objetivo:&lt;/strong&gt; Crear una infraestructura en AWS utilizando:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Terraform&lt;/strong&gt;: Definir la infraestructura como código.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ansible&lt;/strong&gt;: Configurar la instancia EC2 con Nginx.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OPA&lt;/strong&gt;: Validar que los recursos cumplan con las políticas de seguridad.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bash&lt;/strong&gt;: Automatizar el proceso de creación y configuración.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Arquitectura del proceso:&lt;/strong&gt;&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%2Fk10l5h4jprvw3q9vmhme.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%2Fk10l5h4jprvw3q9vmhme.png" alt="Arquitectura del proceso" width="800" height="539"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El diagrama muestra el flujo de trabajo utilizando &lt;strong&gt;Everything as Code&lt;/strong&gt; para crear una infraestructura en AWS. Cada herramienta cumple una función específica en el proceso:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Se &lt;strong&gt;inicializan&lt;/strong&gt; los recursos de terraform para preparar el directorio de trabajo.&lt;/li&gt;
&lt;li&gt;Se genera el &lt;strong&gt;plan&lt;/strong&gt; de ejecución de terraform para crear los recursos en AWS.&lt;/li&gt;
&lt;li&gt;Se ejecutan las &lt;strong&gt;validaciones&lt;/strong&gt; de OPA para asegurar que los recursos cumplen con las políticas de seguridad.&lt;/li&gt;
&lt;li&gt;Se &lt;strong&gt;aplica&lt;/strong&gt; el plan de terraform para crear los recursos en AWS.&lt;/li&gt;
&lt;li&gt;Se ejecuta el &lt;strong&gt;playbook&lt;/strong&gt; de Ansible para configurar la instancia EC2 con Nginx.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Estructura del proyecto:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── ansible
│   ├── ansible.cfg                   # Configuración de Ansible
│   ├── ec2-instance.yml              # Playbook principal
│   ├── hosts                         # Inventario
│   ├── roles
│   │   ├── nginx-setup               # Rol para configurar Nginx
│   │   │   ├── handlers
│   │   │   │   └── main.yml          # Manejador para reiniciar Nginx
│   │   │   └── tasks
│   │   │       └── main.yml          # Instalación y configuración de Nginx
│   │   └── web-index                 # Rol para configurar la página de inicio
│   │       ├── tasks
│   │       │   └── main.yml          # Copia la plantilla de la página de inicio
│   │       └── templates
│   │           └── index.html        # Página de inicio personalizada
│   ├── terraform_generated_key.pem   # Clave privada generada por Terraform
│   └── vars
│       └── ec2-instance.yml          # Variables para el playbook
├── opa
│   └── policy.rego                   # Políticas de validación con OPA
├── scripts
│   ├── apply_ansible.sh              # Ejecuta Ansible
│   ├── apply_terraform.sh            # Aplica Terraform
│   ├── pipeline.sh                   # Orquesta Terraform, OPA y Ansible
│   └── validate_opa.sh               # Valida con OPA
└── terraform
    ├── 01-vpc.tf                     # Creación de VPC y redes
    ├── 02-ec2.tf                     # Creación de EC2 con security group
    ├── outputs.tf                    # Salidas de Terraform
    ├── providers.tf                  # Configuración del proveedor AWS
    ├── variables.auto.tfvars         # Valores por defecto
    ├── variables.tf                  # Definición de variables
    └── versions.tf                   # Configuración de versiones
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;1. Definiendo la infraestructura con Terraform:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;En el directorio &lt;code&gt;terraform&lt;/code&gt;, se definen los recursos de AWS, en este caso:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Una VPC con una subred pública, un internet gateway y una route table.&lt;/li&gt;
&lt;li&gt;Una instancia EC2 con un security group y una key pair.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Después de ejecutar &lt;code&gt;scripts/apply_terraform.sh&lt;/code&gt;, los recursos se crearán en AWS y obtendrás la información de salida con el id de la instancia EC2, la dirección IP pública y la ruta de la clave privada generada.&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%2F135d55epgyhhh2hzm2w0.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%2F135d55epgyhhh2hzm2w0.png" alt="Resultado de terraform apply" width="800" height="190"&gt;&lt;/a&gt;&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%2Fcgsv8qjsrsj6d5peo28a.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%2Fcgsv8qjsrsj6d5peo28a.png" alt="Instancia de EC2 en AWS" width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Validando la infraestructura con OPA:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;En el directorio &lt;code&gt;opa&lt;/code&gt;, se definen las políticas de validación con OPA. Estas políticas se aplican a los recursos planificados por Terraform para asegurar que cumplan con las políticas de seguridad antes de ser creados en AWS. Las políticas definidas en &lt;code&gt;policy.rego&lt;/code&gt; validan que:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;En todos los recursos aplicables, el tag &lt;code&gt;Name&lt;/code&gt; debe estar presente.&lt;/li&gt;
&lt;li&gt;Las instancias EC2 no deben generar un costo superior a $0.05 USD por hora.&lt;/li&gt;
&lt;li&gt;Los security groups no deben permitir todo el tráfico desde cualquier origen.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Después de ejecutar &lt;code&gt;scripts/validate_opa.sh&lt;/code&gt;, OPA validará los recursos planificados por Terraform y mostrará los resultados de la validación. Si los recursos no cumplen con las políticas, OPA mostrará los errores.&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%2Fa38t6aoihm11cx2dhpqi.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%2Fa38t6aoihm11cx2dhpqi.png" alt="Resultado fallido de OPA" width="800" height="217"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Después de corregir los errores, OPA mostrará un resultado exitoso.&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%2Fr7kq5fv4pgkikfid5lae.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%2Fr7kq5fv4pgkikfid5lae.png" alt="Resultado exitoso de OPA" width="800" height="124"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Configurando la instancia EC2 con Ansible:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;En el directorio &lt;code&gt;ansible&lt;/code&gt;, se definen los playbooks y roles de Ansible. El playbook &lt;code&gt;ec2-instance.yml&lt;/code&gt; instala Nginx y copia una página de inicio personalizada. Después de ejecutar &lt;code&gt;scripts/apply_ansible.sh&lt;/code&gt;, Ansible configurará la instancia EC2 con Nginx y la página de inicio personalizada.&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%2Fyygjzn528415x7u6haa0.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%2Fyygjzn528415x7u6haa0.png" alt="Resultado de Ansible" width="800" height="334"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Una vez finalizado el proceso, podrás acceder a la dirección IP pública de la instancia EC2 en tu navegador o con &lt;code&gt;curl&lt;/code&gt; para ver la página de inicio personalizada.&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%2Fe63wcr8zy04f3focf6dn.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%2Fe63wcr8zy04f3focf6dn.png" alt="Página de inicio personalizada" width="800" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Orquestando todo el proceso con un Bash script:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;El script &lt;code&gt;scripts/pipeline.sh&lt;/code&gt; orquesta todo el proceso anterior de creación de infraestructura en AWS utilizando Terraform, validación con OPA y configuración con Ansible. Al ejecutar este script, se ejecutarán las siguientes tareas:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Inicialización de Terraform.&lt;/li&gt;
&lt;li&gt;Generación del plan de ejecución de Terraform.&lt;/li&gt;
&lt;li&gt;Conversión del plan de Terraform en un formato compatible con OPA.&lt;/li&gt;
&lt;li&gt;Validación de los recursos planificados con OPA.&lt;/li&gt;
&lt;li&gt;Solicitud de confirmación para aplicar los cambios.&lt;/li&gt;
&lt;li&gt;Aplicación del plan de Terraform.&lt;/li&gt;
&lt;li&gt;Ejecución del playbook de Ansible para configurar la instancia EC2.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  📂 Repositorio del proyecto
&lt;/h2&gt;

&lt;p&gt;Para seguir el ejemplo y explorar el proyecto completo, puedes clonar el repositorio asociado.&lt;/p&gt;

&lt;p&gt;Repositorio: &lt;a href="https://github.com/israoo/eac-cloud-provisioning.git" rel="noopener noreferrer"&gt;https://github.com/israoo/eac-cloud-provisioning.git&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Este repositorio contiene:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Código de Terraform para crear la infraestructura en AWS.&lt;/li&gt;
&lt;li&gt;Políticas de validación con OPA.&lt;/li&gt;
&lt;li&gt;Playbooks y roles de Ansible para configurar la instancia EC2.&lt;/li&gt;
&lt;li&gt;Scripts de Bash para orquestar los procesos.&lt;/li&gt;
&lt;li&gt;Instrucciones detalladas en el archivo &lt;code&gt;README.md&lt;/code&gt; sobre cómo configurar y ejecutar el proyecto.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  📈 Beneficios de Everything as Code
&lt;/h2&gt;

&lt;p&gt;Adoptar el enfoque de Everything as Code en tu organización puede proporcionar una serie de beneficios significativos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Automatización total&lt;/strong&gt;: La infraestructura y las aplicaciones se pueden crear, configurar y gestionar de forma automática, reduciendo el tiempo y los errores manuales.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistencia y reproducibilidad&lt;/strong&gt;: Los entornos de desarrollo, pruebas y producción se pueden replicar de forma consistente, lo que facilita la detección y corrección de problemas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Seguridad y cumplimiento&lt;/strong&gt;: Las políticas de seguridad y cumplimiento se pueden aplicar de forma consistente en toda la infraestructura y las aplicaciones, reduciendo los riesgos de seguridad.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Control de versiones y auditoría&lt;/strong&gt;: Todo el código de infraestructura y configuración se puede controlar con un sistema de control de versiones, lo que permite auditar y revertir cambios si es necesario.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Colaboración y transparencia&lt;/strong&gt;: Los equipos de desarrollo, operaciones y seguridad pueden colaborar de forma más eficaz al utilizar un enfoque común basado en código.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Escalabilidad y flexibilidad&lt;/strong&gt;: La infraestructura y las aplicaciones se pueden escalar y adaptar fácilmente a medida que cambian los requisitos del negocio.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integración con CI/CD&lt;/strong&gt;: Se puede automatizar de punta a punta el proceso validación, aplicación y configuración de la infraestructura y las aplicaciones.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  💡 EaC vs Enfoque tradicional
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Aspecto&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Enfoque tradicional&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Everything as Code (EaC)&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Provisionamiento&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manual a través de la consola de AWS o scripts aislados&lt;/td&gt;
&lt;td&gt;Declarativo con Terraform o similares&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Configuración&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manual a través de SSH o scripts aislados&lt;/td&gt;
&lt;td&gt;Declarativo con Ansible u otras herramientas&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Validación y seguridad&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manual y revisiones ad-hoc&lt;/td&gt;
&lt;td&gt;Automatizada con OPA o similares&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Escalabilidad&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manual y propenso a errores&lt;/td&gt;
&lt;td&gt;Definida en código y fácilmente replicable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Auditoria y cambios&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Difícil de rastrear y revertir&lt;/td&gt;
&lt;td&gt;Control de versiones y auditoría con Git&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Colaboración&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Silos entre equipos de desarrollo y operaciones&lt;/td&gt;
&lt;td&gt;Colaboración entre equipos con un enfoque común&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Errores y problemas&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Difícil de detectar y corregir&lt;/td&gt;
&lt;td&gt;Detección temprana y corrección de errores&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;EaC no solo &lt;strong&gt;optimiza&lt;/strong&gt; la creación y gestión de la infraestructura, sino que también &lt;strong&gt;mejora&lt;/strong&gt; la colaboración entre equipos, la seguridad y la escalabilidad de los entornos de TI.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  🔗 Referencias/Extras
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/es_es/wellarchitected/latest/devops-guidance/everything-as-code.html" rel="noopener noreferrer"&gt;Everything as Code AWS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.hashicorp.com/terraform/docs" rel="noopener noreferrer"&gt;Documentación oficial de Terraform&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.ansible.com/" rel="noopener noreferrer"&gt;Documentación oficial de Ansible&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.openpolicyagent.org/docs/latest/" rel="noopener noreferrer"&gt;Documentación oficial de OPA&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 ¿Qué sigue?
&lt;/h2&gt;

&lt;p&gt;Ahora que conoces Everything as Code (EaC), el siguiente paso es aplicarlo en tus proyectos. Empieza definiendo tu infraestructura y configuración como código, automatizando cada etapa del proceso para lograr entornos más consistentes y seguros.&lt;/p&gt;

&lt;p&gt;Si quieres llevar este enfoque aún más lejos, &lt;strong&gt;integra herramientas de CI/CD&lt;/strong&gt; para automatizar despliegues. En este sentido, &lt;strong&gt;GitHub Actions&lt;/strong&gt; es una excelente opción. Te invito a leer mi artículo sobre &lt;a href="https://dev.to/israoo/que-es-cicd-y-como-puede-acelerar-tus-despliegues-en-minutos-2fgk"&gt;¿Qué es CI/CD y cómo puede acelerar tus despliegues en minutos?&lt;/a&gt; para aprender más al respecto.&lt;/p&gt;

&lt;p&gt;¡No dudes en compartir tus experiencias y desafíos al implementar EaC en tu organización!&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

</description>
      <category>terraform</category>
      <category>ansible</category>
      <category>opa</category>
      <category>español</category>
    </item>
    <item>
      <title>EKS con Terraform: Todo lo necesario, desde la red hasta los nodos</title>
      <dc:creator>Israel Oña Ordoñez 🚀</dc:creator>
      <pubDate>Tue, 28 Jan 2025 04:59:03 +0000</pubDate>
      <link>https://dev.to/israoo/eks-con-terraform-todo-lo-necesario-desde-la-red-hasta-los-nodos-3p55</link>
      <guid>https://dev.to/israoo/eks-con-terraform-todo-lo-necesario-desde-la-red-hasta-los-nodos-3p55</guid>
      <description>&lt;h2&gt;
  
  
  📝 TL;DR
&lt;/h2&gt;

&lt;p&gt;EKS (Elastic Kubernetes Service) es un servicio de AWS que permite desplegar clústeres de Kubernetes de forma sencilla. Con Terraform, puedes automatizar la creación de un clúster de EKS y todos los recursos necesarios. En este artículo, encontrarás un proyecto completo que despliega un clúster de EKS con Terraform, incluyendo la creación de una VPC, subredes, grupos de seguridad, roles de IAM y nodos.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  🌟 Una solución práctica
&lt;/h2&gt;

&lt;p&gt;Elastic Kubernetes Service (EKS) es una de las opciones de Kubernetes más populares en la nube. Sin embargo, configurar un clúster de EKS manualmente puede ser un proceso tedioso y propenso a errores, por lo que es recomendable automatizarlo. Una forma de hacerlo es utilizando Terraform, una herramienta de infraestructura como código que te permite definir y gestionar la infraestructura de tu aplicación de forma declarativa.&lt;/p&gt;

&lt;p&gt;He creado un proyecto de Terraform que despliega un clúster de EKS, incluyendo la creación de una VPC, subredes, grupos de seguridad, roles de IAM y nodos. Este proyecto te permitirá desplegar un clúster de EKS con un solo comando, ahorrándote tiempo y esfuerzo, pero también te servirá como punto de partida para &lt;strong&gt;personalizar y extender&lt;/strong&gt; la configuración según tus necesidades.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  🏗️ Estructura del proyecto
&lt;/h2&gt;

&lt;p&gt;El proyecto está organizado en varios archivos de Terraform, cada uno de los cuales se encarga de crear un conjunto específico de recursos. A continuación, se muestra la estructura del proyecto:&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="nb"&gt;.&lt;/span&gt;
├── 1.01-vpc.tf
├── 1.02-private_subnets.tf
├── 1.03-public_subnets.tf
├── 1.04-elastic_ips.tf
├── 1.05-nat_gateway.tf
├── 1.06-internet_gateway.tf
├── 1.07-private_route_tables.tf
├── 1.08-public_route_table.tf
├── 1.09-private_routes.tf
├── 1.10-public_routes.tf
├── 1.11-private_route_table_association.tf
├── 1.12-public_route_table_association.tf
├── 1.13-security_groups.tf
├── 2.01-control_plane_iam_role.tf
├── 2.02-worker_node_iam_role.tf
├── 3.01-eks_cluster.tf
├── 3.02-launch_template.tf
├── 3.03-node_group.tf
├── 3.04-eks_access.tf
├── eks_user_data.sh
├── outputs.tf
├── providers.tf
├── variables.auto.tfvars
├── variables.tf
└── versions.tf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cada archivo tiene un nombre descriptivo que indica su función en el proyecto. Por ejemplo, &lt;code&gt;1.01-vpc.tf&lt;/code&gt; se encarga de crear la VPC, &lt;code&gt;1.02-private_subnets.tf&lt;/code&gt; crea las subredes privadas, &lt;code&gt;1.03-public_subnets.tf&lt;/code&gt; crea las subredes públicas, etc. Los archivos están numerados para indicar el orden en que deberían ser aplicados aunque Terraform se encarga de gestionar las dependencias entre los recursos.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚙️ Recursos creados
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. VPC
&lt;/h3&gt;

&lt;p&gt;El primer archivo, &lt;code&gt;1.01-vpc.tf&lt;/code&gt;, crea una VPC con una CIDR &lt;code&gt;10.0.0.0/16&lt;/code&gt;, habilita el DNS hostnames que permite a los nodos de EKS tener nombres de dominio de AWS y habilita el DNS support que permite a los nodos de EKS resolver nombres de dominio de AWS.&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%2Fwlluiv1tegqcr8ap9fpu.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%2Fwlluiv1tegqcr8ap9fpu.png" alt="Configuración de VPC" width="800" height="227"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Subredes privadas y públicas
&lt;/h3&gt;

&lt;p&gt;Los archivos &lt;code&gt;1.02-private_subnets.tf&lt;/code&gt; y &lt;code&gt;1.03-public_subnets.tf&lt;/code&gt; crean las subredes privadas y públicas respectivamente.&lt;/p&gt;

&lt;p&gt;Para poder comunicarse con internet, las subredes privadas utilizan NAT Gateways &lt;code&gt;1.05-nat_gateway.tf&lt;/code&gt; que requieren una IP pública &lt;code&gt;1.04-elastic_ips.tf&lt;/code&gt;.&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%2Frchqqepobi6gqe5wru73.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%2Frchqqepobi6gqe5wru73.png" alt="Configuración de subredes privadas" width="800" height="304"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Las subredes públicas utilizan un Internet Gateway &lt;code&gt;1.06-internet_gateway.tf&lt;/code&gt; para permitir el tráfico de entrada y salida a internet.&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%2Fmq4mxot84le7vb42zvev.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%2Fmq4mxot84le7vb42zvev.png" alt="Configuración de subredes públicas" width="800" height="304"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para habilitar la comunicación entre las subredes y el internet, se crean las tablas de rutas &lt;code&gt;1.07-private_route_tables.tf&lt;/code&gt;, &lt;code&gt;1.08-public_route_table.tf&lt;/code&gt;, las rutas &lt;code&gt;1.09-private_routes.tf&lt;/code&gt;, &lt;code&gt;1.10-public_routes.tf&lt;/code&gt; y se asocian las tablas de rutas a las subredes &lt;code&gt;1.11-private_route_table_association.tf&lt;/code&gt;, &lt;code&gt;1.12-public_route_table_association.tf&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Grupos de seguridad
&lt;/h3&gt;

&lt;p&gt;El archivo &lt;code&gt;1.13-security_groups.tf&lt;/code&gt; crea los grupos de seguridad necesarios para el clúster de EKS.&lt;/p&gt;

&lt;p&gt;Se crea un grupo de seguridad para el control plane de EKS que permite el tráfico de entrada desde el internet en el puerto 443 y el tráfico de salida a internet en todos los puertos.&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%2Fzf7nufg8fc1vn4hgzfij.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%2Fzf7nufg8fc1vn4hgzfij.png" alt="Grupo de seguridad para el control plane" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Se crea un grupo de seguridad para los nodos de EKS que permite el tráfico de entrada desde el control plane en el puerto 10250 y el tráfico de salida a internet en todos los puertos.&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%2Fv1yufi3kocx7vgatrqwq.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%2Fv1yufi3kocx7vgatrqwq.png" alt="Grupo de seguridad para los nodos" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Roles de IAM
&lt;/h3&gt;

&lt;p&gt;El archivo &lt;code&gt;2.01-control_plane_iam_role.tf&lt;/code&gt; crea un rol de IAM para el control plane de EKS que permite a EKS administrar recursos en tu cuenta de AWS.&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%2Folvt1z6k04js0m075dj4.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%2Folvt1z6k04js0m075dj4.png" alt="Rol de IAM para el control plane" width="800" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El archivo &lt;code&gt;2.02-worker_node_iam_role.tf&lt;/code&gt; crea un rol de IAM para los nodos de EKS que permite a los nodos de EKS acceder a los repositorios de imágenes de Amazon ECR, al control plane de EKS, a los servicios de SSM y CloudWatch.&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%2Fjyp9decwod1ivrakeatu.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%2Fjyp9decwod1ivrakeatu.png" alt="Rol de IAM para los nodos" width="800" height="471"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Clúster de EKS
&lt;/h3&gt;

&lt;p&gt;El archivo &lt;code&gt;3.01-eks_cluster.tf&lt;/code&gt; crea el clúster de EKS con la versión &lt;code&gt;1.31&lt;/code&gt; de Kubernetes.&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%2F5fn32c7aur7sbi0k2n3d.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%2F5fn32c7aur7sbi0k2n3d.png" alt="Clúster de EKS" width="800" height="471"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Nodos de EKS
&lt;/h3&gt;

&lt;p&gt;El archivo &lt;code&gt;3.02-launch_template.tf&lt;/code&gt; crea un launch template para los nodos de EKS que utiliza una imagen de Amazon Linux 2023 y un script de usuario &lt;code&gt;eks_user_data.sh&lt;/code&gt; que instala los componentes necesarios para que los nodos se unan al clúster de EKS.&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%2Fa2alobamssx44lblsj38.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%2Fa2alobamssx44lblsj38.png" alt="Launch template para los nodos" width="800" height="390"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El archivo &lt;code&gt;3.03-node_group.tf&lt;/code&gt; crea un node group para los nodos de EKS que utiliza el launch template creado anteriormente.&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%2F8jwcx854qwlijfryczrp.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%2F8jwcx854qwlijfryczrp.png" alt="Node group para los nodos" width="800" height="589"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Acceso a EKS
&lt;/h3&gt;

&lt;p&gt;El archivo &lt;code&gt;3.04-eks_access.tf&lt;/code&gt; configura un IAM access entry en el clúster de EKS para permitir el acceso a un usuario de IAM (cloud_user) con permisos de administrador.&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%2Fp5hqim4czemczkr9jpvn.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%2Fp5hqim4czemczkr9jpvn.png" alt="Acceso a EKS" width="800" height="515"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  🔧 Configuración
&lt;/h2&gt;

&lt;p&gt;El proyecto utiliza un archivo de variables &lt;code&gt;variables.auto.tfvars&lt;/code&gt; para definir los valores de las variables de Terraform. A continuación, se muestra un ejemplo de cómo se definen las variables en el archivo &lt;code&gt;variables.auto.tfvars&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;aws_user&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"cloud_user"&lt;/span&gt; &lt;span class="c1"&gt;# Nombre del usuario de AWS que se utilizará para acceder al clúster de EKS como administrador&lt;/span&gt;

&lt;span class="nx"&gt;eks&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&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;"eks-cluster"&lt;/span&gt; &lt;span class="c1"&gt;# Nombre del clúster de EKS&lt;/span&gt;
  &lt;span class="nx"&gt;cluster_version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"1.31"&lt;/span&gt;        &lt;span class="c1"&gt;# Versión de Kubernetes&lt;/span&gt;
  &lt;span class="nx"&gt;worker_nodes&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;node_group_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"eks-managed-node-group"&lt;/span&gt; &lt;span class="c1"&gt;# Nombre del node group&lt;/span&gt;
    &lt;span class="nx"&gt;ebs_volume&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;size&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;    &lt;span class="c1"&gt;# Tamaño del volumen EBS en GB&lt;/span&gt;
      &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"gp3"&lt;/span&gt; &lt;span class="c1"&gt;# Tipo del volumen EBS&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;instance_type&lt;/span&gt;              &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"t3a.medium"&lt;/span&gt; &lt;span class="c1"&gt;# Tipo de instancia de los nodos&lt;/span&gt;
    &lt;span class="nx"&gt;desired_capacity&lt;/span&gt;           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;            &lt;span class="c1"&gt;# Número de nodos deseados&lt;/span&gt;
    &lt;span class="nx"&gt;min_size&lt;/span&gt;                   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;            &lt;span class="c1"&gt;# Número mínimo de nodos&lt;/span&gt;
    &lt;span class="nx"&gt;max_size&lt;/span&gt;                   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;            &lt;span class="c1"&gt;# Número máximo de nodos&lt;/span&gt;
    &lt;span class="nx"&gt;max_unavailable_percentage&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;           &lt;span class="c1"&gt;# Porcentaje máximo de nodos no disponibles durante una actualización&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;# Etiquetas para todos los recursos creados&lt;/span&gt;
  &lt;span class="nx"&gt;environment&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Prod"&lt;/span&gt;
  &lt;span class="nx"&gt;service&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"demo"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;vpc&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;# Configuración de la VPC&lt;/span&gt;
  &lt;span class="nx"&gt;cidr_block&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"10.0.0.0/16"&lt;/span&gt;
  &lt;span class="nx"&gt;private_subnet_1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;cidr_block&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"10.0.1.0/24"&lt;/span&gt;
    &lt;span class="nx"&gt;availability_zone&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1a"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;private_subnet_2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;cidr_block&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"10.0.2.0/24"&lt;/span&gt;
    &lt;span class="nx"&gt;availability_zone&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1b"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;private_subnet_3&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;cidr_block&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"10.0.3.0/24"&lt;/span&gt;
    &lt;span class="nx"&gt;availability_zone&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1c"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;public_subnet_1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;cidr_block&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"10.0.4.0/24"&lt;/span&gt;
    &lt;span class="nx"&gt;availability_zone&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1a"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;public_subnet_2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;cidr_block&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"10.0.5.0/24"&lt;/span&gt;
    &lt;span class="nx"&gt;availability_zone&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1b"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;public_subnet_3&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;cidr_block&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"10.0.6.0/24"&lt;/span&gt;
    &lt;span class="nx"&gt;availability_zone&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1c"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En esta configuración, se usan 3 subredes privadas y 3 subredes públicas en 3 zonas de disponibilidad de la región &lt;code&gt;us-east-1&lt;/code&gt;. Se crean 2 nodos de EKS con un volumen EBS de 20 GB, tipo &lt;code&gt;gp3&lt;/code&gt;, instancia &lt;code&gt;t3a.medium&lt;/code&gt;, y se configura el node group para tener entre 1 y 3 nodos con un máximo del 50% de nodos no disponibles durante una actualización.&lt;/p&gt;

&lt;h2&gt;
  
  
  🛠️ Despliegue
&lt;/h2&gt;

&lt;p&gt;Para desplegar el proyecto, sigue estos pasos:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Clona el repositorio:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/israoo/eks-cluster-setup.git
&lt;span class="nb"&gt;cd &lt;/span&gt;eks-cluster-setup
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Inicializa Terraform:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform init
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Planifica los recursos a crear:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform plan &lt;span class="nt"&gt;-out&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;eks-cluster-setup.tfplan
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Aplica los cambios:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform apply eks-cluster-setup.tfplan
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Accede al clúster de EKS:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws eks update-kubeconfig &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;terraform output &lt;span class="nt"&gt;-raw&lt;/span&gt; eks_cluster_name&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Verifica que los nodos de EKS se han unido al clúster:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get nodes
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;¡Listo! Ahora tienes un clúster de EKS desplegado con Terraform.&lt;/p&gt;

&lt;h2&gt;
  
  
  📂 Repositorio del proyecto
&lt;/h2&gt;

&lt;p&gt;Para obtener el código completo del proyecto, visita el repositorio en GitHub:&lt;/p&gt;

&lt;p&gt;Repositorio: &lt;a href="https://github.com/israoo/eks-cluster-setup" rel="noopener noreferrer"&gt;https://github.com/israoo/eks-cluster-setup&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Este repositorio contiene:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Archivos de Terraform para desplegar un clúster de EKS.&lt;/li&gt;
&lt;li&gt;Documentación sobre los recursos creados y su configuración.&lt;/li&gt;
&lt;li&gt;Configuraciones personalizables para adaptar el clúster a tus necesidades.&lt;/li&gt;
&lt;li&gt;Instrucciones detalladas en el archivo README.md sobre cómo usar el proyecto.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  🎯 Recomendaciones adicionales
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Seguridad&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Restringe el acceso al clúster mediante una VPN o rangos de IP específicos.&lt;/li&gt;
&lt;li&gt;Configura un ACL en las subredes para controlar el tráfico de red.&lt;/li&gt;
&lt;li&gt;Habilita el cifrado de datos en el control plane y en los nodos de EKS con una clave KMS.&lt;/li&gt;
&lt;li&gt;Deshabilita el access entry configurado con el archivo &lt;code&gt;3.04-eks_access.tf&lt;/code&gt; y crea roles de IAM específicos para los usuarios que necesiten acceso al clúster.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Tráfico de red&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Configura un api gateway para gestionar las peticiones HTTP.&lt;/li&gt;
&lt;li&gt;Configura un WAF para proteger tu aplicación de ataques.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Dentro del cluster de EKS puedes configurar diferentes servicios para mejorar la escalabilidad, resiliencia, observabilidad y seguridad de las aplicaciones desplegadas en el clúster.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  🔗 Referencias/Extras
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/es_es/eks/latest/userguide/what-is-eks.html" rel="noopener noreferrer"&gt;Documentación oficial de EKS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.hashicorp.com/tutorials/terraform/eks" rel="noopener noreferrer"&gt;Documentación oficial de Terraform&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/home/" rel="noopener noreferrer"&gt;Documentación oficial de Kubernetes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 ¿Qué sigue?
&lt;/h2&gt;

&lt;p&gt;Con un clúster de EKS completamente funcional, puedes comenzar a desplegar tus aplicaciones en Kubernetes. Puedes utilizar Helm o Kustomize para gestionar los manifiestos de tus aplicaciones. Si quieres aprender más sobre Helm y Kustomize, te invito a leer mi artículo sobre &lt;a href="https://dev.to/israoo/helm-vs-kustomize-cual-es-mejor-para-gestionar-manifiestos-en-kubernetes-3d7"&gt;Helm vs Kustomize&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;¡Espero que este proyecto te sea útil y si tienes dudas o sugerencias, no dudes en compartirlas en los comentarios!&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

</description>
      <category>devops</category>
      <category>eks</category>
      <category>terraform</category>
      <category>español</category>
    </item>
    <item>
      <title>Crea imágenes Docker ligeras y seguras</title>
      <dc:creator>Israel Oña Ordoñez 🚀</dc:creator>
      <pubDate>Sun, 26 Jan 2025 04:13:19 +0000</pubDate>
      <link>https://dev.to/israoo/crea-imagenes-docker-ligeras-y-seguras-hj7</link>
      <guid>https://dev.to/israoo/crea-imagenes-docker-ligeras-y-seguras-hj7</guid>
      <description>&lt;h2&gt;
  
  
  📝 TL;DR
&lt;/h2&gt;

&lt;p&gt;Optimizar tus imágenes Docker es esencial para mejorar los tiempos de construcción y despliegue, reducir costos y mejorar la seguridad. Este artículo muestra cómo usar multi-stage builds, elegir imágenes ligeras y aplicar buenas prácticas para crear imágenes Docker más eficientes.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  🤔 ¿Por qué optimizar imágenes Docker?
&lt;/h2&gt;

&lt;p&gt;En la contenerización, el tamaño y la seguridad de las imágenes Docker tienen un impacto significativo en el rendimiento, la eficiencia y la seguridad de las aplicaciones. Las imágenes grandes aumentan los tiempos de construcción, despliegue y consumo de recursos, mientras que las vulnerabilidades en las imágenes pueden exponer tu aplicación a riesgos de seguridad.&lt;/p&gt;

&lt;p&gt;Optimizar tus imágenes Docker te permite:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mejorar los tiempos de construcción y despliegue:&lt;/strong&gt; Imágenes más pequeñas se construyen y despliegan más rápido.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reducir costos de almacenamiento y transferencia:&lt;/strong&gt; Imágenes más ligeras ocupan menos espacio y se transfieren más rápido.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mejorar la seguridad:&lt;/strong&gt; Reducir vulnerabilidades y riesgos de seguridad en tus imágenes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  ⚙️ Principales estrategias de optimización
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Multi-stage builds&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Las multi-stage builds te permiten dividir la construcción de tu imagen en múltiples etapas, lo que te permite compilar y empaquetar tu aplicación en una etapa y copiar solo los artefactos necesarios a una imagen final más pequeña.&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%2Fs843yljjtsnr6evksov9.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%2Fs843yljjtsnr6evksov9.png" alt="Multi-stage build" width="800" height="613"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Beneficios:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Imágenes más pequeñas:&lt;/strong&gt; La imagen final, basada en una imagen más ligera, solo contiene los artefactos necesarios.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reduce la superficie de ataque:&lt;/strong&gt; Las etapas de construcción no se incluyen en la imagen final.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Elegir imágenes base ligeras&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Usar imágenes base ligeras y especializadas, como Alpine Linux, Slim o Buster, en lugar de imágenes genéricas como Ubuntu o Debian, puede reducir significativamente el tamaño de tus imágenes.&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%2Fl16u7ufbc4lehyj10hpf.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%2Fl16u7ufbc4lehyj10hpf.png" alt="Imágenes base ligeras" width="800" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Beneficios:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Imágenes más pequeñas:&lt;/strong&gt; Las imágenes base ligeras tienen un tamaño reducido.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Menos vulnerabilidades:&lt;/strong&gt; Menos paquetes y dependencias significan menos vulnerabilidades potenciales.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Usar un usuario no-root&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Ejecutar contenedores con un usuario no-root (sin privilegios) mejora la seguridad de tus aplicaciones, ya que limita los daños potenciales en caso de una vulnerabilidad o ataque.&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%2Flpaap8ci7gr1uf2m0t5f.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%2Flpaap8ci7gr1uf2m0t5f.png" alt="Usuario no-root" width="800" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Beneficios:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mejora la seguridad:&lt;/strong&gt; Limita los daños potenciales en caso de una vulnerabilidad o ataque.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cumplimiento de estándares de seguridad:&lt;/strong&gt; Algunas regulaciones y estándares de seguridad requieren ejecutar aplicaciones con usuarios no-root.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  4. &lt;strong&gt;Excluir archivos innecesarios&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Usar &lt;code&gt;.dockerignore&lt;/code&gt; para excluir archivos y directorios innecesarios de tus imágenes Docker puede reducir significativamente el tamaño de tus imágenes y mejorar los tiempos de construcción.&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%2Fijj3jlxcjfo7o1bm9ikw.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%2Fijj3jlxcjfo7o1bm9ikw.png" alt="Excluir archivos innecesarios" width="800" height="707"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Beneficios:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Imágenes más pequeñas:&lt;/strong&gt; Menos archivos y directorios innecesarios.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mejora los tiempos de construcción:&lt;/strong&gt; Menos archivos a copiar y procesar.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  5. &lt;strong&gt;Optimizar capas de imagen&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Reducir el número de capas de imagen y combinar instrucciones en una sola capa puede mejorar el rendimiento y la eficiencia de tus imágenes Docker.&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%2F0zoulno28k49ypt0877z.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%2F0zoulno28k49ypt0877z.png" alt="Optimizar capas de imagen" width="800" height="388"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Beneficios:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mejora el rendimiento:&lt;/strong&gt; Menos capas significa menos operaciones de lectura/escritura.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reduce el tamaño de la imagen:&lt;/strong&gt; Menos capas y posibilidad de eliminar archivos temporales en la misma capa donde se crean.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  6. &lt;strong&gt;Escaneo de vulnerabilidades&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Utilizar herramientas de escaneo de vulnerabilidades, como Trivy, te permite identificar y corregir vulnerabilidades en tus imágenes Docker antes de desplegarlas en producción.&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%2Fdzo45o5d5z91pqfprfr9.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%2Fdzo45o5d5z91pqfprfr9.png" alt="Escaneo de vulnerabilidades" width="800" height="516"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Beneficios:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mejora la seguridad:&lt;/strong&gt; Identifica y corrige vulnerabilidades antes de desplegar tus imágenes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Protege tu aplicación:&lt;/strong&gt; Reduce el riesgo de ataques y brechas de seguridad.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 Resultados de la optimización
&lt;/h2&gt;

&lt;p&gt;Al aplicar estas estrategias de optimización, puedes obtener los siguientes resultados:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Imágenes más pequeñas:&lt;/strong&gt; Reducción significativa del tamaño de las imágenes Docker, en este caso, de 1.12 GB a 159 MB.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mejora de los tiempos de construcción:&lt;/strong&gt; Reducción en los tiempos de construcción, en este caso, 60% más rápido.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mejora de la seguridad:&lt;/strong&gt; Reducción de vulnerabilidades y riesgos de seguridad en las imágenes, en este caso, 0 vulnerabilidades.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mejora de la eficiencia:&lt;/strong&gt; Reducción de costos de transferencia, en este caso, 85% menos de datos transferidos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cumplimiento de estándares de seguridad:&lt;/strong&gt; Ejecución de contenedores con un usuario no-root para mejorar la seguridad.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  📂 Repositorio del proyecto
&lt;/h2&gt;

&lt;p&gt;Para ver un ejemplo práctico de cómo aplicar estas estrategias de optimización, puedes clonar o explorar el repositorio asociado.&lt;/p&gt;

&lt;p&gt;Repositorio: &lt;a href="https://github.com/israoo/docker-image-optimization" rel="noopener noreferrer"&gt;https://github.com/israoo/docker-image-optimization&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Este repositorio contiene:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Un ejemplo de &lt;code&gt;Dockerfile&lt;/code&gt; con las mejores prácticas de optimización.&lt;/li&gt;
&lt;li&gt;Un archivo &lt;code&gt;.dockerignore&lt;/code&gt; para excluir archivos innecesarios.&lt;/li&gt;
&lt;li&gt;Un script para escanear vulnerabilidades en la imagen Docker con Trivy.&lt;/li&gt;
&lt;li&gt;Instrucciones detalladas en el archivo README.md sobre cómo construir, optimizar y escanear la imagen Docker paso a paso.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  🔗 Referencias/Extras
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/reference/" rel="noopener noreferrer"&gt;Documentación oficial de Docker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/engine/reference/builder/" rel="noopener noreferrer"&gt;Dockerfile reference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html" rel="noopener noreferrer"&gt;Docker security cheat sheet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://trivy.dev/latest/docs/" rel="noopener noreferrer"&gt;Documentación oficial de Trivy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 ¿Qué sigue?
&lt;/h2&gt;

&lt;p&gt;Prueba estas técnicas en tus proyectos y comparte los resultados. ¿Conoces otras estrategias para optimizar imágenes Docker? ¡Déjalas en los comentarios!&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

</description>
      <category>docker</category>
      <category>optimizacion</category>
      <category>devops</category>
      <category>español</category>
    </item>
    <item>
      <title>Helm vs Kustomize: ¿Cuál es mejor para gestionar manifiestos en Kubernetes?</title>
      <dc:creator>Israel Oña Ordoñez 🚀</dc:creator>
      <pubDate>Mon, 20 Jan 2025 15:37:41 +0000</pubDate>
      <link>https://dev.to/israoo/helm-vs-kustomize-cual-es-mejor-para-gestionar-manifiestos-en-kubernetes-3d7</link>
      <guid>https://dev.to/israoo/helm-vs-kustomize-cual-es-mejor-para-gestionar-manifiestos-en-kubernetes-3d7</guid>
      <description>&lt;h2&gt;
  
  
  📝 TL;DR
&lt;/h2&gt;

&lt;p&gt;Helm y Kustomize son herramientas esenciales para gestionar manifiestos en Kubernetes. Helm es ideal para empaquetar y compartir configuraciones reutilizables, mientras que Kustomize sobresale en la personalización y simplicidad. Este artículo te ayudará a decidir cuál usar en tu próximo proyecto.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  🌟 El reto de gestionar manifiestos en Kubernetes
&lt;/h2&gt;

&lt;p&gt;Gestionar despliegues en &lt;strong&gt;Kubernetes&lt;/strong&gt; puede ser un desafío, especialmente cuando se trata de mantener y personalizar múltiples manifiestos YAML. &lt;strong&gt;Helm&lt;/strong&gt; y &lt;strong&gt;Kustomize&lt;/strong&gt; son dos herramientas populares que facilitan la gestión de configuraciones y despliegues en Kubernetes.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  🌍 Visión general
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Helm
&lt;/h3&gt;

&lt;p&gt;Helm es un gestor de paquetes para Kubernetes que permite empaquetar, compartir y desplegar aplicaciones.&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%2Fy9ds48gw5sim4x64pfd9.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%2Fy9ds48gw5sim4x64pfd9.png" alt="Ejemplo de Helm" width="800" height="527"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Características principales&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Usa plantillas Go para generar manifiestos YAML.&lt;/li&gt;
&lt;li&gt;Soporte para repositorios públicos y privados.&lt;/li&gt;
&lt;li&gt;Gestión de versiones y actualizaciones.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Ventajas&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Facilita la reutilización de configuraciones.&lt;/li&gt;
&lt;li&gt;Permite compartir y distribuir aplicaciones.&lt;/li&gt;
&lt;li&gt;Amplia comunidad y soporte.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Desventajas&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Curva de aprendizaje para manejar plantillas.&lt;/li&gt;
&lt;li&gt;Complejidad en personalizaciones avanzadas.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Para usar helm, se debe instalar el cliente de helm en tu máquina local. Para instalar helm, puedes seguir las instrucciones en la &lt;a href="https://helm.sh/docs/intro/install/" rel="noopener noreferrer"&gt;documentación oficial de Helm&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Los comandos básicos de helm son:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;helm create &amp;lt;nombre&amp;gt;&lt;/code&gt;: Crea un nuevo chart.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;helm install &amp;lt;nombre&amp;gt; &amp;lt;ruta&amp;gt;&lt;/code&gt;: Instala un chart.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;helm upgrade &amp;lt;nombre&amp;gt; &amp;lt;ruta&amp;gt;&lt;/code&gt;: Actualiza un chart.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;helm uninstall &amp;lt;nombre&amp;gt;&lt;/code&gt;: Desinstala un chart.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;helm list&lt;/code&gt;: Lista los charts instalados.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;helm rollback &amp;lt;nombre&amp;gt; &amp;lt;versión&amp;gt;&lt;/code&gt;: Revierte a una versión anterior.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;helm template &amp;lt;nombre&amp;gt; &amp;lt;ruta&amp;gt;&lt;/code&gt;: Genera los manifiestos YAML.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;helm package &amp;lt;ruta&amp;gt;&lt;/code&gt;: Empaqueta un chart en un archivo &lt;code&gt;.tgz&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;helm repo add &amp;lt;nombre&amp;gt; &amp;lt;url&amp;gt;&lt;/code&gt;: Añade un repositorio.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;helm repo update&lt;/code&gt;: Actualiza los repositorios.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;helm lint &amp;lt;ruta&amp;gt;&lt;/code&gt;: Verifica la sintaxis del chart.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Kustomize
&lt;/h3&gt;

&lt;p&gt;Kustomize es una herramienta nativa de Kubernetes que permite personalizar y gestionar manifiestos YAML sin plantillas.&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%2F1vwzdvgm82zby2gdruba.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%2F1vwzdvgm82zby2gdruba.png" alt="Ejemplo de Kustomize parte 1" width="800" height="451"&gt;&lt;/a&gt;&lt;br&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%2Fx2epddnpt207ec9gm0jr.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%2Fx2epddnpt207ec9gm0jr.png" alt="Ejemplo de Kustomize parte 2" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Características principales&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Usa overlays o patches para modificar manifiestos.&lt;/li&gt;
&lt;li&gt;Integración nativa con &lt;code&gt;kubectl&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;No requiere plantillas adicionales.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Ventajas&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simplifica la personalización de manifiestos.&lt;/li&gt;
&lt;li&gt;Fácil integración con flujos de CI/CD.&lt;/li&gt;
&lt;li&gt;Soporte nativo en Kubernetes.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Desventajas&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No incluye gestión de versiones ni repositorios centralizados.&lt;/li&gt;
&lt;li&gt;Limitado en la reutilización de configuraciones.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Para usar kustomize, se debe instalar el cliente de kubectl en tu máquina local. Para instalar kubectl, puedes seguir las instrucciones en la &lt;a href="https://kubernetes.io/docs/tasks/tools/install-kubectl/" rel="noopener noreferrer"&gt;documentación oficial de Kubernetes&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Los comandos básicos de kustomize son:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;kubectl apply -k &amp;lt;ruta&amp;gt;&lt;/code&gt;: Aplica los manifiestos personalizados.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kubectl diff -k &amp;lt;ruta&amp;gt;&lt;/code&gt;: Muestra las diferencias antes de aplicar.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kubectl kustomize &amp;lt;ruta&amp;gt;&lt;/code&gt;: Genera los manifiestos personalizados.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kubectl delete -k &amp;lt;ruta&amp;gt;&lt;/code&gt;: Elimina los recursos creados.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kubectl get -k &amp;lt;ruta&amp;gt;&lt;/code&gt;: Muestra los recursos creados.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kubectl describe -k &amp;lt;ruta&amp;gt;&lt;/code&gt;: Muestra detalles de los recursos creados.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  💡 Comparación
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Característica&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Helm&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Kustomize&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Propósito&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Empaquetar y compartir configuraciones&lt;/td&gt;
&lt;td&gt;Personalizar y gestionar manifiestos&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Reutilización&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Alta, mediante charts reutilizables&lt;/td&gt;
&lt;td&gt;Baja, requiere configuraciones específicas&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Simplicidad&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Complejo para personalizaciones avanzadas&lt;/td&gt;
&lt;td&gt;Sencillo y directo en YAML&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Gestión de versiones&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Incluye historial y rollback&lt;/td&gt;
&lt;td&gt;No incluye, depende de &lt;code&gt;git&lt;/code&gt; o &lt;code&gt;kubectl&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Comunidad&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Amplia y activa&lt;/td&gt;
&lt;td&gt;Limitada, pero integrada en Kubernetes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Flexibilidad&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Menos flexible en personalizaciones&lt;/td&gt;
&lt;td&gt;Más flexible y modular&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  🤔 ¿Cuál elegir?
&lt;/h2&gt;

&lt;p&gt;La elección entre Helm y Kustomize depende de tus necesidades y preferencias. Aquí algunas consideraciones:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Usa Helm si&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Necesitas empaquetar y compartir configuraciones.&lt;/li&gt;
&lt;li&gt;Deseas gestionar versiones y actualizaciones.&lt;/li&gt;
&lt;li&gt;Prefieres plantillas Go para generar manifiestos.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Usa Kustomize si&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Buscas personalizar manifiestos sin plantillas.&lt;/li&gt;
&lt;li&gt;Quieres una integración nativa con &lt;code&gt;kubectl&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Prefieres simplicidad y flexibilidad en YAML.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  📂 Repositorio del proyecto
&lt;/h2&gt;

&lt;p&gt;Para explorar los ejemplos de Helm y Kustomize, puedes clonar o explorar el repositorio asociado.&lt;/p&gt;

&lt;p&gt;Repositorio: &lt;a href="https://github.com/israoo/helm-vs-kustomize" rel="noopener noreferrer"&gt;https://github.com/israoo/helm-vs-kustomize&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Este repositorio contiene:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ejemplos de configuraciones en Helm y Kustomize.&lt;/li&gt;
&lt;li&gt;Scripts para probar y comparar ambas herramientas.&lt;/li&gt;
&lt;li&gt;Instrucciones detalladas en el archivo README.md sobre cómo usar el repositorio.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  🔗 Referencias/Extras
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://helm.sh/docs/" rel="noopener noreferrer"&gt;Documentación oficial de Helm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kustomize.io/" rel="noopener noreferrer"&gt;Documentación oficial de Kustomize&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://helm.sh/docs/intro/cheatsheet/" rel="noopener noreferrer"&gt;Cheat sheet de Helm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/kubernetes-sigs/kustomize/tree/master/examples" rel="noopener noreferrer"&gt;Ejemplos prácticos de Kustomize&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 ¿Qué sigue?
&lt;/h2&gt;

&lt;p&gt;¿Prefieres Helm o Kustomize para gestionar tus despliegues? ¡Comparte tu experiencia y cuéntanos qué herramienta prefieres en los comentarios!&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>helm</category>
      <category>kustomize</category>
      <category>español</category>
    </item>
    <item>
      <title>5 errores comunes en Kubernetes y cómo solucionarlos rápidamente</title>
      <dc:creator>Israel Oña Ordoñez 🚀</dc:creator>
      <pubDate>Mon, 13 Jan 2025 15:57:04 +0000</pubDate>
      <link>https://dev.to/israoo/5-errores-comunes-en-kubernetes-y-como-solucionarlos-rapidamente-2i68</link>
      <guid>https://dev.to/israoo/5-errores-comunes-en-kubernetes-y-como-solucionarlos-rapidamente-2i68</guid>
      <description>&lt;h2&gt;
  
  
  📝 TL;DR
&lt;/h2&gt;

&lt;p&gt;Desplegar aplicaciones en Kubernetes puede ser complicado al inicio debido a errores como imágenes no disponibles, configuraciones YAML incorrectas o recursos insuficientes. Aquí descubrirás los 5 errores más comunes al trabajar con Kubernetes y aprenderás a solucionarlos de manera rápida y efectiva.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  🌟 El desafío de evitar errores en Kubernetes
&lt;/h2&gt;

&lt;p&gt;Trabajar con &lt;strong&gt;Kubernetes&lt;/strong&gt;, especialmente al inicio, puede ser una experiencia desafiante. Muchas veces, pequeños errores de configuración pueden causar grandes problemas al desplegar pods. Este artículo aborda 5 de los errores más comunes que podrías enfrentar y ofrece soluciones rápidas para ayudarte a dominar Kubernetes sin frustraciones.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  🔥 Errores comunes y soluciones
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Imagen de contenedor no disponible
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Indicador
&lt;/h4&gt;

&lt;p&gt;El pod entra en estado ErrImagePull o ImagePullBackOff.&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%2Fzlao35tx61n6gt0xzw5v.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%2Fzlao35tx61n6gt0xzw5v.png" alt="Imagen de contenedor no disponible" width="800" height="663"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Causa más común
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;La imagen no existe o no es accesible desde el registro.&lt;/li&gt;
&lt;li&gt;Errores en el nombre, etiqueta o versión de la imagen.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Solución
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Verifica que la imagen exista y sea accesible:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker pull registry.example.com/image:tag
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Verifica el nombre y la etiqueta de la imagen en el archivo YAML del pod.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&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;my-container&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;registry.example.com/image:tag&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Si es un registro privado, configura las credenciales:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl create secret docker-registry my-registry-secret &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--docker-server&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;registry.example.com &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--docker-username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;my-user &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--docker-password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;my-password
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Agrega las credenciales al archivo YAML del pod:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;imagePullSecrets&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;my-registry-secret&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;my-container&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;registry.example.com/image:tag&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  2. Etiquetas y selectores incorrectos
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Indicador
&lt;/h4&gt;

&lt;p&gt;Un Service no puede encontrar los pods.&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%2Fuf85gy0coluuy2bki4ef.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%2Fuf85gy0coluuy2bki4ef.png" alt="Etiquetas y selectores incorrectos" width="590" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Causa más común
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Las etiquetas de los pods no coinciden con los selectores del Service.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Solución
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Verifica que las etiquetas de los pods coincidan con los selectores del Service.&lt;/p&gt;

&lt;p&gt;Etiquetas del pod:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&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;my-app&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Selectores del Service:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&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;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;my-app&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Inspecciona el estado del recurso:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl describe service my-service
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  3. Recursos insuficientes
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Indicador
&lt;/h4&gt;

&lt;p&gt;El pod permanece en estado Pending o CrashLoopBackOff.&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%2Fnpalbdfwivtfb3of39xv.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%2Fnpalbdfwivtfb3of39xv.png" alt="Recursos insuficientes" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Causa más común
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;No hay suficientes recursos (CPU, memoria) disponibles en el clúster.&lt;/li&gt;
&lt;li&gt;Los límites de recursos son demasiado bajos.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Solución
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Verifica los eventos del pod para encontrar la causa:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl describe pod my-pod
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Aumenta los recursos en el archivo YAML del pod:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&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;my-container&lt;/span&gt;
      &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;64Mi"&lt;/span&gt;
          &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;250m"&lt;/span&gt;
        &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;128Mi"&lt;/span&gt;
          &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;500m"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Confirma que haya nodos disponibles en el clúster:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get nodes
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  4. Configuración YAML incorrecta
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Indicador
&lt;/h4&gt;

&lt;p&gt;El pod no se crea debido a errores de sintaxis en el archivo YAML.&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%2F8ic45lguaqc47tth90sh.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%2F8ic45lguaqc47tth90sh.png" alt="Congiguración YAML incorrecta" width="800" height="352"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Causa más común
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Errores de sintaxis, sangría o formato en el archivo YAML.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Solución
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Verifica la sintaxis del archivo YAML antes de aplicarlo:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; my-pod.yaml &lt;span class="nt"&gt;--dry-run&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;client
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Usa herramientas de validación de YAML para encontrar errores:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yamllint my-pod.yaml
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Instalar yamllint &lt;a href="https://yamllint.readthedocs.io/en/stable/quickstart.html#installing-yamllint" rel="noopener noreferrer"&gt;https://yamllint.readthedocs.io/en/stable/quickstart.html#installing-yamllint&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Usa &lt;strong&gt;kubectl explain&lt;/strong&gt; para entender la estructura de los recursos:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl explain pod.spec
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  5. Variables de entorno incorrectas
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Indicador
&lt;/h4&gt;

&lt;p&gt;El pod falla con errores relacionados con variables de entorno incorrectas o faltantes.&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%2Fm13vj7ogx46bcg3bvat0.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%2Fm13vj7ogx46bcg3bvat0.png" alt="Variables de entorno incorrectas" width="800" height="606"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Causa más común
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Variables de entorno no definidas o con valores incorrectos.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Solución
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Verifica que las variables de entorno estén definidas en el archivo YAML del pod:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&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;my-container&lt;/span&gt;
      &lt;span class="na"&gt;env&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;MY_VAR&lt;/span&gt;
          &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-value&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Si usas ConfigMaps o Secrets, asegúrate de que estén montados correctamente:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&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;my-container&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;configMapRef&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;my-configmap&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;my-secret&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  📂 Repositorio del proyecto
&lt;/h2&gt;

&lt;p&gt;Para practicar y aprender más sobre estos errores comunes, puedes clonar o explorar el repositorio asociado.&lt;/p&gt;

&lt;p&gt;Repositorio: &lt;a href="https://github.com/israoo/k8s-common-errors" rel="noopener noreferrer"&gt;https://github.com/israoo/k8s-common-errors&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Este repositorio contiene:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ejemplos de manifiestos YAML con errores comunes.&lt;/li&gt;
&lt;li&gt;Scripts de ayuda para verificar y solucionar los errores.&lt;/li&gt;
&lt;li&gt;Instrucciones detalladas en el archivo README.md sobre cómo usar el repositorio.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  🔗 Referencias/Extras
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/es/docs/home/" rel="noopener noreferrer"&gt;Documentación oficial de Kubernetes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/es/docs/tasks/debug/debug-application/" rel="noopener noreferrer"&gt;Solución de problemas - Kubernetes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/reference/kubectl/quick-reference/" rel="noopener noreferrer"&gt;Cheat sheet de kubectl&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 ¿Qué sigue?
&lt;/h2&gt;

&lt;p&gt;¿Quieres aprender más sobre solución de problemas en Kubernetes? Comenta tus dudas o comparte problemas que te gustaría resolver en futuros artículos.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>troubleshooting</category>
      <category>devops</category>
      <category>español</category>
    </item>
    <item>
      <title>Domina Bash con ejemplos prácticos de Git</title>
      <dc:creator>Israel Oña Ordoñez 🚀</dc:creator>
      <pubDate>Wed, 08 Jan 2025 03:12:30 +0000</pubDate>
      <link>https://dev.to/israoo/domina-bash-con-ejemplos-practicos-de-git-3k0k</link>
      <guid>https://dev.to/israoo/domina-bash-con-ejemplos-practicos-de-git-3k0k</guid>
      <description>&lt;h2&gt;
  
  
  📝 TL;DR
&lt;/h2&gt;

&lt;p&gt;Bash es un lenguaje de scripting utilizado en sistemas tipo Unix para automatizar tareas. Aprende a usarlo mientras automatizas operaciones de Git con un script que te permitirá realizar commits, push, cambiar de ramas y más, ahorrando tiempo y esfuerzo en tu flujo de trabajo diario.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  🤔 ¿Por qué aprender Bash?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Bash&lt;/strong&gt; es un lenguaje de scripting utilizado en sistemas tipo Unix para automatizar tareas. Su capacidad para ejecutar comandos del sistema y manipular archivos de forma sencilla lo convierte en una herramienta esencial para optimizar operaciones diarias.&lt;/p&gt;

&lt;p&gt;Como caso práctico aprenderás a &lt;strong&gt;automatizar operaciones rutinarias de Git&lt;/strong&gt; con Bash, como realizar commits, push, cambiar de ramas y más, mostrando cómo puedes &lt;strong&gt;ahorrar tiempo y esfuerzo&lt;/strong&gt; en tu flujo de trabajo diario.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  🔑 Conceptos básicos de Bash
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Shebang (&lt;code&gt;#!/bin/bash&lt;/code&gt;):&lt;/strong&gt; Indica que el archivo debe ser ejecutado con Bash.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Variables&lt;/strong&gt;: Almacenan valores y se acceden con &lt;code&gt;$&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;&lt;span class="nv"&gt;VARIABLE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Hello World"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$VARIABLE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Funciones&lt;/strong&gt;: Bloques de código reutilizables.&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="k"&gt;function &lt;/span&gt;greeting&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Hi!"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Condicionales (&lt;code&gt;if&lt;/code&gt;, &lt;code&gt;else&lt;/code&gt;):&lt;/strong&gt; Ejecutan comandos basados en condiciones.&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="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$USER&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"root"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"You are root"&lt;/span&gt;
&lt;span class="k"&gt;else
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"You are not root"&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Bucles (&lt;code&gt;for&lt;/code&gt;, &lt;code&gt;while&lt;/code&gt;):&lt;/strong&gt; Repiten comandos hasta que se cumpla una condición.&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="k"&gt;for &lt;/span&gt;i &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;1..5&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Number: &lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;done

while&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$i&lt;/span&gt; &lt;span class="nt"&gt;-le&lt;/span&gt; 5 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Number: &lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="o"&gt;((&lt;/span&gt;i++&lt;span class="o"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  ⚙️ Git Helper Script
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Script:&lt;/strong&gt; git-helper.sh&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;#!/bin/bash&lt;/span&gt;

show_menu&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"==================================="&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"          Git Helper Script        "&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"==================================="&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"1) Perform git pull"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"2) Create a new branch"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"3) Switch to an existing branch"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"4) Add files and commit"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"5) Show repository status (git status)"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"6) Push to the current branch"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"7) Show commit history (git log)"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"8) Exit"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"==================================="&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

git_pull&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Performing git pull..."&lt;/span&gt;
  git pull
&lt;span class="o"&gt;}&lt;/span&gt;

create_branch&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"Enter the name of the new branch: "&lt;/span&gt; branch_name
  &lt;span class="k"&gt;if &lt;/span&gt;git branch &lt;span class="nt"&gt;--list&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$branch_name&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error: The branch '&lt;/span&gt;&lt;span class="nv"&gt;$branch_name&lt;/span&gt;&lt;span class="s2"&gt;' already exists."&lt;/span&gt;
    &lt;span class="k"&gt;return
  fi

  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Creating and switching to branch &lt;/span&gt;&lt;span class="nv"&gt;$branch_name&lt;/span&gt;&lt;span class="s2"&gt;..."&lt;/span&gt;
  git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$branch_name&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

switch_branch&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;branches&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git branch&lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$branches&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"No branches available in this repository."&lt;/span&gt;
    &lt;span class="k"&gt;return
  fi

  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Available branches:"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$branches&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

  &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"Enter the name of the branch you want to switch to: "&lt;/span&gt; branch_name
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; git branch &lt;span class="nt"&gt;--list&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$branch_name&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error: The branch '&lt;/span&gt;&lt;span class="nv"&gt;$branch_name&lt;/span&gt;&lt;span class="s2"&gt;' does not exist."&lt;/span&gt;
    &lt;span class="k"&gt;return
  fi

  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Switching to branch &lt;/span&gt;&lt;span class="nv"&gt;$branch_name&lt;/span&gt;&lt;span class="s2"&gt;..."&lt;/span&gt;
  git checkout &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$branch_name&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

git_commit&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    &lt;/span&gt;git status

    &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"Which files do you want to add? (use . for all or 'exit' to cancel): "&lt;/span&gt; files
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$files&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"exit"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
      &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Operation canceled."&lt;/span&gt;
      &lt;span class="k"&gt;return
    fi

    &lt;/span&gt;git add &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$files&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

    &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"Enter the commit message: "&lt;/span&gt; commit_message
    git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$commit_message&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Commit completed."&lt;/span&gt;
    &lt;span class="nb"&gt;break
  &lt;/span&gt;&lt;span class="k"&gt;done&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

git_status&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Showing repository status..."&lt;/span&gt;
  git status
&lt;span class="o"&gt;}&lt;/span&gt;

git_push&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Pushing to branch &lt;/span&gt;&lt;span class="nv"&gt;$branch&lt;/span&gt;&lt;span class="s2"&gt;..."&lt;/span&gt;
  git push origin &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$branch&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

git_log&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Recent commit history:"&lt;/span&gt;
  git log &lt;span class="nt"&gt;--oneline&lt;/span&gt; &lt;span class="nt"&gt;--graph&lt;/span&gt; &lt;span class="nt"&gt;--decorate&lt;/span&gt; &lt;span class="nt"&gt;-10&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

check_git_repo&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; .git &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error: This does not appear to be a Git repository."&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
  &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

main&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  check_git_repo

  &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    &lt;/span&gt;show_menu
    &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"Select an option: "&lt;/span&gt; choice
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nv"&gt;$choice&lt;/span&gt; &lt;span class="k"&gt;in
      &lt;/span&gt;1&lt;span class="p"&gt;)&lt;/span&gt; git_pull &lt;span class="p"&gt;;;&lt;/span&gt;
      2&lt;span class="p"&gt;)&lt;/span&gt; create_branch &lt;span class="p"&gt;;;&lt;/span&gt;
      3&lt;span class="p"&gt;)&lt;/span&gt; switch_branch &lt;span class="p"&gt;;;&lt;/span&gt;
      4&lt;span class="p"&gt;)&lt;/span&gt; git_commit &lt;span class="p"&gt;;;&lt;/span&gt;
      5&lt;span class="p"&gt;)&lt;/span&gt; git_status &lt;span class="p"&gt;;;&lt;/span&gt;
      6&lt;span class="p"&gt;)&lt;/span&gt; git_push &lt;span class="p"&gt;;;&lt;/span&gt;
      7&lt;span class="p"&gt;)&lt;/span&gt; git_log &lt;span class="p"&gt;;;&lt;/span&gt;
      8&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Exiting..."&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;exit &lt;/span&gt;0 &lt;span class="p"&gt;;;&lt;/span&gt;
      &lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Invalid option. Please try again."&lt;/span&gt;
        &lt;span class="k"&gt;continue&lt;/span&gt;
        &lt;span class="p"&gt;;;&lt;/span&gt;
    &lt;span class="k"&gt;esac&lt;/span&gt;
    &lt;span class="nb"&gt;break
  &lt;/span&gt;&lt;span class="k"&gt;done&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Resultado:&lt;/strong&gt;&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%2Fiheu8febtuzheillgyiw.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%2Fiheu8febtuzheillgyiw.png" alt="Ejecución del script" width="523" height="299"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ejecución:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Guarda el script como &lt;code&gt;git-helper.sh&lt;/code&gt; y hazlo ejecutable:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x git-helper.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;(Opcional) Colócalo en un directorio que esté en tu PATH (por ejemplo, &lt;code&gt;/usr/local/bin&lt;/code&gt;) para usarlo globalmente:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mv &lt;/span&gt;git-helper.sh /usr/local/bin/git-helper
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ejecútalo:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git-helper
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  🛠️ Paso a paso
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Paso 1: Crear un menú principal
&lt;/h3&gt;

&lt;p&gt;El primer paso es crear un &lt;strong&gt;menú principal&lt;/strong&gt; con las opciones disponibles.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;show_menu&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"==================================="&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"          Git Helper Script        "&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"==================================="&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"1) Perform git pull"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"2) Create a new branch"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"3) Switch to an existing branch"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"4) Add files and commit"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"5) Show repository status (git status)"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"6) Push to the current branch"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"7) Show commit history (git log)"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"8) Exit"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"==================================="&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explicación:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Utilizamos &lt;code&gt;echo&lt;/code&gt; para mostrar mensajes en la consola.&lt;/li&gt;
&lt;li&gt;El menú se muestra con las opciones disponibles.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Paso 2: Validar si es un repositorio Git
&lt;/h3&gt;

&lt;p&gt;Antes de realizar cualquier operación de Git, es importante &lt;strong&gt;verificar si el directorio actual es un repositorio Git&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;check_git_repo&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; .git &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error: This does not appear to be a Git repository."&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;1
  &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explicación:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verificamos con &lt;code&gt;-d .git&lt;/code&gt; si existe un directorio &lt;code&gt;.git&lt;/code&gt; en el directorio actual.&lt;/li&gt;
&lt;li&gt;Si no es un repositorio Git, mostramos un mensaje de error y salimos del script con &lt;code&gt;exit 1&lt;/code&gt; (código de error).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Paso 3: Crear funciones para las operaciones de Git
&lt;/h3&gt;

&lt;p&gt;Cada función realiza una operación específica de Git. A continuación, se muestran algunas de las funciones disponibles:&lt;/p&gt;

&lt;h4&gt;
  
  
  Crear una nueva rama
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;create_branch&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"Enter the name of the new branch: "&lt;/span&gt; branch_name
  &lt;span class="k"&gt;if &lt;/span&gt;git branch &lt;span class="nt"&gt;--list&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$branch_name&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error: The branch '&lt;/span&gt;&lt;span class="nv"&gt;$branch_name&lt;/span&gt;&lt;span class="s2"&gt;' already exists."&lt;/span&gt;
  &lt;span class="k"&gt;fi

  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Creating and switching to branch &lt;/span&gt;&lt;span class="nv"&gt;$branch_name&lt;/span&gt;&lt;span class="s2"&gt;..."&lt;/span&gt;
  git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$branch_name&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explicación:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Con &lt;code&gt;read -p&lt;/code&gt; leemos la entrada del usuario para el nombre de la nueva rama y almacenamos el valor en &lt;code&gt;branch_name&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Usamos &lt;code&gt;git branch --list&lt;/code&gt; para listar las ramas existentes y &lt;code&gt;grep -q&lt;/code&gt; para buscar si la rama almacenada en &lt;code&gt;branch_name&lt;/code&gt; existe en la lista.

&lt;ul&gt;
&lt;li&gt;Si la rama ya existe, mostramos un mensaje de error y salimos de la función.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Si la rama no existe, creamos y cambiamos a la nueva rama con &lt;code&gt;git checkout -b&lt;/code&gt;.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h4&gt;
  
  
  Cambiar a una rama existente
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;switch_branch&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;branches&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git branch&lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$branches&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"No branches available in this repository."&lt;/span&gt;
    &lt;span class="k"&gt;return
  fi

  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Available branches:"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$branches&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

  &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"Enter the name of the branch you want to switch to: "&lt;/span&gt; branch_name
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; git branch &lt;span class="nt"&gt;--list&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$branch_name&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error: The branch '&lt;/span&gt;&lt;span class="nv"&gt;$branch_name&lt;/span&gt;&lt;span class="s2"&gt;' does not exist."&lt;/span&gt;
    &lt;span class="k"&gt;return
  fi

  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Switching to branch &lt;/span&gt;&lt;span class="nv"&gt;$branch_name&lt;/span&gt;&lt;span class="s2"&gt;..."&lt;/span&gt;
  git checkout &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$branch_name&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explicación:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Almacena las ramas existentes en la variable &lt;code&gt;branches&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Con &lt;code&gt;-z&lt;/code&gt; verificamos si la variable &lt;code&gt;branches&lt;/code&gt; está vacía.

&lt;ul&gt;
&lt;li&gt;Si no hay ramas disponibles, mostramos un mensaje y salimos de la función.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Mostramos las ramas disponibles y leemos la entrada del usuario para la rama a la que desea cambiar.&lt;/li&gt;

&lt;li&gt;Usamos &lt;code&gt;git branch --list&lt;/code&gt; y &lt;code&gt;grep -q&lt;/code&gt; para verificar si la rama existe.

&lt;ul&gt;
&lt;li&gt;Si la rama no existe, mostramos un mensaje de error y salimos de la función.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Cambiamos a la rama seleccionada con &lt;code&gt;git checkout&lt;/code&gt;.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  📂 Repositorio del proyecto
&lt;/h2&gt;

&lt;p&gt;Para seguir este ejemplo de automatización de operaciones de Git con Bash, puedes clonar o explorar el repositorio asociado.&lt;/p&gt;

&lt;p&gt;Repositorio: &lt;a href="https://github.com/israoo/git-helper-bash" rel="noopener noreferrer"&gt;https://github.com/israoo/git-helper-bash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Este repositorio contiene:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Script &lt;code&gt;git-helper.sh&lt;/code&gt; con las funciones para automatizar operaciones de Git.&lt;/li&gt;
&lt;li&gt;Instrucciones detalladas en el archivo README.md sobre cómo configurar y ejecutar el script paso a paso.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  🔗 Referencias/Extras
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.gnu.org/software/bash/manual/" rel="noopener noreferrer"&gt;Documentación oficial de Bash&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://devhints.io/bash" rel="noopener noreferrer"&gt;Bash scripting cheat sheet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.freecodecamp.org/espanol/news/tutorial-de-programacion-de-bash-script-de-shell-de-linux-y-linea-de-comandos-para-principiantes/" rel="noopener noreferrer"&gt;Tutorial de programación de Bash&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 ¿Qué sigue?
&lt;/h2&gt;

&lt;p&gt;¿Ya estás usando git tags o submódulos? Agrega estas funcionalidades a tu script para mejorar aún más tu flujo de trabajo con Git. ¡Coméntalo y comparte tus ideas!&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

</description>
      <category>bash</category>
      <category>scripting</category>
      <category>git</category>
      <category>español</category>
    </item>
    <item>
      <title>¿Qué es CI/CD y cómo puede acelerar tus despliegues en minutos?</title>
      <dc:creator>Israel Oña Ordoñez 🚀</dc:creator>
      <pubDate>Fri, 03 Jan 2025 04:04:47 +0000</pubDate>
      <link>https://dev.to/israoo/que-es-cicd-y-como-puede-acelerar-tus-despliegues-en-minutos-2fgk</link>
      <guid>https://dev.to/israoo/que-es-cicd-y-como-puede-acelerar-tus-despliegues-en-minutos-2fgk</guid>
      <description>&lt;h2&gt;
  
  
  📝 TL;DR
&lt;/h2&gt;

&lt;p&gt;CI/CD (integración continua y despliegue continuo) automatiza el proceso de integración del código, pruebas y despliegue. Gracias a CI/CD reduces errores humanos, aumentas la velocidad de entrega y aseguras una mayor calidad del software. En este artículo verás qué es, cómo funciona y un ejemplo para llevar a cabo.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  🤔 ¿Qué es CI/CD?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;CI/CD&lt;/strong&gt; se refiere a &lt;strong&gt;Integración Continua (CI)&lt;/strong&gt; y &lt;strong&gt;Despliegue Continuo (CD)&lt;/strong&gt;. Es un elemento imprescindible en las prácticas de &lt;strong&gt;DevOps&lt;/strong&gt; que permite acelerar el ciclo de vida de desarrollo del software.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Integración Continua (CI)&lt;/strong&gt;: En el momento en que un programador sube un commit al repositorio central, se combina este código nuevo para probar sus cambios, si alguna prueba falla se obtiene una alerta temprana.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Despliegue Continuo (CD)&lt;/strong&gt;: Automatiza el proceso de despliegue de una aplicación en un entorno de pruebas o producción de forma rápida.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  🔧 Ejemplo: Pipeline con GitHub Actions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Objetivo:&lt;/strong&gt; Configurar un pipeline de CI/CD que:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Construya y pruebe tu aplicación automáticamente.&lt;/li&gt;
&lt;li&gt;Despliegue los archivos estáticos en &lt;strong&gt;GitHub Pages&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Flujo del pipeline:&lt;/strong&gt;&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%2Fo7z3uwq67khn83s3rele.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%2Fo7z3uwq67khn83s3rele.png" alt="Diagrama de flujo" width="800" height="538"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Archivo YAML:&lt;/strong&gt; .github/workflows/cicd.yml&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;CI/CD demo&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;master&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-24.04&lt;/span&gt;
    &lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;id-token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&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&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@v4&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;Configure Node.js&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/setup-node@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;18"&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;Install dependencies&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm install&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;Run tests&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm test&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&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm run build&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;Upload static files as artifact&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/upload-pages-artifact@v3&lt;/span&gt;
        &lt;span class="na"&gt;with&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;github-pages&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;./dist&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;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-24.04&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;environment&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;github-pages&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ steps.deployment.outputs.page_url }}&lt;/span&gt;
    &lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;id-token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;
      &lt;span class="na"&gt;pages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&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;Deploy to GitHub Pages&lt;/span&gt;
        &lt;span class="na"&gt;id&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;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/deploy-pages@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;artifact_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github-pages&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Ejecución del pipeline:&lt;/strong&gt;&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%2F549djzem0jbwdl2z9z5i.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%2F549djzem0jbwdl2z9z5i.png" alt="GitHub Actions pipeline" width="800" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Explicación:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Build:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Checkout:&lt;/strong&gt; Descarga el código del repositorio.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configure Node.js:&lt;/strong&gt; Configura Node.js v18.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Install dependencies:&lt;/strong&gt; Instala dependencias con npm install.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run tests:&lt;/strong&gt; Corre los tests con npm test.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build:&lt;/strong&gt; Genera los archivos estáticos con npm run build.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Upload static files as artifact:&lt;/strong&gt; Sube los archivos generados en ./dist como artefacto estático.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deploy:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deploy to GitHub Pages:&lt;/strong&gt; Utiliza los artefactos generados para desplegar automáticamente en &lt;strong&gt;GitHub Pages&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  📂 Repositorio del proyecto
&lt;/h2&gt;

&lt;p&gt;Para seguir este ejemplo de CI/CD con GitHub Actions, puedes clonar o explorar el repositorio asociado.&lt;/p&gt;

&lt;p&gt;Repositorio: &lt;a href="https://github.com/israoo/basic-ci-cd-github-actions" rel="noopener noreferrer"&gt;https://github.com/israoo/basic-ci-cd-github-actions&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Este repositorio contiene:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Código fuente de la aplicación de ejemplo.&lt;/li&gt;
&lt;li&gt;Archivo de configuración del pipeline (cicd.yml).&lt;/li&gt;
&lt;li&gt;Instrucciones detalladas en el archivo README.md sobre cómo configurar y ejecutar el pipeline paso a paso.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  📈 Beneficios clave del CI/CD
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Despliegues más rápidos y frecuentes&lt;/strong&gt;: Reduces el tiempo entre desarrollo y entrega.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Detección temprana de errores&lt;/strong&gt;: Las pruebas automáticas alertan sobre problemas antes de llegar a producción.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reducción de errores manuales&lt;/strong&gt;: Todo el proceso está automatizado.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mayor confianza y calidad&lt;/strong&gt;: Cada cambio pasa por pruebas antes de ser desplegado.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;En pocas palabras: &lt;strong&gt;Menos dolores de cabeza y más despliegues.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  💡 Comparación: CI/CD vs. Flujos de trabajo tradicionales
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Aspecto&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Flujo tradicional&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;CI/CD&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Integración de código&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manual y ocasional&lt;/td&gt;
&lt;td&gt;Continua y automática&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Pruebas&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Ejecutadas manualmente&lt;/td&gt;
&lt;td&gt;Automatizadas en cada cambio&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Despliegue&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Proceso manual y propenso a errores&lt;/td&gt;
&lt;td&gt;Automatizado y confiable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Frecuencia de entregas&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Poco frecuente (semanas/meses)&lt;/td&gt;
&lt;td&gt;Frecuente (diario o incluso por hora)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  🔗 Referencias/Extras
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.github.com/en/actions" rel="noopener noreferrer"&gt;Documentación oficial de GitHub Actions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/actions/starter-workflows" rel="noopener noreferrer"&gt;Más ejemplos de pipelines CI/CD&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://about.gitlab.com/es/topics/ci-cd/" rel="noopener noreferrer"&gt;¿Qué es la CI/CD?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/es_es/prescriptive-guidance/latest/strategy-cicd-litmus/understanding-cicd.html" rel="noopener noreferrer"&gt;Comprensión de la CI/CD&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 ¿Qué sigue?
&lt;/h2&gt;

&lt;p&gt;¿Te gustaría ver un pipeline CI/CD más avanzado o con despliegue a otra plataforma? ¡Dímelo en los comentarios!&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

</description>
      <category>devops</category>
      <category>githubactions</category>
      <category>cicd</category>
      <category>español</category>
    </item>
  </channel>
</rss>
