From Local Containers to the Cloud: My Hands-On K8s and Amazon EKS Journey
My Hands-On K8s and Amazon EKS Journey
When diving into DevOps and cloud-native architecture, reading about container orchestration is one thing, but actually building and breaking things is where the real learning happens. Recently, I decided to move past theoretical knowledge and get my hands dirty with Docker, Kubernetes, and ultimately, Amazon Elastic Kubernetes Service (EKS).
This write-up covers my practical journey of taking raw containerized workloads and learning how to deploy, manage, and scale them in an AWS cloud environment.
- Laying the Foundation: Docker Fundamentals
Before orchestrating containers, I needed to master how they are built and run. Kicking off my labs, I focused on the Docker CLI to understand the isolation between a host machine and a container environment.
I practiced pulling images and running both interactive and detached containers:
Bash
docker pull nginx
docker run -d --name my-nginx nginx
The real "aha" moment came when using docker exec -it <container_name> /bin/bash to jump inside a running container. This clearly demonstrated that a container operates with its own isolated filesystem and environment, completely separate from my host machine.
docker pull nginx
docker run -d --name my-nginx nginx
The real "aha" moment came when using docker exec -it <container_name> /bin/bash to jump inside a running container. This clearly demonstrated that a container operates with its own isolated filesystem and environment, completely separate from my host machine.
- Moving to Kubernetes: Pods & Declarative YAML
Once I had individual containers running, the next challenge was managing them at scale. Kubernetes was the natural next step. I started with the smallest deployable unit: The Pod.
Rather than relying on imperative command-line instructions, I fully embraced Infrastructure as Code (IaC) by writing declarative YAML manifests.
YAML
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: nginx
spec:
containers:
- name: nginx-container
image: nginx
Applying this with kubectl apply -f pod.yaml and verifying it with kubectl get pods bridged the gap between code and infrastructure. I also spent time using yq to manipulate these YAML files directly from the terminal, a crucial skill for CI/CD pipelines.
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: nginx
spec:
containers:
- name: nginx-container
image: nginx
Applying this with kubectl apply -f pod.yaml and verifying it with kubectl get pods bridged the gap between code and infrastructure. I also spent time using yq to manipulate these YAML files directly from the terminal, a crucial skill for CI/CD pipelines.
- Connecting the Dots: Labels, Selectors, and Services
Deploying a Pod is easy, but Pod IPs are ephemeral—they change if a Pod crashes or is recreated. To solve this, I explored ClusterIP Services.
By attaching Labels to my Pods, I could use Selectors within a Service manifest to route internal traffic reliably, regardless of which specific Pod was currently running. This taught me the core Kubernetes routing flow:Client ➔ K8s Service ➔ Selector ➔ Matching Pod
- Automation and Scaling: Deployments & ReplicaSets
Manually deploying Pods isn’t viable for production. To automate this, I implemented Deployments. By simply declaring replicas: 2 in my Deployment YAML, Kubernetes automatically created a ReplicaSet to ensure that exactly two instances of my application were running at all times.
When I intentionally deleted a running Pod, Kubernetes instantly spun up a replacement. This was a perfect demonstration of K8s's most powerful feature: continuously monitoring and correcting the cluster to match the user's desired state.
- Taking it to the Cloud: Amazon EKS
After grasping local K8s concepts, it was time to transition to enterprise-grade infrastructure using Amazon EKS.
Setting up EKS required tying together several AWS services:
Provisioning the EKS Control Plane and Worker Nodes.
Configuring IAM roles for proper cluster permissions.
Using eksctl and the AWS CLI to streamline cluster creation.
Once the infrastructure was up, I updated my local kubeconfig to point to the AWS cluster. Running kubectl get nodes and seeing my AWS EC2 instances report back as K8s worker nodes was a major milestone. It proved that the exact same YAML manifests I used locally could now deploy globally scalable applications on AWS.
- Developing a Troubleshooting Workflow
Things don’t always work on the first try. I developed a structured debugging workflow rather than blindly tearing down and rebuilding resources:
Check Status: kubectl get pods, deployments, or services
Investigate: kubectl describe pod <name> or kubectl logs <name>
Analyze: Check YAML indentation, image names, and label/selector matching.
Remediate: Fix the YAML and re-apply (kubectl apply -f).
The Road Ahead
This hands-on progression—from spinning up a single Docker container to managing a resilient AWS EKS cluster—has solidified my understanding of modern DevOps infrastructure.
This hands-on progression—from spinning up a single Docker container to managing a resilient AWS EKS cluster—has solidified my understanding of modern DevOps infrastructure.
My next steps on the AWS and cloud-native roadmap include:
Networking & Ingress: Exposing EKS applications to the public internet using AWS ALBs and Ingress controllers.
Persistent Storage: Attaching AWS EBS volumes to K8s Pods for stateful applications.
Security & Config: Managing environment variables with ConfigMaps and Secrets.
Observability: Implementing Prometheus and Grafana for cluster monitoring.
Kubernetes and AWS can seem overwhelming on paper, but building this architecture layer by layer has demystified the cloud-native ecosystem. I'm excited to continue scaling these foundations into production-ready AWS deployments.
Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article