π My First Real K8s Deploy! Getting the Django Notes App Live (and Troubleshooting!)

Hey Hashnode fam! π
There's nothing quite like that "Eureka!" moment when you deploy your first actual application to Kubernetes. All that YAML, all those concepts... suddenly, it just clicks! For me, that moment came when I decided to take a beloved simple project and launch it into the K8s universe.
I chose the fantastic LondheShubham153/django-notes-app
! π It's a straightforward Django app for managing notes β perfect for focusing on the Kubernetes side without getting bogged down in app complexity.
A huge shoutout to Shubham Londhe for creating this wonderfully clear repository and for his excellent way of teaching. It made this learning journey genuinely enjoyable! π
In this post, I'll walk you through how I got this app up and running using just three core Kubernetes YAMLs: namespace.yml
, deployment.yml
, and service.yml
. And because learning means facing hiccups, I'll also share some common issues you might face and how to fix them! Let's get that app online! π
Why Kubernetes for a Simple App? π€
You might be thinking, "K8s for a tiny notes app? Isn't that like using a rocket launcher to swat a fly?" ππ¦
And yes, for a production scenario without complex needs, it might be overkill. But for learning, it's phenomenal! It forces you to understand:
How your app fits into a container.
How Kubernetes magically keeps it running.
How to expose it to the world.
The foundations of scalability and resilience (even if we're not fully showing it off here!).
It's like getting behind the wheel of a high-performance car on a simple track β you really get a feel for what it can do! ποΈπ¨
The Project: LondheShubham153/django-notes-app
π
Again, a big thank you to LondheShubham153 for this awesome little Django app!
What it is: A basic CRUD (Create, Read, Update, Delete) notes application built with Django.
Why it's great for K8s learning: It's simple, well-structured, and easy to containerize. For this initial deployment, we'll run it with its default SQLite database (which means notes won't stick around if your Pod restarts β but that's a "next step" to tackle!).
Before we deploy: You need to have this Django app in a Docker image and pushed to a registry (like Docker Hub) that your Kubernetes cluster can access.
You'd typically do: docker build -t yourdockerhubusername/django-notes-app:latest . then docker push yourdockerhubusername/django-notes-app:latest.
Our Kubernetes Building Blocks (The YAML Files)! π§±
Let's peek into the magic spellbooks (YAML files) we'll use!
1. The Private Sandbox: namespace.yml
ποΈ
First, a Namespace
. Think of it as creating a dedicated, clean playroom for your app within the big Kubernetes house. It keeps your app's resources separate from others, preventing clutter and conflicts.
YAML
# namespace.yml
apiVersion: v1
kind: Namespace
metadata:
name: django-notes-app-ns # Our dedicated sandbox for the notes app!
Why a Namespace? Good practice! It's like having separate folders for different projects on your computer. Keeps things tidy and easy to manage! π
2. The App Manager: deployment.yml
π§βπ»
This is where the real work happens! A Deployment
tells Kubernetes: "Hey, run this specific app, always make sure you have X copies of it, and if one copy goes down, spin up a new one!"
YAML
# deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: notes-app-deployment
namespace: django-notes-app-ns # Deploy this into our sandbox!
labels:
app: django-notes-app # A label for our app, used by the Service
spec:
replicas: 1 # For simplicity, let's start with one copy of our app
selector:
matchLabels:
app: django-notes-app # This Deployment will manage Pods with this label
template: # This describes the Pods that the Deployment will create
metadata:
labels:
app: django-notes-app # Assign this label to our Pods
spec:
containers:
- name: django-notes-app-container
image: yourdockerhubusername/django-notes-app:latest # π¨ IMPORTANT: REPLACE WITH YOUR DOCKER IMAGE!
ports:
- containerPort: 8000 # Django's default development server port
env: # Basic environment variables Django might need
- name: DEBUG
value: "True" # Set to "False" for production and configure ALLOWED_HOSTS!
- name: DJANGO_SETTINGS_MODULE
value: "notes_app.settings"
# For production, you'd also need SECRET_KEY here (consider using a Kubernetes Secret!)
What's happening here?
We're defining a
Deployment
for our notes app inside thedjango-notes-app-ns
Namespace.We're asking for
1
replica
(copy) of our app Pod. Kubernetes will ensure this copy is always running.It pulls your Docker
image
(don't forget to replace the placeholder!).Our Django app listens on
port: 8000
inside its container.
3. The Stable Address: service.yml
π
Pods are like nomads with ever-changing IPs. A Service
gives them a stable, unchanging address and intelligently balances traffic if you have multiple copies. For this quick test, we'll use a NodePort
Service to access our app from outside the cluster.
YAML
# service.yml
apiVersion: v1
kind: Service
metadata:
name: notes-app-service
namespace: django-notes-app-ns # Our Service lives in the same sandbox!
spec:
selector:
app: django-notes-app # This Service will route traffic to Pods with this label
ports:
- protocol: TCP
port: 80 # The port the Service itself will listen on (clients will connect to this)
targetPort: 8000 # The port our Django app is actually listening on inside the Pod
nodePort: 30080 # (Optional) Kubernetes will open this specific port on EACH Node (range 30000-32767). Pick one not in use!
type: NodePort # This type exposes our app via the Node's IP and a specific port
Why NodePort
? For learning and quick demos, NodePort
is super convenient! Kubernetes will open port 30080
(or another random one if you omit nodePort
) on every server (Node) in your cluster. You can then access your app via ANY_NODE_IP:30080
! π
Let's Deploy! The Simple Steps! π
Before you start, make sure you have:
A running Kubernetes cluster (Minikube, Kind, Docker Desktop K8s, or a cloud cluster).
kubectl
configured to connect to your cluster.Your
django-notes-app
Docker image built and pushed to a public (or accessible) registry.
Save the YAMLs: Copy the YAML snippets above into files named
namespace.yml
,deployment.yml
, andservice.yml
in a dedicated directory.Create the Namespace:
Bash
kubectl apply -f namespace.yml # Expected Output: namespace/django-notes-app-ns created
Deploy Your Application:
Bash
kubectl apply -f deployment.yml # Expected Output: deployment.apps/notes-app-deployment created
Give it a few moments for Kubernetes to pull the image and create the Pod!
Expose Your Application:
Bash
kubectl apply -f service.yml # Expected Output: service/notes-app-service created
Verify & Access Your App! π
Check all resources in your namespace:
Bash
kubectl get all -n django-notes-app-ns
You should see your Pod(s), Deployment, and Service! All looking
Running
orReady
!Get your Service details (find that NodePort!):
Bash
kubectl get service notes-app-service -n django-notes-app-ns
Look for the
PORT(S)
column. It should show something like80:30080/TCP
. The30080
(or whatevernodePort
was assigned) is your external port!Find your Node's IP:
If you're using Minikube:
minikube ip
If you're using Docker Desktop K8s: Your Node IP is usually
localhost
or127.0.0.1
.For cloud clusters: Get the public IP of any worker node (e.g., via
kubectl get nodes -o wide
).
Access your app! Open your browser and go to:
http://<YOUR_NODE_IP>:<NODE_PORT> (e.g., http://192.168.49.2:30080 or http://localhost:30080)
Congratulations! You should see the Django Notes App running! ππ
π₯ Common Issues You Might Face & How to Fix Them! π©Ή
It's rare for a first deploy to go perfectly smooth. Here are some common hiccups and how to debug them! Don't get discouraged! πͺ
1. ImagePullBackOff
or ErrImagePull
πΌοΈβ
What it means: Kubernetes tried to pull your Docker image but failed.
Common Causes:
Typo in image name: You spelled
yourdockerhubusername/django-notes-app:latest
wrong.Image not found: You didn't push the image, or it's a private registry and Kubernetes doesn't have credentials.
Incorrect tag: You used
latest
but pushed withv1.0
.
How to Fix:
Check Pod events:
kubectl describe pod <pod-name> -n django-notes-app-ns
(Look under "Events" section).Verify image name: Double-check your
deployment.yml
image
field.Check registry: Is the image public? If private, you'll need a
imagePullSecrets
in your Deployment.
2. CrashLoopBackOff
ππ₯
What it means: Your Pod started, but the container inside immediately crashed and Kubernetes is trying to restart it repeatedly.
Common Causes:
Application error: Your Django app has a bug that prevents it from starting.
Incorrect
CMD
orENTRYPOINT
in Dockerfile: The container isn't running the right command.Missing environment variables: Your app needs specific env vars (
SECRET_KEY
, database URL) to start.Port mismatch: Your app expects a different port than you exposed.
How to Fix:
Check Pod logs:
kubectl logs <pod-name> -n django-notes-app-ns
(This is your #1 debugging tool!). Look for error messages from your Django app.Check Pod events:
kubectl describe pod <pod-name> -n django-notes-app-ns
(Look for "Liveness probe failed" or other errors).Review Dockerfile: Ensure your
CMD
orENTRYPOINT
correctly runs the Django development server (e.g.,python manage.py runserver 0.0.0.0:8000
).Environment Variables: For Django, make sure
DEBUG
isTrue
for dev, and you set aSECRET_KEY
(even a dummy one for local testing).
3. Service Not Accessible / No Endpoints π«π
What it means: Your Service is running, but it's not routing traffic to any Pods, or you can't access it from outside.
Common Causes:
Label mismatch: The
selector
in yourservice.yml
doesn't exactly match thelabels
in yourdeployment.yml
(or your Pods). This is a very common one!targetPort
incorrect: ThetargetPort
in your Service doesn't match thecontainerPort
your app is listening on.Firewall/Security Group: Your cloud provider's firewall might be blocking the
NodePort
.No running Pods: The Pods linked to the Service are in
Pending
orCrashLoopBackOff
state.
How to Fix:
Check Service Endpoints:
kubectl get endpoints notes-app-service -n django-notes-app-ns
. If the list is empty, no Pods are connected!Verify Labels: Triple-check that
spec.selector.app
inservice.yml
exactly matchesspec.template.metadata.labels.app
indeployment.yml
.Verify Ports: Ensure
service.yml
targetPort
matchesdeployment.yml
containerPort
.Check Pod Status: Use
kubectl get pods -n django-notes-app-ns
. Are theyRunning
andReady
? If not, fix those first (see issues above).Firewall: If on a cloud VM, ensure the
NodePort
(e.g., 30080) is open in your VM's security group/firewall rules.
4. Pending
Pods β³
What it means: Your Pods are stuck, waiting to be scheduled onto a Node.
Common Causes:
Not enough resources: The cluster doesn't have enough CPU or memory for your Pod.
Node Taints/Tolerations: Nodes might have specific restrictions your Pod can't meet.
Volume issues: If you were using Persistent Volumes (not in this simple deploy, but good to know!), storage might not be available.
How to Fix:
Describe Pod:
kubectl describe pod <pod-name> -n django-notes-app-ns
. Look for messages like "Insufficient cpu" or "Insufficient memory" in the "Events" section.Check Node Resources:
kubectl top nodes
(if metrics server is installed) orkubectl describe node <node-name>
.
What's Next? My K8s Learning Journey Continues! βοΈ
This deploy was just the start! For a production-ready Django app, you'd definitely want to explore:
Persistent Storage (Crucial for Django!): Using
PersistentVolumeClaims
andPersistentVolumes
for your PostgreSQL/MySQL database so your notes actually stick around across Pod restarts! πΎDatabase Deployment: Running a proper database (like PostgreSQL) also in Kubernetes (often using
StatefulSets
).Ingress: Using an
Ingress
controller to expose your app on a proper domain name (e.g.,notes.yourdomain.com
) with HTTPS, instead of a raw IP and port.Secrets & ConfigMaps: Securely managing database credentials, API keys, and other configurations. π
CI/CD: Automating the build, push, and deploy process! ποΈβ‘οΈπ
Health Checks: Adding
livenessProbe
andreadinessProbe
to your Deployment to make it even more resilient.
This simple deployment was incredibly rewarding and clarified so many core Kubernetes concepts. If you're new to Kubernetes, I highly recommend picking a small, familiar app and trying to deploy it end-to-end. It makes all the theory truly click!
Have you had similar "A-Ha!" moments or faced other common K8s deployment issues? Share your experiences and tips in the comments below! π Let's learn and build awesome things together!
Subscribe to my newsletter
Read articles from Hritik Raj directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Hritik Raj
Hritik Raj
π Hey there! I'm a university student currently diving into the world of DevOps. I'm passionate about building efficient, scalable systems and love exploring how things work behind the scenes. My areas of interest include: βοΈ Cloud Computing π§ Networking & Infrastructure π’οΈ Databases βοΈ Automation & CI/CD Currently learning tools like Docker, Kubernetes, and exploring various cloud platforms. Here to learn, build, and share my journey. Letβs connect and grow together! π