Skip to content

Repository files navigation

SMS Spam Detection System - Implementation Overview

This repository contains the operational setup for the SMS Spam Detection system, covering assignments A1 through A4 with complete deployment instructions.

Repository Links

  • app - Spring Boot frontend and API gateway
  • model-service - Flask ML backend with scikit-learn
  • lib-version - Version-aware Maven library
  • operation - Docker Compose orchestration, Kubernetes Provisioning, Monitoring, Service Mesh (this repository)

Repository Links (Tag: a1)

Repository Links (Tag: a2)

Repository Links (Tag: a3)

Repository Links (Tag: a4)

Prerequisistes

Required Tools

  1. Git: Version control system
# Ubuntu/Debian
sudo apt update && sudo apt install git

# macOS
brew install git
  1. Docker & Docker Compose: Container runtime
# Ubuntu/Debian
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker $USER
sudo apt install docker-compose-plugin
# Restart session or run: newgrp docker
  1. Java 25 & Maven: For building Java applications
sudo apt install openjdk-25-jdk maven
  1. Python 3: For machine learning service
sudo apt install python3 python3-pip python3-flask python3-scikit-learn python3-joblib
  1. Vagrant & VirtualBox: For Kubernetes cluster provisioning (A2)
sudo apt install virtualbox vagrant
  1. kubectl & Helm: Kubernetes tools (A2-A4)
# kubectl
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl && sudo mv kubectl /usr/local/bin/

# Helm
curl https://get.helm.sh/helm-v3.14.0-linux-amd64.tar.gz -o helm.tar.gz
tar -zxvf helm.tar.gz && sudo mv linux-amd64/helm /usr/local/bin/

Environment Variables

Set these environment variables for GitHub Package Registry access:

export GITHUB_USERNAME="your-github-username"
export GITHUB_TOKEN="your-github-personal-access-token"

Quick Start

A1: Docker Compose

git clone https://github.com/doda25-team6/app.git
git clone https://github.com/doda25-team6/model-service.git
git clone https://github.com/doda25-team6/lib-version.git
git clone https://github.com/doda25-team6/operation.git
cd operation
git checkout a1
docker compose up --build

Access the application at http://localhost:8080/sms/

A2-A4: Kubernetes Cluster

cd operation
vagrant up

cd ansible && ansible-playbook -u vagrant -i 192.168.56.100, finalization.yml

# Enable Istio sidecar injection for the namespace
kubectl label ns default istio-injection=enabled

# Deploy the application with Prometheus
cd /vagrant/charts/project-app
helm install project .

This will:

  1. Create 3 VMs (1 controller + 2 workers)
  2. Install Kubernetes v1.32.4
  3. Configure networking (Flannel CNI)
  4. Install cluster services (MetalLB, Nginx Ingress, Dashboard, Istio)

Access the cluster:

# From host machine
kubectl --kubeconfig=admin.conf get nodes

# Or SSH into controller
vagrant ssh ctrl
kubectl get nodes

Destroy cluster:

vagrant destroy -f

Istio traffic management (Gateway, VirtualService, DestinationRule)

Defaults (can be overridden):

  • Gateway name: istio.gateway.name (default: istio-gateway)
  • IngressGateway selector labels: istio.gateway.selector (default: { istio: ingressgateway })

Canary 90/10 + sticky sessions

  • The chart implements “assign once, then pin”:
  • First request gets assigned via 90/10 routing to v1/v2.
  • The response sets a cookie (default exp_canary=v1|v2).
  • Reloads send the cookie, and routing becomes sticky per user.

First request (observe assignment via Set-Cookie):

curl -i http://192.168.56.91/

Sticky follow-up:

curl -i -c user.cookies http://192.168.56.91/
curl -i -b user.cookies http://192.168.56.91/

Force a version with a cookie:

curl -i -H "Cookie: exp_canary=v1" http://192.168.56.91/
curl -i -H "Cookie: exp_canary=v2" http://192.168.56.91/

Rate Limiting (Istio IngressGateway + Redis)

This section explains the configuration, testing, and verification steps for the rate limiting implementation.

Configuration

Rate limiting policies are defined in the values.yaml file.

Settings Breakdown

  • Domain: ratelimit
  • Unit: minute
  • SMS Bucket (/sms*): Limited to 6 requests per minute.
  • Default Bucket (Fallback): Limited to 50 requests per minute for all other paths.
# Global rate limiting configuration
rateLimit:
  unit: minute

limits:
  sms:
    requestsPerUnit: 20

  default:
    requestsPerUnit: 60

Testing Rate Limits

You can verify the rate limits by running the following curl loops.

1. Test SMS Bucket (/sms)

Expected Behavior: The first 20 requests return 200, and subsequent requests return 429.

for i in $(seq 1 40); do
  code=$(curl -s -o /dev/null -w "%{http_code}" "http://192.168.56.91/sms/")
  echo "call $i: HTTP $code"
done

2. Test Default/Global Bucket (/)

Expected Behavior: The first 60 requests return 200, and subsequent requests return 429.

for i in $(seq 1 70); do
  code=$(curl -s -o /dev/null -w "%{http_code}" "http://192.168.56.91/")
  echo "call $i: HTTP $code"
done

Verification (Redis Counters)

To inspect the actual counters in Redis, access the cluster via the VM and execute the Redis CLI commands.

1. Identify the Redis Pod

Find the name of the rate limit Redis pod:

kubectl get pods -n default | grep redis

2. Access Redis CLI

Open a shell inside the Redis container:

kubectl exec -it -n default {step1_podname} -- redis-cli

4. Check Keys and Values

Once inside the Redis CLI prompt, you can list keys and check specific counters:

# List all keys to find the rate limit key
keys *

# Get the value of a specific key
get <keyname>

A1: Containerization

This assignment demonstrates containerization of the SMS Spam Detection system using Docker Compose.

Step 1: Build lib-version Library

# Set environment variables for GitHub access
export GITHUB_USERNAME="your-username"
export GITHUB_TOKEN="your-token"

# Build the shared library
cd lib-version
mvn clean compile
mvn test
cd ..

Step 2: Build and Start Services

# Navigate to operation directory
cd operation

# Build and start all services
docker compose up --build

Step 3: Verify Deployment

# Check running containers
docker compose ps

# View service logs
docker compose logs -f app
docker compose logs -f model-service

# Test the API
curl -X POST -H "Content-Type: application/json" \
  -d '{"sms": "Hello world"}' \
  http://localhost:8080/sms/

Step 4: Access Application

Step 5: Stop Services

docker compose down

A2: Kubernetes Cluster Provisioning

Kubernetes Cluster Setup Details

IP Allocations

Service IP Address Purpose
Controller 192.168.56.100 Kubernetes API server
Worker 1 192.168.56.101 Worker node
Worker 2 192.168.56.102 Worker node
Nginx Ingress 192.168.56.90 HTTP/HTTPS traffic
Istio Gateway 192.168.56.91 Service mesh traffic
MetalLB Pool 192.168.56.90-99 LoadBalancer IPs

Installed Components

  • Kubernetes: v1.32.4 (kubeadm, kubelet, kubectl)
  • Container Runtime: Containerd 1.7.28
  • CNI: Flannel v0.26.7
  • Load Balancer: MetalLB v0.15.2
  • Ingress: Nginx Ingress Controller
  • Dashboard: Kubernetes Dashboard
  • Service Mesh: Istio 1.25.2
  • Package Manager: Helm 3.x
  • Storage: NFS server on controller

Step 1: Provision Cluster

# Navigate to operation directory
cd operation

# Start Kubernetes cluster (takes 10-15 minutes)
vagrant up

This creates:

  • 1 control plane node (192.168.56.100)
  • 2 worker nodes (192.168.56.101, 192.168.56.102)

Step 2: Configure Cluster Services

# Run finalization playbook
cd ansible
ansible-playbook -u vagrant -i 192.168.56.100, finalization.yml
cd ..

Step 3: Configure kubectl

# Set kubectl context
export KUBECONFIG=$(pwd)/admin.conf

# Verify cluster
kubectl get nodes
kubectl get pods -A

Step 4: Verify Installation

After vagrant up completes, verify all services:

vagrant ssh ctrl

# All nodes should be Ready
kubectl get nodes
# Check cluster components
kubectl get pods -n metallb-system # Load balancer
kubectl get pods -n ingress-nginx # Ingress controller
kubectl get pods -n istio-system # Service mesh
istioctl version
kubectl get pods -n kubernetes-dashboard # Dashboard
kubectl get svc --all-namespaces | grep LoadBalancer # Check Loadbalancer services

Accessing Kubernetes Dashboard

Option 1: Port forwarding

From ctrl:

kubectl port-forward -n kubernetes-dashboard svc/kubernetes-dashboard-kong-proxy 8443:443 --address 0.0.0.0

Then access: https://192.168.56.100:8443

Option 2: Via hostname

Add to /etc/hosts:

192.168.56.90 dashboard.local

Access: http://dashboard.local

Get login token:

vagrant ssh ctrl
kubectl -n kubernetes-dashboard create token admin-user

A3: Monitoring and Operations

This assignment deploys monitoring and operational tools using Helm charts.

Step 1: Enable Istio Injection

# Enable sidecar injection for default namespace
kubectl label ns default istio-injection=enabled

Step 2: Deploy Application with Monitoring

# Deploy using Helm chart
cd /vagrant/charts/project-app
helm install project .

Step 3: Access Monitoring Stack

# Get service IPs
kubectl get svc -A

# Access URLs (replace with actual IPs from above):
# Grafana: http://192.168.56.90/grafana/
# Prometheus: http://192.168.56.90/prometheus/
# Kubernetes Dashboard: http://192.168.56.90/kubernetes-dashboard/

Accessing Prometheus UI

From ctrl:

kubectl port-forward --address 0.0.0.0 svc/project-project-app-prometheus 9090:9090

Then access: http://192.168.56.100:9090

Option 2: Via hostname

Add to /etc/hosts:

192.168.56.90 prometheus.local

Access: http://prometheus.local

Accessing AlertManager UI

From ctrl:

kubectl port-forward --address 0.0.0.0 svc/project-project-app-alertmanager 9093:9093

Then access: http://192.168.56.100:9093

Option 2: Via hostname

Add to /etc/hosts:

192.168.56.90 alertmanager.local

Access: http://alertmanager.local

AlertManager displays Prometheus alerts. To test, generate high traffic and alerts will appear when request rate exceeds 15/min for 1 minute.

Generate Test Traffic:

# Sends 90 requests at ~60/min (triggers alert)
for i in {1..90}; do curl -s "http://192.168.56.91/" > /dev/null; echo "Request $i sent"; sleep 1.0; done

To configure email alerts:

  1. Get Gmail App Password: https://myaccount.google.com/apppasswords (requires 2FA)
  2. Create Secret: kubectl create secret generic alertmanager-smtp --from-literal=smtp-password='YOUR_APP_PASSWORD'
  3. Deploy: helm upgrade project . --set alertmanager.email.to=your@gmail.com --set alertmanager.email.from=your@gmail.com

Accessing App

Add to /etc/hosts:

192.168.56.91 project.local

Access: http://project.local http://project.local/metrics

The application includes Prometheus monitoring with three types of metrics:

  • Counter: click_rate_total, navigation_requests_total{page}
  • Gauge: time_on_site_seconds
  • Histogram: page_load_seconds{page}

Accessing Grafana

Grafana is automatically deployed with the application for metrics visualization.

Access via port-forward:

kubectl port-forward --address 0.0.0.0 svc/project-project-app-grafana 3000:3000

Then access: http://192.168.56.100:3000

  • Username: admin
  • Password: admin

Option 2: Via hostname

Add to /etc/hosts:

192.168.56.90 grafana.local

Access: http://grafana.local

Dashboard Location:

  • Navigate to Dashboards → "Application Metrics"
  • Dashboard is automatically provisioned on deployment

Dashboard Panels (using Prometheus metric names):

  1. click_rate_total - Time Series showing request rate (using rate() function)
  2. time_on_site_seconds - Gauge with color thresholds (red <10s, yellow 10-30s, green >30s)
  3. navigation_requests_total - Histogram showing page visit distribution
  4. page_load_seconds (P95) - Time Series showing 95th percentile load time (using histogram_quantile())
  5. click_rate_total (Total) - Stat panel showing total prediction count
  6. page_load_seconds (Statistics) - Table with avg, P50, P95, P99 by page

Advanced Features:

  • Uses PromQL functions: rate(), histogram_quantile(), sum by()
  • Aggregates metrics across pods where appropriate
  • Interactive timeframe selector (5m to 30d)
  • Auto-refresh intervals (5s to 5m)

Manual Dashboard Import (Optional):

If the dashboard isn't auto-loaded:

  1. Copy JSON from charts/project-app/dashboards/application-metrics.json
  2. In Grafana: Dashboards → Import → Paste JSON
  3. Select "Prometheus" as datasource
  4. Click Import

Experimentation Dashboard (A4):

  • Name: "Continuous Experimentation Dashboard"
  • Focus: Comparing v1 (Stable) vs v2 (Canary) performance

Dashboard Location:

  • Navigate to Dashboards → "Continuous Experimentation Dashboard"
  • Dashboard is automatically provisioned on deployment

Dashboard Panels:

  1. Request Rate Comparison - Traffic volume split between versions
  2. Response Time Comparison (P95) - Gauge showing if v2 is slower/faster
  3. Average Prediction Confidence - Gauge tracking model certainty (Green > 80%)
  4. Low Confidence Predictions - Rate of predictions < 70% confidence
  5. User Engagement - Time on site comparison (sticky session duration)

Manual Dashboard Import (Optional):

  1. Copy JSON from charts/project-app/dashboards/experimentation-dashboard.json
  2. Follow the same import steps as above.

Step 4: Verify Monitoring

kubectl get pods

A4: Service Mesh

This assignment demonstrates Istio service mesh capabilities including traffic management and observability.

Step 1: Enable Istio Injection and deployment (from A3)

# Enable Istio sidecar injection for the namespace
kubectl label ns default istio-injection=enabled

# Deploy the application with Prometheus
cd /vagrant/charts/project-app
helm install project .

# Note: This Helm chart deploys the application, model service, Prometheus, Grafana, and associated Istio resources (Gateway, VirtualServices, DestinationRules) for traffic management.

Step 2: Verify Istio Installation

# Check Istio components
kubectl get pods -n istio-system

# Verify sidecar injection
kubectl get pods -o jsonpath='{.items[*].spec.containers[*].name}'

Step 3: Test Service Mesh Features

# Check virtual services
kubectl get virtualservice -n default

# Check destination rules
kubectl get destinationrule -n default

# Check gateway
kubectl get gateway -n default

Step 4: Access Application via Istio

Port Forwarding for Istio Gateway

# Access Istio Gateway directly
kubectl port-forward --address 0.0.0.0 svc/istio-gateway 8080:80 -n istio-system
# Then access: http://localhost:8080/sms/

Troubleshooting

Common Issues

Docker Issues

  • Permission denied: Add user to docker group: sudo usermod -aG docker $USER
  • Port already in use: Change ports in docker-compose.yml
  • Build fails: Ensure Docker daemon is running

Kubernetes Issues

  • VT-x not available: Enable virtualization in BIOS
  • Vagrant fails: Run vagrant destroy -f then vagrant up
  • Ansible fails: Check SSH connectivity to VMs
  • Pods not starting:
kubectl describe pod <pod-name> -n <namespace>
kubectl logs <pod-name> -n <namespace>
  • MetalLB not assigning IPs:
kubectl describe ipaddresspool -n metallb-system
kubectl logs -n metallb-system -l app=metallb
  • Istio issues:
istioctl analyze
kubectl get pods -n istio-system

General Issues

  • GitHub authentication: Set GITHUB_USERNAME and GITHUB_TOKEN
  • Out of disk space: Clean up with docker system prune -a
  • Network issues: Check firewall settings

Configuration

Change worker count:

WORKER_COUNT=3 vagrant up

Adjust resources:

CTRL_CPUS=4 CTRL_MEMORY=8192 vagrant up

Useful Commands

# Docker cleanup
docker compose down --remove-orphans
docker system prune -a

# Kubernetes cleanup
kubectl delete ns project
helm uninstall project

# Vagrant cleanup
vagrant destroy -f

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages