<?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: Bianca Torres</title>
    <description>The latest articles on DEV Community by Bianca Torres (@bnkintech).</description>
    <link>https://dev.to/bnkintech</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3687974%2Fcf1ddab4-58c9-4a84-9c56-8b4e59f28886.jpeg</url>
      <title>DEV Community: Bianca Torres</title>
      <link>https://dev.to/bnkintech</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bnkintech"/>
    <language>en</language>
    <item>
      <title>Karpenter en el mundo cloud native: lo que conté en KubeFest #3</title>
      <dc:creator>Bianca Torres</dc:creator>
      <pubDate>Mon, 26 Oct 2026 22:38:59 +0000</pubDate>
      <link>https://dev.to/bnkintech/karpenter-en-el-mundo-cloud-native-lo-que-conte-en-kubefest-3-1bdn</link>
      <guid>https://dev.to/bnkintech/karpenter-en-el-mundo-cloud-native-lo-que-conte-en-kubefest-3-1bdn</guid>
      <description>&lt;p&gt;El pasado 24 de Octubre dí la charla "Karpenter en el mundo cloud native" en KubeFest #3, un evento organizado por la comunidad Platform Engineering Perú. Me gustó mucho el ambiente: habían personas que operan Kubernetes en su trabajo y al final salieron preguntas muy buenas.&lt;/p&gt;

&lt;p&gt;Quería dejar por escrito lo que conté, para quien no pudo ir o para quien quiera revisar los ejemplos con más calma.&lt;/p&gt;

&lt;h2&gt;
  
  
  Todo empieza con un pod en Pending
&lt;/h2&gt;

&lt;p&gt;¿A quién no le ha pasado?. Haces el deploy, parece que todo está bien, y un pod se queda en &lt;code&gt;Pending&lt;/code&gt;. Revisas el clúster, hay nodos, hay recursos libres... y el pod sigue sin arrancar.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Pending&lt;/code&gt; quiere decir que el scheduler todavía no encuentra un nodo donde ponerlo. Lo que confunde es que el scheduler no mira el espacio libre total del clúster, mira nodo por nodo. Si un pod pide 2 CPU y tienes tres nodos con 1 CPU libre cada uno, en total hay 3 CPU libres, pero el pod no entra en ninguno. Y a eso súmale que puede necesitar una zona específica, una arquitectura o un tipo de nodo en particular.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ kubectl describe pod web-6f9c
Events:
  Type     Reason            Message
  Warning  FailedScheduling  0/3 nodes are available: 3 Insufficient cpu.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg1ae8u7s9h4ksbi8qx4a.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg1ae8u7s9h4ksbi8qx4a.png" alt="Pod en Pending por falta de espacio en un solo nodo" width="799" height="313"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Algo super importante: si realmente falta capacidad, un autoscaler puede crear nodos. Pero si el problema está en la configuración del pod, por más nodos que agregues va a seguir esperando.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Y dónde entra Karpenter?
&lt;/h2&gt;

&lt;p&gt;Karpenter vive al costado del clúster. Por un lado está pendiente de la API de Kubernetes para detectar pods que no se pueden programar. Por el otro, le pide máquinas nuevas a Amazon EC2.&lt;/p&gt;

&lt;p&gt;Algo que quise recalcar durante la charla: Karpenter no reemplaza al scheduler. Él consigue las máquinas, pero quien decide en qué nodo va cada pod sigue siendo Kubernetes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Antes: Cluster Autoscaler y sus grupos
&lt;/h2&gt;

&lt;p&gt;Antes de Karpenter, lo más común en AWS era usar Cluster Autoscaler. Funciona con grupos de nodos que defines de antemano (en EKS son Auto Scaling Groups), cada uno con su tipo de instancia y su mínimo y máximo. Por ejemplo, un grupo general con &lt;code&gt;m5.large&lt;/code&gt;, otro de memoria con &lt;code&gt;r5.xlarge&lt;/code&gt;, otro con GPU, y así.&lt;/p&gt;

&lt;p&gt;Cuando ve pods pendientes, se pregunta si agregando un nodo a alguno de esos grupos el pod entraría. Si la respuesta es sí, escala ese grupo.&lt;/p&gt;

&lt;p&gt;Cluster Autoscaler funciona bien y es muy usado. El tema es cuando tienes muchas aplicaciones con necesidades distintas: cada combinación de tamaño, arquitectura o GPU termina siendo un grupo más, y cada grupo hay que configurarlo y mantenerlo. Ahí surge la pregunta que da pie a nuestro tema central: ¿y si en vez de preparar grupos, la capacidad se eligiera según lo que piden 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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fejku3u68tlkj7qssunkm.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fejku3u68tlkj7qssunkm.png" alt="Cluster Autoscaler y Karpenter" width="800" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Lo que propone Karpenter
&lt;/h2&gt;

&lt;p&gt;Karpenter le da la vuelta. La aplicación dice lo que necesita (memoria, arquitectura, si puede correr en Spot) y nosotros definimos en un NodePool qué tipos de instancias permitimos y con qué límites. Con eso, más lo que AWS tenga disponible en ese momento, Karpenter lanza el nodo que hace falta.&lt;/p&gt;

&lt;p&gt;Ahora, tampoco es magia. No siempre va a elegir la máquina más barata y no puede garantizar que una instancia esté disponible, tambien depende mucho de tu configuración definida en el NodePool. Y no creo que una herramienta sea mejor que la otra en todos los casos: depende de tu infraestructura, y conviene medir antes y después, porque el ahorro no viene solo.&lt;/p&gt;

&lt;p&gt;Un poco de contexto: Karpenter nació en AWS en 2021 como proyecto open source. En 2023 sus APIs pasaron a beta y la parte neutral del proyecto se donó a la CNCF, dentro de Kubernetes SIG Autoscaling. La versión 1.0, que estabiliza las APIs principales, salió en agosto de 2024.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por dentro
&lt;/h2&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcva8zai19of52ppk62i4.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcva8zai19of52ppk62i4.png" alt="Aprovisionamiento paso a paso" width="800" height="170"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El flujo es más o menos así: hay un pod sin asignar, Karpenter mira sus requests y restricciones, crea un NodeClaim, se lanza la instancia en EC2, el nodo se registra en el clúster y recién ahí el scheduler le asigna el pod, que pasa a &lt;code&gt;Running&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Tambien hay que considerar que esto toma su tiempo, que la instancia ya exista no significa que esté lista, todavía tiene que arrancar y unirse al clúster.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cómo elige la máquina
&lt;/h3&gt;

&lt;p&gt;Karpenter no lanza un nodo por cada pod que llega. Primero espera alrededor de un segundo sin pods nuevos (hasta diez segundos como máximo) para juntarlos y decidir en lote. Después suma lo que piden en CPU, memoria y GPU, sin olvidarse de los DaemonSets ni de lo que reserva el sistema en cada nodo.&lt;/p&gt;

&lt;p&gt;Con eso arma una lista de hasta 60 tipos de instancia que sirven, desde el más chico donde entra todo hasta otros más grandes, y se la pasa a EC2 Fleet para que lance una. En On-Demand se prioriza el precio más bajo y en Spot se combina el precio con el riesgo de interrupción.&lt;/p&gt;

&lt;p&gt;Si EC2 no tiene capacidad de algún tipo en una zona, Karpenter lo descarta por un rato y sigue con los demás. Por eso, mientras más tipos de instancia permitas, más alternativas tiene. Limitarlo a una o dos familias puede parecer más seguro, pero en la práctica lo vuelve más frágil, sobre todo con Spot.&lt;/p&gt;

&lt;h2&gt;
  
  
  NodePool, EC2NodeClass y NodeClaim
&lt;/h2&gt;

&lt;p&gt;Estos tres son los que más se confunden, así que les dediqué un buen rato en la charla.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnapacvtcaq03bmbqmzjw.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnapacvtcaq03bmbqmzjw.png" alt="NodePool, EC2NodeClass, NodeClaim y Node" width="800" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El NodePool son las reglas: qué nodos puede crear Karpenter, con qué arquitecturas, categorías, si son Spot u On-Demand, los límites y cómo maneja la disrupción. La EC2NodeClass es la parte de AWS: la imagen, las subredes, los security groups y el rol de la instancia. Y el NodeClaim es la solicitud concreta de una máquina. Ese no lo escribes tú, lo crea Karpenter, y es lo primero que yo reviso cuando algo no funciona.&lt;/p&gt;

&lt;p&gt;Un NodePool sencillo se ve así:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;karpenter.sh/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NodePool&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;general&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;nodeClassRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;                       &lt;span class="c1"&gt;# 1. enlaza con la EC2NodeClass&lt;/span&gt;
        &lt;span class="na"&gt;group&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;karpenter.k8s.aws&lt;/span&gt;
        &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;EC2NodeClass&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;default&lt;/span&gt;
      &lt;span class="na"&gt;requirements&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kubernetes.io/arch&lt;/span&gt;         &lt;span class="c1"&gt;# 2. arquitectura permitida&lt;/span&gt;
          &lt;span class="na"&gt;operator&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;In&lt;/span&gt;
          &lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;amd64"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;karpenter.sh/capacity-type&lt;/span&gt; &lt;span class="c1"&gt;# 3. solo On-Demand&lt;/span&gt;
          &lt;span class="na"&gt;operator&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;In&lt;/span&gt;
          &lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;on-demand"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;karpenter.k8s.aws/instance-category&lt;/span&gt; &lt;span class="c1"&gt;# 4. cómputo, general, memoria&lt;/span&gt;
          &lt;span class="na"&gt;operator&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;In&lt;/span&gt;
          &lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;c"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;m"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;r"&lt;/span&gt;&lt;span class="pi"&gt;]&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;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;100"&lt;/span&gt;                            &lt;span class="c1"&gt;# 5. tope de capacidad del NodePool&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hay que encontrar un equilibrio: si restringes demasiado, Karpenter se queda sin opciones, y si abres mucho, toca validar bien qué tipos van a aparecer. Y el NodePool solo no alcanza, también necesitas la EC2NodeClass, los permisos y la red bien configurados.&lt;/p&gt;

&lt;h3&gt;
  
  
  Leer un NodeClaim
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ kubectl get nodeclaims
NAME            TYPE         CAPACITY    ZONE         NODE           READY
general-x7k2p   m6i.large    on-demand   us-east-1a   ip-10-0-1-23   True
general-b4m9t   c6i.xlarge   spot        us-east-1b   ip-10-0-2-87   True
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cada NodeClaim pasa por cuatro condiciones: &lt;code&gt;Launched&lt;/code&gt; cuando EC2 aceptó la solicitud, &lt;code&gt;Registered&lt;/code&gt; cuando el nodo se unió al clúster, &lt;code&gt;Initialized&lt;/code&gt; cuando terminó de arrancar y quitó sus taints de inicio, y &lt;code&gt;Ready&lt;/code&gt; cuando ya se le pueden asignar pods. Si un pod sigue en &lt;code&gt;Pending&lt;/code&gt;, fíjate cuál de esas condiciones no llegó a &lt;code&gt;True&lt;/code&gt;. Y si ni siquiera aparece un NodeClaim, el problema está antes: en el NodePool o en los requests del pod.&lt;/p&gt;

&lt;h2&gt;
  
  
  Si lo quieres instalar en EKS
&lt;/h2&gt;

&lt;p&gt;Esto es lo que necesitas tener listo:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Los permisos de IAM: el rol del controlador (con EKS Pod Identity o IRSA) y el rol de los nodos.&lt;/li&gt;
&lt;li&gt;La etiqueta &lt;code&gt;karpenter.sh/discovery&lt;/code&gt; en las subredes y security groups que va a usar.&lt;/li&gt;
&lt;li&gt;Una cola de interrupciones con SQS y EventBridge, para que reciba los avisos de Spot y de mantenimiento.&lt;/li&gt;
&lt;li&gt;Un lugar donde correr el controlador que no sean los nodos que él mismo administra, por ejemplo un managed node group pequeño o Fargate.&lt;/li&gt;
&lt;li&gt;Al menos un NodePool y una EC2NodeClass. Sin eso no crea ningún nodo.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;helm upgrade &lt;span class="nt"&gt;--install&lt;/span&gt; karpenter oci://public.ecr.aws/karpenter/karpenter &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--version&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;KARPENTER_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--namespace&lt;/span&gt; kube-system &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--set&lt;/span&gt; settings.clusterName&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CLUSTER_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--set&lt;/span&gt; settings.interruptionQueue&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CLUSTER_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mi consejo es seguir la guía oficial de getting started para la versión exacta que vas a instalar, porque los detalles cambian entre versiones. De hecho es la misma guía que seguí para la Demo mostrada en la charla.&lt;/p&gt;

&lt;h2&gt;
  
  
  Los requests importan más de lo que parece
&lt;/h2&gt;

&lt;p&gt;Karpenter decide qué máquina lanzar sumando los requests de los pods. Y ojo que request, uso real y límite no son lo mismo: el request es lo que reserva el scheduler, el uso real es lo que la app consume en ese momento y el límite es el tope.&lt;/p&gt;

&lt;p&gt;Si pones requests muy altos, vas a terminar con nodos más grandes o más nodos de los que necesitas. Si los pones muy bajos, se te llenan los nodos de pods que después compiten por recursos cuando sube la carga. Karpenter trabaja con lo que declaras, no puede adivinar lo que tu aplicación necesita de verdad, así que ajustar los requests con métricas reales sigue siendo trabajo nuestro.&lt;/p&gt;

&lt;h2&gt;
  
  
  Consolidación
&lt;/h2&gt;

&lt;p&gt;Karpenter no solo agrega capacidad, también la saca cuando sobra.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff4va9dicc74ca37bxk13.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff4va9dicc74ca37bxk13.png" alt="Consolidación de nodos" width="800" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Si los pods de varios nodos con poco uso entran en menos nodos, los reacomoda y elimina los que quedan sobrando. Esto se configura en el NodePool:&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;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;disruption&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;consolidationPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;WhenEmptyOrUnderutilized&lt;/span&gt;
    &lt;span class="na"&gt;consolidateAfter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;5m&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Con &lt;code&gt;WhenEmptyOrUnderutilized&lt;/code&gt; retira los nodos vacíos y también los que están poco usados, siempre que sus pods entren en otro lado o en un nodo más barato. Ahorras más, pero se mueven más pods. Con &lt;code&gt;WhenEmpty&lt;/code&gt; solo retira nodos que no tienen pods de aplicación (los DaemonSets no cuentan), así que ahorras menos pero no desaloja nada. Y &lt;code&gt;consolidateAfter&lt;/code&gt; es cuánto espera desde que el último pod entró o salió del nodo antes de considerarlo, para no reaccionar a cada pico.&lt;/p&gt;

&lt;p&gt;Antes de sacar un nodo, Karpenter verifica que los pods entren en lo que queda, respetando sus restricciones y sus PodDisruptionBudgets. Si recién estás empezando, yo arrancaría con &lt;code&gt;WhenEmpty&lt;/code&gt; o con un &lt;code&gt;consolidateAfter&lt;/code&gt; más largo, y vería cuántos pods se mueven antes de ponerlo más agresivo.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Spot u On-Demand?
&lt;/h2&gt;

&lt;p&gt;On-Demand se paga a tarifa normal y es más predecible, aunque tampoco es infalible. Spot puede salir mucho más barato, pero no siempre hay disponibilidad y AWS puede recuperar la instancia avisándote con unos dos minutos de anticipación.&lt;/p&gt;

&lt;p&gt;Antes de meter Spot, revisa que tengas varias réplicas, reintentos, el estado y los datos protegidos, muchos tipos de instancia permitidos, y que hayas probado una interrupción de verdad. Yo lo decidiría según qué tan crítica es la aplicación y cuánto riesgo estás dispuesto a aceptar, no solo por el precio por hora.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cuando Karpenter retira nodos
&lt;/h2&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq3ngan75me9hi0d4yuar.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq3ngan75me9hi0d4yuar.png" alt="Disrupciones y protecciones" width="800" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Un nodo puede salir por consolidación, por drift (cuando ya no coincide con la configuración, por ejemplo porque hay una AMI nueva), porque llegó a su &lt;code&gt;expireAfter&lt;/code&gt; o por una interrupción de Spot. Para protegerte hay algunas herramientas, aunque cada una tiene su alcance.&lt;/p&gt;

&lt;p&gt;El PodDisruptionBudget va en tu aplicación:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;policy/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PodDisruptionBudget&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;web-pdb&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;minAvailable&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;web&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Los disruption budgets van en el NodePool y controlan cuántos nodos se pueden retirar a la vez y en qué horario:&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;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;disruption&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;budgets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;nodes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;10%"&lt;/span&gt;                    &lt;span class="c1"&gt;# como máximo 10 % de los nodos a la vez&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;nodes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0"&lt;/span&gt;                      &lt;span class="c1"&gt;# ninguno en este horario...&lt;/span&gt;
        &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;9&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;mon-fri"&lt;/span&gt;     &lt;span class="c1"&gt;# ...de lunes a viernes desde las 9:00&lt;/span&gt;
        &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;8h&lt;/span&gt;                    &lt;span class="c1"&gt;# durante 8 horas&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y si hay un pod (o un nodo) que no quieres que Karpenter toque, puedes usar esta anotación:&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;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;karpenter.sh/do-not-disrupt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cuidado con el PDB: si lo haces muy estricto, por ejemplo con &lt;code&gt;minAvailable&lt;/code&gt; igual al número de réplicas, puede bloquear la consolidación indefinidamente. Y ninguna de estas protecciones te salva de una interrupción de Spot o de una falla, así que la aplicación igual tiene que aguantar perder un nodo.&lt;/p&gt;

&lt;p&gt;La pregunta que le dejé al público fue: ¿qué impacto tiene esa acción en mi aplicación, y cómo compruebo que se recupera?&lt;/p&gt;

&lt;h2&gt;
  
  
  Para cerrar
&lt;/h2&gt;

&lt;p&gt;Si me quedo con algo de esta charla es que Karpenter consigue capacidad según lo que realmente piden tus pods y la devuelve cuando ya no hace falta, que entender bien la diferencia entre NodePool, EC2NodeClass y NodeClaim te ahorra mucho tiempo al depurar, y que bajar costos nunca debería ir en contra de la disponibilidad.&lt;/p&gt;

&lt;p&gt;¿Vale la pena usarlo? Si tus cargas cambian bastante, si necesitas muchos tipos de instancia o si mantener grupos de nodos ya se volvió un dolor de cabeza, probablemente sí. Pero úsalo porque resuelve un problema que puedes medir, no porque esté de moda.&lt;/p&gt;

&lt;p&gt;Gracias a Platform Engineering Perú por la invitación y por organizar KubeFest #3, y a todos los que fueron y se quedaron a preguntar.&lt;/p&gt;

&lt;p&gt;Aquí les dejo los slides de la presentación: &lt;a href="https://speakerdeck.com/bnktch13/karpenter-en-el-mundo-cloud-native" rel="noopener noreferrer"&gt;https://speakerdeck.com/bnktch13/karpenter-en-el-mundo-cloud-native&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Referencias
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://karpenter.sh/docs/" rel="noopener noreferrer"&gt;Documentación oficial de Karpenter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://karpenter.sh/docs/concepts/nodepools/" rel="noopener noreferrer"&gt;Concepto de NodePools&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://karpenter.sh/docs/concepts/disruption/" rel="noopener noreferrer"&gt;Disruption y consolidación&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://karpenter.sh/docs/faq/" rel="noopener noreferrer"&gt;Cómo elige el tipo de instancia (FAQ)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://karpenter.sh/docs/getting-started/getting-started-with-karpenter/" rel="noopener noreferrer"&gt;Getting started con Karpenter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-instance-termination-notices.html" rel="noopener noreferrer"&gt;Avisos de interrupción de Spot en EC2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/blogs/containers/announcing-karpenter-1-0/" rel="noopener noreferrer"&gt;Announcing Karpenter 1.0 (AWS)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cncf.io/blog/2024/11/06/karpenter-v1-0-0-beta/" rel="noopener noreferrer"&gt;Karpenter v1.0.0 (CNCF)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>kubefest</category>
      <category>karpenter</category>
      <category>eks</category>
      <category>cloudnative</category>
    </item>
    <item>
      <title>EKS Auto Mode: correr Kubernetes sin andar peleando con los nodos</title>
      <dc:creator>Bianca Torres</dc:creator>
      <pubDate>Fri, 04 Sep 2026 18:54:26 +0000</pubDate>
      <link>https://dev.to/aws-builders/eks-auto-mode-correr-kubernetes-sin-andar-peleando-con-los-nodos-5954</link>
      <guid>https://dev.to/aws-builders/eks-auto-mode-correr-kubernetes-sin-andar-peleando-con-los-nodos-5954</guid>
      <description>&lt;p&gt;Si algo aprendí gestionando EKS en producción, es que mantener los nodos se lleva más tiempo del que uno imagina. Managed node groups, Karpenter, el EBS CSI driver, actualizar AMIs, y el clásico "¿por qué este pod lleva 10 minutos en Pending?" a la hora menos pensada. No es lo más entretenido del rol, pero es parte de lo que nos toca hacer para mantener un cluster sano en producción.&lt;/p&gt;

&lt;p&gt;Por eso, cuando probé EKS Auto Mode, me hice esta pregunta: "si dejo que AWS haga todo esto por mí, ¿qué gano y qué pierdo?". Este artículo es esa respuesta, con un laboratorio que puedes seguir tú mismo en menos de 30 minutos.&lt;/p&gt;




&lt;h2&gt;
  
  
  Mantener nodos es casi un segundo trabajo
&lt;/h2&gt;

&lt;p&gt;Antes de vender la solución, hablemos del problema de verdad. En un EKS "clásico", tú te encargas de un montón de cosas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Crear y dimensionar los node groups&lt;/strong&gt;. ¿m5.large? ¿c6i.xlarge? ¿Spot u On-Demand? Cada decisión te la cobra el futuro.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Instalar y afinar un autoscaler&lt;/strong&gt;. Cluster Autoscaler o Karpenter. Los dos piden configuración, permisos IAM y mantenimiento.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cuidar los add-ons&lt;/strong&gt;. CoreDNS, kube-proxy, EBS CSI, VPC CNI... instalarlos, versionarlos, actualizarlos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parchear las AMIs&lt;/strong&gt;. Cada vez que aparece una vulnerabilidad de seguridad en el sistema operativo del nodo (CVE), es nuestro trabajo subsanarlo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Debuggear el scheduling&lt;/strong&gt;. Ese &lt;code&gt;0/3 nodes are available: Insufficient memory&lt;/code&gt; que aparece justo cuando ya te ibas a desconectar.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lo irónico es que nada de eso hace tu producto mejor. Es puro "impuesto de plataforma". Trabajo que haces para que Kubernetes exista, no para que tu app sea mejor.&lt;/p&gt;

&lt;h2&gt;
  
  
  Entonces, ¿Qué es EKS Auto Mode?
&lt;/h2&gt;

&lt;p&gt;AWS se hace cargo del cómputo, el almacenamiento y el networking del cluster por ti. Por dentro usa Karpenter y nodos con Bottlerocket, pero todo eso queda tras bambalinas. Tú ya no administras node groups ni instalas add-ons uno por uno.&lt;/p&gt;

&lt;p&gt;Tú declaras tus apps, AWS decide y levanta la infraestructura para correrlas. Los nodos aparecen cuando tus pods los necesitan, y se van cuando ya no.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lab: de cero a app corriendo, con nodos que aparecen solos
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Lo que necesitas:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;AWS CLI v2 configurado (aws configure)&lt;/li&gt;
&lt;li&gt;eksctl v0.195.0 o más&lt;/li&gt;
&lt;li&gt;kubectl&lt;/li&gt;
&lt;li&gt;Permisos IAM sobre EC2, EKS, IAM y VPC&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Paso 1: Crear el cluster con Auto Mode
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;eksctl create cluster &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; demo-automode &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--enable-auto-mode&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ese único comando te crea el cluster, la VPC, las subredes, activa Auto Mode y deja los add-ons esenciales gestionados por AWS. Tarda aproximadamente unos 15 minutos.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9v3u1tatl83kisvak02o.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9v3u1tatl83kisvak02o.png" width="800" height="374"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;h3&gt;
  
  
  Paso 2: Mirar el cluster recién creado
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get nodes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6ooel015gnezm45kl9mq.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6ooel015gnezm45kl9mq.png" width="680" height="66"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get nodepools
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Faa2p3hzavm6kt0pws5kt.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Faa2p3hzavm6kt0pws5kt.png" width="537" height="87"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Auto Mode crea dos node pools automáticamente:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;system arranca con 1 nodo desde el inicio.&lt;/strong&gt; Ese nodo corre los componentes internos del propio cluster (CoreDNS y los add-ons gestionados). Por eso kubectl get nodes sí te muestra un nodo apenas creas el cluster.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;general-purpose arranca con 0 nodos.&lt;/strong&gt; Este es el pool donde van a caer tus aplicaciones, y ahí es donde se ve la magia: se queda vacío hasta que despliegas algo que necesite cómputo.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Así que el cambio de chip es este: ver el pool de tus cargas en cero no significa que algo se rompió. Significa que todavía no hay nada tuyo que correr, y AWS no está cobrándote nodos de más.&lt;/p&gt;



&lt;h3&gt;
  
  
  Paso 3: Desplegar una app
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# nginx-demo.yaml&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx-demo&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&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;nginx-demo&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx-demo&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&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;nginx:latest&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;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;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="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx-demo&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;LoadBalancer&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx-demo&lt;/span&gt;
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
    &lt;span class="na"&gt;targetPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; nginx-demo.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5e4gplo1a74bpow4a37c.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5e4gplo1a74bpow4a37c.png" width="380" height="70"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;h3&gt;
  
  
  Paso 4: Ver Auto Mode en acción
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get nodes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En unos 30 segundos vas a ver aparecer un nodo nuevo en el pool general-purpose (ese que estaba en cero) sin que tú lo hayas pedido. AWS se dio cuenta de que tus pods necesitan cómputo y levantó una instancia EC2 solo.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3btj7alhozjck9eo5f26.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3btj7alhozjck9eo5f26.png" alt=" " width="683" height="87"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;h3&gt;
  
  
  Paso 5: Escalar y mirar qué pasa
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl scale deployment nginx-demo &lt;span class="nt"&gt;--replicas&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10
kubectl get nodes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Al escalar en numero de replicas de nuestra app, tener un solo nodo será insuficiente. Si la capacidad de ahora no alcanza, Auto Mode levanta más. No tocaste ningún autoscaler, no editaste ningún node group.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbxtcup3zmi5nlz4o7z76.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbxtcup3zmi5nlz4o7z76.png" width="520" height="46"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdvf0upi0vyoj3jyyx5k5.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdvf0upi0vyoj3jyyx5k5.png" width="683" height="116"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;h3&gt;
  
  
  Paso 6: Destruir
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;eksctl delete cluster &lt;span class="nt"&gt;--name&lt;/span&gt; demo-automode &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Es super importante que al finalizar nuestro laboratorio destruymos todos los recursos creado, para evitar costos innecesarios. Un cluster olvidado es una sorpresa fea en la factura.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsvbm9w8xa0n2y83h59rl.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsvbm9w8xa0n2y83h59rl.png" alt=" " width="797" height="113"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h4&gt;
  
  
  Clásico vs Auto Mode
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Qué&lt;/th&gt;
&lt;th&gt;EKS clásico&lt;/th&gt;
&lt;th&gt;EKS Auto Mode&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Gestión de nodos&lt;/td&gt;
&lt;td&gt;Manual / tu propio Karpenter&lt;/td&gt;
&lt;td&gt;AWS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Add-ons (CoreDNS, CSI, etc.)&lt;/td&gt;
&lt;td&gt;Los instalas y versionas tú&lt;/td&gt;
&lt;td&gt;Gestionados&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Actualizar AMIs&lt;/td&gt;
&lt;td&gt;Lo gestionas tú&lt;/td&gt;
&lt;td&gt;AWS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Autoscaling&lt;/td&gt;
&lt;td&gt;Configuras CA o Karpenter&lt;/td&gt;
&lt;td&gt;Automático&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tu tiempo operando&lt;/td&gt;
&lt;td&gt;Mucho&lt;/td&gt;
&lt;td&gt;Poco&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Personalización&lt;/td&gt;
&lt;td&gt;Total&lt;/td&gt;
&lt;td&gt;Acotada&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Curva de arranque&lt;/td&gt;
&lt;td&gt;Empinada&lt;/td&gt;
&lt;td&gt;Suave&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Cuándo usarlo y cuándo no (Según mi opinión)
&lt;/h2&gt;

&lt;p&gt;Úsalo si:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Arrancas un cluster nuevo y quieres velocidad sin construir toda una plataforma.&lt;/li&gt;
&lt;li&gt;Tu equipo es chico y no quieres tener a alguien dedicado a cuidar nodos.&lt;/li&gt;
&lt;li&gt;Tus workloads son bastante estándar: APIs, workers, web.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Piénsalo dos veces si:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dependes de configuraciones muy específicas de nodo (kernels custom, DaemonSets exigentes, GPUs con drivers a medida).&lt;/li&gt;
&lt;li&gt;Ya tienes un Karpenter afinado que te ahorra dinero y no lo quieres soltar.&lt;/li&gt;
&lt;li&gt;Necesitas control total del ciclo de vida de la AMI por temas de compliance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Auto Mode te cambia control por simplicidad. Ganas horas de operación, cedes algunos grados de personalización. Para la mayoría, ese cambio vale muchísimo la pena. Para casos muy puntuales, todavía no.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Y cuánto me va a costar?
&lt;/h2&gt;

&lt;p&gt;Auto Mode suma un pequeño cargo de gestión encima del costo del EC2 que corre por debajo. Pero no te quedes solo con "cuánto cuesta el add-on". La cuenta real es: cuánto cuesta el add-on menos las horas de ingeniería que dejas de gastar cuidando nodos, autoscalers y parches. Cuando sumas ese tiempo, el número se ve muy distinto.&lt;/p&gt;

&lt;h2&gt;
  
  
  En conclusión
&lt;/h2&gt;

&lt;p&gt;EKS Auto Mode no es magia. Es AWS haciendo el trabajo de plataforma que muchos veníamos haciendo a mano. Si gestionas clusters en producción, pruébalo con un workload que no sea crítico y mide cuánto tiempo dejas de invertir en cosas que no hacen mejor tu producto.&lt;/p&gt;

</description>
      <category>eksautomode</category>
      <category>aws</category>
      <category>kubernetes</category>
      <category>devops</category>
    </item>
    <item>
      <title>Nunca más hardcodees un token: Seguridad en GitHub para DevOps</title>
      <dc:creator>Bianca Torres</dc:creator>
      <pubDate>Wed, 10 Jun 2026 21:41:47 +0000</pubDate>
      <link>https://dev.to/aws-builders/nunca-mas-hardcodees-un-token-seguridad-en-github-para-devops-a44</link>
      <guid>https://dev.to/aws-builders/nunca-mas-hardcodees-un-token-seguridad-en-github-para-devops-a44</guid>
      <description>&lt;p&gt;El pasado sábado 6 de junio tuve la oportunidad de participar como speaker en el GitHub Community Day Perú 2026, donde compartí una charla sobre un tema que sigue siendo una de las causas más frecuentes de incidentes de seguridad: la exposición accidental de credenciales.&lt;/p&gt;

&lt;p&gt;Durante la sesión hablamos de herramientas gratuitas que muchos equipos ya tienen disponibles dentro de GitHub, pero que no siempre aprovechan al máximo. Usamos GitHub todos los días para gestionar código, colaborar con nuestros equipos y automatizar despliegues, pero en muchas ocasiones solo utilizamos una pequeña parte de todo lo que la plataforma nos ofrece.&lt;/p&gt;

&lt;p&gt;La buena noticia es que GitHub incorpora múltiples funcionalidades de seguridad que pueden ayudarnos a prevenir filtraciones de credenciales, proteger nuestros pipelines y mejorar nuestra postura de seguridad sin necesidad de adquirir herramientas adicionales.&lt;/p&gt;

&lt;p&gt;En este artículo recopilo los principales conceptos que vimos durante la charla, junto con una demostración práctica de cómo desplegar una aplicación en AWS sin almacenar una sola credencial permanente.&lt;/p&gt;




&lt;h2&gt;
  
  
  El problema
&lt;/h2&gt;

&lt;p&gt;Todos lo hemos hecho.&lt;/p&gt;

&lt;p&gt;Hardcodear un API key “solo por ahora”, pushear un .env por accidente o compartir un token por Slack para salir de un apuro.&lt;/p&gt;

&lt;p&gt;Son errores comunes, pero las consecuencias pueden ser graves: desde una factura inesperada en AWS hasta una filtración de información sensible.&lt;/p&gt;

&lt;p&gt;En 2025, De acuerdo al &lt;a href="https://www.gitguardian.com/state-of-secrets-sprawl-report-2026" rel="noopener noreferrer"&gt;reporte de GitGuardian&lt;/a&gt;, GitHub detectó más de 28 millones de secretos expuestos en repositorios públicos. Access Keys de AWS, tokens de GitHub, webhooks de Slack y muchas otras credenciales quedaron visibles para cualquiera que quisiera utilizarlas.&lt;/p&gt;

&lt;p&gt;El flujo típico suele verse así:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Un developer necesita desplegar una aplicación.&lt;/li&gt;
&lt;li&gt;Crea una Access Key y Secret Key.&lt;/li&gt;
&lt;li&gt;Las almacena en un archivo .env o directamente en el código.&lt;/li&gt;
&lt;li&gt;El archivo termina llegando al repositorio.&lt;/li&gt;
&lt;li&gt;Un bot detecta las credenciales y comienza a utilizarlas en cuestión de segundos.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;La solución no es simplemente “tener más cuidado”.&lt;br&gt;
La solución es construir mecanismos que hagan mucho más difícil que estos errores lleguen a producción.&lt;/p&gt;

&lt;p&gt;GitHub nos ofrece varias capas de protección que pueden ayudarnos precisamente con eso.&lt;/p&gt;


&lt;h2&gt;
  
  
  Las 5 capas de Seguridad en Github
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. GitHub Secrets
&lt;/h3&gt;

&lt;p&gt;La primera línea de defensa es evitar almacenar información sensible dentro del código.&lt;/p&gt;

&lt;p&gt;GitHub Secrets permite guardar valores cifrados que pueden ser consumidos por GitHub Actions durante la ejecución de un workflow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Características:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Encriptados mediante libsodium.&lt;/li&gt;
&lt;li&gt;Ocultos automáticamente en los logs.&lt;/li&gt;
&lt;li&gt;No pueden visualizarse nuevamente después de guardarse.&lt;/li&gt;
&lt;li&gt;Disponibles a nivel de repositorio, environment u organización.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjk6t6obf4wm5n9906wy8.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%2Fjk6t6obf4wm5n9906wy8.png" alt=" " width="800" height="559"&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%2F9uhlkg4vlh6exyuubogx.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%2F9uhlkg4vlh6exyuubogx.png" alt=" " width="800" height="395"&gt;&lt;/a&gt;&lt;br&gt;
Además, los Environments agregan controles adicionales como:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Aprobaciones manuales para producción.&lt;/li&gt;
&lt;li&gt;Restricciones por branch.&lt;/li&gt;
&lt;li&gt;Wait timers.&lt;/li&gt;
&lt;li&gt;Protección de despliegues críticos.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Si todavía tienes credenciales hardcodeadas en tu código, este debería ser el primer cambio que realices.&lt;/p&gt;


&lt;h3&gt;
  
  
  2. OIDC con AWS (Zero Credentials)
&lt;/h3&gt;

&lt;p&gt;OIDC es un protocolo de autenticación que permite que dos servicios se reconozcan sin compartir credenciales.&lt;/p&gt;

&lt;p&gt;Tradicionalmente, muchos pipelines almacenan Access Keys de AWS dentro de GitHub Secrets.&lt;br&gt;
Aunque esto es mejor que hardcodearlas, seguimos dependiendo de credenciales permanentes que pueden ser filtradas o comprometidas.&lt;/p&gt;

&lt;p&gt;Con OpenID Connect (OIDC) podemos eliminar completamente ese problema.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿Cómo funciona?&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;GitHub Actions inicia la ejecución del workflow.&lt;/li&gt;
&lt;li&gt;GitHub genera un token JWT temporal.&lt;/li&gt;
&lt;li&gt;AWS valida el token mediante un OIDC Provider.&lt;/li&gt;
&lt;li&gt;AWS verifica que el repositorio tenga permiso para asumir un rol específico.&lt;/li&gt;
&lt;li&gt;AWS entrega credenciales temporales.&lt;/li&gt;
&lt;li&gt;Las credenciales expiran automáticamente&lt;/li&gt;
&lt;/ol&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%2F3rhwo70v35tzvwb61g2k.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%2F3rhwo70v35tzvwb61g2k.png" alt=" " width="800" height="836"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No hay keys. No hay tokens permanentes. Nada que pueda leakearse.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Paso 1 — Crear el OIDC Provider en IAM:&lt;/strong&gt;&lt;br&gt;
Provider URL: token.actions.githubusercontent.com&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%2F26qewlehd5xzjztqbdsw.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%2F26qewlehd5xzjztqbdsw.png" alt=" " width="800" height="584"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Paso 2 — Crear un IAM Role con trust policy:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Principal"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Federated"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:iam::ACCOUNT_ID:oidc-provider/token.actions.githubusercontent.com"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sts:AssumeRoleWithWebIdentity"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Condition"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"StringEquals"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"token.actions.githubusercontent.com:aud"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sts.amazonaws.com"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"StringLike"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"token.actions.githubusercontent.com:sub"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"repo:MI-ORG/MI-REPO:*"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La condición &lt;code&gt;StringLike&lt;/code&gt; es clave: solo TU repo puede asumir este rol. Si alguien forkea tu repo, no puede deployar.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Paso 3 — Usar en el workflow de Github Actions:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;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;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read&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;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aws-actions/configure-aws-credentials@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;role-to-assume&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ vars.AWS_ROLE_ARN }}&lt;/span&gt;
      &lt;span class="na"&gt;aws-region&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;us-east-1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Eso es todo. Cero secrets de AWS en GitHub.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. Secret Scanning
&lt;/h3&gt;

&lt;p&gt;Incluso con buenas prácticas, los errores siguen ocurriendo.&lt;/p&gt;

&lt;p&gt;Por eso GitHub incorpora Secret Scanning.&lt;br&gt;
Esta funcionalidad analiza automáticamente los commits buscando patrones asociados a credenciales conocidas.&lt;/p&gt;

&lt;p&gt;Actualmente puede detectar más de 200 tipos de secretos pertenecientes a más de 100 proveedores.&lt;br&gt;
Ejemplo: AWS, GitHub, Slack, Stripe, Twilio, npm, etc.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Para habilitarlo:&lt;/strong&gt;&lt;br&gt;
Settings → Code security and analysis → Secret scanning → Enable&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%2Fb4mrax35c5o8h7betkxj.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%2Fb4mrax35c5o8h7betkxj.png" alt=" " width="800" height="137"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cuando GitHub detecta una credencial:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Genera una alerta.&lt;/li&gt;
&lt;li&gt;Muestra exactamente dónde se encuentra.&lt;/li&gt;
&lt;li&gt;En algunos casos coordina la revocación automática con el proveedor.&lt;/li&gt;
&lt;/ol&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%2Feom2hnpvlgmdcj0bdxbs.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%2Feom2hnpvlgmdcj0bdxbs.png" alt=" " width="799" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Es una capa reactiva, pero extremadamente útil.&lt;/p&gt;


&lt;h3&gt;
  
  
  4. Push Protection
&lt;/h3&gt;

&lt;p&gt;Mientras Secret Scanning detecta problemas después del commit, Push Protection intenta detenerlos antes.&lt;/p&gt;

&lt;p&gt;Cuando GitHub detecta una credencial durante un push, simplemente bloquea la operació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%2Fdpw3l0o2agvynd9yn3is.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%2Fdpw3l0o2agvynd9yn3is.png" alt=" " width="800" height="791"&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%2F1mmb45sqxim4prglx348.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%2F1mmb45sqxim4prglx348.png" alt=" " width="800" height="422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El secret nunca llegó al repo. Nunca se expuso. Protección proactiva.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Para habilitarlo:&lt;/strong&gt;&lt;br&gt;
Settings → Code security and analysis → Push protection → Enable&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%2F8tr65sumyjrihmrtoq0q.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%2F8tr65sumyjrihmrtoq0q.png" alt=" " width="800" height="104"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  5. Dependabot
&lt;/h3&gt;

&lt;p&gt;La seguridad no se limita únicamente a las credenciales.&lt;br&gt;
Muchas vulnerabilidades provienen de dependencias desactualizadas.&lt;/p&gt;

&lt;p&gt;Cuando se publica un CVE crítico que afecta una librería utilizada por nuestro proyecto, Dependabot puede:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Detectar la vulnerabilidad.&lt;/li&gt;
&lt;li&gt;Generar una alerta.&lt;/li&gt;
&lt;li&gt;Crear automáticamente un Pull Request con la actualización.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F91rq1k34savqexv265hx.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%2F91rq1k34savqexv265hx.png" alt=" " width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Configuración&lt;/strong&gt; (&lt;code&gt;.github/dependabot.yml&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
&lt;span class="na"&gt;updates&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;package-ecosystem&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;npm"&lt;/span&gt;
    &lt;span class="na"&gt;directory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/"&lt;/span&gt;
    &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;weekly"&lt;/span&gt;
      &lt;span class="na"&gt;day&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;monday"&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;package-ecosystem&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;github-actions"&lt;/span&gt;
    &lt;span class="na"&gt;directory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/"&lt;/span&gt;
    &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;weekly"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Además de dependencias de aplicación, Dependabot también ayuda a mantener actualizadas las GitHub Actions utilizadas por nuestros pipelines.&lt;/p&gt;




&lt;h2&gt;
  
  
  Demo: Deploy completo sin credenciales
&lt;/h2&gt;

&lt;p&gt;Para demostrar cómo funcionan varias de estas capas trabajando juntas, preparé una aplicación sencilla que lee un secreto desde una variable de entorno y lo muestra en una página web.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;El código relevante:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SECRET_MESSAGE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SECRET_MESSAGE&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;No secret configured&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La aplicación no conoce el valor del secreto.&lt;br&gt;
Simplemente espera encontrar una variable de entorno durante la ejecución.&lt;/p&gt;

&lt;p&gt;La demostración consistió en desplegar esta aplicación en Amazon ECS Fargate, utilizando GitHub Actions para automatizar todo el proceso y OIDC para autenticarnos en AWS sin necesidad de almacenar Access Keys permanentes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;El flujo:&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;GitHub Secret (SECRET_MESSAGE)
       ↓
GitHub Actions (OIDC → sin AWS keys)
       ↓
Build Docker image → Push a ECR
       ↓
Update ECS Task Definition (inyecta el secret)
       ↓
Deploy a ECS Fargate
       ↓
App muestra el secret
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fm92dnqd0x3d50fjm77ly.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%2Fm92dnqd0x3d50fjm77ly.png" alt=" " width="800" height="537"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resultado:&lt;/strong&gt; El secret se muestra en la app, pero si buscas en todo el repositorio, no lo vas a encontrar. Se inyecta en runtime a través de la Task Definition de ECS. Nunca existió en el código fuente.&lt;/p&gt;




&lt;h2&gt;
  
  
  Qué puedes hacer hoy
&lt;/h2&gt;

&lt;p&gt;Si te llevas algo de este artículo, que sea esto:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Habilita Push Protection&lt;/strong&gt;: Protección inmediata contra leaks accidentales.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Migra de AWS access keys a OIDC&lt;/strong&gt;: Eliminas el riesgo más grande de tu pipeline.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Agrega &lt;code&gt;dependabot.yml&lt;/code&gt;&lt;/strong&gt;: Un archivo y tus dependencias se mantienen actualizadas automáticamente.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mueve secrets hardcodeados a GitHub Secrets&lt;/strong&gt;: Revisa tu código, busca tokens hardcodeados, y muévelos.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Conclusión
&lt;/h2&gt;

&lt;p&gt;La seguridad de credenciales no tiene que ser complicada.&lt;/p&gt;

&lt;p&gt;GitHub nos proporciona múltiples capas de protección que abarcan desde la prevención de errores humanos mediante Push Protection, hasta la detección de credenciales expuestas con Secret Scanning y la eliminación completa de credenciales permanentes mediante OIDC.&lt;/p&gt;

&lt;p&gt;La principal reflexión que quise transmitir durante mi charla en el GitHub Community Day Perú 2026 es que muchas veces utilizamos GitHub todos los días, pero no aprovechamos todo el potencial que nos ofrece en materia de seguridad.&lt;/p&gt;

&lt;p&gt;Con unas pocas configuraciones podemos reducir significativamente el riesgo de exposición de credenciales y fortalecer nuestros pipelines sin añadir complejidad innecesaria.&lt;/p&gt;

&lt;p&gt;Las diapositivas utilizadas para la presentación están disponibles en: &lt;a href="https://dev.tourl"&gt;https://speakerdeck.com/bnktch13/seguridad-en-github-para-devops&lt;/a&gt;&lt;br&gt;
Y el código completo del ejemplo utilizado durante la demostración está disponible en: &lt;a href="https://dev.tourl"&gt;https://github.com/BnkTCh/secure-deploy-demo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Te invito a explorarlo, probarlo y adaptarlo a tus propios proyectos.&lt;/p&gt;

&lt;p&gt;Y si estuviste presente en la charla durante el GitHub Community Day Perú 2026, gracias por acompañarme y por todas las preguntas y conversaciones que hicieron la sesión aún más interesante.&lt;/p&gt;

</description>
      <category>seguridad</category>
      <category>github</category>
      <category>devops</category>
      <category>aws</category>
    </item>
    <item>
      <title>Prompts que construyen: cómo dominar Amazon Q Developer en tu día a día</title>
      <dc:creator>Bianca Torres</dc:creator>
      <pubDate>Mon, 05 Jan 2026 02:22:14 +0000</pubDate>
      <link>https://dev.to/bnkintech/prompts-que-construyen-como-dominar-amazon-q-developer-en-tu-dia-a-dia-1h57</link>
      <guid>https://dev.to/bnkintech/prompts-que-construyen-como-dominar-amazon-q-developer-en-tu-dia-a-dia-1h57</guid>
      <description>&lt;p&gt;¿Sabías que el 40% del tiempo de un desarrollador se va en tareas repetitivas como leer documentación, generar boilerplate y debuggear errores?&lt;/p&gt;

&lt;p&gt;Como DevOps Engineer, he descubierto que Amazon Q Developer puede transformar estas tareas tediosas en procesos eficientes. No es solo "otra IA más": es un asistente especializado que entiende el ecosistema AWS.&lt;/p&gt;

&lt;p&gt;En este artículo te muestro cómo usarlo de forma práctica y, más importante, cómo escribir prompts que generen resultados reales, no respuestas genéricas.&lt;/p&gt;

&lt;p&gt;Este artículo está basado en una charla que di sobre Amazon Q Developer y Prompt Engineering.&lt;/p&gt;

&lt;p&gt;Si prefieres el formato video, aquí puedes verla completa:&lt;br&gt;
&lt;a href="https://www.youtube.com/live/M3sr0p8G5OU?si=YI9GLC-6PN8ygRql" rel="noopener noreferrer"&gt;https://www.youtube.com/live/M3sr0p8G5OU?si=YI9GLC-6PN8ygRql&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%2Fk09auazy60uer27myu0a.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%2Fk09auazy60uer27myu0a.png" alt=" " width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿Qué es Amazon Q Developer?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Amazon Q Developer es un asistente de IA generativa enfocado en:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Desarrollo de software&lt;/li&gt;
&lt;li&gt;Administración de AWS&lt;/li&gt;
&lt;li&gt;Mejores prácticas oficiales&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Se integra directamente en:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;IDEs como VS Code&lt;/li&gt;
&lt;li&gt;AWS Console&lt;/li&gt;
&lt;li&gt;CLI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A diferencia de otras herramientas genéricas, Amazon Q está entrenado con:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Documentación oficial de AWS&lt;/li&gt;
&lt;li&gt;Ejemplos reales&lt;/li&gt;
&lt;li&gt;Buenas prácticas del ecosistema cloud&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;¿Cómo funciona Amazon Q Developer?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Amazon Q Developer funciona sobre Amazon Bedrock, utilizando distintos Large Language Models (LLMs), entre ellos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Amazon Titan&lt;/li&gt;
&lt;li&gt;GPT (y otros modelos disponibles)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Algunos puntos clave:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No usa un único modelo fijo&lt;/li&gt;
&lt;li&gt;Cuanto más popular es un lenguaje o framework, mejor entrenado estará el modelo.&lt;/li&gt;
&lt;li&gt;Más datos de entrenamiento → mejores sugerencias&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Por eso, tecnologías comunes como Terraform, Kubernetes o Python suelen tener respuestas de muy buena calidad.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿Qué podemos hacer con Amazon Q Developer?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;En el día a día, Amazon Q puede ayudarte a:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Autocompletar código más rápido&lt;/li&gt;
&lt;li&gt;Obtener soluciones simples sin salir del IDE&lt;/li&gt;
&lt;li&gt;Explicar y documentar código&lt;/li&gt;
&lt;li&gt;Explicar mensajes de error&lt;/li&gt;
&lt;li&gt;Generar pruebas&lt;/li&gt;
&lt;li&gt;Crear código base (boilerplate)&lt;/li&gt;
&lt;li&gt;Mejorar tu productividad en general&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;La clave no es solo qué hace, sino cómo se lo pides.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Casos de uso reales donde Amazon Q brilla&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Para DevOps Engineers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Infraestructura como código: Generar templates de CloudFormation/Terraform&lt;/li&gt;
&lt;li&gt;Troubleshooting: Interpretar logs de CloudWatch y errores de servicios AWS&lt;/li&gt;
&lt;li&gt;Automatización: Crear scripts de CI/CD y pipelines&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para Developers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SDK de AWS: Generar código para interactuar con servicios AWS&lt;/li&gt;
&lt;li&gt;Serverless: Crear funciones Lambda con mejores prácticas&lt;/li&gt;
&lt;li&gt;Containerización: Dockerfiles optimizados para ECS/EKS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para Cloud Architects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Diseño de arquitecturas: Sugerir patrones y servicios apropiados&lt;/li&gt;
&lt;li&gt;Optimización de costos: Identificar oportunidades de ahorro&lt;/li&gt;
&lt;li&gt;Seguridad: Implementar controles y políticas IAM&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;¿Qué es un prompt?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Un prompt es simplemente:&lt;br&gt;
La instrucción que le das a la IA para que realice una tarea.&lt;br&gt;
Pero la diferencia entre frustración y productividad está en la calidad del prompt.&lt;/p&gt;

&lt;p&gt;Prompt vago vs Prompt bueno&lt;/p&gt;

&lt;p&gt;Prompt vago:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Explícame este error
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Prompt bueno:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Explícame este error que ocurre en un pod de Kubernetes en EKS cuando intento 
desplegar una aplicación Spring Boot en Java 17 y el pod entra en estado 
CrashLoopBackOff.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👉 El contexto lo es todo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Buenas prácticas de Prompt Engineering&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;La regla de las 4 C:&lt;/p&gt;

&lt;p&gt;Estas son las prácticas que mejor resultado me han dado usando Amazon Q Developer:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Claro&lt;br&gt;
Sé específico sobre lo que quieres.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Contexto&lt;br&gt;
Incluye información clave como:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lenguaje&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Versión&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Servicio&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Entorno&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Conciso&lt;br&gt;
Evita el ruido innecesario.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Continuo&lt;br&gt;
Itera. Ajusta el prompt según la respuesta que recibes.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Checklist antes de enviar un prompt&lt;/p&gt;

&lt;p&gt;Antes de presionar Enter, pregúntate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;¿Qué quiero exactamente? (tarea + resultado esperado)&lt;/li&gt;
&lt;li&gt;¿Dónde corre? (lenguaje, versión, servicio, entorno)&lt;/li&gt;
&lt;li&gt;¿Es claro y corto?&lt;/li&gt;
&lt;li&gt;¿Qué siguiente paso pediré si no es perfecto?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Prompt engineering es un diálogo, no una orden única.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusión&lt;/strong&gt;&lt;br&gt;
Amazon Q Developer puede ahorrarte mucho tiempo si sabes cómo hablarle.&lt;/p&gt;

&lt;p&gt;No se trata de escribir prompts "bonitos", sino prompts útiles, con intención clara, contexto técnico y capacidad de iteración.&lt;/p&gt;

&lt;p&gt;Si eres DevOps Engineer, Cloud Engineer o Developer y trabajas con AWS, aprender a usar Amazon Q Developer bien es una ventaja real, no solo hype.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Próximos pasos:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Instala Amazon Q Developer en tu IDE favorito:&lt;br&gt;
&lt;a href="https://docs.aws.amazon.com/es_es/amazonq/latest/qdeveloper-ug/q-in-IDE-setup.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/es_es/amazonq/latest/qdeveloper-ug/q-in-IDE-setup.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Practica con un proyecto real - empieza con tareas simples&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Documenta tus prompts exitosos - crea tu propia biblioteca&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Comparte con tu equipo - la productividad se multiplica&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;¿Y tú?&lt;br&gt;
¿Ya usas Amazon Q Developer en tu día a día?&lt;/p&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>ai</category>
      <category>promptengineering</category>
    </item>
  </channel>
</rss>
