<?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: Prithiviraj R</title>
    <description>The latest articles on DEV Community by Prithiviraj R (@prithiviraj_rengarajan).</description>
    <link>https://dev.to/prithiviraj_rengarajan</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%2F2615547%2F59c7b82d-71af-44c5-82c5-57460a9ceb5b.jpg</url>
      <title>DEV Community: Prithiviraj R</title>
      <link>https://dev.to/prithiviraj_rengarajan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/prithiviraj_rengarajan"/>
    <language>en</language>
    <item>
      <title>EKS-node-viewer: See Your EKS Costs in Real-Time (No Dashboard Needed)</title>
      <dc:creator>Prithiviraj R</dc:creator>
      <pubDate>Sat, 21 Feb 2026 12:47:28 +0000</pubDate>
      <link>https://dev.to/prithiviraj_rengarajan/eks-node-viewer-see-your-eks-costs-in-real-time-no-dashboard-needed-34n2</link>
      <guid>https://dev.to/prithiviraj_rengarajan/eks-node-viewer-see-your-eks-costs-in-real-time-no-dashboard-needed-34n2</guid>
      <description>&lt;h2&gt;
  
  
  🔥 Meet eks-node-viewer
&lt;/h2&gt;

&lt;p&gt;A tiny CLI tool from AWS Labs. Built originally for Karpenter demos. Now open source. And honestly, &lt;strong&gt;underrated&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One command:&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;eks-node-viewer &lt;span class="nt"&gt;--resources&lt;/span&gt; cpu,memory
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;You instantly see:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every node in your cluster&lt;/li&gt;
&lt;li&gt;CPU + Memory usage (based on pod requests)&lt;/li&gt;
&lt;li&gt;Instance type (t3.medium, c6a.2xlarge...)&lt;/li&gt;
&lt;li&gt;On-Demand vs Spot&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cost per hour AND per month&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Pods per node&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Real-time. In your terminal. No dashboard hopping. No Grafana. No console tab-switching.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 When I Use It
&lt;/h2&gt;

&lt;p&gt;I use eks-node-viewer when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Debugging uneven pod scheduling across nodes&lt;/li&gt;
&lt;li&gt;✅ Checking if Karpenter consolidation is actually working&lt;/li&gt;
&lt;li&gt;✅ Quick cost sanity check before a prod deploy&lt;/li&gt;
&lt;li&gt;✅ Spotting nodes that are packed too tight (or wasting capacity)&lt;/li&gt;
&lt;li&gt;✅ Answering "why is my bill so high?" in 30 seconds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you run multiple clusters (or even one busy prod cluster), this is a ridiculously fast way to understand what's happening.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 Let's Build a Demo
&lt;/h2&gt;

&lt;p&gt;I'll show you exactly how to use eks-node-viewer with a real EKS cluster.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What we'll do:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create an EKS cluster (1 node)&lt;/li&gt;
&lt;li&gt;Install eks-node-viewer&lt;/li&gt;
&lt;li&gt;Deploy workloads&lt;/li&gt;
&lt;li&gt;Watch costs in real-time&lt;/li&gt;
&lt;li&gt;See Karpenter-style scaling (optional)&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Step 1: Create EKS Cluster
&lt;/h2&gt;

&lt;p&gt;First, we need an EKS cluster. I'm using &lt;code&gt;eksctl&lt;/code&gt; because it's the fastest way.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create Cluster Config
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; eks-node-viewer-cluster.yaml &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: eks-node-viewer-demo
  region: us-east-1
  version: "1.31"

managedNodeGroups:
  - name: demo-nodes
    instanceType: t3.medium
    minSize: 1
    maxSize: 1
    desiredCapacity: 1
    volumeSize: 20
    labels:
      role: demo
    tags:
      Environment: demo
      Tool: eks-node-viewer
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create the Cluster
&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="nt"&gt;-f&lt;/span&gt; eks-node-viewer-cluster.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While it's creating, let's install eks-node-viewer.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Install eks-node-viewer
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Option 1: Using Go (Recommended)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go &lt;span class="nb"&gt;install &lt;/span&gt;github.com/awslabs/eks-node-viewer/cmd/eks-node-viewer@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Option 2: Using Homebrew (Mac)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew tap aws/tap
brew &lt;span class="nb"&gt;install &lt;/span&gt;eks-node-viewer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Option 3: Download Binary
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Download latest release&lt;/span&gt;
curl &lt;span class="nt"&gt;-LO&lt;/span&gt; https://github.com/awslabs/eks-node-viewer/releases/latest/download/eks-node-viewer_&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;_&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;.tar.gz

&lt;span class="c"&gt;# Extract&lt;/span&gt;
&lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-xzf&lt;/span&gt; eks-node-viewer_&lt;span class="k"&gt;*&lt;/span&gt;.tar.gz

&lt;span class="c"&gt;# Move to PATH&lt;/span&gt;
&lt;span class="nb"&gt;sudo mv &lt;/span&gt;eks-node-viewer /usr/local/bin/
&lt;span class="nb"&gt;sudo chmod&lt;/span&gt; +x /usr/local/bin/eks-node-viewer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Verify Installation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;eks-node-viewer &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;span class="c"&gt;# Output: eks-node-viewer version v0.7.4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 3: Connect to Cluster
&lt;/h2&gt;

&lt;p&gt;Once your cluster is ready, update your kubeconfig:&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;# List clusters&lt;/span&gt;
aws eks list-clusters &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1

&lt;span class="c"&gt;# Update kubeconfig&lt;/span&gt;
aws eks update-kubeconfig &lt;span class="nt"&gt;--name&lt;/span&gt; eks-node-viewer-demo &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1

&lt;span class="c"&gt;# Verify connection&lt;/span&gt;
kubectl get nodes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output:&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;NAME                             STATUS   ROLES    AGE   VERSION
ip-192-168-13-156.ec2.internal   Ready    &amp;lt;none&amp;gt;   2m    v1.31.14-eks-70ce843
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ Cluster is ready!&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4: Run eks-node-viewer (Baseline)
&lt;/h2&gt;

&lt;p&gt;Now for the magic. Run eks-node-viewer:&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;# Set AWS region (important!)&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;AWS_REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;us-east-1

&lt;span class="c"&gt;# Run eks-node-viewer&lt;/span&gt;
eks-node-viewer &lt;span class="nt"&gt;--resources&lt;/span&gt; cpu,memory
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What you'll see:&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;1 nodes (550m/1930m) 28.5% cpu    ███████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ $0.042/hour | $30.368/month
        540Mi/3376720Ki  16.4% memory ███████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
6 pods (0 pending 6 running 6 bound)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Let's break this down:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;1 nodes&lt;/strong&gt; - You have 1 node (t3.medium)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;550m/1930m&lt;/strong&gt; - Using 550 millicores out of 1930m available (28.5%)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;540Mi/3376720Ki&lt;/strong&gt; - Using 540MB out of 3.3GB RAM (16.4%)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;$0.042/hour | $30.368/month&lt;/strong&gt; - This is costing you $30/month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;6 pods&lt;/strong&gt; - System pods (coredns, kube-proxy, aws-node, metrics-server)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📸 &lt;strong&gt;Screenshot this!&lt;/strong&gt; This is your baseline.&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%2Frgcsgksrxippgz3jdzdr.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%2Frgcsgksrxippgz3jdzdr.png" alt=" " width="800" height="111"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 5: Deploy Nginx (Watch Costs Update)
&lt;/h2&gt;

&lt;p&gt;Keep eks-node-viewer running in Terminal 1.&lt;/p&gt;

&lt;p&gt;Open a &lt;strong&gt;NEW terminal&lt;/strong&gt; (Terminal 2) and deploy nginx:&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;# Set region&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;AWS_REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;us-east-1

&lt;span class="c"&gt;# Deploy nginx with 5 replicas&lt;/span&gt;
kubectl create deployment nginx &lt;span class="nt"&gt;--image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;nginx &lt;span class="nt"&gt;--replicas&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;5

&lt;span class="c"&gt;# Check deployment&lt;/span&gt;
kubectl get deployments
kubectl get pods
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output:&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;NAME    READY   UP-TO-DATE   AVAILABLE   AGE
nginx   5/5     5            5           30s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Switch back to Terminal 1 (eks-node-viewer).&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You'll see it update in real-time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1 nodes (750m/1930m) 38.9% cpu    ████████████████░░░░░░░░░░░░░░░░░░░░░░░░ $0.042/hour | $30.368/month
        840Mi/3376720Ki  25.5% memory ███████████░░░░░░░░░░░░░░░░░░░░░░░░░░░
11 pods (0 pending 11 running 11 bound)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What changed:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CPU usage: 28.5% → 38.9%&lt;/li&gt;
&lt;li&gt;Memory usage: 16.4% → 25.5%&lt;/li&gt;
&lt;li&gt;Pods: 6 → 11 (added 5 nginx pods)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost: Still $30/month&lt;/strong&gt; (same node)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📸 &lt;strong&gt;Screenshot this!&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%2Fy7hdwxm8p76r1emnezmx.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%2Fy7hdwxm8p76r1emnezmx.png" alt=" " width="800" height="169"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 6: Deploy CPU-Intensive App
&lt;/h2&gt;

&lt;p&gt;Let's stress the CPU and watch it happen live:&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;# Deploy stress test (Terminal 2)&lt;/span&gt;
kubectl create deployment stress &lt;span class="nt"&gt;--image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;polinux/stress &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--replicas&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3 &lt;span class="nt"&gt;--&lt;/span&gt; stress &lt;span class="nt"&gt;--cpu&lt;/span&gt; 1 &lt;span class="nt"&gt;--timeout&lt;/span&gt; 3600s

&lt;span class="c"&gt;# Check pods&lt;/span&gt;
kubectl get pods | &lt;span class="nb"&gt;grep &lt;/span&gt;stress
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;In eks-node-viewer (Terminal 1):&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;1 nodes (1550m/1930m) 80.3% cpu   ████████████████████████████████░░░░░░░░ $0.042/hour | $30.368/month
        1140Mi/3376720Ki  34.6% memory ██████████████░░░░░░░░░░░░░░░░░░░░░░░░
14 pods (0 pending 14 running 14 bound)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What changed:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CPU usage: 38.9% → &lt;strong&gt;80.3%&lt;/strong&gt; 🔥&lt;/li&gt;
&lt;li&gt;Memory usage: 25.5% → 34.6%&lt;/li&gt;
&lt;li&gt;Pods: 11 → 14 (added 3 stress pods)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost: Still $30/month&lt;/strong&gt; (same node, but now heavily utilized)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📸 &lt;strong&gt;Screenshot this!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is the key insight:&lt;/strong&gt; You can see your node is now 80% utilized. If you add more workloads, you'll need another node (and another $30/month).&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 7: Scale Up (Watch Node Get Packed)
&lt;/h2&gt;

&lt;p&gt;Let's push it further:&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;# Scale nginx to 20 replicas (Terminal 2)&lt;/span&gt;
kubectl scale deployment nginx &lt;span class="nt"&gt;--replicas&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;20

&lt;span class="c"&gt;# Watch pods&lt;/span&gt;
kubectl get pods | &lt;span class="nb"&gt;grep &lt;/span&gt;nginx | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;In eks-node-viewer:&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;1 nodes (1850m/1930m) 95.9% cpu   ████████████████████████████████████████ $0.042/hour | $30.368/month
        1640Mi/3376720Ki  49.8% memory ████████████████████░░░░░░░░░░░░░░░░░░
29 pods (0 pending 29 running 29 bound)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What changed:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CPU usage: 80.3% → &lt;strong&gt;95.9%&lt;/strong&gt; 🚨&lt;/li&gt;
&lt;li&gt;Memory usage: 34.6% → 49.8%&lt;/li&gt;
&lt;li&gt;Pods: 14 → 29 (added 15 more nginx pods)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Node is almost maxed out!&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📸 &lt;strong&gt;Screenshot this!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real-world insight:&lt;/strong&gt; If you were using Karpenter, it would see this 95% CPU usage and provision a new node. You'd see a second line appear in eks-node-viewer with another $30/month cost.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 8: Check Pod Distribution
&lt;/h2&gt;

&lt;p&gt;In eks-node-viewer, you can see exactly how pods are distributed:&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;# Run with pods resource&lt;/span&gt;
eks-node-viewer &lt;span class="nt"&gt;--resources&lt;/span&gt; cpu,memory,pods
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output:&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;1 nodes (1850m/1930m) 95.9% cpu    ████████████████████████████████████████ $0.042/hour | $30.368/month
        1640Mi/3376720Ki  49.8% memory ████████████████████░░░░░░░░░░░░░░░░░░
        29/110 pods       26.4% pods   ███████████░░░░░░░░░░░░░░░░░░░░░░░░░░░
29 pods (0 pending 29 running 29 bound)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;New info:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;29/110 pods&lt;/strong&gt; - You have 29 pods running, max capacity is 110 pods per node&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;26.4% pods&lt;/strong&gt; - You're using 26% of pod capacity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is useful for understanding if you're hitting pod limits (which can happen before CPU/memory limits).&lt;/p&gt;

&lt;p&gt;📸 &lt;strong&gt;Screenshot this!&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 9: Cleanup (Watch Resources Free Up)
&lt;/h2&gt;

&lt;p&gt;Let's clean up and watch the resources free up in real-time:&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;# Delete deployments (Terminal 2)&lt;/span&gt;
kubectl delete deployment nginx stress

&lt;span class="c"&gt;# Watch pods terminating&lt;/span&gt;
kubectl get pods
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;In eks-node-viewer:&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;1 nodes (550m/1930m) 28.5% cpu    ███████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░ $0.042/hour | $30.368/month
        540Mi/3376720Ki  16.4% memory ███████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
6 pods (0 pending 6 running 6 bound)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Back to baseline!&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CPU: 95.9% → 28.5%&lt;/li&gt;
&lt;li&gt;Memory: 49.8% → 16.4%&lt;/li&gt;
&lt;li&gt;Pods: 29 → 6&lt;/li&gt;
&lt;li&gt;Cost: Still $30/month (node still exists)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📸 &lt;strong&gt;Screenshot this!&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 Real-World Use Cases
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Use Case 1: "Why is my bill so high?"
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Before eks-node-viewer:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open AWS Console&lt;/li&gt;
&lt;li&gt;Go to EC2 → Instances&lt;/li&gt;
&lt;li&gt;Filter by cluster&lt;/li&gt;
&lt;li&gt;Manually check instance types&lt;/li&gt;
&lt;li&gt;Look up pricing&lt;/li&gt;
&lt;li&gt;Calculate total&lt;/li&gt;
&lt;li&gt;Check utilization in Grafana&lt;/li&gt;
&lt;li&gt;Realize you have 10 nodes at 20% utilization 😱&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;With eks-node-viewer:&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;eks-node-viewer &lt;span class="nt"&gt;--resources&lt;/span&gt; cpu,memory
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output:&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;10 nodes (2000m/19300m) 10.4% cpu   ████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ $0.416/hour | $303.68/month
         5400Mi/33767200Ki 16.4% memory ███████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
60 pods (0 pending 60 running 60 bound)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Instant insight:&lt;/strong&gt; You're paying $303/month for 10 nodes that are only 10% utilized. You could consolidate to 2-3 nodes and save $200/month.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Time saved:&lt;/strong&gt; 15 minutes → 30 seconds&lt;/p&gt;




&lt;h3&gt;
  
  
  Use Case 2: "Pods are pending"
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; You deploy a new app and pods are stuck in Pending state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get pods
&lt;span class="c"&gt;# NAME                    READY   STATUS    RESTARTS   AGE&lt;/span&gt;
&lt;span class="c"&gt;# my-app-7d8f9c5b-xk2lp   0/1     Pending   0          2m&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Check eks-node-viewer:&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;3 nodes (5700m/5790m) 98.4% cpu   ████████████████████████████████████████ $0.126/hour | $91.10/month
        11200Mi/10130160Ki 113.2% memory ████████████████████████████████████████
85 pods (5 pending 80 running 80 bound)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Instant insight:&lt;/strong&gt; Nodes are at 98% CPU and &lt;strong&gt;113% memory&lt;/strong&gt; (overcommitted). You need more nodes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Scale up or let Karpenter add nodes.&lt;/p&gt;




&lt;h3&gt;
  
  
  Use Case 3: "Is Karpenter working?"
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; You installed Karpenter but you're not sure if it's actually consolidating nodes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal 1:&lt;/strong&gt; Run eks-node-viewer&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;eks-node-viewer &lt;span class="nt"&gt;--resources&lt;/span&gt; cpu,memory
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Terminal 2:&lt;/strong&gt; Scale down workload&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl scale deployment my-app &lt;span class="nt"&gt;--replicas&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Watch eks-node-viewer:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;After 30 seconds (Karpenter's default consolidation delay)&lt;/li&gt;
&lt;li&gt;You should see nodes disappear&lt;/li&gt;
&lt;li&gt;Cost should decrease&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;If nodes DON'T disappear:&lt;/strong&gt; Karpenter isn't working. Check your NodePool configuration.&lt;/p&gt;




&lt;h3&gt;
  
  
  Use Case 4: "On-Demand vs Spot Cost Comparison"
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Filter by capacity type:&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;&lt;span class="c"&gt;# Show only On-Demand nodes&lt;/span&gt;
eks-node-viewer &lt;span class="nt"&gt;--node-selector&lt;/span&gt; karpenter.sh/capacity-type&lt;span class="o"&gt;=&lt;/span&gt;on-demand

&lt;span class="c"&gt;# Show only Spot nodes&lt;/span&gt;
eks-node-viewer &lt;span class="nt"&gt;--node-selector&lt;/span&gt; karpenter.sh/capacity-type&lt;span class="o"&gt;=&lt;/span&gt;spot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example output:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;On-Demand:&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;5 nodes (5000m/9650m) 51.8% cpu   ████████████████████░░░░░░░░░░░░░░░░░░░ $0.208/hour | $151.84/month
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Spot:&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;5 nodes (5000m/9650m) 51.8% cpu   ████████████████████░░░░░░░░░░░░░░░░░░ $0.062/hour | $45.26/month
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Instant insight:&lt;/strong&gt; Same workload, same utilization, but Spot is &lt;strong&gt;70% cheaper&lt;/strong&gt; ($151 vs $45).&lt;/p&gt;




&lt;h2&gt;
  
  
  🧹 Cleanup
&lt;/h2&gt;

&lt;p&gt;When you're done with the demo:&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;# Delete deployments&lt;/span&gt;
kubectl delete deployment nginx stress

&lt;span class="c"&gt;# Delete cluster&lt;/span&gt;
eksctl delete cluster &lt;span class="nt"&gt;--name&lt;/span&gt; eks-node-viewer-demo &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1

&lt;span class="c"&gt;# Verify deletion&lt;/span&gt;
aws eks list-clusters &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🎯 Key Takeaways
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What eks-node-viewer Shows You
&lt;/h3&gt;

&lt;p&gt;✅ &lt;strong&gt;Real-time cost&lt;/strong&gt; - Per hour and per month&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Instance types&lt;/strong&gt; - t3.medium, c6a.2xlarge, etc.&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Capacity type&lt;/strong&gt; - On-Demand vs Spot&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Resource usage&lt;/strong&gt; - CPU, Memory, Pods&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Utilization bars&lt;/strong&gt; - Visual representation&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Pod distribution&lt;/strong&gt; - How many pods per node  &lt;/p&gt;
&lt;h3&gt;
  
  
  When to Use It
&lt;/h3&gt;

&lt;p&gt;✅ &lt;strong&gt;Cost visibility&lt;/strong&gt; - Quick cost checks&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Capacity planning&lt;/strong&gt; - Before deploying new apps&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Debugging&lt;/strong&gt; - Why are pods pending?&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Karpenter monitoring&lt;/strong&gt; - Is consolidation working?&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Optimization&lt;/strong&gt; - Finding underutilized nodes  &lt;/p&gt;
&lt;h3&gt;
  
  
  Why It's Better Than Alternatives
&lt;/h3&gt;

&lt;p&gt;✅ &lt;strong&gt;No setup&lt;/strong&gt; - Just install and run&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;No dashboard&lt;/strong&gt; - Works in terminal&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Real-time&lt;/strong&gt; - Updates as things change&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Cost-aware&lt;/strong&gt; - Shows pricing automatically&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Fast&lt;/strong&gt; - Answer questions in seconds  &lt;/p&gt;


&lt;h2&gt;
  
  
  🚀 Try It Yourself
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;5-minute quick start:&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;&lt;span class="c"&gt;# 1. Install&lt;/span&gt;
go &lt;span class="nb"&gt;install &lt;/span&gt;github.com/awslabs/eks-node-viewer/cmd/eks-node-viewer@latest

&lt;span class="c"&gt;# 2. Set region&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;AWS_REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;us-east-1

&lt;span class="c"&gt;# 3. Run&lt;/span&gt;
eks-node-viewer &lt;span class="nt"&gt;--resources&lt;/span&gt; cpu,memory

&lt;span class="c"&gt;# 4. Deploy something&lt;/span&gt;
kubectl create deployment nginx &lt;span class="nt"&gt;--image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;nginx &lt;span class="nt"&gt;--replicas&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10

&lt;span class="c"&gt;# 5. Watch it update!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. You'll get it immediately.&lt;/p&gt;




&lt;h2&gt;
  
  
  📚 Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/awslabs/eks-node-viewer" rel="noopener noreferrer"&gt;https://github.com/awslabs/eks-node-viewer&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Karpenter Docs:&lt;/strong&gt; &lt;a href="https://karpenter.sh" rel="noopener noreferrer"&gt;https://karpenter.sh&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EKS Best Practices:&lt;/strong&gt; &lt;a href="https://aws.github.io/aws-eks-best-practices/" rel="noopener noreferrer"&gt;https://aws.github.io/aws-eks-best-practices/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS Pricing:&lt;/strong&gt; &lt;a href="https://aws.amazon.com/ec2/pricing/" rel="noopener noreferrer"&gt;https://aws.amazon.com/ec2/pricing/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💬 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;eks-node-viewer is one of those tools that seems simple but becomes indispensable once you start using it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before:&lt;/strong&gt; Checking costs meant opening 5 tabs, clicking through dashboards, and doing mental math.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;After:&lt;/strong&gt; One command. Instant visibility. Make decisions in seconds.&lt;/p&gt;

&lt;p&gt;If you run EKS (especially with Karpenter), try this once. You'll understand why it's underrated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Have you used eks-node-viewer?&lt;/strong&gt; What's your favorite use case? Let me know in the comments! 👇&lt;/p&gt;




&lt;h1&gt;
  
  
  AWS #EKS #Kubernetes #Karpenter #DevOps #CloudCost #CostOptimization #eks-node-viewer
&lt;/h1&gt;




&lt;p&gt;&lt;strong&gt;Happy Learning&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Prithiviraj Rengarajan&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;DevOps Engineer&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>eks</category>
      <category>finops</category>
    </item>
    <item>
      <title>Building a Multi-Agent AI System with Amazon Bedrock and Agent Squad</title>
      <dc:creator>Prithiviraj R</dc:creator>
      <pubDate>Sat, 21 Feb 2026 04:27:03 +0000</pubDate>
      <link>https://dev.to/prithiviraj_rengarajan/building-a-multi-agent-ai-system-with-amazon-bedrock-and-agent-squad-3dph</link>
      <guid>https://dev.to/prithiviraj_rengarajan/building-a-multi-agent-ai-system-with-amazon-bedrock-and-agent-squad-3dph</guid>
      <description>&lt;p&gt;Modern AI applications are no longer single, monolithic chatbots. As use cases expand across &lt;strong&gt;technology, healthcare, finance, travel, security, and operations&lt;/strong&gt;, a single general-purpose model quickly becomes inefficient, expensive, and hard to control.&lt;/p&gt;

&lt;p&gt;This is where &lt;strong&gt;multi-agent AI systems&lt;/strong&gt; come in.&lt;/p&gt;

&lt;p&gt;A multi-agent system divides responsibility across &lt;strong&gt;specialized AI agents&lt;/strong&gt;, each designed to handle a specific domain. Instead of asking one model to “know everything,” the system intelligently decides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Which agent is best suited for this question?&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Which model should respond?&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;How do we preserve conversation context across agents?&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this tutorial, we implement this architecture using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AWS Agent Squad&lt;/strong&gt; for orchestration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amazon Bedrock&lt;/strong&gt; for foundation models&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Streamlit&lt;/strong&gt; for a clean, interactive UI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result is a &lt;strong&gt;scalable, cost-efficient, and production-friendly AI assistant&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 What Is AWS Agent Squad?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Agent Squad&lt;/strong&gt; is an open-source orchestration framework from AWS that helps you build &lt;strong&gt;collaborative, multi-agent AI systems&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;At a high level, Agent Squad provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;central orchestrator&lt;/strong&gt; to manage agents&lt;/li&gt;
&lt;li&gt;Automatic &lt;strong&gt;intent-based routing&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Shared &lt;strong&gt;conversation memory&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Clean abstractions for adding new agents or tools&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You define:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What each agent specializes in&lt;/li&gt;
&lt;li&gt;Which foundation model it uses&lt;/li&gt;
&lt;li&gt;How requests are routed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Agent Squad handles the rest.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧩 Core Concepts You Should Understand
&lt;/h2&gt;

&lt;p&gt;Before diving deeper, it’s important to understand the three core building blocks.&lt;/p&gt;

&lt;h3&gt;
  
  
  1️⃣ Orchestrator (The Brain)
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;AgentSquad orchestrator&lt;/strong&gt; is the control plane of the system.&lt;/p&gt;

&lt;p&gt;Its responsibilities include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Receiving user input&lt;/li&gt;
&lt;li&gt;Maintaining session and conversation context&lt;/li&gt;
&lt;li&gt;Comparing the query against agent descriptions&lt;/li&gt;
&lt;li&gt;Selecting the most relevant agent&lt;/li&gt;
&lt;li&gt;Forwarding the request and returning the response&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of it as an &lt;strong&gt;AI traffic controller&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  2️⃣ Specialized Agents (Domain Experts)
&lt;/h3&gt;

&lt;p&gt;Each agent is configured with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;name&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;clear domain description&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;foundation model&lt;/strong&gt; from Amazon Bedrock&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tech Agent → AWS, cloud, software engineering&lt;/li&gt;
&lt;li&gt;Health Agent → fitness, wellness, nutrition&lt;/li&gt;
&lt;li&gt;Travel Agent → destinations, itineraries, tourism&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The descriptions are critical—they are what the classifier uses to decide &lt;em&gt;who should answer&lt;/em&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%2F6d0w2dgqw7ktdyug16uf.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%2F6d0w2dgqw7ktdyug16uf.png" alt=" " width="800" height="456"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  3️⃣ Classifier Model (The Router)
&lt;/h3&gt;

&lt;p&gt;Agent Squad uses a &lt;strong&gt;lightweight classifier model&lt;/strong&gt; (Claude Haiku in this tutorial) to analyze:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The user’s question&lt;/li&gt;
&lt;li&gt;All agent descriptions&lt;/li&gt;
&lt;li&gt;Previous conversation context&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It does &lt;strong&gt;not generate the final answer&lt;/strong&gt;.&lt;br&gt;
Its only job is to determine &lt;em&gt;which agent is best suited&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;This keeps costs low and routing fast.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔄 How the System Works (End-to-End Flow)
&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.amazonaws.com%2Fuploads%2Farticles%2Fzk5h3fszl2mze3xqns9v.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%2Fzk5h3fszl2mze3xqns9v.png" alt=" " width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s walk through a complete request lifecycle.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: User Submits a Query
&lt;/h3&gt;

&lt;p&gt;The user types a question into the Streamlit chat UI, such as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“What is AWS Lambda?”&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Step 2: Request Reaches the Orchestrator
&lt;/h3&gt;

&lt;p&gt;The Streamlit frontend sends the input to the &lt;strong&gt;Agent Squad orchestrator&lt;/strong&gt;, along with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User ID&lt;/li&gt;
&lt;li&gt;Session ID&lt;/li&gt;
&lt;li&gt;Conversation history&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Step 3: Intelligent Agent Selection
&lt;/h3&gt;

&lt;p&gt;The orchestrator invokes the &lt;strong&gt;classifier model (Claude Haiku)&lt;/strong&gt;, providing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The user query&lt;/li&gt;
&lt;li&gt;Agent descriptions&lt;/li&gt;
&lt;li&gt;Context from prior messages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The classifier evaluates semantic relevance and selects the &lt;strong&gt;Tech Agent&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 4: Response Generation
&lt;/h3&gt;

&lt;p&gt;The selected agent (using &lt;strong&gt;Claude Sonnet&lt;/strong&gt;) generates a &lt;strong&gt;high-quality, domain-specific response&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Because the agent is specialized:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Answers are more accurate&lt;/li&gt;
&lt;li&gt;Prompts are shorter&lt;/li&gt;
&lt;li&gt;Token usage is optimized&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Step 5: Response Returned to the UI
&lt;/h3&gt;

&lt;p&gt;The response is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Displayed to the user&lt;/li&gt;
&lt;li&gt;Tagged with the agent name&lt;/li&gt;
&lt;li&gt;Stored in session history for context continuity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Demo:&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%2Fdw8xy80kqfotdn9zgfs8.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%2Fdw8xy80kqfotdn9zgfs8.png" alt=" " width="800" height="401"&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%2F58boqag830untu93z8a3.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%2F58boqag830untu93z8a3.png" alt=" " width="800" height="313"&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%2F6kf3c8kiye0gyg6dkyby.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%2F6kf3c8kiye0gyg6dkyby.png" alt=" " width="800" height="177"&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%2Fmrru1lkhkwkkf8byr1g3.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%2Fmrru1lkhkwkkf8byr1g3.png" alt=" " width="800" height="348"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 Why This Architecture Is Powerful
&lt;/h2&gt;

&lt;p&gt;This pattern offers several key advantages:&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Specialization Over Generalization
&lt;/h3&gt;

&lt;p&gt;Each agent is optimized for a domain, improving accuracy and relevance.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Lower Costs
&lt;/h3&gt;

&lt;p&gt;Only the selected agent generates the response.&lt;br&gt;
The classifier uses a cheaper, faster model.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Easy Extensibility
&lt;/h3&gt;

&lt;p&gt;Adding a new domain is as simple as registering another agent.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Production Readiness
&lt;/h3&gt;

&lt;p&gt;Clear separation of concerns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;UI&lt;/li&gt;
&lt;li&gt;Routing&lt;/li&gt;
&lt;li&gt;Reasoning&lt;/li&gt;
&lt;li&gt;Model invocation&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ✅ Enterprise-Friendly
&lt;/h3&gt;

&lt;p&gt;This architecture aligns well with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Security boundaries&lt;/li&gt;
&lt;li&gt;Compliance requirements&lt;/li&gt;
&lt;li&gt;Observability and monitoring&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🏭 Real-World Use Cases
&lt;/h2&gt;

&lt;p&gt;This multi-agent pattern is ideal for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Customer support platforms&lt;/li&gt;
&lt;li&gt;Internal developer portals&lt;/li&gt;
&lt;li&gt;AI-powered knowledge bases&lt;/li&gt;
&lt;li&gt;Multi-domain enterprise assistants&lt;/li&gt;
&lt;li&gt;Workflow automation systems&lt;/li&gt;
&lt;li&gt;DevOps and cloud operations copilots&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Reference: &lt;br&gt;
Github: &lt;a href="https://github.com/awslabs/agent-squad" rel="noopener noreferrer"&gt;https://github.com/awslabs/agent-squad&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Happy Learning&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Prithiviraj Rengarajan&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;DevOps Engineer&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ai</category>
    </item>
    <item>
      <title>From Ingress to Gateway API: Building a Production-Ready Kubernetes Gateway on AWS EKS</title>
      <dc:creator>Prithiviraj R</dc:creator>
      <pubDate>Sat, 31 Jan 2026 09:12:27 +0000</pubDate>
      <link>https://dev.to/prithiviraj_rengarajan/from-ingress-to-gateway-api-building-a-production-ready-kubernetes-gateway-on-aws-eks-39dh</link>
      <guid>https://dev.to/prithiviraj_rengarajan/from-ingress-to-gateway-api-building-a-production-ready-kubernetes-gateway-on-aws-eks-39dh</guid>
      <description>&lt;h2&gt;
  
  
  🎯 Introduction
&lt;/h2&gt;

&lt;p&gt;Kubernetes Ingress is being deprecated! With Ingress NGINX scheduled for decommissioning in March 2026, it's time to migrate to the &lt;strong&gt;Gateway API&lt;/strong&gt; - the official successor that offers better role separation, portability, and expressiveness.&lt;/p&gt;

&lt;p&gt;In this comprehensive guide, I'll walk you through deploying a production-ready Gateway API setup on AWS EKS using Envoy Gateway, demonstrating the modern approach to Kubernetes traffic management.&lt;/p&gt;

&lt;h2&gt;
  
  
  📋 Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Why Gateway API?&lt;/li&gt;
&lt;li&gt;Architecture Overview&lt;/li&gt;
&lt;li&gt;Prerequisites&lt;/li&gt;
&lt;li&gt;Understanding Gateway API Components&lt;/li&gt;
&lt;li&gt;Step-by-Step Implementation&lt;/li&gt;
&lt;li&gt;Testing and Verification&lt;/li&gt;
&lt;li&gt;Troubleshooting&lt;/li&gt;
&lt;li&gt;Cleanup&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🚀 Why Gateway API?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Problem with Ingress
&lt;/h3&gt;

&lt;p&gt;Traditional Kubernetes Ingress has several limitations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Monolithic design&lt;/strong&gt;: Single resource controls everything&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vendor-specific annotations&lt;/strong&gt;: Not portable across providers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Limited expressiveness&lt;/strong&gt;: Can't handle advanced routing scenarios&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No role separation&lt;/strong&gt;: Cluster admins and developers share the same resource&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Being deprecated&lt;/strong&gt;: Ingress NGINX decommissioning in March 2026&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Gateway API Benefits
&lt;/h3&gt;

&lt;p&gt;Gateway API solves these problems with:&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Role-based model&lt;/strong&gt;: Clear separation between infrastructure, cluster admin, and developer concerns&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Portable &amp;amp; consistent&lt;/strong&gt;: Standard API across all providers (AWS, GCP, Azure, on-prem)&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;More expressive&lt;/strong&gt;: Header-based routing, query parameters, traffic splitting, request/response modification&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Future-proof&lt;/strong&gt;: Official Kubernetes successor, graduated to GA (v1.0.0)&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Better security&lt;/strong&gt;: Fine-grained RBAC and policy attachment  &lt;/p&gt;


&lt;h2&gt;
  
  
  🏗️ Architecture Overview
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Ingress vs Gateway API Flow
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Traditional Ingress:&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;Client → External LB (Ingress Controller) → Ingress Resource → Service → Pods
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Modern Gateway API:&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;Client Request
    ↓
External Load Balancer (NLB)
    ↓
Gateway Controller Pod (Envoy)
    ↓
GatewayClass (Infra Provider)
    ↓
Gateway (Cluster Admin)
    ↓
HTTPRoute (Developers)
    ↓
Service → Pods
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Role Separation
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th&gt;Responsibility&lt;/th&gt;
&lt;th&gt;Resources&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Infrastructure Provider&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Provides Gateway implementation&lt;/td&gt;
&lt;td&gt;GatewayClass&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cluster Administrator&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Configures listeners, TLS, load balancers&lt;/td&gt;
&lt;td&gt;Gateway&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Application Developer&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Defines routing rules for their apps&lt;/td&gt;
&lt;td&gt;HTTPRoute, TCPRoute, etc.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  📦 Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before starting, ensure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AWS Account&lt;/strong&gt; with appropriate permissions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS CLI&lt;/strong&gt; configured (&lt;code&gt;aws configure&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;kubectl&lt;/strong&gt; (v1.28+)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;eksctl&lt;/strong&gt; (v0.150+)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Helm&lt;/strong&gt; (v3.0+)&lt;/li&gt;
&lt;li&gt;Basic understanding of Kubernetes concepts&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Install Required Tools
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install eksctl (macOS)&lt;/span&gt;
brew tap weaveworks/tap
brew &lt;span class="nb"&gt;install &lt;/span&gt;weaveworks/tap/eksctl

&lt;span class="c"&gt;# Install kubectl&lt;/span&gt;
brew &lt;span class="nb"&gt;install &lt;/span&gt;kubectl

&lt;span class="c"&gt;# Install Helm&lt;/span&gt;
brew &lt;span class="nb"&gt;install &lt;/span&gt;helm

&lt;span class="c"&gt;# Verify installations&lt;/span&gt;
eksctl version
kubectl version &lt;span class="nt"&gt;--client&lt;/span&gt;
helm version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧩 Understanding Gateway API Components
&lt;/h2&gt;

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

&lt;p&gt;&lt;strong&gt;What it is&lt;/strong&gt;: Defines the controller implementation (like a StorageClass for storage)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Who manages it&lt;/strong&gt;: Infrastructure provider (platform team)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Purpose&lt;/strong&gt;: Specifies which Gateway controller will handle Gateway resources&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;gateway.networking.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;GatewayClass&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;eg&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;controllerName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gateway.envoyproxy.io/gatewayclass-controller&lt;/span&gt;
  &lt;span class="na"&gt;parametersRef&lt;/span&gt;&lt;span class="pi"&gt;:&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;gateway.envoyproxy.io&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;EnvoyProxy&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;internet-facing-proxy&lt;/span&gt;
    &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;envoy-gateway-system&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Points:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One GatewayClass per controller type&lt;/li&gt;
&lt;li&gt;Can have multiple GatewayClasses (e.g., internal, external, premium)&lt;/li&gt;
&lt;li&gt;Immutable once created&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Gateway
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What it is&lt;/strong&gt;: Defines the load balancer configuration and listeners&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Who manages it&lt;/strong&gt;: Cluster administrator&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Purpose&lt;/strong&gt;: Configures how traffic enters the cluster (ports, protocols, TLS)&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;gateway.networking.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Gateway&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;demo-gateway&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;gatewayClassName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;eg&lt;/span&gt;
  &lt;span class="na"&gt;listeners&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;http&lt;/span&gt;
    &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;HTTP&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="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;https&lt;/span&gt;
    &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;HTTPS&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;443&lt;/span&gt;
    &lt;span class="na"&gt;tls&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;certificateRefs&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-cert&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Points:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creates the actual load balancer (NLB in AWS)&lt;/li&gt;
&lt;li&gt;Defines listeners (HTTP, HTTPS, TCP, UDP)&lt;/li&gt;
&lt;li&gt;Manages TLS certificates&lt;/li&gt;
&lt;li&gt;Can have multiple listeners on different ports&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. HTTPRoute
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What it is&lt;/strong&gt;: Defines routing rules for HTTP traffic&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Who manages it&lt;/strong&gt;: Application developers&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Purpose&lt;/strong&gt;: Routes traffic from Gateway to backend services&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;gateway.networking.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;HTTPRoute&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;backend-route&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;parentRefs&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;demo-gateway&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;matches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PathPrefix&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;/api&lt;/span&gt;
    &lt;span class="na"&gt;backendRefs&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;backend-service&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Points:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Attached to a Gateway via &lt;code&gt;parentRefs&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Supports path, header, query parameter matching&lt;/li&gt;
&lt;li&gt;Can split traffic between multiple backends&lt;/li&gt;
&lt;li&gt;Supports request/response modification&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. EnvoyProxy (Envoy Gateway Specific)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What it is&lt;/strong&gt;: Configuration for Envoy Gateway's data plane&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Who manages it&lt;/strong&gt;: Infrastructure provider&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Purpose&lt;/strong&gt;: Customizes how Envoy Gateway creates load balancers&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;gateway.envoyproxy.io/v1alpha1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;EnvoyProxy&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;internet-facing-proxy&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;envoy-gateway-system&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;provider&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;Kubernetes&lt;/span&gt;
    &lt;span class="na"&gt;kubernetes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;envoyService&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;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;service.beta.kubernetes.io/aws-load-balancer-scheme&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;internet-facing"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Points:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Envoy Gateway specific (not part of standard Gateway API)&lt;/li&gt;
&lt;li&gt;Controls load balancer type (internal vs internet-facing)&lt;/li&gt;
&lt;li&gt;Configures resource limits, replicas, etc.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🛠️ Step-by-Step Implementation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Create EKS Cluster
&lt;/h3&gt;

&lt;p&gt;Create a new EKS cluster with Kubernetes 1.31:&lt;br&gt;
&lt;/p&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; eks-gateway-demo &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;--version&lt;/span&gt; 1.31 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--nodegroup-name&lt;/span&gt; gateway-nodes &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--node-type&lt;/span&gt; t3.medium &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--nodes&lt;/span&gt; 2 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--nodes-min&lt;/span&gt; 2 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--nodes-max&lt;/span&gt; 4 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--managed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What this does:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creates a new EKS cluster named &lt;code&gt;eks-gateway-demo&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Uses Kubernetes version 1.31 (latest stable)&lt;/li&gt;
&lt;li&gt;Creates 2 t3.medium nodes in a managed node group&lt;/li&gt;
&lt;li&gt;Sets up VPC, subnets, security groups automatically&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Time&lt;/strong&gt;: ~15-20 minutes&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Verify:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get nodes
&lt;span class="c"&gt;# Should show 2 nodes in Ready state&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Install Gateway API CRDs
&lt;/h3&gt;

&lt;p&gt;Install the Gateway API Custom Resource Definitions:&lt;br&gt;
&lt;/p&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; https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.0.0/standard-install.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What this installs:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GatewayClass CRD&lt;/li&gt;
&lt;li&gt;Gateway CRD&lt;/li&gt;
&lt;li&gt;HTTPRoute CRD&lt;/li&gt;
&lt;li&gt;ReferenceGrant CRD&lt;/li&gt;
&lt;li&gt;TCPRoute, UDPRoute, TLSRoute CRDs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Verify:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get crd | &lt;span class="nb"&gt;grep &lt;/span&gt;gateway
&lt;span class="c"&gt;# Should show gateway-related CRDs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Install Envoy Gateway
&lt;/h3&gt;

&lt;p&gt;Install Envoy Gateway as the Gateway controller:&lt;br&gt;
&lt;/p&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; https://github.com/envoyproxy/gateway/releases/download/v1.0.0/install.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What this installs:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Envoy Gateway controller deployment&lt;/li&gt;
&lt;li&gt;Required RBAC (ServiceAccount, ClusterRole, ClusterRoleBinding)&lt;/li&gt;
&lt;li&gt;Envoy Gateway configuration&lt;/li&gt;
&lt;li&gt;Webhook configurations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Wait for it to be ready:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nb"&gt;wait&lt;/span&gt; &lt;span class="nt"&gt;--timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2m &lt;span class="nt"&gt;-n&lt;/span&gt; envoy-gateway-system &lt;span class="se"&gt;\&lt;/span&gt;
  deployment/envoy-gateway &lt;span class="nt"&gt;--for&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;condition&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Available
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Verify:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get pods &lt;span class="nt"&gt;-n&lt;/span&gt; envoy-gateway-system
&lt;span class="c"&gt;# Should show envoy-gateway pod running&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Configure Internet-Facing Load Balancer
&lt;/h3&gt;

&lt;p&gt;Create EnvoyProxy configuration for internet-facing NLB:&lt;br&gt;
&lt;/p&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; - &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyProxy
metadata:
  name: internet-facing-proxy
  namespace: envoy-gateway-system
spec:
  provider:
    type: Kubernetes
    kubernetes:
      envoyService:
        type: LoadBalancer
        annotations:
          service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why this is needed:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;By default, Envoy Gateway creates internal load balancers&lt;/li&gt;
&lt;li&gt;This configuration makes the NLB internet-facing&lt;/li&gt;
&lt;li&gt;AWS-specific annotation controls the load balancer scheme&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 5: Create GatewayClass
&lt;/h3&gt;

&lt;p&gt;Create a GatewayClass that references the EnvoyProxy configuration:&lt;br&gt;
&lt;/p&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; - &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: eg
spec:
  controllerName: gateway.envoyproxy.io/gatewayclass-controller
  parametersRef:
    group: gateway.envoyproxy.io
    kind: EnvoyProxy
    name: internet-facing-proxy
    namespace: envoy-gateway-system
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Verify:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get gatewayclass
&lt;span class="c"&gt;# Should show 'eg' with ACCEPTED=True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 6: Deploy Sample Applications
&lt;/h3&gt;

&lt;p&gt;Deploy backend and frontend applications:&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;# Backend Application&lt;/span&gt;
kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; - &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
spec:
  replicas: 2
  selector:
    matchLabels:
      app: backend
  template:
    metadata:
      labels:
        app: backend
    spec:
      containers:
      - name: backend
        image: hashicorp/http-echo
        args:
        - "-text=Backend API Response"
        ports:
        - containerPort: 5678
---
apiVersion: v1
kind: Service
metadata:
  name: backend-service
spec:
  selector:
    app: backend
  ports:
  - port: 80
    targetPort: 5678
&lt;/span&gt;&lt;span class="no"&gt;EOF
&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;&lt;span class="c"&gt;# Frontend Application&lt;/span&gt;
kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; - &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
spec:
  replicas: 2
  selector:
    matchLabels:
      app: frontend
  template:
    metadata:
      labels:
        app: frontend
    spec:
      containers:
      - name: frontend
        image: hashicorp/http-echo
        args:
        - "-text=Frontend UI Response"
        ports:
        - containerPort: 5678
---
apiVersion: v1
kind: Service
metadata:
  name: frontend-service
spec:
  selector:
    app: frontend
  ports:
  - port: 80
    targetPort: 5678
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Verify:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get pods
kubectl get svc
&lt;span class="c"&gt;# Should show 4 pods (2 backend + 2 frontend) and 2 services&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 7: Create Gateway
&lt;/h3&gt;

&lt;p&gt;Create the Gateway resource that provisions the NLB:&lt;br&gt;
&lt;/p&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; - &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: demo-gateway
spec:
  gatewayClassName: eg
  listeners:
  - name: http
    protocol: HTTP
    port: 80
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What happens:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Envoy Gateway controller sees the new Gateway&lt;/li&gt;
&lt;li&gt;Creates an Envoy proxy deployment&lt;/li&gt;
&lt;li&gt;Creates a LoadBalancer Service&lt;/li&gt;
&lt;li&gt;AWS provisions an internet-facing NLB&lt;/li&gt;
&lt;li&gt;NLB targets are registered (takes 2-3 minutes)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Monitor Gateway creation:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get gateway demo-gateway &lt;span class="nt"&gt;-w&lt;/span&gt;
&lt;span class="c"&gt;# Wait for ADDRESS to be populated and PROGRAMMED=True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Get the NLB DNS:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get gateway demo-gateway &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.status.addresses[0].value}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 8: Create HTTPRoutes
&lt;/h3&gt;

&lt;p&gt;Create routing rules for backend and frontend:&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;# Backend Route&lt;/span&gt;
kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; - &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: backend-route
spec:
  parentRefs:
  - name: demo-gateway
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /api
    backendRefs:
    - name: backend-service
      port: 80
&lt;/span&gt;&lt;span class="no"&gt;EOF
&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;&lt;span class="c"&gt;# Frontend Route&lt;/span&gt;
kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; - &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: frontend-route
spec:
  parentRefs:
  - name: demo-gateway
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: frontend-service
      port: 80
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How HTTPRoute works:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;parentRefs&lt;/strong&gt;: Attaches the route to a Gateway&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;matches&lt;/strong&gt;: Defines conditions for routing (path, headers, query params)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;backendRefs&lt;/strong&gt;: Specifies which Service to route to&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Path matching order:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More specific paths are matched first&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/api&lt;/code&gt; matches before &lt;code&gt;/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;This is why backend-route works correctly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Verify:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get httproute
kubectl describe httproute backend-route
&lt;span class="c"&gt;# Should show ACCEPTED=True and ResolvedRefs=True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧪 Testing and Verification
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Wait for NLB to be Ready
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check NLB status in AWS&lt;/span&gt;
aws elbv2 describe-load-balancers &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;--query&lt;/span&gt; &lt;span class="s1"&gt;'LoadBalancers[?contains(LoadBalancerName, `envoy`)].{Name:LoadBalancerName,State:State.Code,Scheme:Scheme}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; table

&lt;span class="c"&gt;# Check target health&lt;/span&gt;
&lt;span class="nv"&gt;TG_ARN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws elbv2 describe-target-groups &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;--query&lt;/span&gt; &lt;span class="s1"&gt;'TargetGroups[?contains(LoadBalancerArns[0], `envoy`)].TargetGroupArn'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; text | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

aws elbv2 describe-target-health &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;--target-group-arn&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$TG_ARN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'TargetHealthDescriptions[*].{Target:Target.Id,State:TargetHealth.State}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; table
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wait until:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NLB State = &lt;code&gt;active&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;At least one target State = &lt;code&gt;healthy&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Test the Endpoints
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Get NLB DNS&lt;/span&gt;
&lt;span class="nv"&gt;NLB_DNS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;kubectl get gateway demo-gateway &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.status.addresses[0].value}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Test backend&lt;/span&gt;
curl http://&lt;span class="nv"&gt;$NLB_DNS&lt;/span&gt;/api
&lt;span class="c"&gt;# Expected: Backend API Response&lt;/span&gt;

&lt;span class="c"&gt;# Test frontend&lt;/span&gt;
curl http://&lt;span class="nv"&gt;$NLB_DNS&lt;/span&gt;/
&lt;span class="c"&gt;# Expected: Frontend UI Response&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Verify Gateway API Resources
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check all Gateway API resources&lt;/span&gt;
kubectl get gatewayclass,gateway,httproute

&lt;span class="c"&gt;# Check Gateway details&lt;/span&gt;
kubectl describe gateway demo-gateway

&lt;span class="c"&gt;# Check HTTPRoute details&lt;/span&gt;
kubectl describe httproute backend-route

&lt;span class="c"&gt;# Check Envoy Gateway logs&lt;/span&gt;
kubectl logs &lt;span class="nt"&gt;-n&lt;/span&gt; envoy-gateway-system deployment/envoy-gateway &lt;span class="nt"&gt;--tail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;50

&lt;span class="c"&gt;# Check Envoy Proxy logs&lt;/span&gt;
&lt;span class="nv"&gt;ENVOY_POD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;kubectl get pods &lt;span class="nt"&gt;-n&lt;/span&gt; envoy-gateway-system &lt;span class="nt"&gt;-l&lt;/span&gt; app.kubernetes.io/component&lt;span class="o"&gt;=&lt;/span&gt;proxy &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.items[0].metadata.name}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
kubectl logs &lt;span class="nt"&gt;-n&lt;/span&gt; envoy-gateway-system &lt;span class="nv"&gt;$ENVOY_POD&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; envoy &lt;span class="nt"&gt;--tail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;50
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔍 How It Works: Deep Dive
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Request Flow
&lt;/h3&gt;

&lt;p&gt;Let's trace a request from client to pod:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Client sends: GET http://nlb-dns.amazonaws.com/api

2. DNS resolves to NLB IP addresses

3. NLB forwards to Envoy proxy pod (NodePort 31735)

4. Envoy proxy receives request on port 10080

5. Envoy matches request against HTTPRoutes:
   - Checks backend-route: path=/api ✓ MATCH
   - Routes to backend-service:80

6. backend-service (ClusterIP) load balances to backend pods

7. Backend pod responds: "Backend API Response"

8. Response flows back through Envoy → NLB → Client
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Gateway Controller Reconciliation Loop
&lt;/h3&gt;

&lt;p&gt;Envoy Gateway continuously watches for changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Watch Gateway API resources (Gateway, HTTPRoute, etc.)

2. On change detected:
   a. Validate resource
   b. Translate to Envoy configuration (xDS)
   c. Update Envoy proxy pods
   d. Update Gateway/HTTPRoute status

3. Watch Envoy proxy pods:
   a. Ensure desired replicas running
   b. Monitor health
   c. Update Gateway status

4. Watch LoadBalancer Service:
   a. Get external IP/DNS
   b. Update Gateway status with address
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Envoy Proxy Configuration
&lt;/h3&gt;

&lt;p&gt;Envoy Gateway translates Gateway API resources to Envoy xDS configuration:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gateway → Listener&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;Gateway&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;listeners&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;http&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;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;HTTP&lt;/span&gt;

&lt;span class="na"&gt;Translates to Envoy Listener&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;default/demo-gateway/http&lt;/span&gt;
  &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0.0.0.0:10080&lt;/span&gt;
  &lt;span class="na"&gt;filter_chains&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;filters&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;envoy.filters.network.http_connection_manager&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;HTTPRoute → Route Configuration&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;HTTPRoute&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;matches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PathPrefix&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;/api&lt;/span&gt;
  &lt;span class="na"&gt;backendRefs&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;backend-service&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;Translates to Envoy Route&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;match&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;prefix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/api&lt;/span&gt;
  &lt;span class="na"&gt;route&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;cluster&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;httproute/default/backend-route/rule/0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Service → Cluster &amp;amp; Endpoints&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;Service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;backend-service&lt;/span&gt;
  &lt;span class="s"&gt;selector&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;app=backend&lt;/span&gt;
  &lt;span class="s"&gt;port&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;

&lt;span class="na"&gt;Translates to Envoy Cluster&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;httproute/default/backend-route/rule/0&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;EDS&lt;/span&gt;
  &lt;span class="na"&gt;endpoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;192.168.15.16:5678  (backend pod 1)&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;192.168.38.106:5678 (backend pod 2)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Load Balancing
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;NLB Level:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Distributes traffic across Envoy proxy pods&lt;/li&gt;
&lt;li&gt;Uses NodePort (31735 in our case)&lt;/li&gt;
&lt;li&gt;Health checks on &lt;code&gt;/healthz&lt;/code&gt; endpoint&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Envoy Level:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Distributes traffic across backend pods&lt;/li&gt;
&lt;li&gt;Default: Round-robin&lt;/li&gt;
&lt;li&gt;Supports weighted, least-request, ring-hash, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Service Level:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kubernetes Service provides ClusterIP&lt;/li&gt;
&lt;li&gt;kube-proxy manages iptables/IPVS rules&lt;/li&gt;
&lt;li&gt;Distributes to healthy endpoints only&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🐛 Troubleshooting
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Issue 1: Gateway Not Getting Address
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptoms:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get gateway demo-gateway
&lt;span class="c"&gt;# ADDRESS column is empty, PROGRAMMED=False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ol&gt;
&lt;li&gt;Envoy Gateway controller not running&lt;/li&gt;
&lt;li&gt;LoadBalancer service not created&lt;/li&gt;
&lt;li&gt;AWS quota limits reached&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Solutions:&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;&lt;span class="c"&gt;# Check controller&lt;/span&gt;
kubectl get pods &lt;span class="nt"&gt;-n&lt;/span&gt; envoy-gateway-system

&lt;span class="c"&gt;# Check controller logs&lt;/span&gt;
kubectl logs &lt;span class="nt"&gt;-n&lt;/span&gt; envoy-gateway-system deployment/envoy-gateway &lt;span class="nt"&gt;--tail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;50

&lt;span class="c"&gt;# Check for LoadBalancer service&lt;/span&gt;
kubectl get svc &lt;span class="nt"&gt;-n&lt;/span&gt; envoy-gateway-system

&lt;span class="c"&gt;# Restart controller if needed&lt;/span&gt;
kubectl rollout restart deployment/envoy-gateway &lt;span class="nt"&gt;-n&lt;/span&gt; envoy-gateway-system
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Issue 2: HTTPRoute Not Accepted
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptoms:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl describe httproute backend-route
&lt;span class="c"&gt;# Conditions show Accepted=False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ol&gt;
&lt;li&gt;Gateway doesn't exist&lt;/li&gt;
&lt;li&gt;parentRefs incorrect&lt;/li&gt;
&lt;li&gt;Backend service doesn't exist&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Solutions:&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;&lt;span class="c"&gt;# Verify Gateway exists&lt;/span&gt;
kubectl get gateway demo-gateway

&lt;span class="c"&gt;# Check parentRefs match Gateway name&lt;/span&gt;
kubectl get httproute backend-route &lt;span class="nt"&gt;-o&lt;/span&gt; yaml | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-A&lt;/span&gt; 5 parentRefs

&lt;span class="c"&gt;# Verify backend service exists&lt;/span&gt;
kubectl get svc backend-service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Issue 3: 404 Not Found
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptoms:&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;curl http://&lt;span class="nv"&gt;$NLB_DNS&lt;/span&gt;/api
&lt;span class="c"&gt;# Returns 404&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ol&gt;
&lt;li&gt;HTTPRoute path doesn't match&lt;/li&gt;
&lt;li&gt;HTTPRoute not attached to Gateway&lt;/li&gt;
&lt;li&gt;Backend service selector wrong&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Solutions:&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;&lt;span class="c"&gt;# Check HTTPRoute status&lt;/span&gt;
kubectl describe httproute backend-route

&lt;span class="c"&gt;# Test backend service directly&lt;/span&gt;
kubectl run test-curl &lt;span class="nt"&gt;--image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;curlimages/curl &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--restart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Never &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  curl backend-service/api

&lt;span class="c"&gt;# Check service endpoints&lt;/span&gt;
kubectl get endpoints backend-service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Issue 4: Connection Timeout
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptoms:&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;curl http://&lt;span class="nv"&gt;$NLB_DNS&lt;/span&gt;/api
&lt;span class="c"&gt;# Hangs and times out&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ol&gt;
&lt;li&gt;NLB targets unhealthy&lt;/li&gt;
&lt;li&gt;Security group blocking traffic&lt;/li&gt;
&lt;li&gt;Network ACLs blocking traffic&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Solutions:&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;&lt;span class="c"&gt;# Check target health&lt;/span&gt;
&lt;span class="nv"&gt;TG_ARN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws elbv2 describe-target-groups &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;--query&lt;/span&gt; &lt;span class="s1"&gt;'TargetGroups[?contains(LoadBalancerArns[0], `envoy`)].TargetGroupArn'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; text | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

aws elbv2 describe-target-health &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1 &lt;span class="nt"&gt;--target-group-arn&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$TG_ARN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Check security groups&lt;/span&gt;
aws ec2 describe-security-groups &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;--filters&lt;/span&gt; &lt;span class="s2"&gt;"Name=tag:kubernetes.io/cluster/eks-gateway-demo,Values=owned"&lt;/span&gt;

&lt;span class="c"&gt;# Check if NLB is internet-facing&lt;/span&gt;
aws elbv2 describe-load-balancers &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;--query&lt;/span&gt; &lt;span class="s1"&gt;'LoadBalancers[?contains(LoadBalancerName, `envoy`)].Scheme'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧹 Cleanup
&lt;/h2&gt;

&lt;p&gt;To avoid AWS charges, clean up all resources:&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;# Delete HTTPRoutes&lt;/span&gt;
kubectl delete httproute backend-route frontend-route

&lt;span class="c"&gt;# Delete Gateway (this deletes the NLB)&lt;/span&gt;
kubectl delete gateway demo-gateway

&lt;span class="c"&gt;# Delete GatewayClass&lt;/span&gt;
kubectl delete gatewayclass eg

&lt;span class="c"&gt;# Delete EnvoyProxy configuration&lt;/span&gt;
kubectl delete envoyproxy internet-facing-proxy &lt;span class="nt"&gt;-n&lt;/span&gt; envoy-gateway-system

&lt;span class="c"&gt;# Uninstall Envoy Gateway&lt;/span&gt;
kubectl delete &lt;span class="nt"&gt;-f&lt;/span&gt; https://github.com/envoyproxy/gateway/releases/download/v1.0.0/install.yaml

&lt;span class="c"&gt;# Delete Gateway API CRDs&lt;/span&gt;
kubectl delete &lt;span class="nt"&gt;-f&lt;/span&gt; https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.0.0/standard-install.yaml

&lt;span class="c"&gt;# Delete applications&lt;/span&gt;
kubectl delete deployment backend frontend
kubectl delete service backend-service frontend-service

&lt;span class="c"&gt;# Delete EKS cluster (this deletes everything)&lt;/span&gt;
eksctl delete cluster &lt;span class="nt"&gt;--name&lt;/span&gt; eks-gateway-demo &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Verify cleanup:&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;&lt;span class="c"&gt;# Check no NLBs remain&lt;/span&gt;
aws elbv2 describe-load-balancers &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;--query&lt;/span&gt; &lt;span class="s1"&gt;'LoadBalancers[?contains(LoadBalancerName, `envoy`)]'&lt;/span&gt;

&lt;span class="c"&gt;# Check cluster deleted&lt;/span&gt;
aws eks list-clusters &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  📊 Comparison: Ingress vs Gateway API
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Ingress&lt;/th&gt;
&lt;th&gt;Gateway API&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Role Separation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Single resource&lt;/td&gt;
&lt;td&gt;✅ GatewayClass, Gateway, HTTPRoute&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Portability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Vendor annotations&lt;/td&gt;
&lt;td&gt;✅ Standard API&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Expressiveness&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Basic path/host&lt;/td&gt;
&lt;td&gt;✅ Headers, query params, weights&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Protocol Support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ HTTP/HTTPS only&lt;/td&gt;
&lt;td&gt;✅ HTTP, HTTPS, TCP, UDP, gRPC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Traffic Splitting&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Limited&lt;/td&gt;
&lt;td&gt;✅ Native support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Request Modification&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Controller-specific&lt;/td&gt;
&lt;td&gt;✅ Standard filters&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Multi-tenancy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Difficult&lt;/td&gt;
&lt;td&gt;✅ Built-in with ReferenceGrant&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Status&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;⚠️ Deprecated (March 2026)&lt;/td&gt;
&lt;td&gt;✅ GA (v1.0.0)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🚀 Production Readiness Checklist
&lt;/h2&gt;

&lt;p&gt;Before going to production:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;[ ] &lt;strong&gt;High Availability&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Multiple Gateway replicas&lt;/li&gt;
&lt;li&gt;[ ] Multi-AZ deployment&lt;/li&gt;
&lt;li&gt;[ ] Pod disruption budgets&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;[ ] &lt;strong&gt;Security&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] TLS enabled on all listeners&lt;/li&gt;
&lt;li&gt;[ ] RBAC configured&lt;/li&gt;
&lt;li&gt;[ ] Network policies in place&lt;/li&gt;
&lt;li&gt;[ ] Secrets encrypted at rest&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;[ ] &lt;strong&gt;Monitoring&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Prometheus metrics scraped&lt;/li&gt;
&lt;li&gt;[ ] Alerts configured&lt;/li&gt;
&lt;li&gt;[ ] Dashboards created&lt;/li&gt;
&lt;li&gt;[ ] Logging aggregated&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;[ ] &lt;strong&gt;Performance&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Load testing completed&lt;/li&gt;
&lt;li&gt;[ ] Resource limits set&lt;/li&gt;
&lt;li&gt;[ ] Autoscaling configured&lt;/li&gt;
&lt;li&gt;[ ] Connection limits tuned&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;[ ] &lt;strong&gt;Disaster Recovery&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Backup strategy defined&lt;/li&gt;
&lt;li&gt;[ ] Restore procedure tested&lt;/li&gt;
&lt;li&gt;[ ] Runbooks documented&lt;/li&gt;
&lt;li&gt;[ ] On-call rotation established&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  📸 Screenshots
&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.amazonaws.com%2Fuploads%2Farticles%2Fepon3yypgq66121y94rc.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%2Fepon3yypgq66121y94rc.png" alt=" " width="800" height="428"&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%2F31cqbs6dypovr9w0hq7a.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%2F31cqbs6dypovr9w0hq7a.png" alt=" " width="800" height="113"&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%2Fhvplba3dzphyewe78gc2.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%2Fhvplba3dzphyewe78gc2.png" alt=" " width="800" height="436"&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%2Fb1aahwwh2crcgtiayg7i.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%2Fb1aahwwh2crcgtiayg7i.png" alt=" " width="800" height="208"&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%2F1w7i96yn8x1vl7tc9xoi.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%2F1w7i96yn8x1vl7tc9xoi.png" alt=" " width="800" height="186"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🎯 Conclusion
&lt;/h2&gt;

&lt;p&gt;Gateway API represents a significant evolution in Kubernetes networking:&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Better separation of concerns&lt;/strong&gt; between infrastructure, cluster admins, and developers&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Portable and consistent&lt;/strong&gt; across all cloud providers and on-premises&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;More expressive&lt;/strong&gt; with advanced routing capabilities&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Future-proof&lt;/strong&gt; as the official successor to Ingress  &lt;/p&gt;

&lt;p&gt;With Ingress NGINX being decommissioned in March 2026, now is the perfect time to migrate to Gateway API. Envoy Gateway provides a production-ready implementation that's easy to deploy and manage.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Takeaways
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Gateway API is not just a replacement&lt;/strong&gt; - it's a complete redesign with better architecture&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Role separation&lt;/strong&gt; makes it easier to manage in large organizations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Envoy Gateway&lt;/strong&gt; is a solid choice for AWS EKS deployments&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Migration from Ingress&lt;/strong&gt; is straightforward with proper planning&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Advanced features&lt;/strong&gt; like traffic splitting and header routing are built-in&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Next Steps
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Explore other Gateway controllers (Istio, Kong, Traefik)&lt;/li&gt;
&lt;li&gt;Implement advanced routing scenarios&lt;/li&gt;
&lt;li&gt;Add observability with Prometheus and Grafana&lt;/li&gt;
&lt;li&gt;Integrate with service mesh for mTLS&lt;/li&gt;
&lt;li&gt;Automate deployments with GitOps (ArgoCD, Flux)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://gateway-api.sigs.k8s.io/" rel="noopener noreferrer"&gt;Gateway API Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gateway.envoyproxy.io/" rel="noopener noreferrer"&gt;Envoy Gateway Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes-sigs.github.io/aws-load-balancer-controller/" rel="noopener noreferrer"&gt;AWS Load Balancer Controller&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/kubernetes/community/tree/master/sig-network" rel="noopener noreferrer"&gt;Kubernetes SIG Network&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Happy Learning&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Prithiviraj Rengarajan&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;DevOps Engineer&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>kubernetes</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Top 15 Container Security Best Practices</title>
      <dc:creator>Prithiviraj R</dc:creator>
      <pubDate>Sun, 25 Jan 2026 19:40:33 +0000</pubDate>
      <link>https://dev.to/prithiviraj_rengarajan/top-15-container-security-best-practices-75o</link>
      <guid>https://dev.to/prithiviraj_rengarajan/top-15-container-security-best-practices-75o</guid>
      <description>&lt;p&gt;*&lt;em&gt;AWS-Specific Implementation (EKS, ECR, ECS) *&lt;/em&gt;                             &lt;/p&gt;

&lt;h2&gt;
  
  
  1. Use Minimal Base Images (AWS)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  EKS / ECS
&lt;/h3&gt;

&lt;p&gt;Use minimal images when building containers deployed to EKS or ECS.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recommended&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Distroless&lt;/li&gt;
&lt;li&gt;Alpine&lt;/li&gt;
&lt;li&gt;AWS-provided minimal images (for Lambda container workloads)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why AWS cares&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Smaller images = faster pulls from ECR&lt;/li&gt;
&lt;li&gt;Reduced blast radius in shared nodes (EKS)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; public.ecr.aws/distroless/base-debian12&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; app /app&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["/app"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  2. Scan Images for Vulnerabilities (Amazon ECR)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Amazon ECR Enhanced Scanning
&lt;/h3&gt;

&lt;p&gt;Amazon ECR provides &lt;strong&gt;native vulnerability scanning&lt;/strong&gt; using Inspector.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enable scanning&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;aws ecr put-registry-scanning-configuration &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--scan-type&lt;/span&gt; ENHANCED &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--rules&lt;/span&gt; &lt;span class="s1"&gt;'[{"scanFrequency":"CONTINUOUS_SCAN"}]'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What you get&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CVE detection&lt;/li&gt;
&lt;li&gt;Severity ratings&lt;/li&gt;
&lt;li&gt;Integration with AWS Security Hub&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. Sign and Verify Images (EKS + ECR)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  AWS + Cosign
&lt;/h3&gt;

&lt;p&gt;Use &lt;strong&gt;Cosign&lt;/strong&gt; with ECR and enforce verification via Kubernetes admission controllers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sign image&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;cosign sign &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--key&lt;/span&gt; awskms:///alias/ecr-signing-key &lt;span class="se"&gt;\&lt;/span&gt;
  123456789012.dkr.ecr.us-east-1.amazonaws.com/app:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Verify in EKS&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use Kyverno or Gatekeeper to block unsigned images&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Benefit&lt;/strong&gt;&lt;br&gt;
Protects against &lt;strong&gt;supply chain attacks&lt;/strong&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  4. Run Containers as Non-Root (EKS &amp;amp; ECS)
&lt;/h2&gt;
&lt;h3&gt;
  
  
  EKS
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;securityContext&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;runAsNonRoot&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;runAsUser&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  ECS Task Definition
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1000"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;AWS impact&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prevents privilege escalation on worker nodes&lt;/li&gt;
&lt;li&gt;Aligns with Pod Security Standards (restricted)&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  5. Implement Resource Limits (EKS &amp;amp; ECS)
&lt;/h2&gt;
&lt;h3&gt;
  
  
  EKS
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&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;256Mi"&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;500m"&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;512Mi"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  ECS
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"cpu"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"memory"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Why this matters in AWS&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prevents noisy-neighbor issues&lt;/li&gt;
&lt;li&gt;Improves cluster stability&lt;/li&gt;
&lt;li&gt;Reduces autoscaling anomalies&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  6. Use Read-Only File Systems (EKS)
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;securityContext&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;readOnlyRootFilesystem&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;AWS Security Benefit&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stops malware persistence&lt;/li&gt;
&lt;li&gt;Blocks runtime tampering&lt;/li&gt;
&lt;li&gt;Reduces blast radius in shared EKS nodes&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  7. Never Store Secrets in Images (AWS Secrets Manager)
&lt;/h2&gt;
&lt;h3&gt;
  
  
  EKS
&lt;/h3&gt;

&lt;p&gt;Use &lt;strong&gt;Secrets Manager + IRSA&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;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;DB_PASSWORD&lt;/span&gt;
    &lt;span class="na"&gt;valueFrom&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;secretKeyRef&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;db-secret&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;password&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ECS
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"secrets"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DB_PASSWORD"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"valueFrom"&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:secretsmanager:..."&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;&lt;strong&gt;Why AWS recommends this&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Central rotation&lt;/li&gt;
&lt;li&gt;IAM-based access&lt;/li&gt;
&lt;li&gt;Audit logging via CloudTrail&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  8. Enable Runtime Security Profiles (EKS)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Seccomp Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;securityContext&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;seccompProfile&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;RuntimeDefault&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Advanced&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Combine with &lt;strong&gt;Falco on EKS&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Stream alerts to CloudWatch or SIEM&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  9. Use Multi-Stage Builds (ECR Optimization)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;AWS Advantage&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Faster ECR pulls&lt;/li&gt;
&lt;li&gt;Lower storage costs&lt;/li&gt;
&lt;li&gt;Fewer vulnerabilities detected
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;node:22&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;build&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm run build

&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; public.ecr.aws/distroless/nodejs22&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=build /app /app&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["app.js"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  10. Network Segmentation (EKS + VPC)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Kubernetes Network Policy
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;policyTypes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Ingress&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Egress&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  AWS Layer
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Security Groups for Pods (EKS)&lt;/li&gt;
&lt;li&gt;Private subnets&lt;/li&gt;
&lt;li&gt;VPC flow logs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Outcome&lt;/strong&gt;&lt;br&gt;
Prevents lateral movement inside the cluster.&lt;/p&gt;




&lt;h2&gt;
  
  
  11. Use Trusted Registries (ECR)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Best Practice
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Disable public registry pulls&lt;/li&gt;
&lt;li&gt;Allow only ECR&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;EKS Admission Policy&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Block images not from &lt;code&gt;*.amazonaws.com&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why&lt;/strong&gt;&lt;br&gt;
Public images are a &lt;strong&gt;major malware vector&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  12. Drop Linux Capabilities (EKS &amp;amp; ECS)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  EKS
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;capabilities&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;drop&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ALL&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ECS
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"linuxParameters"&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;"capabilities"&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;"drop"&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="s2"&gt;"ALL"&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;&lt;strong&gt;AWS Security Gain&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reduces kernel attack surface&lt;/li&gt;
&lt;li&gt;Limits container breakout attempts&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  13. Logging &amp;amp; Monitoring (AWS Native)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  EKS
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;CloudWatch Container Insights&lt;/li&gt;
&lt;li&gt;Fluent Bit&lt;/li&gt;
&lt;li&gt;Falco → CloudWatch Logs&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ECS
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;awslogs driver&lt;/li&gt;
&lt;li&gt;FireLens for advanced routing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Security Use Case&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Detect suspicious syscalls&lt;/li&gt;
&lt;li&gt;Audit container behavior&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  14. Image Lifecycle Management (ECR)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ECR Lifecycle Policy
&lt;/h3&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;"rules"&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;"rulePriority"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Expire untagged images after 30 days"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"selection"&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;"tagStatus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"untagged"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"countType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sinceImagePushed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"countUnit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"days"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"countNumber"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"expire"&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;&lt;strong&gt;Benefits&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reduces attack surface&lt;/li&gt;
&lt;li&gt;Controls storage cost&lt;/li&gt;
&lt;li&gt;Forces fresh rebuilds&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  15. Prevent Container Escape (EKS &amp;amp; ECS)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  EKS
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;No privileged pods&lt;/li&gt;
&lt;li&gt;No hostPath mounts&lt;/li&gt;
&lt;li&gt;Enforce &lt;strong&gt;Pod Security Admission (restricted)&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ECS
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"privileged"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;AWS Security Impact&lt;/strong&gt;&lt;br&gt;
Container escape = EC2 compromise&lt;br&gt;
These controls &lt;strong&gt;block the most dangerous attack vector&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  AWS Security Alignment
&lt;/h2&gt;

&lt;p&gt;These 15 practices directly map to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;AWS Well-Architected Framework – Security Pillar&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;EKS Best Practices Guide&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Zero Trust container principles&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CIS Kubernetes Benchmarks&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final AWS-Focused Takeaway
&lt;/h2&gt;

&lt;p&gt;If you are running containers on &lt;strong&gt;EKS, ECS, or ECR&lt;/strong&gt;, these controls are &lt;strong&gt;not optional hardening&lt;/strong&gt;—they are &lt;strong&gt;baseline production requirements&lt;/strong&gt;. When applied together, they significantly reduce:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Misconfiguration risk&lt;/li&gt;
&lt;li&gt;Supply chain attacks&lt;/li&gt;
&lt;li&gt;Runtime compromises&lt;/li&gt;
&lt;li&gt;Cloud security incidents&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Happy learning&lt;br&gt;
Prithiviraj Rengarajan&lt;br&gt;
DevOps Engineer&lt;/p&gt;

</description>
      <category>aws</category>
      <category>docker</category>
      <category>kubernetes</category>
      <category>security</category>
    </item>
    <item>
      <title>One small Docker decision can have an outsized impact on your AWS workloads.</title>
      <dc:creator>Prithiviraj R</dc:creator>
      <pubDate>Sun, 18 Jan 2026 00:25:32 +0000</pubDate>
      <link>https://dev.to/prithiviraj_rengarajan/one-small-docker-decision-can-have-an-outsized-impact-on-your-aws-workloads-5doj</link>
      <guid>https://dev.to/prithiviraj_rengarajan/one-small-docker-decision-can-have-an-outsized-impact-on-your-aws-workloads-5doj</guid>
      <description>&lt;p&gt;Most teams don’t realize how much their Node.js base image affects build time, storage costs, and runtime performance—until they compare them side by side.&lt;/p&gt;

&lt;p&gt;📦 node:22 → 1.12 GB&lt;br&gt;
📦 bitnami/node:22 → 974 MB&lt;/p&gt;

&lt;p&gt;Lean alternatives:&lt;br&gt;
📦 node:22-slim → 220 MB&lt;br&gt;
📦 node:22-alpine → 155 MB&lt;br&gt;
📦 Chainguard Node → 145 MB&lt;br&gt;
📦 Distroless Node → 141 MB&lt;/p&gt;

&lt;p&gt;That’s nearly 1 GB of overhead eliminated by a simple base image change.&lt;/p&gt;

&lt;p&gt;Why this matters on AWS:&lt;/p&gt;

&lt;p&gt;Faster CI/CD pipelines (CodeBuild, GitHub Actions, Jenkins)&lt;/p&gt;

&lt;p&gt;Lower ECR storage and data transfer costs&lt;/p&gt;

&lt;p&gt;Smaller attack surface → fewer CVEs to track&lt;/p&gt;

&lt;p&gt;Faster cold starts on EKS and ECS&lt;/p&gt;

&lt;p&gt;Better developer feedback loops&lt;/p&gt;

&lt;p&gt;The best part: you can unlock these improvements without touching application code—just choose the right base image.&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%2Fgbsry26sqrv70xsatiou.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%2Fgbsry26sqrv70xsatiou.png" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy learning&lt;br&gt;
Prithiviraj Rengarajan&lt;br&gt;
DevOps Engineer&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Building a Smart Inbox: AI-Powered Message Routing on AWS EKS</title>
      <dc:creator>Prithiviraj R</dc:creator>
      <pubDate>Sat, 17 Jan 2026 06:06:20 +0000</pubDate>
      <link>https://dev.to/prithiviraj_rengarajan/building-a-smart-inbox-ai-powered-message-routing-on-aws-eks-4g27</link>
      <guid>https://dev.to/prithiviraj_rengarajan/building-a-smart-inbox-ai-powered-message-routing-on-aws-eks-4g27</guid>
      <description>&lt;p&gt;Real-time sentiment analysis and intelligent message prioritization using Kubernetes, AWS Bedrock, and React&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In this comprehensive guide, I'll walk you through building a production-ready, AI-powered message routing system using AWS services. This project demonstrates how to leverage modern cloud-native technologies to create an intelligent application that automatically analyzes message sentiment and routes them accordingly.&lt;/p&gt;

&lt;p&gt;&lt;a href="/Users/prithivirajrengarajan/Documents/smart2.png" class="article-body-image-wrapper"&gt;&lt;img src="/Users/prithivirajrengarajan/Documents/smart2.png" alt="smart2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What We Built:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A sentiment analysis API using AWS Bedrock (Claude 3 Haiku)&lt;/li&gt;
&lt;li&gt;Kubernetes deployment on Amazon EKS&lt;/li&gt;
&lt;li&gt;React frontend with real-time updates&lt;/li&gt;
&lt;li&gt;Persistent storage with DynamoDB&lt;/li&gt;
&lt;li&gt;Container registry with Amazon ECR&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Tech Stack:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Backend:&lt;/strong&gt; Python, FastAPI&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI/ML:&lt;/strong&gt; AWS Bedrock (Claude 3 Haiku)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Container Orchestration:&lt;/strong&gt; Amazon EKS (Kubernetes)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database:&lt;/strong&gt; Amazon DynamoDB&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Container Registry:&lt;/strong&gt; Amazon ECR&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frontend:&lt;/strong&gt; React, Vite&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Infrastructure:&lt;/strong&gt; AWS (EKS, EC2, VPC, Load Balancer)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Architecture Overview&lt;/li&gt;
&lt;li&gt;Why These AWS Services?&lt;/li&gt;
&lt;li&gt;Setting Up Amazon EKS&lt;/li&gt;
&lt;li&gt;Building the Backend API&lt;/li&gt;
&lt;li&gt;Containerization with Docker&lt;/li&gt;
&lt;li&gt;Amazon ECR Setup&lt;/li&gt;
&lt;li&gt;DynamoDB Configuration&lt;/li&gt;
&lt;li&gt;Kubernetes Deployment&lt;/li&gt;
&lt;li&gt;Frontend Development&lt;/li&gt;
&lt;li&gt;Testing &amp;amp; Demo&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Architecture Overview
&lt;/h2&gt;

&lt;p&gt;Our Smart Inbox follows a modern microservices architecture:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────┐
│   Browser   │
│  (React UI) │
└──────┬──────┘
       │ HTTP
       ▼
┌─────────────────┐
│ Network Load    │
│   Balancer      │
└────────┬────────┘
         │
         ▼
┌─────────────────────────┐
│   Kubernetes Service    │
│   (smart-inbox-service) │
└────────┬────────────────┘
         │
    ┌────┴────┐
    ▼         ▼
┌────────┐ ┌────────┐
│ Pod 1  │ │ Pod 2  │  (2 replicas for HA)
│FastAPI │ │FastAPI │
└───┬────┘ └───┬────┘
    │          │
    └────┬─────┘
         ▼
    ┌─────────────┐
    │ AWS Bedrock │
    │  (Claude)   │
    └─────────────┘
         │
         ▼
    ┌─────────────┐
    │  DynamoDB   │
    │  (Storage)  │
    └─────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Data Flow:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;User submits message via React frontend&lt;/li&gt;
&lt;li&gt;Request hits Network Load Balancer&lt;/li&gt;
&lt;li&gt;Load Balancer routes to one of the Kubernetes pods&lt;/li&gt;
&lt;li&gt;FastAPI application processes the request&lt;/li&gt;
&lt;li&gt;AWS Bedrock analyzes sentiment using Claude AI&lt;/li&gt;
&lt;li&gt;Results stored in DynamoDB&lt;/li&gt;
&lt;li&gt;Response sent back to frontend&lt;/li&gt;
&lt;li&gt;Dashboard updates in real-time&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Why These AWS Services?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Amazon EKS (Elastic Kubernetes Service)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What is it?&lt;/strong&gt;&lt;br&gt;
Amazon EKS is a managed Kubernetes service that makes it easy to run Kubernetes on AWS without needing to install and operate your own Kubernetes control plane.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why we chose it:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Managed Control Plane:&lt;/strong&gt; AWS handles Kubernetes master nodes, updates, and patches&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;High Availability:&lt;/strong&gt; Multi-AZ deployment by default&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Scalability:&lt;/strong&gt; Auto-scaling for both pods and nodes&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Security:&lt;/strong&gt; Integrated with AWS IAM for authentication&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Production-Ready:&lt;/strong&gt; Used by thousands of companies worldwide&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Cost-Effective:&lt;/strong&gt; Pay only for worker nodes, control plane is managed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Our Use Case:&lt;/strong&gt;&lt;br&gt;
We use EKS to orchestrate our containerized FastAPI application, ensuring high availability with 2 pod replicas and automatic failover.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Concepts:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cluster:&lt;/strong&gt; The Kubernetes control plane and worker nodes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nodes:&lt;/strong&gt; EC2 instances that run your containers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pods:&lt;/strong&gt; Smallest deployable units containing one or more containers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Service:&lt;/strong&gt; Exposes pods to network traffic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployment:&lt;/strong&gt; Manages pod replicas and updates&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  2. Amazon EC2 (Worker Nodes)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What is it?&lt;/strong&gt;&lt;br&gt;
EC2 instances serve as worker nodes in our EKS cluster, running the actual containerized applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why we chose it:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Flexibility:&lt;/strong&gt; Choose instance types based on workload&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Performance:&lt;/strong&gt; Dedicated compute resources&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Control:&lt;/strong&gt; Full control over node configuration&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Cost Options:&lt;/strong&gt; On-demand, Reserved, or Spot instances&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Our Configuration:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Instance Type:&lt;/strong&gt; t3.medium (2 vCPU, 4GB RAM)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Count:&lt;/strong&gt; 2 nodes for high availability&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auto-scaling:&lt;/strong&gt; Min 2, Max 4, Desired 2&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why t3.medium?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Balanced compute and memory for our API workload&lt;/li&gt;
&lt;li&gt;Burstable performance for handling traffic spikes&lt;/li&gt;
&lt;li&gt;Cost-effective for development and small production workloads&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  3. Amazon DynamoDB
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What is it?&lt;/strong&gt;&lt;br&gt;
DynamoDB is a fully managed NoSQL database service that provides fast and predictable performance with seamless scalability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why we chose it:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Serverless:&lt;/strong&gt; No servers to manage&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Performance:&lt;/strong&gt; Single-digit millisecond latency&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Scalability:&lt;/strong&gt; Automatically scales up/down&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Pay-per-request:&lt;/strong&gt; Only pay for what you use&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;High Availability:&lt;/strong&gt; Multi-AZ replication by default&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;No Schema:&lt;/strong&gt; Flexible data model&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Our Use Case:&lt;/strong&gt;&lt;br&gt;
We store analyzed messages with their sentiment scores, timestamps, and metadata.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Table Schema:&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;Primary Key: message_id (String)

Attributes:
- message_id: Unique identifier
- text: Original message content
- sender: Email of sender
- category: Message category (general, support, feedback, complaint)
- sentiment: AI-detected sentiment (positive, negative, neutral)
- confidence: Confidence score (0.0 - 1.0)
- timestamp: When message was analyzed
- priority: Routing priority (NORMAL, HIGH)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why NoSQL over SQL?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No complex relationships needed&lt;/li&gt;
&lt;li&gt;Flexible schema for future attributes&lt;/li&gt;
&lt;li&gt;Better performance for simple key-value lookups&lt;/li&gt;
&lt;li&gt;Easier to scale horizontally&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  4. Amazon ECR (Elastic Container Registry)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What is it?&lt;/strong&gt;&lt;br&gt;
ECR is a fully managed Docker container registry that makes it easy to store, manage, and deploy Docker container images.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why we chose it:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Integration:&lt;/strong&gt; Native integration with EKS&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Security:&lt;/strong&gt; Images encrypted at rest and in transit&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Scanning:&lt;/strong&gt; Automatic vulnerability scanning&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;IAM Integration:&lt;/strong&gt; Fine-grained access control&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;High Availability:&lt;/strong&gt; Replicated across multiple AZs&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;No Limits:&lt;/strong&gt; Unlimited repositories and images&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Our Use Case:&lt;/strong&gt;&lt;br&gt;
We store our FastAPI application Docker image, which EKS pulls to run in pods.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Image Details:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Repository:&lt;/strong&gt; smart-inbox&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Base Image:&lt;/strong&gt; python:3.11-slim&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Size:&lt;/strong&gt; ~200MB&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Platform:&lt;/strong&gt; linux/amd64 (for EC2 compatibility)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why ECR over Docker Hub?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Faster pulls from within AWS&lt;/li&gt;
&lt;li&gt;Better security with IAM&lt;/li&gt;
&lt;li&gt;No rate limiting&lt;/li&gt;
&lt;li&gt;Integrated with AWS services&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  5. AWS Bedrock (Claude 3 Haiku)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What is it?&lt;/strong&gt;&lt;br&gt;
AWS Bedrock is a fully managed service that offers foundation models from leading AI companies through a single API.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why we chose it:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Managed Service:&lt;/strong&gt; No infrastructure to manage&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Multiple Models:&lt;/strong&gt; Access to Claude, Llama, Titan, etc.&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Pay-per-use:&lt;/strong&gt; Only pay for API calls&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Low Latency:&lt;/strong&gt; Fast inference times&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Security:&lt;/strong&gt; Data not used for training&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Compliance:&lt;/strong&gt; SOC, HIPAA, GDPR compliant&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why Claude 3 Haiku?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fast:&lt;/strong&gt; Optimized for speed (sub-second responses)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost-Effective:&lt;/strong&gt; $0.25 per 1K input tokens&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accurate:&lt;/strong&gt; High accuracy for sentiment analysis&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Context:&lt;/strong&gt; 200K token context window&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reliable:&lt;/strong&gt; Consistent output format&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Our Prompt:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Analyze the sentiment of this message. Return ONLY valid JSON.

Message: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;

Respond with this exact format:
{{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sentiment&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;positive&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;confidence&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;: 0.95}}

Sentiment must be: positive, neutral, or negative
Confidence must be: 0.0 to 1.0&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Alternative Approaches:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS Comprehend (simpler but less flexible)&lt;/li&gt;
&lt;li&gt;SageMaker (more control but more complex)&lt;/li&gt;
&lt;li&gt;Third-party APIs (vendor lock-in concerns)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Setting Up Amazon EKS
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Create IAM Role for EKS Cluster
&lt;/h3&gt;

&lt;p&gt;EKS needs permissions to manage AWS resources on your behalf.&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;# Create trust policy&lt;/span&gt;
aws iam create-role &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--role-name&lt;/span&gt; smart-inbox-eks-cluster-role &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--assume-role-policy-document&lt;/span&gt; &lt;span class="s1"&gt;'{
    "Version": "2012-10-17",
    "Statement": [{
      "Effect": "Allow",
      "Principal": {"Service": "eks.amazonaws.com"},
      "Action": "sts:AssumeRole"
    }]
  }'&lt;/span&gt;

&lt;span class="c"&gt;# Attach required policy&lt;/span&gt;
aws iam attach-role-policy &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--role-name&lt;/span&gt; smart-inbox-eks-cluster-role &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--policy-arn&lt;/span&gt; arn:aws:iam::aws:policy/AmazonEKSClusterPolicy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What this does:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creates an IAM role that EKS can assume&lt;/li&gt;
&lt;li&gt;Grants permissions to manage networking, load balancers, and EC2 instances&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 2: Create EKS Cluster
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws eks create-cluster &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; smart-inbox-cluster &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;--role-arn&lt;/span&gt; arn:aws:iam::&amp;lt;ACCOUNT_ID&amp;gt;:role/smart-inbox-eks-cluster-role &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--resources-vpc-config&lt;/span&gt; &lt;span class="nv"&gt;subnetIds&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;SUBNET_1&amp;gt;,&amp;lt;SUBNET_2&amp;gt;,&amp;lt;SUBNET_3&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--kubernetes-version&lt;/span&gt; 1.31
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Parameters Explained:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--name&lt;/code&gt;: Cluster identifier&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--region&lt;/code&gt;: AWS region (us-east-1 for lowest latency to Bedrock)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--role-arn&lt;/code&gt;: IAM role created in Step 1&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--resources-vpc-config&lt;/code&gt;: Network configuration

&lt;ul&gt;
&lt;li&gt;Requires at least 2 subnets in different AZs&lt;/li&gt;
&lt;li&gt;Subnets must have internet gateway for public access&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;--kubernetes-version&lt;/code&gt;: Latest stable version&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What happens:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;AWS provisions Kubernetes control plane (2-3 master nodes)&lt;/li&gt;
&lt;li&gt;Sets up etcd database for cluster state&lt;/li&gt;
&lt;li&gt;Configures API server, scheduler, and controller manager&lt;/li&gt;
&lt;li&gt;Takes 10-15 minutes to complete&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Verification:&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;aws eks describe-cluster &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; smart-inbox-cluster &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;--query&lt;/span&gt; &lt;span class="s1"&gt;'cluster.status'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected output: &lt;code&gt;"ACTIVE"&lt;/code&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 3: Create Node Group
&lt;/h3&gt;

&lt;p&gt;Worker nodes run your actual application containers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create IAM Role for Nodes:&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;&lt;span class="c"&gt;# Create role&lt;/span&gt;
aws iam create-role &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--role-name&lt;/span&gt; smart-inbox-eks-node-role &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--assume-role-policy-document&lt;/span&gt; &lt;span class="s1"&gt;'{
    "Version": "2012-10-17",
    "Statement": [{
      "Effect": "Allow",
      "Principal": {"Service": "ec2.amazonaws.com"},
      "Action": "sts:AssumeRole"
    }]
  }'&lt;/span&gt;

&lt;span class="c"&gt;# Attach required policies&lt;/span&gt;
aws iam attach-role-policy &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--role-name&lt;/span&gt; smart-inbox-eks-node-role &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--policy-arn&lt;/span&gt; arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy

aws iam attach-role-policy &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--role-name&lt;/span&gt; smart-inbox-eks-node-role &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--policy-arn&lt;/span&gt; arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy

aws iam attach-role-policy &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--role-name&lt;/span&gt; smart-inbox-eks-node-role &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--policy-arn&lt;/span&gt; arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Create Node Group:&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;aws eks create-nodegroup &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cluster-name&lt;/span&gt; smart-inbox-cluster &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--nodegroup-name&lt;/span&gt; smart-inbox-nodes &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;--subnets&lt;/span&gt; &amp;lt;SUBNET_1&amp;gt; &amp;lt;SUBNET_2&amp;gt; &amp;lt;SUBNET_3&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--node-role&lt;/span&gt; arn:aws:iam::&amp;lt;ACCOUNT_ID&amp;gt;:role/smart-inbox-eks-node-role &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--scaling-config&lt;/span&gt; &lt;span class="nv"&gt;minSize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2,maxSize&lt;span class="o"&gt;=&lt;/span&gt;4,desiredSize&lt;span class="o"&gt;=&lt;/span&gt;2 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--instance-types&lt;/span&gt; t3.medium &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--disk-size&lt;/span&gt; 20
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Configuration Explained:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;minSize=2&lt;/code&gt;: Minimum nodes for high availability&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;maxSize=4&lt;/code&gt;: Maximum nodes for scaling&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;desiredSize=2&lt;/code&gt;: Initial node count&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;instance-types=t3.medium&lt;/code&gt;: 2 vCPU, 4GB RAM&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;disk-size=20&lt;/code&gt;: 20GB EBS volume per node&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What happens:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;AWS launches EC2 instances in your subnets&lt;/li&gt;
&lt;li&gt;Installs kubelet, kube-proxy, and container runtime&lt;/li&gt;
&lt;li&gt;Joins nodes to the EKS cluster&lt;/li&gt;
&lt;li&gt;Takes 5-10 minutes&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Step 4: Configure kubectl
&lt;/h3&gt;

&lt;p&gt;Connect your local kubectl to the EKS cluster:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws eks update-kubeconfig &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; smart-inbox-cluster &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Verify connection:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Expected output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NAME                          STATUS   ROLES    AGE   VERSION
ip-172-31-x-x.ec2.internal    Ready    &amp;lt;none&amp;gt;   5m    v1.31.0
ip-172-31-y-y.ec2.internal    Ready    &amp;lt;none&amp;gt;   5m    v1.31.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Building the Backend API
&lt;/h2&gt;

&lt;p&gt;Our backend is a FastAPI application that handles sentiment analysis requests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Project Structure
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;backend/
├── app/
│   ├── main.py          # FastAPI application
│   ├── sentiment.py     # Bedrock integration
│   ├── models.py        # Pydantic models
│   ├── database.py      # DynamoDB operations
│   └── requirements.txt # Python dependencies
└── Dockerfile           # Container definition
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Core Components
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. FastAPI Application (main.py)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;FastAPI is a modern, fast web framework for building APIs with Python.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why FastAPI?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Fast performance (comparable to Node.js)&lt;/li&gt;
&lt;li&gt;✅ Automatic API documentation (Swagger UI)&lt;/li&gt;
&lt;li&gt;✅ Type hints and validation&lt;/li&gt;
&lt;li&gt;✅ Async support&lt;/li&gt;
&lt;li&gt;✅ Easy to learn and use&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Key Endpoints:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;POST /api/analyze&lt;/code&gt; - Analyze message sentiment&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GET /api/messages&lt;/code&gt; - Retrieve recent messages&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GET /api/stats&lt;/code&gt; - Get sentiment statistics&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GET /health&lt;/code&gt; - Health check for load balancer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Bedrock Integration (sentiment.py)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Handles communication with AWS Bedrock API.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Features:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Structured prompts for consistent output&lt;/li&gt;
&lt;li&gt;JSON parsing with error handling&lt;/li&gt;
&lt;li&gt;Fallback to neutral sentiment on errors&lt;/li&gt;
&lt;li&gt;Regex extraction for robust JSON parsing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Data Models (models.py)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Pydantic models ensure data validation.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Automatic request validation&lt;/li&gt;
&lt;li&gt;Type safety&lt;/li&gt;
&lt;li&gt;Clear API contracts&lt;/li&gt;
&lt;li&gt;Automatic documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. Database Layer (database.py)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Abstracts DynamoDB operations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Functions:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;save_message()&lt;/code&gt; - Store analyzed message&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;get_recent_messages()&lt;/code&gt; - Retrieve messages&lt;/li&gt;
&lt;li&gt;Decimal conversion for DynamoDB compatibility&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Part 2: Containerization, Deployment &amp;amp; Frontend
&lt;/h2&gt;




&lt;h2&gt;
  
  
  Containerization with Docker
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Why Docker?
&lt;/h3&gt;

&lt;p&gt;Docker containers package your application with all its dependencies, ensuring it runs consistently across different environments.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Consistency:&lt;/strong&gt; "Works on my machine" → "Works everywhere"&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Isolation:&lt;/strong&gt; Each container is isolated&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Portability:&lt;/strong&gt; Run anywhere Docker runs&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Efficiency:&lt;/strong&gt; Lightweight compared to VMs&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Scalability:&lt;/strong&gt; Easy to replicate&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Our Dockerfile
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python:3.11-slim&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; app/requirements.txt .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--no-cache-dir&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; app/ .&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 8000&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Line-by-Line Explanation:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;FROM python:3.11-slim&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Base image: Python 3.11 on Debian&lt;/li&gt;
&lt;li&gt;"slim" variant: Smaller size (~150MB vs ~900MB)&lt;/li&gt;
&lt;li&gt;Official Python image from Docker Hub&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;WORKDIR /app&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sets working directory inside container&lt;/li&gt;
&lt;li&gt;All subsequent commands run from /app&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;COPY app/requirements.txt .&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Copy dependencies file first&lt;/li&gt;
&lt;li&gt;Enables Docker layer caching&lt;/li&gt;
&lt;li&gt;Rebuilds only if requirements change&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;RUN pip install --no-cache-dir -r requirements.txt&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install Python packages&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--no-cache-dir&lt;/code&gt;: Reduces image size&lt;/li&gt;
&lt;li&gt;Runs during build, not runtime&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;COPY app/ .&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Copy application code&lt;/li&gt;
&lt;li&gt;Done after pip install for better caching&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;EXPOSE 8000&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Documents which port the app uses&lt;/li&gt;
&lt;li&gt;Doesn't actually publish the port&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Command to run when container starts&lt;/li&gt;
&lt;li&gt;Uvicorn: ASGI server for FastAPI&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--host 0.0.0.0&lt;/code&gt;: Listen on all interfaces&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--port 8000&lt;/code&gt;: Application port&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Building for Production
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Multi-platform build&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker buildx build &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--platform&lt;/span&gt; linux/amd64 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-t&lt;/span&gt; smart-inbox:latest &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What this does:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;buildx&lt;/code&gt;: Docker's build extension&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--platform linux/amd64&lt;/code&gt;: Target architecture&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-t smart-inbox:latest&lt;/code&gt;: Tag the image&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.&lt;/code&gt;: Build context (current directory)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Image Size Optimization:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Base image: python:3.11-slim (150MB)&lt;/li&gt;
&lt;li&gt;Dependencies: ~50MB&lt;/li&gt;
&lt;li&gt;Application code: &amp;lt;1MB&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Total:&lt;/strong&gt; ~200MB&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best Practices Applied:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Use slim base images&lt;/li&gt;
&lt;li&gt;✅ Multi-stage builds (if needed)&lt;/li&gt;
&lt;li&gt;✅ Layer caching optimization&lt;/li&gt;
&lt;li&gt;✅ .dockerignore file&lt;/li&gt;
&lt;li&gt;✅ Non-root user (production)&lt;/li&gt;
&lt;li&gt;✅ Health checks&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Amazon ECR Setup
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Creating the Repository
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ecr create-repository &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--repository-name&lt;/span&gt; smart-inbox &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;--image-scanning-configuration&lt;/span&gt; &lt;span class="nv"&gt;scanOnPush&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Features Enabled:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;scanOnPush=true&lt;/code&gt;: Automatic vulnerability scanning&lt;/li&gt;
&lt;li&gt;Encryption at rest (AES-256)&lt;/li&gt;
&lt;li&gt;Encryption in transit (TLS)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pushing Images to ECR
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Authenticate Docker to ECR&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;aws ecr get-login-password &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1 | &lt;span class="se"&gt;\&lt;/span&gt;
  docker login &lt;span class="nt"&gt;--username&lt;/span&gt; AWS &lt;span class="nt"&gt;--password-stdin&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &amp;lt;ACCOUNT_ID&amp;gt;.dkr.ecr.us-east-1.amazonaws.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2: Tag Image&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;docker tag smart-inbox:latest &lt;span class="se"&gt;\&lt;/span&gt;
  &amp;lt;ACCOUNT_ID&amp;gt;.dkr.ecr.us-east-1.amazonaws.com/smart-inbox:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3: Push Image&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;docker push &lt;span class="se"&gt;\&lt;/span&gt;
  &amp;lt;ACCOUNT_ID&amp;gt;.dkr.ecr.us-east-1.amazonaws.com/smart-inbox:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What happens:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Docker compresses image layers&lt;/li&gt;
&lt;li&gt;Uploads to ECR&lt;/li&gt;
&lt;li&gt;ECR scans for vulnerabilities&lt;/li&gt;
&lt;li&gt;Image available for EKS to pull&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Image URI Format:&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;&amp;lt;account-id&amp;gt;.dkr.ecr.&amp;lt;region&amp;gt;.amazonaws.com/&amp;lt;repository&amp;gt;:&amp;lt;tag&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  DynamoDB Configuration
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Creating the Table
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws dynamodb create-table &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--table-name&lt;/span&gt; smart-inbox-messages &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--attribute-definitions&lt;/span&gt; &lt;span class="nv"&gt;AttributeName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;message_id,AttributeType&lt;span class="o"&gt;=&lt;/span&gt;S &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--key-schema&lt;/span&gt; &lt;span class="nv"&gt;AttributeName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;message_id,KeyType&lt;span class="o"&gt;=&lt;/span&gt;HASH &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--billing-mode&lt;/span&gt; PAY_PER_REQUEST &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Configuration Explained:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Attribute Definitions:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;message_id&lt;/code&gt;: String type (S)&lt;/li&gt;
&lt;li&gt;Only key attributes need to be defined&lt;/li&gt;
&lt;li&gt;Other attributes are schema-less&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Key Schema:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;HASH&lt;/code&gt;: Partition key (required)&lt;/li&gt;
&lt;li&gt;No sort key (RANGE) needed for our use case&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Billing Mode:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;PAY_PER_REQUEST&lt;/code&gt;: On-demand pricing&lt;/li&gt;
&lt;li&gt;Alternative: &lt;code&gt;PROVISIONED&lt;/code&gt; (fixed capacity)&lt;/li&gt;
&lt;li&gt;Better for unpredictable workloads&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Data Model Design
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Item Structure:&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;"message_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"uuid-string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Message content"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"sender"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"email@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"category"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"general"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"sentiment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"positive"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.95&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-01-17T10:00:00Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"priority"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"NORMAL"&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;&lt;strong&gt;Design Decisions:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;UUID as Partition Key&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensures even distribution across partitions&lt;/li&gt;
&lt;li&gt;Prevents hot partitions&lt;/li&gt;
&lt;li&gt;Globally unique&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;No Sort Key&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple access pattern (get by ID)&lt;/li&gt;
&lt;li&gt;Scan for recent messages (acceptable for low volume)&lt;/li&gt;
&lt;li&gt;Could add timestamp as sort key for better queries&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Denormalized Data&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All data in one item&lt;/li&gt;
&lt;li&gt;No joins needed&lt;/li&gt;
&lt;li&gt;Optimized for read performance&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Handling Floats:&lt;/strong&gt;&lt;br&gt;
DynamoDB doesn't support float types natively.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;decimal&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;

&lt;span class="c1"&gt;# Before saving
&lt;/span&gt;&lt;span class="n"&gt;message_data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;confidence&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;confidence&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;# After reading
&lt;/span&gt;&lt;span class="n"&gt;confidence&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;confidence&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Kubernetes Deployment
&lt;/h2&gt;

&lt;h3&gt;
  
  
  IAM Roles for Service Accounts (IRSA)
&lt;/h3&gt;

&lt;p&gt;Pods need AWS permissions to access Bedrock and DynamoDB.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why IRSA?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ No hardcoded credentials&lt;/li&gt;
&lt;li&gt;✅ Automatic credential rotation&lt;/li&gt;
&lt;li&gt;✅ Fine-grained permissions per pod&lt;/li&gt;
&lt;li&gt;✅ Follows AWS best practices&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Setup Steps:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Get OIDC Provider ID&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;aws eks describe-cluster &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; smart-inbox-cluster &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'cluster.identity.oidc.issuer'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; text
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Create 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="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::&amp;lt;ACCOUNT_ID&amp;gt;:oidc-provider/oidc.eks.us-east-1.amazonaws.com/id/&amp;lt;OIDC_ID&amp;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;"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;"oidc.eks.us-east-1.amazonaws.com/id/&amp;lt;OIDC_ID&amp;gt;: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;"system:serviceaccount:smart-inbox:smart-inbox-sa"&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;&lt;strong&gt;3. Create IAM Role&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;aws iam create-role &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--role-name&lt;/span&gt; smart-inbox-pod-role &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--assume-role-policy-document&lt;/span&gt; file://trust-policy.json

aws iam attach-role-policy &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--role-name&lt;/span&gt; smart-inbox-pod-role &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--policy-arn&lt;/span&gt; arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess

aws iam attach-role-policy &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--role-name&lt;/span&gt; smart-inbox-pod-role &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--policy-arn&lt;/span&gt; arn:aws:iam::aws:policy/AmazonBedrockFullAccess
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Kubernetes Manifests
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Namespace (namespace.yaml)&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;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;Namespace&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;smart-inbox&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why namespaces?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Logical isolation&lt;/li&gt;
&lt;li&gt;Resource quotas&lt;/li&gt;
&lt;li&gt;Access control&lt;/li&gt;
&lt;li&gt;Organization&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Service Account (serviceaccount.yaml)&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;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;ServiceAccount&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;smart-inbox-sa&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;smart-inbox&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;eks.amazonaws.com/role-arn&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;arn:aws:iam::&amp;lt;ACCOUNT_ID&amp;gt;:role/smart-inbox-pod-role&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key annotation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Links Kubernetes SA to AWS IAM role&lt;/li&gt;
&lt;li&gt;Enables IRSA&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Deployment (deployment.yaml)&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;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;smart-inbox-api&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;smart-inbox&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;smart-inbox&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;smart-inbox&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;serviceAccountName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;smart-inbox-sa&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;api&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;&amp;lt;ACCOUNT_ID&amp;gt;.dkr.ecr.us-east-1.amazonaws.com/smart-inbox:latest&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;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8000&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;DYNAMODB_TABLE&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;smart-inbox-messages&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;AWS_DEFAULT_REGION&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;us-east-1&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;256Mi"&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;512Mi"&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;span class="na"&gt;livenessProbe&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;httpGet&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/health&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;8000&lt;/span&gt;
          &lt;span class="na"&gt;initialDelaySeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;
          &lt;span class="na"&gt;periodSeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
        &lt;span class="na"&gt;readinessProbe&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;httpGet&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/health&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;8000&lt;/span&gt;
          &lt;span class="na"&gt;initialDelaySeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
          &lt;span class="na"&gt;periodSeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Configuration Explained:&lt;/strong&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;replicas: 2&lt;/code&gt;: Two pod instances&lt;/li&gt;
&lt;li&gt;High availability&lt;/li&gt;
&lt;li&gt;Load distribution&lt;/li&gt;
&lt;li&gt;Zero-downtime updates&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;requests&lt;/code&gt;: Guaranteed resources&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;limits&lt;/code&gt;: Maximum resources&lt;/li&gt;
&lt;li&gt;Prevents resource starvation&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;livenessProbe&lt;/code&gt;: Restart if unhealthy&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;readinessProbe&lt;/code&gt;: Remove from service if not ready&lt;/li&gt;
&lt;li&gt;Ensures traffic only to healthy pods&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. Service (service.yaml)&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;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;smart-inbox-service&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;smart-inbox&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;service.beta.kubernetes.io/aws-load-balancer-type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;nlb"&lt;/span&gt;
    &lt;span class="na"&gt;service.beta.kubernetes.io/aws-load-balancer-scheme&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;internet-facing"&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;smart-inbox&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;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http&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;8000&lt;/span&gt;
    &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Service Types:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ClusterIP&lt;/code&gt;: Internal only (default)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NodePort&lt;/code&gt;: Exposes on node IP&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;LoadBalancer&lt;/code&gt;: Creates AWS NLB (our choice)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why Network Load Balancer?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Layer 4 (TCP) load balancing&lt;/li&gt;
&lt;li&gt;✅ Ultra-low latency&lt;/li&gt;
&lt;li&gt;✅ Handles millions of requests/sec&lt;/li&gt;
&lt;li&gt;✅ Static IP addresses&lt;/li&gt;
&lt;li&gt;✅ TLS termination support&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Port Mapping:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;port: 80&lt;/code&gt;: External port (HTTP)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;targetPort: 8000&lt;/code&gt;: Container port&lt;/li&gt;
&lt;li&gt;Traffic: 80 → 8000&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Deploying to Kubernetes
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Apply manifests&lt;/span&gt;
kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; kubernetes/namespace.yaml
kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; kubernetes/serviceaccount.yaml
kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; kubernetes/deployment.yaml
kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; kubernetes/service.yaml

&lt;span class="c"&gt;# Verify deployment&lt;/span&gt;
kubectl get pods &lt;span class="nt"&gt;-n&lt;/span&gt; smart-inbox
kubectl get svc &lt;span class="nt"&gt;-n&lt;/span&gt; smart-inbox

&lt;span class="c"&gt;# Check logs&lt;/span&gt;
kubectl logs &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;smart-inbox &lt;span class="nt"&gt;-n&lt;/span&gt; smart-inbox
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Deployment Process:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Kubernetes pulls image from ECR&lt;/li&gt;
&lt;li&gt;Creates 2 pod replicas&lt;/li&gt;
&lt;li&gt;Assigns IAM role via IRSA&lt;/li&gt;
&lt;li&gt;Runs health checks&lt;/li&gt;
&lt;li&gt;Provisions Network Load Balancer&lt;/li&gt;
&lt;li&gt;Routes traffic to healthy pods&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Load Balancer Provisioning:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Takes 2-3 minutes&lt;/li&gt;
&lt;li&gt;Creates in multiple AZs&lt;/li&gt;
&lt;li&gt;Assigns DNS name&lt;/li&gt;
&lt;li&gt;Configures health checks&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Frontend Development
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Technology Stack
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;React + Vite&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why React?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Component-based architecture&lt;/li&gt;
&lt;li&gt;✅ Virtual DOM for performance&lt;/li&gt;
&lt;li&gt;✅ Large ecosystem&lt;/li&gt;
&lt;li&gt;✅ Easy to learn&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why Vite?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Lightning-fast HMR (Hot Module Replacement)&lt;/li&gt;
&lt;li&gt;✅ Optimized builds&lt;/li&gt;
&lt;li&gt;✅ Modern tooling&lt;/li&gt;
&lt;li&gt;✅ Better DX than Create React App&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Project Structure
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;frontend/
├── src/
│   ├── App.jsx              # Main component
│   ├── App.css              # Styles
│   ├── components/
│   │   ├── MessageForm.jsx  # Message submission
│   │   ├── Dashboard.jsx    # Messages list
│   │   └── SentimentCard.jsx # Individual message
│   └── api/
│       └── client.js        # API calls
├── index.html
├── package.json
└── vite.config.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Key Features
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Real-Time Statistics&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;stats&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setStats&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;positive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;negative&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;neutral&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;interval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Poll every 5s&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;clearInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;)&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;&lt;strong&gt;Auto-refresh every 5 seconds:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Polls &lt;code&gt;/api/stats&lt;/code&gt; endpoint&lt;/li&gt;
&lt;li&gt;Updates dashboard without page reload&lt;/li&gt;
&lt;li&gt;Clean up on component unmount&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Message Submission&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;messageData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;analyzeMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;messageData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Refresh messages&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error analyzing message&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&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;&lt;strong&gt;User experience:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Loading state during analysis&lt;/li&gt;
&lt;li&gt;Error handling with user feedback&lt;/li&gt;
&lt;li&gt;Automatic refresh after submission&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Color-Coded Sentiment Cards&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sentimentColors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;positive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bg-green-100 border-green-500&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;negative&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bg-red-100 border-red-500&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;neutral&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bg-gray-100 border-gray-500&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Visual feedback:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🟢 Green: Positive messages&lt;/li&gt;
&lt;li&gt;🔴 Red: Negative messages (with URGENT badge)&lt;/li&gt;
&lt;li&gt;⚪ Gray: Neutral messages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. API Client&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;API_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&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;VITE_API_URL&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;baseURL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;API_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;analyzeMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/analyze&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Environment variables:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Development: &lt;code&gt;http://localhost:8000&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Production: Load Balancer URL&lt;/li&gt;
&lt;li&gt;Configured in &lt;code&gt;.env&lt;/code&gt; file&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Styling Approach
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;CSS-in-JS vs CSS Modules vs Plain CSS&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We chose &lt;strong&gt;Plain CSS&lt;/strong&gt; for simplicity:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ No build complexity&lt;/li&gt;
&lt;li&gt;✅ Easy to understand&lt;/li&gt;
&lt;li&gt;✅ Good performance&lt;/li&gt;
&lt;li&gt;✅ Sufficient for our needs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Design System:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Purple gradient header&lt;/li&gt;
&lt;li&gt;Card-based layout&lt;/li&gt;
&lt;li&gt;Responsive grid&lt;/li&gt;
&lt;li&gt;Smooth transitions&lt;/li&gt;
&lt;li&gt;Mobile-friendly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Building a Smart Inbox: AI-Powered Message Routing on AWS EKS&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 3: Testing &amp;amp; Deployment
&lt;/h2&gt;




&lt;h2&gt;
  
  
  Testing &amp;amp; Demo
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Testing Strategy
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Unit Testing (Backend)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Test sentiment analysis
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_analyze_sentiment&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;analyze_sentiment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;I love this!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sentiment&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;positive&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;confidence&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.7&lt;/span&gt;

&lt;span class="c1"&gt;# Test database operations
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_save_message&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;message_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;test-123&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Test message&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sentiment&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;positive&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;save_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# Verify in DynamoDB
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Integration Testing&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;&lt;span class="c"&gt;# Test API endpoints&lt;/span&gt;
curl http://&amp;lt;API_URL&amp;gt;/health
&lt;span class="c"&gt;# Expected: {"status":"healthy"}&lt;/span&gt;

curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://&amp;lt;API_URL&amp;gt;/api/analyze &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"text":"Great product!","sender":"test@test.com","category":"feedback"}'&lt;/span&gt;
&lt;span class="c"&gt;# Expected: Full analysis response with sentiment&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Load Testing&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;&lt;span class="c"&gt;# Using Apache Bench&lt;/span&gt;
ab &lt;span class="nt"&gt;-n&lt;/span&gt; 1000 &lt;span class="nt"&gt;-c&lt;/span&gt; 10 http://&amp;lt;API_URL&amp;gt;/health

&lt;span class="c"&gt;# Using k6&lt;/span&gt;
k6 run &lt;span class="nt"&gt;--vus&lt;/span&gt; 10 &lt;span class="nt"&gt;--duration&lt;/span&gt; 30s load-test.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Demo Scenarios
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Scenario 1: Positive Customer Feedback&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;Message: "I absolutely love this product! The quality is amazing and 
         delivery was super fast. Your customer service team was 
         incredibly helpful. Thank you so much!"
Sender: happy.customer@example.com
Category: Feedback

Expected Result:
✅ Sentiment: POSITIVE
✅ Confidence: 95%+
✅ Priority: NORMAL
✅ Card Color: Green
✅ No urgent badge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Scenario 2: Angry Customer Complaint&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;Message: "This is completely unacceptable! I've been waiting for 3 weeks 
         with no response. The product arrived damaged and I want a full 
         refund immediately. Worst experience ever!"
Sender: angry.customer@example.com
Category: Complaint

Expected Result:
✅ Sentiment: NEGATIVE
✅ Confidence: 90%+
✅ Priority: HIGH
✅ Card Color: Red
✅ URGENT badge displayed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Scenario 3: Neutral Inquiry&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;Message: "Hi, I would like to know more about your pricing plans and 
         available features. Can you please send me the detailed 
         information? Also, what are the payment options?"
Sender: inquiry@example.com
Category: General

Expected Result:
✅ Sentiment: NEUTRAL
✅ Confidence: 80%+
✅ Priority: NORMAL
✅ Card Color: Gray
✅ No urgent badge
&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%2Fap49v2i7glg67trbgysz.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%2Fap49v2i7glg67trbgysz.png" alt=" " width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What We Built
&lt;/h3&gt;

&lt;p&gt;A production-ready, AI-powered message routing system that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Analyzes sentiment in real-time using AWS Bedrock&lt;/li&gt;
&lt;li&gt;✅ Runs on Kubernetes for high availability&lt;/li&gt;
&lt;li&gt;✅ Scales automatically based on demand&lt;/li&gt;
&lt;li&gt;✅ Provides beautiful, responsive UI&lt;/li&gt;
&lt;li&gt;✅ Handles thousands of messages per day&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Key Takeaways
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Cloud-Native Architecture Works&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kubernetes provides excellent orchestration&lt;/li&gt;
&lt;li&gt;Managed services reduce operational burden&lt;/li&gt;
&lt;li&gt;Serverless components lower costs&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;AI Integration is Straightforward&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS Bedrock makes AI accessible&lt;/li&gt;
&lt;li&gt;No ML expertise required&lt;/li&gt;
&lt;li&gt;Pay-per-use pricing is economical&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Modern Tools Improve Productivity&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;FastAPI for rapid API development&lt;/li&gt;
&lt;li&gt;React + Vite for fast frontend&lt;/li&gt;
&lt;li&gt;Docker for consistent deployments&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;AWS Services Integrate Well&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;EKS, ECR, DynamoDB work seamlessly&lt;/li&gt;
&lt;li&gt;IAM provides unified security&lt;/li&gt;
&lt;li&gt;CloudWatch for centralized monitoring&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Skills Demonstrated
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;✅ Kubernetes orchestration&lt;/li&gt;
&lt;li&gt;✅ Docker containerization&lt;/li&gt;
&lt;li&gt;✅ AWS cloud architecture&lt;/li&gt;
&lt;li&gt;✅ API development (FastAPI)&lt;/li&gt;
&lt;li&gt;✅ Frontend development (React)&lt;/li&gt;
&lt;li&gt;✅ AI/ML integration (Bedrock)&lt;/li&gt;
&lt;li&gt;✅ Database design (DynamoDB)&lt;/li&gt;
&lt;li&gt;✅ DevOps practices&lt;/li&gt;
&lt;li&gt;✅ Security best practices&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/eks/" rel="noopener noreferrer"&gt;Amazon EKS Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/bedrock/" rel="noopener noreferrer"&gt;AWS Bedrock Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/dynamodb/" rel="noopener noreferrer"&gt;DynamoDB Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://fastapi.tiangolo.com/" rel="noopener noreferrer"&gt;FastAPI Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://react.dev/" rel="noopener noreferrer"&gt;React Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Published:&lt;/strong&gt; January 17, 2026&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Author:&lt;/strong&gt;  Prithiviraj Rengarajan&lt;br&gt;
&lt;strong&gt;Tags:&lt;/strong&gt; AWS, EKS, Kubernetes, AI, Bedrock, DynamoDB, FastAPI, React, Cloud Architecture&lt;/p&gt;

</description>
      <category>ai</category>
      <category>aws</category>
      <category>kubernetes</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>🚀 AWS Introduces Regional NAT Gateway: Simplifying Outbound Connectivity</title>
      <dc:creator>Prithiviraj R</dc:creator>
      <pubDate>Wed, 31 Dec 2025 10:57:34 +0000</pubDate>
      <link>https://dev.to/prithiviraj_rengarajan/aws-introduces-regional-nat-gateway-simplifying-outbound-connectivity-4noj</link>
      <guid>https://dev.to/prithiviraj_rengarajan/aws-introduces-regional-nat-gateway-simplifying-outbound-connectivity-4noj</guid>
      <description>&lt;p&gt;AWS has introduced Regional NAT Gateway, a significant improvement to how outbound internet access is handled for workloads running in private subnets. This change meaningfully reduces architectural complexity while improving availability and security.&lt;/p&gt;

&lt;p&gt;Let’s start with the basics.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is a NAT Gateway?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A NAT Gateway allows resources in private subnets to access the internet for outbound traffic (for example, OS updates, package downloads, external APIs) without allowing inbound internet traffic.&lt;/p&gt;

&lt;p&gt;Traditionally, NAT Gateways were zonal resources, which came with architectural and operational overhead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🔹 Traditional (Zonal) NAT Gateway Model&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the classic design:&lt;/p&gt;

&lt;p&gt;One NAT Gateway per Availability Zone&lt;/p&gt;

&lt;p&gt;NAT Gateways deployed in public subnets&lt;/p&gt;

&lt;p&gt;AZ-specific route tables pointing to the local NAT Gateway&lt;/p&gt;

&lt;p&gt;More AZs = more NAT Gateways + more routing complexity&lt;/p&gt;

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

&lt;p&gt;Increased cost due to multiple NAT Gateways&lt;/p&gt;

&lt;p&gt;Operational overhead managing routes per AZ&lt;/p&gt;

&lt;p&gt;Public subnet dependency&lt;/p&gt;

&lt;p&gt;Risk of misconfiguration&lt;/p&gt;

&lt;p&gt;IP exhaustion concerns at scale&lt;/p&gt;

&lt;p&gt;Because of these factors, many teams tried to avoid NAT Gateways where possible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🔹 New: Regional NAT Gateway&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Regional NAT Gateway fundamentally changes this model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Characteristics:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Created at the VPC level&lt;/p&gt;

&lt;p&gt;No public subnets required&lt;/p&gt;

&lt;p&gt;Automatically scales across all Availability Zones&lt;/p&gt;

&lt;p&gt;A single NAT Gateway serves private subnets in all AZs&lt;/p&gt;

&lt;p&gt;AWS manages high availability internally&lt;/p&gt;

&lt;p&gt;This eliminates the need to think about NAT placement per AZ.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✅ Benefits&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Simpler Architecture&lt;/p&gt;

&lt;p&gt;Fewer NAT Gateways&lt;/p&gt;

&lt;p&gt;Fewer route tables&lt;/p&gt;

&lt;p&gt;Cleaner VPC design&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Improved Security&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No public subnets required&lt;/p&gt;

&lt;p&gt;Reduced blast radius and misconfiguration risk&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Built-in High Availability&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No need to deploy or manage NATs per AZ&lt;/p&gt;

&lt;p&gt;Automatically adapts as workloads scale across AZs&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lower Operational Overhead&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Less maintenance&lt;/p&gt;

&lt;p&gt;Fewer moving parts&lt;/p&gt;

&lt;p&gt;Easier to reason about networking&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;📊 Architectural Impact&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In AWS reference diagrams, you’ll notice that Regional NAT Gateways completely remove public subnets from the design. NAT now operates cleanly at the VPC level, which results in a more elegant and maintainable architecture.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Historically, many teams avoided NAT Gateways due to:&lt;/p&gt;

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

&lt;p&gt;Maintenance complexity&lt;/p&gt;

&lt;p&gt;IP exhaustion risks&lt;/p&gt;

&lt;p&gt;With Regional NAT Gateway, most of these concerns are significantly reduced. You get:&lt;/p&gt;

&lt;p&gt;Simpler architecture&lt;/p&gt;

&lt;p&gt;Built-in high availability&lt;/p&gt;

&lt;p&gt;Less operational burden&lt;/p&gt;

&lt;p&gt;For modern AWS environments, this is a change well worth evaluating and adopting.&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%2Fkzrde8d43ifqaykxwo79.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%2Fkzrde8d43ifqaykxwo79.png" alt=" " width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy Learning&lt;/p&gt;

&lt;p&gt;Prithiviraj Rengarajan&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>news</category>
      <category>networking</category>
      <category>aws</category>
    </item>
    <item>
      <title>Deploying a Professional Kubernetes Web UI Dashboard (kubectl-webui)</title>
      <dc:creator>Prithiviraj R</dc:creator>
      <pubDate>Fri, 05 Dec 2025 09:07:42 +0000</pubDate>
      <link>https://dev.to/prithiviraj_rengarajan/deploying-a-professional-kubernetes-web-ui-dashboard-kubectl-webui-2d2n</link>
      <guid>https://dev.to/prithiviraj_rengarajan/deploying-a-professional-kubernetes-web-ui-dashboard-kubectl-webui-2d2n</guid>
      <description>&lt;p&gt;A practical, step‑by‑step guide to containerizing, publishing, and running a lightweight Kubernetes Web UI on EKS using ECR, eksctl and standard Kubernetes manifests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why this guide?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Working with Kubernetes purely from the CLI is powerful, but sometimes you need a small, secure web UI to help teams quickly inspect resources, tail logs, and run quick in‑pod commands without giving full kubectl access. This blog post walks through building &lt;code&gt;kubectl-webui&lt;/code&gt;—a production‑aware Flask UI packaged as a container, pushed to ECR, and deployed to an AWS EKS cluster with RBAC, sample apps for testing, and a short troubleshooting section.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Make sure you have the following installed and configured:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS CLI (&lt;code&gt;aws --version&lt;/code&gt;) and credentials (run &lt;code&gt;aws configure&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Docker (&lt;code&gt;docker --version&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;kubectl (&lt;code&gt;kubectl version --client&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;eksctl (&lt;code&gt;eksctl version&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Verify AWS identity with:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;aws sts get-caller-identity&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Project overview&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Repository structure (important files):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl-webui/
├── app.py # Flask application
├── Dockerfile # Docker build configuration
├── requirements.txt # Python dependencies
├── templates/ # HTML templates
├── static/ # CSS / assets
├── scripts/ # helper shell scripts
├── nginx.conf
└── supervisord.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Build the Docker image&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dockerfile highlights:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Base image: &lt;code&gt;python:3.9-slim&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Installs &lt;code&gt;kubectl&lt;/code&gt; and AWS CLI inside the image for cluster interactions.&lt;/li&gt;
&lt;li&gt;Uses &lt;code&gt;supervisord&lt;/code&gt; + &lt;code&gt;nginx&lt;/code&gt; to serve the app alongside process supervision.&lt;/li&gt;
&lt;li&gt;Adds an unprivileged &lt;code&gt;app&lt;/code&gt; user and copies application files.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Build command (AMD64 for EKS node compatibility):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker build --platform linux/amd64 -t kubectl-webui-professional:amd64 .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify the image exists:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker images | grep kubectl-webui
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Push image to Amazon ECR&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create the repository, login, tag and push:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
REGION="us-west-2"
REPO_NAME="kubectl-webui"


aws ecr create-repository --repository-name $REPO_NAME --region $REGION
aws ecr get-login-password --region $REGION | docker login --username AWS --password-stdin $ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com


docker tag kubectl-webui-professional:amd64 $ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com/$REPO_NAME:professional


docker push $ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com/$REPO_NAME:professional
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Confirm the image with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws ecr describe-images --repository-name $REPO_NAME --region $REGION
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  &lt;strong&gt;Create an EKS cluster&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;Create a managed cluster for testing or production readiness:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;eksctl create cluster \
--name kubectl-webui-cluster \
--region us-west-2 \
--nodegroup-name kubectl-webui-nodes \
--node-type t3.medium \
--nodes 2 --nodes-min 1 --nodes-max 3 --managed


aws eks update-kubeconfig --region us-west-2 --name kubectl-webui-cluster
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.amazonaws.com%2Fuploads%2Farticles%2Fv5c0ucf54iy31bd8n65b.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%2Fv5c0ucf54iy31bd8n65b.png" alt=" " width="800" height="173"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deploy the Web UI and RBAC manifests&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A single YAML (&lt;code&gt;kubectl-webui-k8s.yaml&lt;/code&gt;) contains Deployment, Service (LoadBalancer), ServiceAccount, ClusterRole and ClusterRoleBinding. Key points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deployment references the ECR image URI (replace &lt;code&gt;ACCOUNT_ID&lt;/code&gt; and &lt;code&gt;REGION&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Container listens on &lt;code&gt;5000&lt;/code&gt; (Flask) and is exposed through an ELB on port &lt;code&gt;80&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;RBAC is scoped to read resources (&lt;code&gt;get&lt;/code&gt;, &lt;code&gt;list&lt;/code&gt;, &lt;code&gt;watch&lt;/code&gt;) for pods, services, nodes, deployments and related objects.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Apply the manifests and watch rollout:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -f kubectl-webui-k8s.yaml
kubectl rollout status deployment/kubectl-webui
kubectl get svc kubectl-webui-service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: the LoadBalancer hostname takes a couple of minutes to provision.&lt;/p&gt;

&lt;p&gt;Deploy sample applications (for testing)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sample-apps.yaml&lt;/code&gt; includes simple test workloads:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;nginx-app&lt;/code&gt; + ClusterIP service&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;redis-app&lt;/code&gt; + ClusterIP service&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;busybox-app&lt;/code&gt; (sleeping pod) to exec into&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;log-collector&lt;/code&gt; DaemonSet (fluentd)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -f sample-apps.yaml

kubectl get all
&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%2Fxsf15p82fk5srbrh0lyf.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%2Fxsf15p82fk5srbrh0lyf.png" alt=" " width="800" height="174"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Testing the dashboard&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Get LoadBalancer hostname:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get svc kubectl-webui-service -o jsonpath='{.status.loadBalancer.ingress[0].hostname}'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Open the returned URL in your browser (http). Example placeholder used in the repo is an ELB hostname.&lt;/li&gt;
&lt;li&gt;Try the UI features:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;List pods, services, deployments&lt;/li&gt;
&lt;li&gt;Describe and view pod logs&lt;/li&gt;
&lt;li&gt;Exec into the &lt;code&gt;busybox&lt;/code&gt; pod to run commands&lt;/li&gt;
&lt;li&gt;View events and basic resource usage&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%2Frl2pxh0kby2k5acstrag.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%2Frl2pxh0kby2k5acstrag.png" alt=" " width="800" height="412"&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%2Fi9vz8kzkshxnd1gohdu9.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%2Fi9vz8kzkshxnd1gohdu9.png" alt=" " width="800" height="385"&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%2F11d97v8r3ejmcqxpct1x.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%2F11d97v8r3ejmcqxpct1x.png" alt=" " width="800" height="378"&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%2Fw1mk8xq2lxxf9j9q1e4x.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%2Fw1mk8xq2lxxf9j9q1e4x.png" alt=" " width="800" height="429"&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%2F5qlqqy9qnekme8qetpzq.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%2F5qlqqy9qnekme8qetpzq.png" alt=" " width="800" height="380"&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%2F212pye2maoxtteslfngs.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%2F212pye2maoxtteslfngs.png" alt=" " width="800" height="398"&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%2Frt8uvjj81hl0ifcskkix.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%2Frt8uvjj81hl0ifcskkix.png" alt=" " width="800" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Troubleshooting (common patterns)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ImagePullBackOff&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensure the image exists in ECR and the image URI used in the Deployment is correct.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;aws ecr describe-images&lt;/code&gt; and &lt;code&gt;kubectl get deployment -o yaml | grep image&lt;/code&gt; to verify.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;RBAC permission errors&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Confirm the ServiceAccount exists: &lt;code&gt;kubectl get sa kubectl-webui-sa&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Test permissions from the service account context:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl auth can-i list pods --as=system:serviceaccount:default:kubectl-webui-sa
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;LoadBalancer stuck in Pending&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Confirm cluster nodes are in public subnets with proper tagging or your cloud provider setup allows ELB provisioning.&lt;/li&gt;
&lt;li&gt;Check &lt;code&gt;kubectl describe svc kubectl-webui-service&lt;/code&gt; and your cloud console for ELB status.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pod fails to start&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inspect logs: &lt;code&gt;kubectl logs -l app=kubectl-webui&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Describe the pod for events: &lt;code&gt;kubectl describe pod -l app=kubectl-webui&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Architecture (high level)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Developer browser → ELB (LoadBalancer) → kubectl-webui Pod → Kubernetes API Server → cluster workloads (nginx, redis, busybox)&lt;/p&gt;

&lt;p&gt;This pattern keeps the UI stateless (single replica acceptable for small teams) and relies on EKS IAM + Kubernetes RBAC to control access.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Security &amp;amp; Production Notes&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Do not&lt;/strong&gt; give this UI cluster‑wide admin rights. Keep RBAC read‑only or narrowly scoped.&lt;/li&gt;
&lt;li&gt;If exposing publicly, place the service behind an HTTPS ALB with authentication (OIDC, Cognito or a reverse proxy with auth).&lt;/li&gt;
&lt;li&gt;Use image scanning and automated CI to build/push images, and use immutable tags (e.g. &lt;code&gt;:sha-&amp;lt;commit&amp;gt;&lt;/code&gt;) rather than &lt;code&gt;:latest&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The kubectl‑webui project demonstrates how a compact, secure web UI can simplify everyday cluster operations while preserving Kubernetes best practices. By containerizing the app, publishing images to ECR, and deploying on EKS with scoped RBAC, you get a reproducible, auditable workflow that teams can trust. For production use, tighten access with HTTPS and authentication, use private networking where possible, and adopt CI/CD with immutable image tags. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Happy learning&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prithiviraj Rengarajan&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;DevOps Engineer&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>aws</category>
      <category>tutorial</category>
      <category>kubernetes</category>
    </item>
    <item>
      <title>Monitoring Demo: Setting Up Prometheus and Grafana on Amazon EKS</title>
      <dc:creator>Prithiviraj R</dc:creator>
      <pubDate>Fri, 28 Nov 2025 11:16:13 +0000</pubDate>
      <link>https://dev.to/prithiviraj_rengarajan/monitoring-demo-setting-up-prometheus-and-grafana-on-amazon-eks-468o</link>
      <guid>https://dev.to/prithiviraj_rengarajan/monitoring-demo-setting-up-prometheus-and-grafana-on-amazon-eks-468o</guid>
      <description>&lt;p&gt;Observability is essential in any Kubernetes environment. To monitor workloads, analyze performance, and gain visibility into cluster health, I set up &lt;strong&gt;Prometheus and Grafana&lt;/strong&gt; inside my Amazon EKS cluster. This demo walks through the exact steps I followed, including the real service and pod names generated during deployment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Create a Dedicated Namespace&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To keep monitoring components organized:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl create namespace monitoring
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Add Helm Repositories&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Prometheus and Grafana are installed using the official Helm charts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Install the Kube-Prometheus Stack&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;kube-prometheus-stack&lt;/strong&gt; chart bundles everything needed for monitoring:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prometheus&lt;/li&gt;
&lt;li&gt;Grafana&lt;/li&gt;
&lt;li&gt;Alertmanager&lt;/li&gt;
&lt;li&gt;Node Exporter&lt;/li&gt;
&lt;li&gt;Kube-State-Metrics&lt;/li&gt;
&lt;li&gt;Prometheus Operator&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Installation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm install kube-prom-stack prometheus-community/kube-prometheus-stack \
  --namespace monitoring
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once deployed, the following services were created in my cluster:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;grafana-nodeport&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prometheus-grafana&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prometheus-kube-prometheus-prometheus&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prometheus-kube-prometheus-operator&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prometheus-kube-state-metrics&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prometheus-prometheus-node-exporter&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;alertmanager-prometheus-kube-prometheus-alertmanager&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All components came up successfully under the &lt;strong&gt;monitoring&lt;/strong&gt; namespace.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Verify the Monitoring Pods&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To ensure the monitoring stack was healthy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get pods -n monitoring
&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%2Foaamtfdugightwhxxxi3.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%2Foaamtfdugightwhxxxi3.png" alt=" " width="800" height="152"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Key components running in my demo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;prometheus-grafana-79f589d988-r74cb&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prometheus-prometheus-kube-prometheus-prometheus-0&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prometheus-kube-prometheus-operator-6cd4f88f57-x5mx2&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prometheus-kube-state-metrics-56f99dc587-rtj22&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prometheus-prometheus-node-exporter-jhnnx&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;alertmanager-prometheus-kube-prometheus-alertmanager-0&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;5. Accessing Grafana&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Helm chart created a NodePort service named &lt;strong&gt;grafana-nodeport&lt;/strong&gt;, exposed on port &lt;strong&gt;30080&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option 1 — Port Forward (Local Access)&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;kubectl port-forward -n monitoring svc/grafana-nodeport 3000:80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then open:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Option 2 — NodePort (Direct Access)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If your EKS worker nodes are publicly accessible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://&amp;lt;worker-node-public-ip&amp;gt;:30080
&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%2F0yo1sprdejr4fvnjcfkt.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%2F0yo1sprdejr4fvnjcfkt.png" alt=" " width="800" height="395"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Grafana Credentials&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Retrieve the admin password:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get secret -n monitoring kube-prom-stack-grafana \
  -o jsonpath="{.data.admin-password}" | base64 --decode
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;6. Accessing Prometheus&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To access the Prometheus UI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl port-forward -n monitoring \
svc/prometheus-kube-prometheus-prometheus 9090:9090
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From here, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check scrape targets&lt;/li&gt;
&lt;li&gt;Explore metrics&lt;/li&gt;
&lt;li&gt;View alerting rules&lt;/li&gt;
&lt;li&gt;Validate ServiceMonitor configurations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Prometheus will automatically discover and scrape the service.&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%2Flfn7nowad60wdzxiufvh.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%2Flfn7nowad60wdzxiufvh.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Built-In Dashboards in Grafana&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Grafana includes preloaded dashboards for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nodes&lt;/li&gt;
&lt;li&gt;Pods&lt;/li&gt;
&lt;li&gt;Workloads&lt;/li&gt;
&lt;li&gt;Kubernetes API server&lt;/li&gt;
&lt;li&gt;Node exporter&lt;/li&gt;
&lt;li&gt;Kube-state-metrics&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%2Fbkv8qjeql34afm0awuok.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%2Fbkv8qjeql34afm0awuok.png" alt=" " width="800" height="382"&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%2Fpq0fbuy4hpkt95dty7hf.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%2Fpq0fbuy4hpkt95dty7hf.png" alt=" " width="800" height="397"&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%2Furaim8464kph2lfg24mq.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%2Furaim8464kph2lfg24mq.png" alt=" " width="800" height="388"&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%2F29jyrx820ttdnu0s9prr.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%2F29jyrx820ttdnu0s9prr.png" alt=" " width="800" height="395"&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%2Fp9frofcwqxhjhezhryme.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%2Fp9frofcwqxhjhezhryme.png" alt=" " width="800" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These dashboards begin populating immediately once Prometheus collects metrics.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This setup delivers a complete observability stack for Amazon EKS.&lt;br&gt;
 With Prometheus collecting metrics and Grafana providing rich visualizations, you gain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full visibility into cluster health&lt;/li&gt;
&lt;li&gt;Metrics for application performance&lt;/li&gt;
&lt;li&gt;Alerts for failures and anomalies&lt;/li&gt;
&lt;li&gt;A foundation for long-term monitoring&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Happy Learning&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Prithiviraj Rengarajan&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;DevOps Engineer&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>monitoring</category>
      <category>kubernetes</category>
      <category>tutorial</category>
      <category>aws</category>
    </item>
    <item>
      <title>Amazon EKS adds native support for the AWS Secrets Store CSI Driver Provider</title>
      <dc:creator>Prithiviraj R</dc:creator>
      <pubDate>Sat, 22 Nov 2025 12:42:37 +0000</pubDate>
      <link>https://dev.to/prithiviraj_rengarajan/amazon-eks-adds-native-support-for-the-aws-secrets-store-csi-driver-provider-1k9c</link>
      <guid>https://dev.to/prithiviraj_rengarajan/amazon-eks-adds-native-support-for-the-aws-secrets-store-csi-driver-provider-1k9c</guid>
      <description>&lt;p&gt;AWS has released a new EKS Add-on that makes it easier to securely fetch secrets from AWS Secrets Manager and SSM Parameter Store and mount them directly into Kubernetes pods — without custom plugins or manual setups.&lt;/p&gt;

&lt;p&gt;🔐 Why this matters&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Centralized &amp;amp; secure secrets management&lt;/li&gt;
&lt;li&gt;Seamless integration with EKS Add-ons&lt;/li&gt;
&lt;li&gt;Mount secrets as files inside pods&lt;/li&gt;
&lt;li&gt;Reduced operational overhead&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Available in all AWS Regions &amp;amp; GovCloud&lt;/p&gt;

&lt;p&gt;Great update for teams running workloads on EKS and looking to streamline secure secret delivery across clusters.&lt;/p&gt;

&lt;h1&gt;
  
  
  AWS #EKS #Kubernetes #DevOps #CloudComputing #SecretsManager #SSM #AWSUpdate 🚀
&lt;/h1&gt;

&lt;p&gt;Reference:&lt;br&gt;
&lt;a href="https://aws.amazon.com/about-aws/whats-new/2025/11/amazon-eks-add-ons-aws-secrets-store-csi-driver-provider/" rel="noopener noreferrer"&gt;https://aws.amazon.com/about-aws/whats-new/2025/11/amazon-eks-add-ons-aws-secrets-store-csi-driver-provider/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/aws/secrets-store-csi-driver-provider-aws" rel="noopener noreferrer"&gt;https://github.com/aws/secrets-store-csi-driver-provider-aws&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Happy Learning&lt;br&gt;
Prithiviraj Rengarajan&lt;br&gt;
DevOps Engineer&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>aws</category>
      <category>kubernetes</category>
      <category>devops</category>
    </item>
    <item>
      <title>Kubernetes Troubleshooting with K8sGPT + Amazon Bedrock</title>
      <dc:creator>Prithiviraj R</dc:creator>
      <pubDate>Fri, 21 Nov 2025 11:37:05 +0000</pubDate>
      <link>https://dev.to/prithiviraj_rengarajan/kubernetes-troubleshooting-with-k8sgpt-amazon-bedrock-1m5a</link>
      <guid>https://dev.to/prithiviraj_rengarajan/kubernetes-troubleshooting-with-k8sgpt-amazon-bedrock-1m5a</guid>
      <description>&lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;br&gt;
Troubleshooting Kubernetes issues often requires switching between logs, events, and documentation. K8sGPT simplifies this by using AI to analyze cluster problems and generate human-readable explanations and solutions.&lt;br&gt;
In this summary, I’ll walk through how I used K8sGPT with Amazon Bedrock to diagnose issues inside an EKS cluster and how it improved the entire troubleshooting experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is K8sGPT?&lt;/strong&gt;&lt;br&gt;
K8sGPT is an open-source CLI and operator that scans Kubernetes resources and uses AI models to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Detect misconfigurations&lt;/li&gt;
&lt;li&gt;Explain errors in simple language&lt;/li&gt;
&lt;li&gt;Provide actionable fixes&lt;/li&gt;
&lt;li&gt;Recommend best practices&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why Integrate with Amazon Bedrock?&lt;br&gt;
Amazon Bedrock enhances K8sGPT by offering:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple LLM choices (Nova, Claude, Llama)&lt;/li&gt;
&lt;li&gt;Secure, enterprise-ready identity (no API keys)&lt;/li&gt;
&lt;li&gt;Low-latency inference from AWS regions&lt;/li&gt;
&lt;li&gt;Cost savings using lightweight models like Nova Lite
&lt;strong&gt;Setup Overview&lt;/strong&gt;
For the demo, I used:
EKS cluster&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%2Frfwqja37g22geruz1uua.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%2Frfwqja37g22geruz1uua.png" alt=" " width="800" height="96"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Broken and misconfigured workloads&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%2Fzpdddi6rctwh9upn3g9r.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%2Fzpdddi6rctwh9upn3g9r.png" alt=" " width="800" height="306"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;K8sGPT with Amazon Bedrock Nova Lite model&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Create the EKS Cluster&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I used a simple &lt;code&gt;eksctl&lt;/code&gt; configuration to provision a small EKS cluster.&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%2Fqpjup7p4s9vnbn8v241w.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%2Fqpjup7p4s9vnbn8v241w.png" alt=" " width="800" height="148"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Install K8sGPT&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Download the K8sGPT CLI and place it in your system’s PATH.&lt;br&gt;
 The installation is straightforward — just download the binary, extract it, and move it into &lt;code&gt;/usr/local/bin/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Configure K8sGPT to Use Bedrock&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;K8sGPT supports Bedrock natively.&lt;br&gt;
 You configure it by adding:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Backend provider → &lt;code&gt;amazonbedrock&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Bedrock region → &lt;code&gt;us-east-1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Model → &lt;code&gt;amazon.nova-lite-v1:0&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then set Bedrock as the default provider.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Create Problematic Kubernetes Resources&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To test K8sGPT, I intentionally deployed workloads with issues:&lt;/p&gt;
&lt;h6&gt;
  
  
  &lt;strong&gt;Examples of injected failures&lt;/strong&gt;
&lt;/h6&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Broken Image Pod&lt;/strong&gt; → invalid image registry&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource Heavy Pod&lt;/strong&gt; → impossible CPU/memory requests&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;StatefulSet with Wrong StorageClass&lt;/strong&gt; → PVC creation failure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These represent issues commonly faced in real Kubernetes environments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Run K8sGPT Analysis&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once workloads are deployed:&lt;br&gt;
k8sgpt analyze &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%2Ftv41jbdimbvc24geptri.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%2Ftv41jbdimbvc24geptri.png" alt=" " width="800" height="561"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;k8sgpt analyze --filter Pod --namespace k8sgpt-demo --explain | head -20
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;K8sGPT quickly identifies issues and generates fixes using AI.&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%2Flvuxsf2xw0ljwk8enaua.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%2Flvuxsf2xw0ljwk8enaua.png" alt=" " width="800" height="590"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example Output (Summarized)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Image Pull Error&lt;/strong&gt;
&lt;em&gt;Issue:&lt;/em&gt; Back-off pulling image
&lt;em&gt;Fix:&lt;/em&gt; Correct the registry/image tag&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Insufficient Resources&lt;/strong&gt;
&lt;em&gt;Issue:&lt;/em&gt; Pods cannot schedule
&lt;em&gt;Fix:&lt;/em&gt; Adjust CPU/memory or scale nodegroup&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Invalid StorageClass&lt;/strong&gt;
&lt;em&gt;Issue:&lt;/em&gt; PVCs stuck in Pending
&lt;em&gt;Fix:&lt;/em&gt; Update storage class or create a valid one&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These explanations are far more readable compared to raw Kubernetes error messages.&lt;/p&gt;

&lt;p&gt;Essential commands&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Essential Test Commands:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Basic Analysis (No AI)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;k8sgpt analyze&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. AI-Powered Analysis&lt;/strong&gt; (Uses Bedrock)&lt;br&gt;
k8sgpt analyze --explain&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Specific Namespace&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;k8sgpt analyze --explain --namespace k8sgpt-demo&lt;/p&gt;

&lt;p&gt;4.&lt;strong&gt;Specific Resource Type&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;k8sgpt analyze --explain --filter Pod&lt;/p&gt;

&lt;p&gt;k8sgpt analyze --explain --filter Deployment&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Multiple Filters&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;k8sgpt analyze --explain --filter Pod,Deployment,Service&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Check Configuration&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;k8sgpt auth list&lt;/p&gt;

&lt;p&gt;k8sgpt filters list&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Verbose Output&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;k8sgpt analyze --explain --verbose&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Benefits Observed&lt;/strong&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  &lt;strong&gt;1. Intelligent Issue Detection&lt;/strong&gt;
&lt;/h6&gt;

&lt;p&gt;K8sGPT identified issues across pods, StatefulSets, services, and jobs.&lt;/p&gt;

&lt;h6&gt;
  
  
  &lt;strong&gt;2. Human-Friendly Explanations&lt;/strong&gt;
&lt;/h6&gt;

&lt;p&gt;It rewrites cryptic Kubernetes errors into simple sentences.&lt;/p&gt;

&lt;h6&gt;
  
  
  &lt;strong&gt;3. Actionable Remediation Steps&lt;/strong&gt;
&lt;/h6&gt;

&lt;p&gt;Includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;kubectl&lt;/code&gt; commands&lt;/li&gt;
&lt;li&gt;Configuration fixes&lt;/li&gt;
&lt;li&gt;Architecture recommendations&lt;/li&gt;
&lt;/ul&gt;

&lt;h6&gt;
  
  
  &lt;strong&gt;4. Speed&lt;/strong&gt;
&lt;/h6&gt;

&lt;p&gt;It analyzed more than a dozen issues in seconds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Amazon Bedrock Model Options&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Speed&lt;/th&gt;
&lt;th&gt;Quality&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;th&gt;Best Use Case&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Nova Lite&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fastest&lt;/td&gt;
&lt;td&gt;Great&lt;/td&gt;
&lt;td&gt;Cheapest&lt;/td&gt;
&lt;td&gt;Day-to-day troubleshooting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Nova Pro&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Excellent&lt;/td&gt;
&lt;td&gt;Moderate&lt;/td&gt;
&lt;td&gt;Complex multi-resource analysis&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Claude 3 Haiku&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fast&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;td&gt;Detailed explanations&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Best recommendation:&lt;/strong&gt; Start with &lt;strong&gt;Nova Lite&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fixing Issues (Summary)&lt;/strong&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  &lt;strong&gt;Fix Image Pull Failure&lt;/strong&gt;
&lt;/h6&gt;

&lt;p&gt;Delete the broken pod and recreate it with a valid image.&lt;/p&gt;

&lt;h6&gt;
  
  
  &lt;strong&gt;Fix Misconfigured Deployment&lt;/strong&gt;
&lt;/h6&gt;

&lt;p&gt;Patch Deployment or update chart values.&lt;/p&gt;

&lt;h6&gt;
  
  
  &lt;strong&gt;Fix Storage Issues&lt;/strong&gt;
&lt;/h6&gt;

&lt;p&gt;Correct the StorageClass or create a valid one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Production Considerations&lt;/strong&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  &lt;strong&gt;Security&lt;/strong&gt;
&lt;/h6&gt;

&lt;ul&gt;
&lt;li&gt;Use IAM Roles&lt;/li&gt;
&lt;li&gt;Avoid embedding credentials&lt;/li&gt;
&lt;li&gt;Enable CloudTrail auditing&lt;/li&gt;
&lt;/ul&gt;

&lt;h6&gt;
  
  
  &lt;strong&gt;Cost&lt;/strong&gt;
&lt;/h6&gt;

&lt;ul&gt;
&lt;li&gt;Monitor Bedrock usage&lt;/li&gt;
&lt;li&gt;Use model tiering based on workload&lt;/li&gt;
&lt;/ul&gt;

&lt;h6&gt;
  
  
  &lt;strong&gt;Integrations&lt;/strong&gt;
&lt;/h6&gt;

&lt;ul&gt;
&lt;li&gt;Prometheus + Grafana&lt;/li&gt;
&lt;li&gt;Alerting systems&lt;/li&gt;
&lt;li&gt;CI/CD pre-deployment checks&lt;/li&gt;
&lt;/ul&gt;

&lt;h6&gt;
  
  
  &lt;strong&gt;In-Cluster Operator Deployment&lt;/strong&gt;
&lt;/h6&gt;

&lt;p&gt;You can deploy K8sGPT operator using Helm and set Bedrock as the backend for ongoing cluster analysis.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before vs After K8sGPT&lt;/strong&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  &lt;strong&gt;Before&lt;/strong&gt;
&lt;/h6&gt;

&lt;ul&gt;
&lt;li&gt;Manual debugging&lt;/li&gt;
&lt;li&gt;Slow MTTR&lt;/li&gt;
&lt;li&gt;High cognitive load&lt;/li&gt;
&lt;li&gt;Heavy dependency on senior engineers&lt;/li&gt;
&lt;/ul&gt;

&lt;h6&gt;
  
  
  &lt;strong&gt;After&lt;/strong&gt;
&lt;/h6&gt;

&lt;ul&gt;
&lt;li&gt;Fast AI-driven diagnostics&lt;/li&gt;
&lt;li&gt;Consistent solutions&lt;/li&gt;
&lt;li&gt;Junior engineers troubleshoot confidently&lt;/li&gt;
&lt;li&gt;Reduced MTTR significantly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;K8sGPT combined with Amazon Bedrock is a powerful way to modernize Kubernetes troubleshooting. It minimizes time spent on debugging, improves team efficiency, and brings clarity to complex cluster issues.&lt;/p&gt;

&lt;p&gt;If you're managing EKS environments at scale, this integration provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Faster resolutions&lt;/li&gt;
&lt;li&gt;Clearer insights&lt;/li&gt;
&lt;li&gt;Better operational consistency&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The future of Kubernetes troubleshooting is AI-driven, and tools like K8sGPT make that future easy to adopt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quick Start Checklist&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Configure AWS credentials&lt;/li&gt;
&lt;li&gt;Install K8sGPT&lt;/li&gt;
&lt;li&gt;Add Amazon Bedrock as AI backend&lt;/li&gt;
&lt;li&gt;Deploy workloads&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;k8sgpt analyze&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Apply the recommended fixes&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Happy Learning&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Prithiviraj Rengarajan&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;DevOps Engineer&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>aws</category>
      <category>kubernetes</category>
      <category>devops</category>
    </item>
    <item>
      <title>The Smart Way to Automate AWS Cost Audits Across Multiple Regions</title>
      <dc:creator>Prithiviraj R</dc:creator>
      <pubDate>Fri, 17 Oct 2025 15:33:44 +0000</pubDate>
      <link>https://dev.to/prithiviraj_rengarajan/the-smart-way-to-automate-aws-cost-audits-across-multiple-regions-2pfi</link>
      <guid>https://dev.to/prithiviraj_rengarajan/the-smart-way-to-automate-aws-cost-audits-across-multiple-regions-2pfi</guid>
      <description>&lt;h5&gt;
  
  
  🌍 &lt;strong&gt;Why AWS Cost Audits Matter&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;Running workloads across multiple AWS regions gives you flexibility — but it also hides a silent cost problem: &lt;strong&gt;idle resources&lt;/strong&gt;.&lt;br&gt;
 An EC2 instance left running, an unattached EBS volume, or an unused Elastic IP can quietly drain your monthly budget.&lt;/p&gt;

&lt;p&gt;That’s where the &lt;strong&gt;AWS Cost Audit Tool&lt;/strong&gt; comes in.&lt;br&gt;
 It’s a lightweight Dockerized app that scans all AWS regions, finds unused resources, and shows your &lt;strong&gt;potential monthly savings&lt;/strong&gt; — all through a simple web dashboard.&lt;/p&gt;

&lt;p&gt;I recently ran it across &lt;strong&gt;17 regions&lt;/strong&gt;, and the results were eye-opening.&lt;/p&gt;
&lt;h5&gt;
  
  
  &lt;strong&gt;⚙️ What the Tool Does&lt;/strong&gt;
&lt;/h5&gt;

&lt;p&gt;✅ Scans &lt;strong&gt;all AWS regions&lt;/strong&gt;&lt;br&gt;
 ✅ Detects idle &lt;strong&gt;EC2 instances&lt;/strong&gt;, &lt;strong&gt;EBS volumes&lt;/strong&gt;, and &lt;strong&gt;Elastic IPs&lt;/strong&gt;&lt;br&gt;
 ✅ Calculates &lt;strong&gt;potential monthly savings&lt;/strong&gt;&lt;br&gt;
 ✅ Displays &lt;strong&gt;real-time progress&lt;/strong&gt; in a web UI&lt;/p&gt;

&lt;p&gt;No need for complex APIs or third-party dashboards — just &lt;strong&gt;Docker, AWS credentials, and your browser&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🚀 Quick Start Guide&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1️⃣ Prerequisites&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Docker installed&lt;/li&gt;
&lt;li&gt;AWS credentials configured&lt;/li&gt;
&lt;li&gt;Any web browser&lt;/li&gt;
&lt;li&gt;clone the github URL "&lt;a href="https://github.com/prithiviraj123/aws-cost-audit-v1" rel="noopener noreferrer"&gt;https://github.com/prithiviraj123/aws-cost-audit-v1&lt;/a&gt;"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;2️⃣ Configure AWS Credentials&lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;.env&lt;/code&gt; file in your project folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AWS_ACCESS_KEY_ID=your-access-key-here
AWS_SECRET_ACCESS_KEY=your-secret-key-here
AWS_DEFAULT_REGION=us-east-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3️⃣ Deploy the Application&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chmod +x deploy-simple.sh
./deploy-simple.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then open: 👉 &lt;strong&gt;&lt;a href="http://localhost:8080" rel="noopener noreferrer"&gt;http://localhost:8080&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  🧭 How to Use It
&lt;/h5&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Test AWS Connection&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;“Test AWS Connection”&lt;/strong&gt;.&lt;br&gt;
 If everything’s configured correctly, you’ll see:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;✅ Connected to AWS Account: [your-account-id]&lt;/p&gt;
&lt;/blockquote&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%2Fryk1wamvjjsx1e0hmfcy.jpeg" 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%2Fryk1wamvjjsx1e0hmfcy.jpeg" alt=" " width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Run Full Audit&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;“Start Full Audit.”&lt;/strong&gt;&lt;br&gt;
 The app will scan all regions — watch the progress bar and logs update live.&lt;br&gt;
 Takes around &lt;strong&gt;5–15 minutes&lt;/strong&gt;, depending on the number of resources.&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%2Fntj5qe4o5yjsmxhqs0cp.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%2Fntj5qe4o5yjsmxhqs0cp.png" alt=" " width="800" height="269"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Review Results&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When complete, you’ll see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Total Idle Resources&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Estimated Monthly Savings&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Detailed Recommendations&lt;/strong&gt; per resource&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can also &lt;strong&gt;export results to Excel&lt;/strong&gt; for record-keeping or reporting.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If it says &lt;em&gt;“Your AWS account is optimized!”&lt;/em&gt; — that’s a good thing 🎉&lt;/p&gt;
&lt;/blockquote&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%2Fqsmtu984tydf6hmwl4hh.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%2Fqsmtu984tydf6hmwl4hh.png" alt=" " width="800" height="371"&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%2Fpsj0snnnhvtd6oektdbt.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%2Fpsj0snnnhvtd6oektdbt.png" alt=" " width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Excel Report&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%2F7zhll4gcu3ljn3sqx4sx.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%2F7zhll4gcu3ljn3sqx4sx.png" alt=" " width="800" height="238"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;💡 What Gets Scanned&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Resource Type&lt;/th&gt;
&lt;th&gt;Criteria&lt;/th&gt;
&lt;th&gt;Recommended Action&lt;/th&gt;
&lt;th&gt;Estimated Savings&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;EC2 Instances&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;CPU usage &amp;lt; 10% (24h)&lt;/td&gt;
&lt;td&gt;Stop or downsize&lt;/td&gt;
&lt;td&gt;$8–200+/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;EBS Volumes&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Unattached (available)&lt;/td&gt;
&lt;td&gt;Delete&lt;/td&gt;
&lt;td&gt;$0.08–0.125 / GB / month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Elastic IPs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Not associated&lt;/td&gt;
&lt;td&gt;Release&lt;/td&gt;
&lt;td&gt;$3.65/month per IP&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This gives you &lt;strong&gt;visibility&lt;/strong&gt; and &lt;strong&gt;actionable insights&lt;/strong&gt; without manual digging.&lt;/p&gt;

&lt;h5&gt;
  
  
  📊 Real Results
&lt;/h5&gt;

&lt;p&gt;After scanning &lt;strong&gt;17 AWS regions&lt;/strong&gt;, the tool revealed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple &lt;strong&gt;idle EC2 instances&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Dozens of &lt;strong&gt;unused EBS volumes&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;A few &lt;strong&gt;unassociated Elastic IPs&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That translated to &lt;strong&gt;immediate cost savings&lt;/strong&gt; and a more optimized environment.&lt;/p&gt;

&lt;h5&gt;
  
  
  🧠 Final Thoughts
&lt;/h5&gt;

&lt;p&gt;The &lt;strong&gt;AWS Cost Audit Tool&lt;/strong&gt; proves that powerful automation doesn’t have to be complicated.&lt;br&gt;
 In just a few commands, you can audit your entire AWS footprint, visualize idle resources, and cut waste.&lt;/p&gt;

&lt;p&gt;No third-party costs, no manual digging — just DevOps simplicity at its best.&lt;/p&gt;

&lt;p&gt;💻 &lt;strong&gt;Simple setup. Real savings. Zero guesswork.&lt;/strong&gt;&lt;br&gt;
 🚀 Run your own audit today and watch your AWS bill shrink!&lt;/p&gt;

&lt;p&gt;Happy Learning&lt;/p&gt;

&lt;p&gt;By &lt;strong&gt;Prithiviraj Rengarajan | DevOps &amp;amp; Cloud Engineer&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>automation</category>
      <category>devops</category>
      <category>tooling</category>
      <category>aws</category>
    </item>
  </channel>
</rss>
