Day 16 of my 90-Day Devops Project: Implementing Canary Deployment
Today, I focused on setting up the basics for canary deployment.
Project Overview
In my day 16 project, I established a canary deployment for a simple web app with Docker and kubernetes (minikube). This method basically enables a phased feature rollout minimizing the risks associated with new releases.
My Folder Structure
Day15-canarydeployment/
│
├── app/
│ ├── app.py
│ ├── requirements.txt
│ └── Dockerfile
│
├── canary/
│ ├── canary.py
│ ├── requirements.txt
│ └── Dockerfile
│
├── deployment/
│ └── k8s/
│ ├── deployment.yaml
│ └── service.yaml
│
└── scripts/
├── deploy.sh
└── monitor.sh
Steps to Complete the Project
Step 1: Application Setup
Create the Main Application
- File:
app/app.py
- File:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def home():
return "Main Application is running!"
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
Dependencies: Create
app/requirements.txt
Flask==2.0.3
Dockerize the Application: Create
app/Dockerfile
FROM python:3.9 WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY app.py . EXPOSE 5000 CMD ["python", "app.py"]
Step 2: Canary Application Setup
Create the Canary Application
- File:
canary/canary.py
- File:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def home():
return "Canary Application is running!"
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5001)
Dependencies: Create
canary/requirements.txt
Flask==2.0.3
Dockerize the Canary Application: Create
canary/Dockerfile
FROM python:3.9-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY canary.py . EXPOSE 5001 CMD ["python", "canary.py"]
Step 3: Kubernetes Deployment
Define all Kubernetes Resources
- Deployments: Create
deployment/k8s/deployment.yaml
- Deployments: Create
apiVersion: apps/v1
kind: Deployment
metadata:
name: main-app
spec:
replicas: 3
selector:
matchLabels:
app: main-app
template:
metadata:
labels:
app: main-app
spec:
containers:
- name: main-app
image: your-docker-repo/main-app:latest
ports:
- containerPort: 5000
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: canary-app
spec:
replicas: 1
selector:
matchLabels:
app: canary-app
template:
metadata:
labels:
app: canary-app
spec:
containers:
- name: canary-app
image: your-docker-repo/canary-app:latest
ports:
- containerPort: 5001
Services: Create
deployment/k8s/service.yaml
apiVersion: v1 kind: Service metadata: name: main-app-service spec: type: ClusterIP selector: app: main-app ports: - port: 80 targetPort: 5000 --- apiVersion: v1 kind: Service metadata: name: canary-app-service spec: type: ClusterIP selector: app: canary-app ports: - port: 81 targetPort: 5001
Step 4: Deployment Scripts
Create Deployment Script
- File:
scripts/deploy.sh
- File:
#!/bin/bash
docker build -t your-docker-repo/main-app:latest ./app
docker build -t your-docker-repo/canary-app:latest ./canary
docker push your-docker-repo/main-app:latest
docker push your-docker-repo/canary-app:latest
kubectl apply -f deployment/k8s/
Monitoring Script
- File:
scripts/monitor.sh
- File:
#!/bin/bash
kubectl logs -l app=main-app
kubectl logs -l app=canary-app
kubectl get deployments
Note: kindly replace all placeholders with your actual details
Challenges and Solutions
Challenges Encountered
Minikube Not Installed:
- Initially, the system didn't recognize Minikube because of a PATH issue. To resolve this, I needed to configure the system PATH properly to ensure Minikube was accessible.
Existing Minikube Instance:
- Minikube detected an existing instance, which prevented me from starting a new cluster. To resolve this, I use the command
minikube delete
to remove the existing instance, and then I could start a new Minikube cluster usingminikube start
.
- Minikube detected an existing instance, which prevented me from starting a new cluster. To resolve this, I use the command
kubectl
Configuration:- To ensure
kubectl
could communicate with the Minikube cluster, I needed to configure thekubectl
context to use Minikube by running the commandkubectl config use-context minikube
.
- To ensure
Solutions
Verify Minikube Installation:
- I used the command "minikube version" to check the Minikube version and ensure its proper installation.
Delete Existing Minikube Cluster:
- The command
minikube delete
helped to remove the existing Minikube instance, which allowed me to start a new cluster.
- The command
Check VirtualBox:
- In addition, I confirmed that VirtualBox was properly installed and operational since Minikube relies on its virtual machine.
Start Minikube:
- After resolving the previous issues, I could start the Minikube cluster using the command
minikube start
.
- After resolving the previous issues, I could start the Minikube cluster using the command
Access Logs:
- To troubleshoot any remaining issues, I checked the Minikube logs using the command
minikube logs
.
- To troubleshoot any remaining issues, I checked the Minikube logs using the command
These steps helped me to resolve the challenges I faced during the setup of the Minikube environment for this project.
Expected Results
- Main Application: When you visit
http://localhost:80
, you should see the message:
Main Application is running!
- Canary Application: When you visit
http://localhost:81
, you should see the message:
Canary Application is running!
Conclusion
Canary deployment ensures a gradual rollout of new application features, allowing teams to collect feedback and
Monitor performance before the full release. By addressing challenges with effective solutions, you can reduce risks and maintain stability.
I think it's a great approach, as it helps identify areas for improvement and allows for changes to be made before a complete release.
Subscribe to my newsletter
Read articles from Abigeal Afolabi directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Abigeal Afolabi
Abigeal Afolabi
🚀 Software Engineer by day, SRE magician by night! ✨ Tech enthusiast with an insatiable curiosity for data. 📝 Harvard CS50 Undergrad igniting my passion for code. Currently delving into the MERN stack – because who doesn't love crafting seamless experiences from front to back? Join me on this exhilarating journey of embracing technology, penning insightful tech chronicles, and unraveling the mysteries of data! 🔍🔧 Let's build, let's write, let's explore – all aboard the tech express! 🚂🌟 #CodeAndCuriosity