<?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: altered</title>
    <description>The latest articles on DEV Community by altered (@altered_c3).</description>
    <link>https://dev.to/altered_c3</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%2F3674051%2Ff0e10a39-962e-4142-8186-4af7d4310ead.png</url>
      <title>DEV Community: altered</title>
      <link>https://dev.to/altered_c3</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/altered_c3"/>
    <language>en</language>
    <item>
      <title>i built and deployed a 3-tier app on kubernetes and aws eks</title>
      <dc:creator>altered</dc:creator>
      <pubDate>Sat, 30 May 2026 15:38:06 +0000</pubDate>
      <link>https://dev.to/altered_c3/i-built-and-deployed-a-3-tier-app-on-kubernetes-and-aws-eks-15dn</link>
      <guid>https://dev.to/altered_c3/i-built-and-deployed-a-3-tier-app-on-kubernetes-and-aws-eks-15dn</guid>
      <description>&lt;p&gt;i recently finished building and deploying a 3-tier application, starting locally on minikube and then migrating it to aws eks. this post is about what i built, how it all connects, and a couple of things that tripped me up along the way as a beginner who recently completed the aws certified cloud practitioner (clf-c02) exam and the kubernetes and cloud native associate (kcna) certification.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;what i built&lt;/strong&gt;&lt;br&gt;
a simple 3-tier app with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a frontend — nginx serving an html page&lt;/li&gt;
&lt;li&gt;a backend — node.js api&lt;/li&gt;
&lt;li&gt;a database — mongodb&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;the full picture&lt;/strong&gt;&lt;br&gt;
browser → aws alb → ingress → frontend pod (nginx) → backend pod (node.js) → database pod (mongodb) → ebs volume (persistent storage)&lt;/p&gt;

&lt;p&gt;nothing really fancy, just needed to do some hands on in the cloud. &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%2Fbkwd8px9qlg0b966x4br.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%2Fbkwd8px9qlg0b966x4br.png" alt="kubectl get all terminal screenshot showing all three pods running" width="800" height="619"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;how it works locally (minikube)&lt;/strong&gt;&lt;br&gt;
i started on minikube, a tool that runs kubernetes on your local machine. the goal was to understand the concepts before touching any cloud resources.&lt;br&gt;
each tier runs in its own kubernetes deployment, which manages your pods and keeps them running. pods talk to each other through services, which give stable dns names inside the cluster. so instead of hardcoding ip addresses, the backend just calls database-service and kubernetes figures out where that is.&lt;br&gt;
sensitive config like database credentials went into a secret. non-sensitive config like the database hostname went into a configmap. both get injected into pods as environment variables at runtime.&lt;br&gt;
the database needed storage that survives pod restarts, so i attached a persistentvolumeclaim. kubernetes provisions the storage and mounts it inside the database pod.&lt;br&gt;
for traffic routing i set up ingress, a single entry point that routes requests based on url path. / goes to the frontend, /api/* goes to the backend.&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%2Ft79dq8nbj9zx195xqgqk.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%2Ft79dq8nbj9zx195xqgqk.png" alt="ive app screenshot showing " width="799" height="390"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;migrating to aws eks&lt;/strong&gt;&lt;br&gt;
once everything worked locally, i deployed the same app to aws eks — amazon's managed kubernetes service. the manifests are pretty much the same except that a few things change when moving to the cloud.&lt;br&gt;
for example, aws ecr(elastic container registry) replaced cases where i would have built images directly into minikube's docker daemon. on eks(elastic kubernetes service), worker nodes are ec2(elastic compute cloud) instances. so i pushed images to amazon ecr (elastic container registry) and updated my deployments to pull from there.&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%2F2c479demn71bh6cw369r.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%2F2c479demn71bh6cw369r.png" alt="ecr repositories showing backend and frontend" width="800" height="215"&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%2F7abzjlfjiojuy6ioyfiq.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%2F7abzjlfjiojuy6ioyfiq.png" alt="ec2 instances showing two t3.small worker nodes running" width="799" height="203"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;i used ebs(elastic block store) for database storage on aws, as opposed to  that on minikube which uses local storage. i updated the storageclass in the initially deployed persistent volume claim from standard to gp2 and installed the ebs csi(container storage interface) driver so kubernetes could provision ebs volumes automatically.&lt;br&gt;
locally i used minikube tunnel to expose the app. on eks, i used the alb(application load balancer). the aws load balancer controller watches the ingress resources and automatically creates a real application load balancer with a public dns address.&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%2F6s8j4f1oprva94mkjlc9.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%2F6s8j4f1oprva94mkjlc9.png" alt="oad balancers page showing the ALB active and internet-facing" width="799" height="166"&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%2F1qlg30sd83ft82basjkr.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%2F1qlg30sd83ft82basjkr.png" alt="terminal showing kubectl get ingress with the ALB address, kubectl get pvc showing Bound, kubectl get nodes showing two ready nodes" width="798" height="142"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;a couple of things that caught me out&lt;/strong&gt;&lt;br&gt;
&lt;u&gt;arm64 vs amd64&lt;/u&gt; — my mac uses apple silicon (arm64). when i built docker images locally and pushed to ecr, the eks nodes (which run on intel/amd processors) couldn't run them. the error showed an exec format error. the fix was rebuilding with &lt;code&gt;docker buildx build --platform linux/amd64&lt;/code&gt; to explicitly target the right architecture. &lt;br&gt;
&lt;u&gt;iam permissions&lt;/u&gt; — on aws, the elastic block store container storage interface driver and the load balancer controller both need to call aws apis to do their jobs. and without the right permissions attached to them, it would fail. this is solved with irsa (iam roles for service accounts) — a way to give kubernetes pods aws permissions without hardcoding credentials. you link a kubernetes service account to an iam role, and pods using that service account automatically get the right aws access.&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%2Frry77c371o8d8r7n64ye.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%2Frry77c371o8d8r7n64ye.png" alt="IAM roles page showing all the eksctl-created IRSA roles" width="799" height="433"&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%2Fjicg2p2l49kcyp4jzpj0.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%2Fjicg2p2l49kcyp4jzpj0.png" alt="EKS cluster page showing three-tier-cluster Active" width="800" height="161"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;looking to build more interesting projects on the cloud and will talk  about my journey here.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>kubernetes</category>
      <category>cloud</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
