Kubernetes end-to-end project with deployment of Django notes application

Hi there! I'm Ojas Jawale, a passionate Cloud, DevOps and Cyber Security enthusiast. I love to dive into the latest new technologies and sharing my journey through blog. I'm always eager to learn and grow in this ever-evolving field of DevOps and Cyber Security. You'll find me writing about CI/CD pipelines, automation, containerization with Docker, and other exciting tech topics related to software quality and deployment. My goal is to demystify complex DevOps and Cyber Security concepts, provide practical tips on automation and testing, and inspire others in the developer and operations community. Let's connect, learn, and build amazing, high-quality software together!
Project Overview
In this Kubernetes project, the goal is to deploy and manage an application using the ojasjawale/notes-app:latest image within a dedicated namespace, notes-app on minikube cluster. This deployment will incorporate a wide range of Kubernetes concepts, each contributing to a robust and secure application environment.
This project is an extension of previous project deployed -> Django Notes App
Where, deployed an Django Notes application using Docker and pushed image on DockerHub. Now as an add-on of kubernetes, using same image deployed on DockerHub.
Installation of Minikube Cluster
For detailed steps of installation of minikube cluster visit -> Minikube Installation
In Next steps we will directly going to setup k8s cluster for project.
Step 1 : Namespace Creation
Create a namespace to organize all Kubernetes resources for this project.
Create
namespace.ymlfile,This YAML file creates a namespace named
notes-appto isolate resources and manage them more easily.
apiVersion: v1
kind: Namespace
metadata:
name: notes-app
- Apply file,
kubectl apply -f namespace.yml


Step 2 : Create Deployment
Deploy the
notes-appusing a Deployment resource to manage replicas and updates.Create
deployment.ymlfile,This Deployment ensures three replicas of the
notes-appcontainer are running and manages updates seamlessly.
apiVersion: apps/v1
kind: Deployment
metadata:
name: notes-app-deployment
namespace: notes-app
spec:
replicas: 3
selector:
matchLabels:
app: notes-app
template:
metadata:
labels:
app: notes-app
spec:
containers:
- name: notes-app
image: ojasjawale/notes-app:latest
ports:
- containerPort: 8000
- Apply file,
kubectl apply -f deployment.yml



Step 3 : Create Service
Expose the
notes-appdeployment using a Service.Create
service.ymlfile,
apiVersion: v1
kind: Service
metadata:
name: notes-app-service
namespace: notes-app
spec:
selector:
app: notes-app
ports:
- protocol: TCP
port: 80
targetPort: 8000
- Apply file,
kubectl apply -f service.yml

- For testing, port forwarding of traffic.
kubectl port-forward service/notes-app-service 8000:80 --address=0.0.0.0 -n notes-app
- Copy Public IP of instance with port 8000 and access application on browser.

Step 4 : Persistent Volumes and Claims
Set up Persistent Volumes (PV) and Persistent Volume Claims (PVC) for stateful applications.
Create
pv.ymlfile,
apiVersion: v1
kind: PersistentVolume
metadata:
name: notes-app-pv
namespace: notes-app
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
hostPath:
path: /mnt/data
- Apply file,
kubectl apply -f pv.yml

Till now persistentVolume is not claimed.
PV defines the storage resource, while PVC requests storage for a pod.
Create
pvc.ymlfile,
Claiming PV storage for POD's.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: notes-app-pvc
namespace: notes-app
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
- Apply file,
kubectl apply -f pvc.yml


- Attach storage to deployment,
apiVersion: apps/v1
kind: Deployment
metadata:
name: notes-app-deployment
namespace: notes-app
spec:
replicas: 3
selector:
matchLabels:
app: notes-app
template:
metadata:
labels:
app: notes-app
spec:
containers:
- name: notes-app
image: ojasjawale/notes-app:latest
ports:
- containerPort: 8000
volumeMounts:
- name: notes-app-storage
mountPath: /data # Mount path inside the container
volumes:
- name: notes-app-storage
persistentVolumeClaim:
claimName: notes-app-pvc # Reference to the PVC

Step 5 : Ingress Controller
To setup Ingress in minikube, need to enable addon called ingress,
minikube addon enable ingress

Set up an Ingress for path-based routing to the application.
Create
ingress.ymlfile,The Ingress routes traffic based on the URL path to the
notes-app-service, which listens on port 80 and forwards it to port 8000 in the pods.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: notes-app-ingress
namespace: notes-app
spec:
rules:
- host: notes-app
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: notes-app-service
port:
number: 80
- path: /app
pathType: Prefix
backend:
service:
name: notes-app-service
port:
number: 80

- Apply file,
kubectl apply -f ingress.yml
- Add an domain entry in
/etc/hostsfile,
sudo nano /etc/hosts

- Now, try to send query on URL,
curl notes-app

- This is an we called it as path based routing using Ingress controller.
Step 6 : Network Policies and CNI
Define Network Policies to control traffic and configure CNI for network management.
Create
networkPolicy.ymlfile,Network Policies control the communication between pods based on labels. CNI (Container Network Interface) is typically configured at the cluster level.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: notes-app-network-policy
namespace: notes-app
spec:
podSelector:
matchLabels:
app: notes-app
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: notes-app
egress:
- to:
- podSelector:
matchLabels:
app: notes-app
- Apply file,
kubectl apply -f networkPolicy.yml

Step 7 : Job and CronJob
Define a Job for one-time tasks and a CronJob for scheduled tasks.
Create
job.ymlfile,
apiVersion: batch/v1
kind: Job
metadata:
name: notes-app-job
namespace: notes-app
spec:
template:
spec:
containers:
- name: notes-app-job
image: ojasjawale/notes-app:latest
ports:
- containerPort: 8000
restartPolicy: OnFailure


- Create
cron.ymlfile,
apiVersion: batch/v1
kind: CronJob
metadata:
name: notes-app-cronjob
namespace: notes-app
spec:
schedule: "0 1 * * *" # Daily at 1 AM
jobTemplate:
spec:
template:
spec:
containers:
- name: notes-app-cronjob
image: ojasjawale/notes-app:latest
ports:
- containerPort: 8000
restartPolicy: OnFailure

Step 8 : Horizontal Pod Auto-scaling
For HPA setup in minikube, Need to enable addon called metrics-server,
minikube addons enable metrics-server

- Modify deployment for resource limiting,
apiVersion: apps/v1
kind: Deployment
metadata:
name: notes-app-deployment
namespace: notes-app
spec:
replicas: 1
selector:
matchLabels:
app: notes-app
template:
metadata:
labels:
app: notes-app
spec:
containers:
- name: notes-app
image: ojasjawale/notes-app:latest
ports:
- containerPort: 8000
resources:
requests:
cpu: "100m" # Minimum CPU required
limits:
cpu: "200m" # Maximum CPU allowed
Implement HPA to scale pods based on CPU utilization.
Create
hpa.ymlfile,
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: notes-app-hpa
namespace: notes-app
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: notes-app-deployment
minReplicas: 1
maxReplicas: 5
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 15

- Apply file,
kubectl apply -f hpa.yml

- Currently, there is only one POD is running,

- Create two screens and in one screen try port-forwarding,
kubectl port-forward service/notes-app-service 8000:80 --address=0.0.0.0 -n notes-app

- Second screen watch for real-time CPU utilization and auto-scaling of POD's,
watch kubectl get hpa -n notes-app
- POD's are scaling up automatically,




Step 9 : Role Base Access Control (RBAC)
- Create service account,
kubectl create serviceaccount k8s-user

Implement RBAC for fine-grained access control.
Create
role.ymlfile,
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: notes-app-role
namespace: notes-app
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]

- Create
roleBinding.ymlfile,
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: notes-app-rolebinding
namespace: notes-app
subjects:
- kind: User
name: k8s-user # Replace with your Kubernetes user
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: notes-app-role
apiGroup: rbac.authorization.k8s.io

Role defines permissions, and RoleBinding assigns those permissions to a user or set of users.
Testing of RBAC configurations,
Run commands using --as=user flag (Where
useris the name of the user you wish to impersonate.)As
k8s-userhas get permissions,

- As k8s-user don't have create resource permission, hence action is forbidden.

Step 10 : Testing application on browser
- Forward port on containerPort from local port and try to access application,
kubectl port-forward service/notes-app-service 8000:80 --address=0.0.0.0 -n notes-app



Connect With Me
Thank you for reading. I hope you were able to understand and learn something new from my blog.
Happy Learning!




