<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Pranav Soni]]></title><description><![CDATA[DevOps & Cloud notes — hands-on labs, architecture decisions, and lessons from building real infrastructure.]]></description><link>https://pranavsoni.hashnode.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1593680282896/kNC7E8IR4.png</url><title>Pranav Soni</title><link>https://pranavsoni.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Fri, 25 Sep 2026 09:22:42 GMT</lastBuildDate><atom:link href="https://pranavsoni.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Kubernetes Architecture, Explained Through My Own EKS Cluster]]></title><description><![CDATA[Kubernetes architecture diagrams look intimidating the first time you see them — boxes inside boxes, arrows going everywhere, terms like "etcd" and "kubelet" thrown around like everyone already knows ]]></description><link>https://pranavsoni.hashnode.dev/kubernetes-architecture-explained-through-my-own-eks-cluster</link><guid isPermaLink="true">https://pranavsoni.hashnode.dev/kubernetes-architecture-explained-through-my-own-eks-cluster</guid><category><![CDATA[Kubernetes]]></category><category><![CDATA[Docker]]></category><category><![CDATA[System Design]]></category><category><![CDATA[securityawareness]]></category><category><![CDATA[AWS]]></category><dc:creator><![CDATA[Pranav Soni]]></dc:creator><pubDate>Mon, 21 Sep 2026 14:36:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6ab13a9e3499efe82b6d36a6/0afff2c8-1286-4658-8a01-a06fe0ca1538.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Kubernetes architecture diagrams look intimidating the first time you see them — boxes inside boxes, arrows going everywhere, terms like "etcd" and "kubelet" thrown around like everyone already knows what they do.</p>
<p>The easiest way I found to actually understand it wasn't reading more diagrams. It was mapping the theory onto a cluster I'd already built — my EKS cluster running <strong>shopflow</strong>, a microservices e-commerce platform I've been building as a hands-on DevOps project.</p>
<p>So here's Kubernetes architecture, explained the way I wish someone had explained it to me: through a real cluster, not a generic one.</p>
<h2>The Two Halves of Every Cluster</h2>
<p>Every Kubernetes cluster splits into two parts:</p>
<ol>
<li><p><strong>The control plane</strong> — the brain. It makes decisions but doesn't run your application.</p>
</li>
<li><p><strong>The worker nodes</strong> — the muscle. This is where your actual application containers run.</p>
</li>
</ol>
<p>In EKS, AWS manages the control plane for you. You don't SSH into it, you don't patch it, you barely think about it — which is exactly why EKS is a good starting point for understanding the <em>concept</em> without getting lost in managing it yourself.</p>
<h2>The Control Plane: Decisions, Not Execution</h2>
<p>The control plane doesn't run your app. It runs the components that decide <em>how</em> your app should run.</p>
<ul>
<li><p><strong>API server</strong> — the front door. Every <code>kubectl</code> command, every CI/CD deploy, every ArgoCD sync goes through here first.</p>
</li>
<li><p><strong>etcd</strong> — the cluster's memory. It stores the entire desired state: what should be running, how many replicas, what config, everything.</p>
</li>
<li><p><strong>Scheduler</strong> — decides which worker node a new pod should land on, based on resource availability.</p>
</li>
<li><p><strong>Controller manager</strong> — constantly compares "what's actually running" against "what etcd says should be running," and corrects any drift.</p>
</li>
</ul>
<p>For shopflow, this is the layer that makes GitOps with ArgoCD actually work. ArgoCD talks to the API server, the API server updates etcd, and the controller manager makes sure the cluster's real state eventually matches it. I don't manually reconcile anything — the control plane's whole job is doing that reconciliation for me.</p>
<h2>The Worker Nodes: Where Your App Actually Lives</h2>
<p>Worker nodes are where the four FastAPI microservices in shopflow actually run as pods.</p>
<p>Each node runs:</p>
<ul>
<li><p><strong>kubelet</strong> — the agent that talks to the control plane and makes sure the containers scheduled to this node are actually running.</p>
</li>
<li><p><strong>kube-proxy</strong> — handles networking so Services can route traffic to the right pods, even as pods get replaced or rescheduled.</p>
</li>
<li><p><strong>Container runtime</strong> — actually runs the containers (pulling images, starting/stopping them).</p>
</li>
</ul>
<p>My HPAs (Horizontal Pod Autoscalers) live at this layer too — they watch resource usage per pod and tell the control plane to schedule more replicas when load increases. The control plane decides <em>where</em> those new pods go; the worker nodes are just where they land and run.</p>
<h2>Where IRSA and OIDC Fit In</h2>
<p>This is the part that took me longest to actually get, and it's not usually in the basic architecture diagrams.</p>
<p>Pods need permissions to talk to AWS services — S3, RDS, KMS, whatever. The naive (and dangerous) approach is hardcoding credentials into the pod. Shopflow instead uses <strong>IRSA (IAM Roles for Service Accounts)</strong> with OIDC.</p>
<p>Here's the flow: EKS runs an OIDC provider. A Kubernetes ServiceAccount gets annotated with an IAM role ARN. When a pod using that ServiceAccount starts, it can assume that IAM role directly — no static credentials anywhere, no secrets to rotate.</p>
<p>This isn't a separate system bolted onto Kubernetes; it's Kubernetes' own trust model (ServiceAccounts, tokens) extended to talk to AWS's IAM. Once I understood that ServiceAccounts are actually identity objects — not just Kubernetes-internal permission scoping — IRSA stopped feeling like magic.</p>
<h2>Namespaces as Blast-Radius Control</h2>
<p>Shopflow's cluster isn't one flat space. The application runs in its own namespace, and monitoring lives in a completely separate one.</p>
<p>That separation matters architecturally: the Prometheus Agent running in the <code>monitoring</code> namespace has its own ServiceAccount and ClusterRole, scoped to read metrics across the whole cluster — but it's still logically isolated from the application namespace. If something goes wrong in one namespace, RBAC and network boundaries stop it from silently affecting the other.</p>
<h2>What Happens When the Cluster Itself Is Unhealthy</h2>
<p>This is where architecture stopped being theoretical for me. If your monitoring stack runs <em>inside</em> the same cluster it's observing, and the cluster has a serious problem, your visibility disappears at the exact moment you need it most.</p>
<p>That's why in shopflow, the Prometheus Agent (lightweight, in-cluster) only <em>collects</em> metrics. The actual Prometheus Server — the one storing data and firing alerts — runs independently on an EC2 instance outside the cluster, receiving metrics over <code>remote_write</code>. If the EKS control plane or nodes have issues, the server keeps running and I can still see exactly when things went wrong.</p>
<p>That's not a Kubernetes-native pattern — it's a decision I made <em>because</em> I understood the architecture well enough to see the failure mode.</p>
<h2>Why Mapping Theory to a Real Cluster Helped</h2>
<p>Reading about the control plane and worker nodes in the abstract never made it click. What made it click was asking, for each component: <em>where does this show up in my actual cluster, and what breaks if it's missing?</em></p>
<ul>
<li><p>No API server → ArgoCD can't sync, <code>kubectl</code> stops responding</p>
</li>
<li><p>No scheduler → new pods stay Pending forever</p>
</li>
<li><p>No kubelet on a node → that node stops reporting healthy, pods get rescheduled elsewhere</p>
</li>
<li><p>No IRSA → pods either can't reach AWS services or (worse) need hardcoded credentials</p>
</li>
</ul>
<p>Kubernetes architecture is a lot easier to hold onto once it's not abstract — once it's the exact set of moving parts keeping your own project alive.</p>
<hr />
<p>Thank You</p>
]]></content:encoded></item></channel></rss>