Kubernetes is a great choice for deploying resilient and scalable applications. In this post, I’ll walk through the process of building Docker images, pushing them to DockerHub, setting up a Kubernetes cluster, deploying the services, and enabling self healing mechanisms. This guide uses a Video Transcriber project with a frontend and backend. I’m running Docker and Kubernetes locally on a Mac.


1. Building and Pushing Docker Images

Docker allows you to package and ship your application as lightweight containers. Here’s how to build and push your images to DockerHub.

Steps:

  • Create Dockerfiles for Frontend and Backend:
    • Frontend Dockerfile:
FROM node:16
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
CMD ["npm", "start"]
  • Backend Dockerfile:
FROM python:3.9
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]
  • Build and Tag Images:
docker build -t mattclemons/transcriber-frontend:latest ./frontend
docker build -t mattclemons/transcriber-backend:latest ./backend
  • Push Images to DockerHub:
docker push mattclemons/transcriber-frontend:latest
docker push mattclemons/transcriber-backend:latest

2. Setting Up the Kubernetes Cluster

Kubernetes manages your containers across multiple nodes, ensuring they run reliably. If you’re running locally (e.g., with minikube), you can skip some cloud specific steps.

Configure kubectl:

Ensure kubectl is installed and configured to connect to your cluster:

kubectl config view
kubectl get nodes

3. Writing Kubernetes Manifests

Kubernetes manifests define how your containers will run and interact.

Frontend Deployment (frontend-deployment.yml):

apiVersion: apps/v1
kind: Deployment
metadata:
name: transcriber-frontend
labels:
app: transcriber-frontend
spec:
replicas: 1
selector:
matchLabels:
app: transcriber-frontend
template:
metadata:
labels:
app: transcriber-frontend
spec:
containers:
- name: transcriber-frontend
image: mattclemons/transcriber-frontend:latest
ports:
- containerPort: 3000
env:
- name: BACKEND_URL
value: "http://transcriber-backend:8000"

Frontend Service (frontend-service.yml):

apiVersion: v1
kind: Service
metadata:
name: transcriber-frontend
spec:
type: LoadBalancer
selector:
app: transcriber-frontend
ports:
- protocol: TCP
port: 3000
targetPort: 3000

Backend Deployment (backend-deployment.yml):

apiVersion: apps/v1
kind: Deployment
metadata:
name: transcriber-backend
labels:
app: transcriber-backend
spec:
replicas: 2
selector:
matchLabels:
app: transcriber-backend
template:
metadata:
labels:
app: transcriber-backend
spec:
containers:
- name: transcriber-backend
image: mattclemons/transcriber-backend:latest
ports:
- containerPort: 8000

Backend Service (backend-service.yml):

apiVersion: v1
kind: Service
metadata:
name: transcriber-backend
spec:
type: LoadBalancer
selector:
app: transcriber-backend
ports:
- protocol: TCP
port: 8000
targetPort: 8000

4. Deploying to Kubernetes

  • Apply Deployments and Services:
kubectl apply -f frontend-deployment.yml
kubectl apply -f frontend-service.yml
kubectl apply -f backend-deployment.yml
kubectl apply -f backend-service.yml
  • Verify Deployment: Check the status of pods and services:
kubectl get pods
kubectl get services
  • Access the Application:
    • Frontend: http://<EXTERNAL-IP>:3000
    • Backend: http://<EXTERNAL-IP>:8000

5. Adding Self Healing

Kubernetes can automatically restart unhealthy pods and ensure traffic is routed only to healthy instances.

Add Probes:

Update deployments with livenessProbe and readinessProbe:

livenessProbe:
httpGet:
path: /
port: 8000
initialDelaySeconds: 5
periodSeconds: 10
readinessProbe:
httpGet:
path: /
port: 8000
initialDelaySeconds: 5
periodSeconds: 10

Resource Limits:

Set resource requests and limits to avoid excessive CPU or memory usage:

resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1"

Apply the Changes:

kubectl apply -f backend-deployment.yml
kubectl apply -f frontend-deployment.yml

6. Testing the Setup

  • Kill a Pod: Simulate a failure:
kubectl delete pod
  • Verify Self Healing: Use kubectl describe to confirm probes are triggering restarts:
kubectl describe pod
  • Load Testing: Simulate traffic to ensure the setup handles real-world scenarios.

7. Next Steps

To take this further, consider the following optimizations:

  • Explore Horizontal Pod Autoscalers: Automatically scale pods based on CPU, memory, or custom metrics. For example:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: backend-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: transcriber-backend
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 75
  • Integrate Monitoring Tools: Use tools like Prometheus and Grafana to monitor resource usage, pod health, and more. These tools provide dashboards and alerting to keep your cluster running smoothly.
  • Optimize for Your Use Case:
    • Fine tune resource requests and limits.
    • Use network policies to secure traffic.
    • Implement rolling updates for zero downtime deployments.

The End

With Kubernetes, Docker, and proper configuration, you now have a resilient, self healing application. This setup ensures downtime is minimized, performance is optimized, and issues are handled automatically.

Categories: DevOps

0 Comments

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *