πŸš€ My First Real K8s Deploy! Getting the Django Notes App LiveπŸŽ‰



This content originally appeared on DEV Community and was authored by Hritik Raj

Hey dev.to fam! πŸ‘‹

There’s something uniquely thrilling about taking a raw application and seeing it hum to life in a Kubernetes cluster. For a while, I’ve been diving deep into K8s concepts, but theory only gets you so far, right? Today, I want to share my “A-Ha!” moment: deploying a simple, but real-world, application to Kubernetes!

I picked a fantastic beginner-friendly project: the LondheShubham153/django-notes-app! πŸ“ It’s a straightforward Django app for creating, reading, updating, and deleting notes. Perfect for focusing on the K8s deployment itself without getting lost in app complexity.

In this post, I’ll walk you through how I got this app running using just three essential Kubernetes YAML files: namespace.yml, deployment.yml, and service.yml. Let’s get that app online! 🌐

Why Kubernetes for a Simple App? πŸ€”

You might think, “Kubernetes for a simple notes app? Isn’t that overkill?” And you’d be right… if this were a production environment without complex needs.

But for learning, it’s perfect! It forces you to understand:

  • How your app runs in a container.
  • How to manage its lifecycle.
  • How to make it accessible.
  • The power of K8s to scale and heal itself (even if we’re not fully showing it off here!).

It’s like learning to drive a race car on a simple track – you get the feel for the power! πŸŽπŸ’¨

The Project: LondheShubham153/django-notes-app πŸ“

Huge shoutout to LondheShubham153 for creating this awesome, straightforward Django project!

  • 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 assume the app uses an internal SQLite database (which means data isn’t persistent across Pod restarts – a good “next step” to address with Persistent Volumes!).

Before we deploy: You’ll need to have this Django app containerized. The original repo includes a Dockerfile. You’d typically build this image and push it to a Docker registry (like Docker Hub) that your Kubernetes cluster can access. For example: docker build -t yourdockerhub/django-notes-app:latest . and then docker push yourdockerhub/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 up, a Namespace. Think of a Namespace as a way to create a private, isolated sandbox within your Kubernetes cluster. It helps keep your resources organized and prevents naming conflicts with other projects.

# namespace.yml
apiVersion: v1
kind: Namespace
metadata:
  name: notes-app-ns # Our dedicated sandbox!

Why a Namespace? Good practice! It’s like having separate folders for different projects on your computer. Keeps things tidy! πŸ“

2. The App Manager: deployment.yml πŸ§‘β€πŸ’»

This is the big one! A Deployment is how we tell Kubernetes: “Hey, run this app, make sure you always have X copies, and if one crashes, replace it!”

# deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: notes-app-deployment
  namespace: notes-app-ns # Deploy this into our sandbox!
  labels:
    app: notes-app
spec:
  replicas: 1 # For simplicity, let's start with one copy
  selector:
    matchLabels:
      app: notes-app # Find Pods with this label
  template:
    metadata:
      labels:
        app: notes-app # Assign this label to our Pods
    spec:
      containers:
      - name: django-notes-app
        image: yourdockerhub/django-notes-app:latest # REPLACE WITH YOUR IMAGE! 🚨
        ports:
        - containerPort: 8000 # Django's default port
        env: # Basic environment variables Django might need
        - name: DEBUG
          value: "True" # Set to False for production!
        - name: DJANGO_SETTINGS_MODULE
          value: "notes_app.settings"
        # Add SECRET_KEY here for production!

What’s happening here?

  • We’re telling Kubernetes to create a Deployment named notes-app-deployment inside our notes-app-ns Namespace.
  • It will ensure 1 replica (copy) of our app is always running.
  • It pulls the Docker image (remember to replace yourdockerhub/django-notes-app:latest with your pushed image!).
  • Our app runs on port: 8000 inside the container.

3. The Stable Address: service.yml πŸ“ž

Pods are like nomads with changing IPs. A Service gives them a stable, unchanging address and helps balance traffic if you have multiple Pod copies. For this quick test, we’ll use a NodePort Service to access our app from outside the cluster.

# service.yml
apiVersion: v1
kind: Service
metadata:
  name: notes-app-service
  namespace: notes-app-ns # Our Service lives in the same sandbox!
spec:
  selector:
    app: notes-app # This Service will route traffic to Pods with this label
  ports:
    - protocol: TCP
      port: 80 # The port the Service will listen on
      targetPort: 8000 # The port our Django app is listening on inside the Pod
      nodePort: 30080 # (Optional) A specific port on EACH node (30000-32767 range)
  type: NodePort # This type exposes our app via the Node's IP and nodePort

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 pushed to a registry.
  1. Save the YAMLs: Copy the YAML snippets above into files named namespace.yml, deployment.yml, and service.yml in a directory.
  2. Create the Namespace:

    kubectl apply -f namespace.yml
    # Output: namespace/notes-app-ns created
    
  3. Deploy Your Application:

    kubectl apply -f deployment.yml
    # Output: deployment.apps/notes-app-deployment created
    

    Give it a few moments to pull the image and create the Pod!

  4. Expose Your Application:

    kubectl apply -f service.yml
    # Output: service/notes-app-service created
    

Verify & Access Your App! πŸŽ‰

  1. Check all resources in your namespace:

    kubectl get all -n notes-app-ns
    

    You should see your Pod(s), Deployment, and Service!

  2. Get your Service details:

    kubectl get service notes-app-service -n notes-app-ns
    

    Look for the PORT(S) column. It should show something like 80:30080/TCP. The 30080 (or whatever nodePort was assigned) is your external port!

  3. 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` or `127.0.0.1`.
  * For cloud clusters: Get the public IP of any worker node.
  1. 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! πŸš€πŸ“

My “A-Ha!” Moments & What I Learned! πŸ’‘

  • kubectl apply is Magical: Just pointing it at a YAML file and seeing K8s make it happen feels incredibly powerful.
  • Deployments are Smart Managers: I only asked for 1 replica, but the Deployment would diligently ensure that one Pod is always running. If I changed replicas to 3, it would magically scale up!
  • Services are True Navigators: That NodePort just opens a door on every node, and the Service reliably forwards traffic to my Pods, even if they restart. The stability is amazing!
  • Namespaces for Organization: Even for a single app, using a Namespace makes everything cleaner.

What’s Next? My K8s Learning Journey Continues! ⏭

This was just the first step! For a production-ready Django app, I’d need to explore:

  • Persistent Storage: Using PersistentVolumeClaims and PersistentVolumes for the database (e.g., PostgreSQL instead of SQLite) so data truly survives Pod restarts.
  • Database Deployment: Running a PostgreSQL database also in Kubernetes (maybe as a StatefulSet).
  • Ingress: Using an Ingress controller to expose my app on a proper domain name (e.g., notes.mydomain.com) with HTTPS, instead of a raw IP and port.
  • Secrets & ConfigMaps: Securely managing database credentials and other configuration.
  • CI/CD: Automating the build, push, and deploy process!

This simple deploy was incredibly rewarding and clarified so many concepts. If you’re new to Kubernetes, I highly recommend picking a small app and trying to deploy it end-to-end. It makes all the theory click!

Have you deployed your first app to Kubernetes? What were your biggest learnings or challenges? Share them in the comments below! πŸ‘‡ Let’s build awesome things together!


This content originally appeared on DEV Community and was authored by Hritik Raj