diff --git a/CLEANUP-GUIDE.md b/CLEANUP-GUIDE.md new file mode 100644 index 00000000..5b1c39de --- /dev/null +++ b/CLEANUP-GUIDE.md @@ -0,0 +1,202 @@ +# 🧹 Cleanup Guide for Kind + Colima + Skaffold Environment + +This guide provides different cleanup options depending on what you want to clean up. + +## πŸ“‹ Quick Reference + +| Scenario | Command | What it cleans | +|----------|---------|----------------| +| **Stop development** | `Ctrl+C` (in skaffold dev) | Stops Skaffold, keeps everything | +| **Clean deployment only** | `skaffold delete` | Removes K8s resources, keeps images | +| **Clean HTTPS setup** | `./cleanup-https.sh` | Removes HTTPS + cert-manager | +| **Complete cleanup** | `./complete-cleanup.sh` | **Everything** (interactive) | +| **Nuclear option** | See manual commands below | Complete manual cleanup | + +## πŸš€ Quick Cleanup Commands + +### 1. Stop Skaffold Development Mode +```bash +# If running skaffold dev, just press: +Ctrl+C + +# Or from another terminal: +skaffold delete --profile=dev +``` + +### 2. Clean Only Kubernetes Resources +```bash +# Remove all bakery-ia resources +kubectl delete namespace bakery-ia + +# Remove cert-manager (if installed) +kubectl delete -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.2/cert-manager.yaml + +# Remove NGINX Ingress +kubectl delete -f https://kind.sigs.k8s.io/examples/ingress/deploy-ingress-nginx.yaml +``` + +### 3. Clean Docker Images +```bash +# Remove bakery images +docker images | grep "bakery/" | awk '{print $1":"$2}' | xargs docker rmi -f + +# Remove dangling images +docker image prune -f + +# Remove build cache +docker builder prune -f +``` + +### 4. Clean Kind Cluster +```bash +# Delete specific cluster +kind delete cluster --name bakery-ia-local + +# Delete all clusters +kind get clusters | xargs -r -I {} kind delete cluster --name {} +``` + +### 5. Clean Colima +```bash +# Stop Colima +colima stop --profile k8s-local + +# Delete Colima profile (removes all Docker data) +colima delete --profile k8s-local --force +``` + +## πŸ”„ Automated Cleanup Scripts + +### Option 1: Complete Cleanup (Recommended) +```bash +# Interactive cleanup of everything +./complete-cleanup.sh +``` + +### Option 2: HTTPS-Only Cleanup +```bash +# Removes HTTPS setup but keeps basic environment +./cleanup-https.sh +``` + +### Option 3: Skaffold-Only Cleanup +```bash +# Quick cleanup of just the deployment +skaffold delete --profile=dev +``` + +## πŸ› οΈ Manual Nuclear Cleanup + +If scripts fail, use these manual commands: + +```bash +# 1. Stop all processes +pkill -f skaffold +pkill -f kubectl + +# 2. Clean Kubernetes +kubectl delete namespace bakery-ia --force --grace-period=0 2>/dev/null || true +kubectl delete -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.2/cert-manager.yaml --ignore-not-found=true +kubectl delete -f https://kind.sigs.k8s.io/examples/ingress/deploy-ingress-nginx.yaml --ignore-not-found=true + +# 3. Clean Docker aggressively +docker stop $(docker ps -aq) 2>/dev/null || true +docker rm $(docker ps -aq) 2>/dev/null || true +docker rmi $(docker images -q) -f 2>/dev/null || true +docker system prune -a -f --volumes + +# 4. Clean Kind completely +kind get clusters | xargs -r -I {} kind delete cluster --name {} + +# 5. Reset Colima completely +colima stop --profile k8s-local 2>/dev/null || true +colima delete --profile k8s-local --force 2>/dev/null || true +rm -rf ~/.colima/k8s-local + +# 6. Clean local files +rm -f *.crt *.key bakery-ia-ca.crt +rm -rf ~/.skaffold/cache + +# 7. Clean hosts file (careful!) +sudo cp /etc/hosts /etc/hosts.backup +sudo sed -i '' '/bakery-ia.local/d' /etc/hosts +sudo sed -i '' '/api.bakery-ia.local/d' /etc/hosts +sudo sed -i '' '/monitoring.bakery-ia.local/d' /etc/hosts +``` + +## 🎯 Cleanup by Use Case + +### Daily Development +```bash +# Quick reset between sessions +skaffold delete --profile=dev +``` + +### Weekly Cleanup +```bash +# Clean up accumulated images and cache +docker image prune -f +docker builder prune -f +``` + +### Project Finished +```bash +# Complete cleanup +./complete-cleanup.sh +``` + +### Something's Broken +```bash +# Nuclear reset +kind delete cluster --name bakery-ia-local +colima delete --profile k8s-local --force +# Then restart with ./skaffold-dev.sh +``` + +## πŸ” Verify Cleanup + +After cleanup, verify with these commands: + +```bash +# Check Docker images +docker images | grep bakery + +# Check Kind clusters +kind get clusters + +# Check Colima status +colima status --profile k8s-local + +# Check Kubernetes (should fail if cluster deleted) +kubectl get pods -n bakery-ia + +# Check hosts file +grep bakery /etc/hosts +``` + +## πŸš€ Restart After Cleanup + +To restart development after cleanup: + +```bash +# Quick start +./skaffold-dev.sh + +# Or with HTTPS +./setup-https.sh + +# Or manual +colima start --cpu 4 --memory 8 --disk 50 --runtime docker --profile k8s-local +kind create cluster --name bakery-ia-local +skaffold dev --profile=dev +``` + +## ⚠️ Important Notes + +1. **Always backup** important data before cleanup +2. **The complete cleanup script is interactive** - it will ask before destructive operations +3. **Colima profile deletion** removes ALL Docker data in that profile +4. **Kind cluster deletion** is permanent - you'll lose all Kubernetes data +5. **Hosts file changes** require sudo permissions + +Choose the cleanup level that matches your needs! 🎯 \ No newline at end of file diff --git a/bakery-ia-ca.crt b/bakery-ia-ca.crt new file mode 100644 index 00000000..192cf0c2 --- /dev/null +++ b/bakery-ia-ca.crt @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIIB9TCCAZygAwIBAgIQAqQJ8a0XYP5XfN9bOoSX6TAKBggqhkjOPQQDAjBbMQsw +CQYDVQQGEwJVUzESMBAGA1UEChMJQmFrZXJ5IElBMRswGQYDVQQLExJCYWtlcnkg +SUEgTG9jYWwgQ0ExGzAZBgNVBAMTEmJha2VyeS1pYS1sb2NhbC1jYTAeFw0yNTA5 +MjgwODA5MzFaFw0yNjA5MjgwODA5MzFaMFsxCzAJBgNVBAYTAlVTMRIwEAYDVQQK +EwlCYWtlcnkgSUExGzAZBgNVBAsTEkJha2VyeSBJQSBMb2NhbCBDQTEbMBkGA1UE +AxMSYmFrZXJ5LWlhLWxvY2FsLWNhMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE +OaGd9w4LnTtcIZQo3P3CtBr8CVCckF1gWoNK3CCU30d29oiGTEU+IWo9CE2Tqszk +ZIWKENOB05VaHbJYs2jArKNCMEAwDgYDVR0PAQH/BAQDAgKkMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFM0ePz20KZn61OMTwWj1aiG0YWVlMAoGCCqGSM49BAMC +A0cAMEQCIE5DgVJTSpPyzHKG836VyMWvT1bNBzlmK+d0txTmivX4AiATgglI/ijl +WD6Uf7SVsaB73mbL4vpHP7HZrZfk3MCo0g== +-----END CERTIFICATE----- diff --git a/cleanup-https.sh b/cleanup-https.sh new file mode 100755 index 00000000..97ce0069 --- /dev/null +++ b/cleanup-https.sh @@ -0,0 +1,103 @@ +#!/bin/bash + +# Bakery IA HTTPS Cleanup Script +# This script removes HTTPS configuration and cert-manager + +set -e + +echo "🧹 Cleaning up HTTPS setup for Bakery IA" +echo "========================================" + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +print_status() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +print_success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +# Remove application +cleanup_application() { + print_status "Removing Bakery IA application..." + + # Try Skaffold cleanup first (if available and was used) + if command -v skaffold &> /dev/null; then + print_status "Cleaning up Skaffold deployment..." + skaffold delete --profile=dev --ignore-not-found=true 2>/dev/null || true + fi + + # Fallback to manual cleanup + print_status "Cleaning up remaining resources..." + kubectl delete -k infrastructure/kubernetes/overlays/dev/ --ignore-not-found=true + + print_success "Application removed" +} + +# Remove certificates and issuers +cleanup_certificates() { + print_status "Removing certificates and issuers..." + kubectl delete clusterissuers --all --ignore-not-found=true + kubectl delete certificates --all -n cert-manager --ignore-not-found=true + kubectl delete secrets local-ca-key-pair -n cert-manager --ignore-not-found=true + print_success "Certificates and issuers removed" +} + +# Remove cert-manager +cleanup_cert_manager() { + print_status "Removing cert-manager..." + kubectl delete -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.2/cert-manager.yaml --ignore-not-found=true + print_success "cert-manager removed" +} + +# Remove ingress controller +cleanup_ingress() { + print_status "Removing NGINX Ingress Controller..." + kubectl delete -f https://kind.sigs.k8s.io/examples/ingress/deploy-ingress-nginx.yaml --ignore-not-found=true + print_success "NGINX Ingress Controller removed" +} + +# Remove local files +cleanup_local_files() { + print_status "Removing local certificate files..." + rm -f bakery-ia-ca.crt + print_success "Local files cleaned up" +} + +# Main cleanup +main() { + print_warning "This will remove all HTTPS configuration and cert-manager from your cluster." + read -p "Are you sure you want to continue? (y/N): " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + print_status "Cleanup cancelled" + exit 0 + fi + + cleanup_application + cleanup_certificates + cleanup_cert_manager + cleanup_ingress + cleanup_local_files + + print_success "πŸŽ‰ Cleanup completed!" + echo "" + echo "Additional cleanup commands (if needed):" + echo " πŸ—‚οΈ Remove hosts entries: sudo sed -i '' '/bakery-ia.local/d' /etc/hosts" + echo " 🐳 Stop Colima: colima stop --profile k8s-local" + echo " πŸ—‘οΈ Delete Kind cluster: kind delete cluster --name bakery-ia-local" + echo "" + print_warning "Note: Hosts file entries and CA certificate may need manual cleanup" +} + +main "$@" \ No newline at end of file diff --git a/complete-cleanup.sh b/complete-cleanup.sh new file mode 100755 index 00000000..8204db47 --- /dev/null +++ b/complete-cleanup.sh @@ -0,0 +1,246 @@ +#!/bin/bash + +# Complete Cleanup Script for Kind + Colima + Skaffold Environment +# This script removes all resources, images, and configurations + +set -e + +echo "🧹 Complete Cleanup for Bakery IA Development Environment" +echo "========================================================" + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +print_status() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +print_success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +print_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# Show what will be cleaned up +show_cleanup_plan() { + echo "" + print_warning "This script will clean up:" + echo " πŸš€ Skaffold deployments and resources" + echo " πŸ‹ Docker images (bakery/* images)" + echo " ☸️ Kubernetes resources in bakery-ia namespace" + echo " πŸ”’ cert-manager and TLS certificates" + echo " 🌐 NGINX Ingress Controller" + echo " πŸ“¦ Kind cluster (bakery-ia-local)" + echo " 🐳 Colima Docker runtime" + echo " πŸ“ Local certificate files" + echo " πŸ—‚οΈ /etc/hosts entries (optional)" + echo "" + read -p "❓ Do you want to continue? (y/N): " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + print_status "Cleanup cancelled" + exit 0 + fi +} + +# 1. Cleanup Skaffold deployments +cleanup_skaffold() { + print_status "πŸš€ Cleaning up Skaffold deployments..." + + if command -v skaffold &> /dev/null; then + # Try to delete with different profiles + skaffold delete --profile=dev 2>/dev/null || true + skaffold delete --profile=debug 2>/dev/null || true + skaffold delete 2>/dev/null || true + print_success "Skaffold deployments cleaned up" + else + print_warning "Skaffold not found, skipping Skaffold cleanup" + fi +} + +# 2. Cleanup Kubernetes resources +cleanup_kubernetes() { + print_status "☸️ Cleaning up Kubernetes resources..." + + if command -v kubectl &> /dev/null && kubectl cluster-info &> /dev/null; then + # Delete application namespace and all resources + kubectl delete namespace bakery-ia --ignore-not-found=true + + # Delete cert-manager + kubectl delete -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.2/cert-manager.yaml --ignore-not-found=true 2>/dev/null || true + + # Delete NGINX Ingress + kubectl delete -f https://kind.sigs.k8s.io/examples/ingress/deploy-ingress-nginx.yaml --ignore-not-found=true 2>/dev/null || true + + # Delete any remaining cluster-wide resources + kubectl delete clusterissuers --all --ignore-not-found=true 2>/dev/null || true + kubectl delete clusterroles,clusterrolebindings -l app.kubernetes.io/name=cert-manager --ignore-not-found=true 2>/dev/null || true + + print_success "Kubernetes resources cleaned up" + else + print_warning "Kubectl not available or cluster not running, skipping Kubernetes cleanup" + fi +} + +# 3. Cleanup Docker images in Colima +cleanup_docker_images() { + print_status "πŸ‹ Cleaning up Docker images..." + + if command -v docker &> /dev/null && docker info &> /dev/null; then + # Remove bakery-specific images + print_status "Removing bakery/* images..." + docker images --format "table {{.Repository}}:{{.Tag}}" | grep "^bakery/" | xargs -r docker rmi -f 2>/dev/null || true + + # Remove dangling images + print_status "Removing dangling images..." + docker image prune -f 2>/dev/null || true + + # Remove unused images (optional - uncomment if you want aggressive cleanup) + # print_status "Removing unused images..." + # docker image prune -a -f 2>/dev/null || true + + # Remove build cache + print_status "Cleaning build cache..." + docker builder prune -f 2>/dev/null || true + + print_success "Docker images cleaned up" + else + print_warning "Docker not available, skipping Docker cleanup" + fi +} + +# 4. Delete Kind cluster +cleanup_kind_cluster() { + print_status "πŸ“¦ Deleting Kind cluster..." + + if command -v kind &> /dev/null; then + # Delete the specific cluster + kind delete cluster --name bakery-ia-local 2>/dev/null || true + + # Also clean up any other bakery clusters + kind get clusters 2>/dev/null | grep -E "(bakery|dev)" | xargs -r -I {} kind delete cluster --name {} 2>/dev/null || true + + print_success "Kind cluster deleted" + else + print_warning "Kind not found, skipping cluster cleanup" + fi +} + +# 5. Stop and clean Colima +cleanup_colima() { + print_status "🐳 Cleaning up Colima..." + + if command -v colima &> /dev/null; then + # Stop the specific profile + colima stop --profile k8s-local 2>/dev/null || true + + # Delete the profile (removes all data) + read -p "❓ Do you want to delete the Colima profile (removes all Docker data)? (y/N): " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + colima delete --profile k8s-local --force 2>/dev/null || true + print_success "Colima profile deleted" + else + print_warning "Colima profile kept (stopped only)" + fi + else + print_warning "Colima not found, skipping Colima cleanup" + fi +} + +# 6. Cleanup local files +cleanup_local_files() { + print_status "πŸ“ Cleaning up local files..." + + # Remove certificate files + rm -f bakery-ia-ca.crt 2>/dev/null || true + rm -f *.crt *.key 2>/dev/null || true + + # Remove any Skaffold cache (if exists) + rm -rf ~/.skaffold/cache 2>/dev/null || true + + print_success "Local files cleaned up" +} + +# 7. Cleanup /etc/hosts entries (optional) +cleanup_hosts_file() { + print_status "πŸ—‚οΈ Cleaning up /etc/hosts entries..." + + if grep -q "bakery-ia.local" /etc/hosts 2>/dev/null; then + read -p "❓ Remove bakery-ia entries from /etc/hosts? (y/N): " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + # Backup hosts file first + sudo cp /etc/hosts /etc/hosts.backup.$(date +%Y%m%d_%H%M%S) + + # Remove entries + sudo sed -i '' '/bakery-ia.local/d' /etc/hosts + sudo sed -i '' '/api.bakery-ia.local/d' /etc/hosts + sudo sed -i '' '/monitoring.bakery-ia.local/d' /etc/hosts + + print_success "Hosts file entries removed" + else + print_warning "Hosts file entries kept" + fi + else + print_status "No bakery-ia entries found in /etc/hosts" + fi +} + +# 8. Show system status after cleanup +show_cleanup_summary() { + echo "" + print_success "πŸŽ‰ Cleanup completed!" + echo "" + print_status "System status after cleanup:" + + # Check remaining Docker images + if command -v docker &> /dev/null && docker info &> /dev/null; then + local bakery_images=$(docker images --format "table {{.Repository}}:{{.Tag}}" | grep "^bakery/" | wc -l) + echo " πŸ‹ Bakery Docker images remaining: $bakery_images" + fi + + # Check Kind clusters + if command -v kind &> /dev/null; then + local clusters=$(kind get clusters 2>/dev/null | wc -l) + echo " πŸ“¦ Kind clusters remaining: $clusters" + fi + + # Check Colima status + if command -v colima &> /dev/null; then + local colima_status=$(colima status --profile k8s-local 2>/dev/null | head -n1 || echo "Not running") + echo " 🐳 Colima k8s-local status: $colima_status" + fi + + echo "" + print_status "To restart development environment:" + echo " πŸš€ Quick start: ./skaffold-dev.sh" + echo " πŸ”’ With HTTPS: ./setup-https.sh" + echo " πŸ—οΈ Manual: colima start --cpu 4 --memory 8 --disk 50 --runtime docker --profile k8s-local" +} + +# Main execution +main() { + show_cleanup_plan + cleanup_skaffold + cleanup_kubernetes + cleanup_docker_images + cleanup_kind_cluster + cleanup_colima + cleanup_local_files + cleanup_hosts_file + show_cleanup_summary +} + +# Run main function +main "$@" \ No newline at end of file diff --git a/infrastructure/kubernetes/README.md b/infrastructure/kubernetes/README.md index 5a2d3bfd..2f56e69d 100644 --- a/infrastructure/kubernetes/README.md +++ b/infrastructure/kubernetes/README.md @@ -1,38 +1,125 @@ # Bakery IA Kubernetes Configuration -This directory contains Kubernetes manifests for deploying the Bakery IA forecasting platform in a local development environment. +This directory contains Kubernetes manifests for deploying the Bakery IA forecasting platform in a local development environment with **permanent localhost access** and **FREE HTTPS support** using cert-manager and NGINX ingress. -## Prerequisites - -1. **Kubernetes Cluster**: Ensure you have a local Kubernetes cluster running (minikube, kind, Docker Desktop, etc.) -2. **kubectl**: Install and configure kubectl to communicate with your cluster -3. **Kustomize**: Built into kubectl v1.14+, or install separately -4. **NGINX Ingress Controller**: Required for ingress functionality - -### Install NGINX Ingress Controller +## ⚑ Quick Start (5 Commands) ```bash -# For minikube -minikube addons enable ingress +# 1. Start Colima +colima start --cpu 4 --memory 8 --disk 50 --runtime docker --profile k8s-local -# For kind -kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml +# 2. Create Kind cluster with permanent localhost access +kind create cluster --config kind-config.yaml -# For Docker Desktop -kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml +# 3. Install NGINX Ingress Controller +kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml && kubectl wait --namespace ingress-nginx --for=condition=ready pod --selector=app.kubernetes.io/component=controller --timeout=300s + +# 4. Configure permanent localhost access +kubectl patch svc ingress-nginx-controller -n ingress-nginx -p '{"spec":{"type":"NodePort","ports":[{"name":"http","port":80,"targetPort":"http","nodePort":30080},{"name":"https","port":443,"targetPort":"https","nodePort":30443}]}}' + +# 5. Deploy your application +skaffold dev --profile=dev + +# πŸŽ‰ Done! Access at: http://localhost ``` +## Prerequisites (macOS Local Development) + +1. **Colima**: Docker runtime for macOS +2. **Kind**: Kubernetes in Docker for local clusters +3. **kubectl**: Kubernetes command-line tool +4. **Skaffold**: For building and deploying applications +5. **NGINX Ingress Controller**: For routing traffic (installed automatically) +6. **cert-manager**: For automatic TLS certificate management (installed automatically) + +### Install Prerequisites (macOS) + +```bash +# Install Homebrew (if not already installed) +/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + +# Install required tools +brew install colima kind kubectl skaffold + +# Verify installations +colima version +kind version +kubectl version --client +skaffold version +``` + +## πŸ”’ HTTPS Setup Options + +### Option 1: Automated HTTPS Setup (Recommended) +```bash +# Run the automated HTTPS setup script +./setup-https.sh +``` + +### Option 2: HTTP Only (Basic Setup) +```bash +# Deploy without HTTPS +kubectl apply -k infrastructure/kubernetes/overlays/dev/ +``` + +## Kind Configuration for Permanent Localhost Access + +The `kind-config.yaml` file in the root directory provides permanent localhost access without port forwarding: + +```yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +name: bakery-ia-local +nodes: +- role: control-plane + kubeadmConfigPatches: + - | + kind: InitConfiguration + nodeRegistration: + kubeletExtraArgs: + node-labels: "ingress-ready=true" + extraPortMappings: + # HTTP ingress + - containerPort: 30080 + hostPort: 80 + protocol: TCP + # HTTPS ingress + - containerPort: 30443 + hostPort: 443 + protocol: TCP + # Direct frontend access (backup) + - containerPort: 30300 + hostPort: 3000 + protocol: TCP + # Direct gateway access (backup) + - containerPort: 30800 + hostPort: 8000 + protocol: TCP +``` + +This configuration maps: +- Port 80 β†’ localhost:80 (HTTP) +- Port 443 β†’ localhost:443 (HTTPS) +- Port 3000 β†’ localhost:3000 (Direct frontend) +- Port 8000 β†’ localhost:8000 (Direct gateway) + ## Directory Structure ``` infrastructure/kubernetes/ +β”œβ”€β”€ kind-config.yaml # Kind cluster configuration with port mapping β”œβ”€β”€ base/ # Base Kubernetes resources β”‚ β”œβ”€β”€ namespace.yaml # Namespace definition β”‚ β”œβ”€β”€ configmap.yaml # Shared configuration β”‚ β”œβ”€β”€ secrets.yaml # Secrets (base64 encoded) -β”‚ β”œβ”€β”€ ingress.yaml # Ingress rules +β”‚ β”œβ”€β”€ ingress.yaml # HTTP ingress rules +β”‚ β”œβ”€β”€ ingress-https.yaml # HTTPS ingress rules β”‚ └── kustomization.yaml # Base kustomization β”œβ”€β”€ components/ # Individual component manifests +β”‚ β”œβ”€β”€ cert-manager/ # Certificate management +β”‚ β”‚ β”œβ”€β”€ cluster-issuer-staging.yaml # Let's Encrypt staging +β”‚ β”‚ β”œβ”€β”€ cluster-issuer-production.yaml # Let's Encrypt production +β”‚ β”‚ └── local-ca-issuer.yaml # Local CA for development β”‚ β”œβ”€β”€ auth/ # Auth service β”‚ β”œβ”€β”€ tenant/ # Tenant service β”‚ β”œβ”€β”€ training/ # Training service @@ -53,34 +140,56 @@ infrastructure/kubernetes/ └── overlays/ └── dev/ # Development environment overlay β”œβ”€β”€ kustomization.yaml # Dev-specific kustomization - └── dev-patches.yaml # Development patches + β”œβ”€β”€ https-kustomization.yaml # HTTPS-specific kustomization + β”œβ”€β”€ dev-patches.yaml # Development patches + └── ingress-https-patch.yaml # HTTPS ingress patch ``` -## Quick Start +## πŸš€ Quick Start (macOS with Kind + Colima) -### 1. Build and Deploy Images (if needed) - -First, ensure your Docker images are built and available to your Kubernetes cluster: +### 1. Start Colima and Create Kind Cluster with Permanent Localhost Access ```bash -# Build all services -docker-compose build +# Start Colima with proper resources for development +colima start --cpu 4 --memory 8 --disk 100 --runtime docker --profile k8s-local -# For minikube, use minikube's Docker daemon -eval $(minikube docker-env) -docker-compose build +# Create Kind cluster with permanent port mapping for localhost access +kind create cluster --config kind-config.yaml -# For kind, load images into the cluster -kind load docker-image bakery/auth-service:latest -kind load docker-image bakery/tenant-service:latest -# ... repeat for all services +# Verify cluster is running and port mappings +kubectl cluster-info +docker port bakery-ia-local-control-plane ``` -### 2. Deploy to Kubernetes +The `kind-config.yaml` configuration provides permanent localhost access on ports 80 and 443 without requiring port forwarding! + +### 2. Install NGINX Ingress Controller for Kind ```bash -# Deploy the development environment -kubectl apply -k infrastructure/kubernetes/overlays/dev/ +# Install NGINX Ingress Controller (Kind-specific with permanent localhost access) +kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml + +# Wait for ingress controller to be ready +kubectl wait --namespace ingress-nginx \ + --for=condition=ready pod \ + --selector=app.kubernetes.io/component=controller \ + --timeout=300s + +# Configure ingress controller for permanent localhost access +kubectl patch svc ingress-nginx-controller -n ingress-nginx -p '{"spec":{"type":"NodePort","ports":[{"name":"http","port":80,"targetPort":"http","nodePort":30080},{"name":"https","port":443,"targetPort":"https","nodePort":30443}]}}' +``` + +### 3. Deploy with Skaffold (No Port Forwarding Required!) + +```bash +# Option A: Development mode with auto-rebuild (Recommended) +skaffold dev --profile=dev + +# Option B: One-time deployment +skaffold run --profile=dev + +# Option C: Debug mode (still includes port forwarding for individual services) +skaffold debug --profile=debug # Check deployment status kubectl get pods -n bakery-ia @@ -88,26 +197,142 @@ kubectl get services -n bakery-ia kubectl get ingress -n bakery-ia ``` -### 3. Access the Application +**Note**: With the new configuration, skaffold no longer needs port forwarding for frontend access since localhost:80 and localhost:443 are permanently mapped! -Add the following to your `/etc/hosts` file (or Windows equivalent): +### 4. Access the Application - Permanent Localhost Access! πŸŽ‰ -``` -127.0.0.1 bakery-ia.local -127.0.0.1 api.bakery-ia.local -127.0.0.1 monitoring.bakery-ia.local -``` +**No /etc/hosts modification needed!** The application is now accessible directly via standard localhost URLs: -For minikube, get the ingress IP: +**Primary Access (Recommended):** +- **Frontend**: http://localhost or https://localhost +- **API Gateway**: http://localhost/api or https://localhost/api + +**Named Host Access (Optional):** +If you prefer named hosts, add to your `/etc/hosts` file: ```bash -minikube ip -# Use this IP instead of 127.0.0.1 in your hosts file +echo "127.0.0.1 bakery-ia.local" | sudo tee -a /etc/hosts +echo "127.0.0.1 api.bakery-ia.local" | sudo tee -a /etc/hosts +echo "127.0.0.1 monitoring.bakery-ia.local" | sudo tee -a /etc/hosts ``` -Access the application: -- Frontend: http://bakery-ia.local or http://localhost:3000 -- API Gateway: http://api.bakery-ia.local or http://localhost:8000/api -- Individual services: Check service NodePorts or use port-forwarding +Then access via: +- Frontend: http://bakery-ia.local or https://bakery-ia.local +- API Gateway: http://api.bakery-ia.local or https://api.bakery-ia.local +- Monitoring: http://monitoring.bakery-ia.local or https://monitoring.bakery-ia.local + +## πŸ”’ HTTPS Configuration (FREE with Let's Encrypt) + +### Automated HTTPS Setup + +The quickest way to enable HTTPS is using the automated setup script: + +```bash +# Run the automated HTTPS setup script +./setup-https.sh +``` + +This script will: +- βœ… Install cert-manager (FREE Let's Encrypt client) +- βœ… Install NGINX Ingress Controller +- βœ… Set up cluster issuers (staging, production, and local CA) +- βœ… Deploy your application with HTTPS support +- βœ… Generate and configure TLS certificates +- βœ… Export CA certificate for browser trust + +### Manual HTTPS Setup + +If you prefer manual setup: + +#### 1. Install cert-manager +```bash +kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.2/cert-manager.yaml +kubectl wait --for=condition=ready pod -l app.kubernetes.io/instance=cert-manager -n cert-manager --timeout=300s +``` + +#### 2. Install NGINX Ingress Controller for Kind +```bash +kubectl apply -f https://kind.sigs.k8s.io/examples/ingress/deploy-ingress-nginx.yaml +kubectl wait --namespace ingress-nginx --for=condition=ready pod --selector=app.kubernetes.io/component=controller --timeout=300s +``` + +#### 3. Apply Certificate Issuers +```bash +kubectl apply -f infrastructure/kubernetes/base/components/cert-manager/cluster-issuer-staging.yaml +kubectl apply -f infrastructure/kubernetes/base/components/cert-manager/local-ca-issuer.yaml +kubectl apply -f infrastructure/kubernetes/base/components/cert-manager/cluster-issuer-production.yaml +``` + +#### 4. Deploy with HTTPS +```bash +kubectl apply -k infrastructure/kubernetes/overlays/dev/ +kubectl patch ingress bakery-ingress -n bakery-ia --patch-file infrastructure/kubernetes/overlays/dev/ingress-https-patch.yaml +``` + +#### 5. Export CA Certificate for Browser Trust +```bash +kubectl get secret local-ca-key-pair -n cert-manager -o jsonpath='{.data.tls\.crt}' | base64 -d > bakery-ia-ca.crt +``` + +### Access HTTPS Application + +After HTTPS setup: +- **πŸ” Frontend:** https://bakery-ia.local +- **πŸ” API Gateway:** https://api.bakery-ia.local +- **πŸ” Monitoring:** https://monitoring.bakery-ia.local + +### Trust the CA Certificate + +**For macOS:** +```bash +open bakery-ia-ca.crt +# In Keychain Access, find "bakery-ia-local-ca" and set to "Always Trust" +``` + +**For Linux:** +```bash +sudo cp bakery-ia-ca.crt /usr/local/share/ca-certificates/ +sudo update-ca-certificates +``` + +### Certificate Management Commands + +```bash +# Check certificate status +kubectl get certificates -n bakery-ia + +# Check certificate details +kubectl describe certificate bakery-ia-tls-cert -n bakery-ia + +# Check cluster issuers +kubectl get clusterissuers + +# Check TLS secret +kubectl get secret bakery-ia-tls-cert -n bakery-ia +``` + +### Switching to Production Let's Encrypt + +To use real Let's Encrypt certificates (requires public domain): + +1. Update the cluster issuer in `ingress-https-patch.yaml`: +```yaml +cert-manager.io/cluster-issuer: "letsencrypt-production" # Change from local-ca-issuer +``` + +2. Update email in cluster issuers to your real email +3. Ensure your domain points to your cluster's external IP + +### Cleanup HTTPS Setup + +```bash +# Run cleanup script +./cleanup-https.sh + +# Or manually clean up +kubectl delete -k infrastructure/kubernetes/overlays/dev/ +kubectl delete -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.2/cert-manager.yaml +rm -f bakery-ia-ca.crt +``` ## Port Forwarding for Direct Access @@ -171,16 +396,26 @@ kubectl scale -n bakery-ia deployment/auth-service --replicas=3 # Or edit the kustomization.yaml replicas section and reapply ``` -### Clean Up +### Clean Up (macOS + Kind + Colima + Skaffold) ```bash -# Delete everything -kubectl delete -k infrastructure/kubernetes/overlays/dev/ +# Option 1: Quick cleanup (development session) +skaffold delete --profile=dev -# Or delete just the namespace (removes everything in it) +# Option 2: Clean up HTTPS setup +./cleanup-https.sh + +# Option 3: Complete cleanup (everything) +./complete-cleanup.sh + +# Option 4: Manual cleanup steps kubectl delete namespace bakery-ia +kind delete cluster --name bakery-ia-local +colima stop --profile k8s-local ``` +**πŸ“– For detailed cleanup options, see [CLEANUP-GUIDE.md](../../CLEANUP-GUIDE.md)** + ## Configuration ### Secrets @@ -219,7 +454,29 @@ Modify the `overlays/dev/` files to customize the development environment: 1. **Images not found**: Ensure images are built and available to the cluster 2. **Pending pods**: Check resource requests and cluster capacity 3. **CrashLoopBackOff**: Check logs and environment variables -4. **Service not accessible**: Verify ingress controller is running and hosts file is configured +4. **Service not accessible**: Verify ingress controller is running and localhost ports are mapped +5. **Database corruption**: If PostgreSQL databases show "could not locate a valid checkpoint record", delete the PVC and restart the pod to get fresh storage +6. **Port conflicts**: If localhost:80 or localhost:443 are already in use, stop other services or change the Kind configuration +7. **HTTPS certificate not issued**: Check cert-manager logs and cluster issuer status +8. **Browser security warnings**: Import and trust the CA certificate (`bakery-ia-ca.crt`) +9. **Certificate pending**: Wait for cert-manager to issue the certificate (usually takes 30-60 seconds) +10. **Kustomize deprecation warnings**: Fixed - using modern `patches` syntax instead of deprecated `patchesStrategicMerge` and `patchesJson6902` + +### Database Recovery Commands + +If you encounter database corruption (common after improper cluster shutdown): + +```bash +# Check which databases are failing +kubectl get pods -n bakery-ia | grep -E "(db|CrashLoopBackOff)" + +# For each corrupted database (example with inventory-db): +kubectl delete pod -n bakery-ia -l app.kubernetes.io/name=inventory-db +kubectl delete pvc -n bakery-ia inventory-db-pvc + +# The deployment will automatically recreate with fresh storage +# Repeat for pos-db-pvc and training-db-pvc if needed +``` ### Debugging Commands @@ -238,6 +495,13 @@ kubectl exec -n bakery-ia -it -- env # Check resource usage kubectl top pods -n bakery-ia kubectl top nodes + +# HTTPS/Certificate debugging +kubectl logs -n cert-manager deployment/cert-manager +kubectl describe clusterissuer letsencrypt-staging +kubectl describe certificate bakery-ia-tls-cert -n bakery-ia +kubectl get challenges -n bakery-ia +kubectl get certificaterequests -n bakery-ia ``` ## Production Considerations @@ -251,7 +515,8 @@ For production deployment, consider: 5. **Backup**: Implement database backup strategies 6. **High Availability**: Use multiple replicas and anti-affinity rules 7. **Security**: Network policies, RBAC, pod security policies -8. **CI/CD**: Integrate with your deployment pipeline +8. **TLS/HTTPS**: Use production Let's Encrypt certificates for public domains +9. **CI/CD**: Integrate with your deployment pipeline ## Next Steps @@ -259,4 +524,200 @@ For production deployment, consider: 2. Implement proper logging with ELK stack or similar 3. Add health checks and metrics endpoints 4. Implement automated testing -5. Set up CI/CD pipelines for automated deployments \ No newline at end of file +5. Set up CI/CD pipelines for automated deployments + +## πŸš€ Complete Setup Guide (macOS + Kind + Colima) - New Permanent Solution! + +### Method 1: Permanent Localhost Access (Recommended - No Port Forwarding!) + +```bash +# 1. Start Colima +colima start --cpu 4 --memory 8 --disk 50 --runtime docker --profile k8s-local + +# 2. Create Kind cluster with permanent port mapping +kind create cluster --config kind-config.yaml + +# 3. Install NGINX Ingress Controller with NodePort configuration +kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml +kubectl wait --namespace ingress-nginx --for=condition=ready pod --selector=app.kubernetes.io/component=controller --timeout=300s + +# 4. Configure ingress for permanent localhost access +kubectl patch svc ingress-nginx-controller -n ingress-nginx -p '{"spec":{"type":"NodePort","ports":[{"name":"http","port":80,"targetPort":"http","nodePort":30080},{"name":"https","port":443,"targetPort":"https","nodePort":30443}]}}' + +# 5. Deploy with Skaffold +skaffold dev --profile=dev + +# 6. Access your application - NO /etc/hosts needed! +# Frontend: http://localhost +# API: http://localhost/api +# HTTPS: https://localhost (with browser security warnings) +``` + +### Method 2: Legacy Setup with HTTPS and Named Hosts + +```bash +# 1. Start Colima +colima start --cpu 4 --memory 8 --disk 50 --runtime docker --profile k8s-local + +# 2. Create standard Kind cluster +kind create cluster --name bakery-ia-local + +# 3. Run automated HTTPS setup (includes cert-manager and ingress) +./setup-https.sh + +# 4. Deploy with Skaffold +skaffold dev --profile=dev + +# 5. Add hosts entries for named hosts +sudo tee -a /etc/hosts << EOF +127.0.0.1 bakery-ia.local +127.0.0.1 api.bakery-ia.local +127.0.0.1 monitoring.bakery-ia.local +EOF + +# 6. Trust CA certificate (for HTTPS) +open bakery-ia-ca.crt +# In Keychain Access, set "bakery-ia-local-ca" to "Always Trust" +``` + +## πŸš€ Skaffold Development Workflow + +### Development Mode (Recommended) +```bash +# Start continuous development mode +skaffold dev --profile=dev +``` + +This will: +- βœ… **Build all Docker images** automatically +- βœ… **Deploy to your Kind cluster** +- βœ… **Watch for file changes** in real-time +- βœ… **Automatically rebuild and redeploy** when you save files +- βœ… **Stream logs** from all services in one terminal + +### Other Skaffold Commands + +```bash +# One-time deployment (no file watching) +skaffold run --profile=dev + +# Debug mode with port forwarding +skaffold debug --profile=debug + +# Force rebuild and deploy +skaffold build --file-output=build.json +skaffold deploy --build-artifacts=build.json + +# Clean up deployed resources +skaffold delete +``` + +### Stopping Skaffold + +```bash +# Stop Skaffold (press Ctrl+C in the terminal running skaffold dev) +# Or run: +skaffold delete + +# Complete cleanup +kind delete cluster --name bakery-ia-local +colima stop --profile k8s-local +``` + +### 🎯 Key Skaffold Benefits + +1. **πŸ”„ Automated builds**: No manual Docker image building +2. **πŸ‘€ File watching**: Instant rebuilds on code changes +3. **πŸ“Š Log streaming**: All service logs in one place +4. **πŸ”— Port forwarding**: Easy access to services during development +5. **⚑ One command deployment**: `skaffold dev` does everything + +### πŸ’‘ Pro Tips + +- Use `skaffold dev --profile=dev` for daily development +- Code changes trigger automatic rebuilds and deployments +- Logs are automatically streamed to your terminal +- Press `Ctrl+C` to stop and clean up everything + +## πŸŽ‰ Summary: What You Get + +### πŸš€ NEW: Permanent Localhost Access (No Port Forwarding!) +- βœ… **Direct localhost access** at http://localhost and https://localhost +- βœ… **Standard web ports** 80 and 443 work directly +- βœ… **No /etc/hosts modifications** required for basic access +- βœ… **No port forwarding commands** needed during development +- βœ… **Bookmark-friendly URLs** like any standard web application +- βœ… **Kind cluster configuration** with permanent port mapping + +### Development Environment +- βœ… **One-command deployment** with `skaffold dev --profile=dev` +- βœ… **Hot-reload development** with automatic rebuilds +- βœ… **Complete observability** with streaming logs and metrics +- βœ… **Easy cleanup** with `skaffold delete` or cleanup scripts +- βœ… **Database corruption protection** with proper PVC management + +### FREE HTTPS with Let's Encrypt (Optional) +- βœ… **Automated certificate management** with cert-manager +- βœ… **Local development certificates** for offline work +- βœ… **Production-ready** Let's Encrypt integration +- βœ… **Auto-renewal** of certificates before expiration +- βœ… **Browser-trusted certificates** with CA import + +### Security Features +- βœ… **TLS 1.3 encryption** for all traffic (when HTTPS is configured) +- βœ… **HTTPS redirects** from HTTP (configurable) +- βœ… **Secure headers** via NGINX Ingress +- βœ… **Certificate transparency** compliance + +### Access URLs - Choose Your Style! + +**🌟 Primary Access (New Permanent Solution):** +- **Frontend:** http://localhost or https://localhost +- **API Gateway:** http://localhost/api or https://localhost/api + +**🏷️ Named Host Access (Optional with /etc/hosts):** +- **Frontend:** http://bakery-ia.local or https://bakery-ia.local +- **API:** http://api.bakery-ia.local or https://api.bakery-ia.local +- **Monitoring:** http://monitoring.bakery-ia.local or https://monitoring.bakery-ia.local + +**πŸ”§ Direct Service Access (Backup):** +- **Frontend Direct:** http://localhost:3000 +- **Gateway Direct:** http://localhost:8000 + +This setup provides production-like development experience with the convenience of standard localhost URLs! πŸš€ + + + Pre-Restart Shutdown Sequence: + + 1. Stop Skaffold: + # If running interactively: Ctrl+C + # If running in background: + pkill -f skaffold + + 2. Delete Kind cluster: + kind delete cluster --name bakery-ia-local + + 3. Stop Colima: + colima stop + + Post-Restart Startup Sequence: + + 1. Start Colima: + colima start + + 2. Create Kind cluster: + kind create cluster --config kind-config.yaml --name bakery-ia-local + + 3. Start Skaffold with dev profile: + skaffold dev -p dev + + What Skaffold Will Do: + + - Check existing Docker images (tagged as :dev) + - Skip rebuilds if source code unchanged + - Load images to new Kind cluster + - Deploy using infrastructure/kubernetes/overlays/dev + - Watch for changes and hot-reload + + The -p dev profile ensures consistent tagging and deployment configuration + as defined in your skaffold.yaml profiles section. \ No newline at end of file diff --git a/infrastructure/kubernetes/base/components/alert-processor/alert-processor-service.yaml b/infrastructure/kubernetes/base/components/alert-processor/alert-processor-service.yaml index 51df6808..da62ec97 100644 --- a/infrastructure/kubernetes/base/components/alert-processor/alert-processor-service.yaml +++ b/infrastructure/kubernetes/base/components/alert-processor/alert-processor-service.yaml @@ -20,6 +20,29 @@ spec: app.kubernetes.io/component: worker spec: initContainers: + - name: wait-for-database + image: busybox:1.36 + command: + - sh + - -c + - | + echo "Waiting for alert processor database to be ready..." + until nc -z $ALERT_PROCESSOR_DB_HOST $ALERT_PROCESSOR_DB_PORT; do + echo "Database not ready yet, waiting..." + sleep 2 + done + echo "Database is ready!" + env: + - name: ALERT_PROCESSOR_DB_HOST + valueFrom: + configMapKeyRef: + name: bakery-config + key: ALERT_PROCESSOR_DB_HOST + - name: ALERT_PROCESSOR_DB_PORT + valueFrom: + configMapKeyRef: + name: bakery-config + key: DB_PORT - name: wait-for-rabbitmq image: busybox:1.36 command: diff --git a/infrastructure/kubernetes/base/components/cert-manager/cert-manager.yaml b/infrastructure/kubernetes/base/components/cert-manager/cert-manager.yaml new file mode 100644 index 00000000..af046130 --- /dev/null +++ b/infrastructure/kubernetes/base/components/cert-manager/cert-manager.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: cert-manager +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: cert-manager-webhook + namespace: cert-manager +--- +# Cert-manager installation using Helm repository +# This will be installed via kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.2/cert-manager.yaml +# The actual installation will be done via command line, this file documents the resources \ No newline at end of file diff --git a/infrastructure/kubernetes/base/components/cert-manager/cluster-issuer-production.yaml b/infrastructure/kubernetes/base/components/cert-manager/cluster-issuer-production.yaml new file mode 100644 index 00000000..a46c312c --- /dev/null +++ b/infrastructure/kubernetes/base/components/cert-manager/cluster-issuer-production.yaml @@ -0,0 +1,23 @@ +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: letsencrypt-production + namespace: cert-manager +spec: + acme: + # The ACME server URL (Let's Encrypt production) + server: https://acme-v02.api.letsencrypt.org/directory + # Email address used for ACME registration + email: admin@bakery-ia.local # Change this to your email + # Name of a secret used to store the ACME account private key + privateKeySecretRef: + name: letsencrypt-production + # Enable the HTTP-01 challenge provider + solvers: + - http01: + ingress: + class: nginx + podTemplate: + spec: + nodeSelector: + "kubernetes.io/os": linux \ No newline at end of file diff --git a/infrastructure/kubernetes/base/components/cert-manager/cluster-issuer-staging.yaml b/infrastructure/kubernetes/base/components/cert-manager/cluster-issuer-staging.yaml new file mode 100644 index 00000000..ebe09a76 --- /dev/null +++ b/infrastructure/kubernetes/base/components/cert-manager/cluster-issuer-staging.yaml @@ -0,0 +1,29 @@ +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: selfsigned-issuer +spec: + selfSigned: {} +--- +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: letsencrypt-staging +spec: + acme: + # The ACME server URL (Let's Encrypt staging) + server: https://acme-staging-v02.api.letsencrypt.org/directory + # Email address used for ACME registration + email: admin@bakery-ia.local # Change this to your email + # Name of a secret used to store the ACME account private key + privateKeySecretRef: + name: letsencrypt-staging + # Enable the HTTP-01 challenge provider + solvers: + - http01: + ingress: + class: nginx + podTemplate: + spec: + nodeSelector: + "kubernetes.io/os": linux \ No newline at end of file diff --git a/infrastructure/kubernetes/base/components/cert-manager/local-ca-issuer.yaml b/infrastructure/kubernetes/base/components/cert-manager/local-ca-issuer.yaml new file mode 100644 index 00000000..0ba198f6 --- /dev/null +++ b/infrastructure/kubernetes/base/components/cert-manager/local-ca-issuer.yaml @@ -0,0 +1,34 @@ +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: local-ca-issuer +spec: + ca: + secretName: local-ca-key-pair +--- +# Create a root CA certificate for local development +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: local-ca-cert + namespace: cert-manager +spec: + isCA: true + commonName: bakery-ia-local-ca + subject: + organizationalUnits: + - "Bakery IA Local CA" + organizations: + - "Bakery IA" + countries: + - "US" + secretName: local-ca-key-pair + privateKey: + algorithm: ECDSA + size: 256 + issuerRef: + name: selfsigned-issuer + kind: ClusterIssuer + group: cert-manager.io + duration: 8760h # 1 year + renewBefore: 720h # 30 days \ No newline at end of file diff --git a/infrastructure/kubernetes/base/components/sales/sales-service.yaml b/infrastructure/kubernetes/base/components/sales/sales-service.yaml index 4ce8cb95..c9c6dac7 100644 --- a/infrastructure/kubernetes/base/components/sales/sales-service.yaml +++ b/infrastructure/kubernetes/base/components/sales/sales-service.yaml @@ -106,6 +106,11 @@ spec: configMapKeyRef: name: bakery-config key: AUTH_SERVICE_URL + - name: GATEWAY_URL + valueFrom: + configMapKeyRef: + name: bakery-config + key: GATEWAY_URL resources: requests: memory: "256Mi" diff --git a/infrastructure/kubernetes/base/components/training/training-service.yaml b/infrastructure/kubernetes/base/components/training/training-service.yaml index d626ba05..a0ee2838 100644 --- a/infrastructure/kubernetes/base/components/training/training-service.yaml +++ b/infrastructure/kubernetes/base/components/training/training-service.yaml @@ -21,7 +21,7 @@ spec: spec: containers: - name: training-service - image: bakery/training-service:latest + image: bakery/training-service:79c869aaa529b2aaf2bbe77d2a2506e3ebdaf2abac3c83505ddfad29f3dbf99e ports: - containerPort: 8000 name: http @@ -106,6 +106,11 @@ spec: configMapKeyRef: name: bakery-config key: AUTH_SERVICE_URL + - name: GATEWAY_URL + valueFrom: + configMapKeyRef: + name: bakery-config + key: GATEWAY_URL resources: requests: memory: "256Mi" diff --git a/infrastructure/kubernetes/base/ingress-https.yaml b/infrastructure/kubernetes/base/ingress-https.yaml new file mode 100644 index 00000000..881cce25 --- /dev/null +++ b/infrastructure/kubernetes/base/ingress-https.yaml @@ -0,0 +1,85 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: bakery-ingress-https + namespace: bakery-ia + labels: + app.kubernetes.io/name: bakery-ia + app.kubernetes.io/component: ingress + annotations: + # Nginx ingress controller annotations + nginx.ingress.kubernetes.io/ssl-redirect: "true" + nginx.ingress.kubernetes.io/force-ssl-redirect: "true" + nginx.ingress.kubernetes.io/proxy-body-size: "10m" + nginx.ingress.kubernetes.io/proxy-connect-timeout: "600" + nginx.ingress.kubernetes.io/proxy-send-timeout: "600" + nginx.ingress.kubernetes.io/proxy-read-timeout: "600" + # CORS configuration for HTTPS + nginx.ingress.kubernetes.io/enable-cors: "true" + nginx.ingress.kubernetes.io/cors-allow-origin: "https://bakery-ia.local,https://api.bakery-ia.local,https://monitoring.bakery-ia.local" + nginx.ingress.kubernetes.io/cors-allow-methods: "GET, POST, PUT, DELETE, OPTIONS, PATCH" + nginx.ingress.kubernetes.io/cors-allow-headers: "Content-Type, Authorization, X-Requested-With, Accept, Origin" + nginx.ingress.kubernetes.io/cors-allow-credentials: "true" + # Cert-manager annotations for automatic certificate issuance + cert-manager.io/cluster-issuer: "letsencrypt-staging" # Change to letsencrypt-production for production + cert-manager.io/acme-challenge-type: http01 +spec: + ingressClassName: nginx + tls: + - hosts: + - bakery-ia.local + - api.bakery-ia.local + - monitoring.bakery-ia.local + secretName: bakery-ia-tls-cert + rules: + - host: bakery-ia.local + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: frontend-service + port: + number: 3000 + - path: /api + pathType: Prefix + backend: + service: + name: gateway-service + port: + number: 8000 + - path: /auth + pathType: Prefix + backend: + service: + name: auth-service + port: + number: 8000 + - host: api.bakery-ia.local + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: gateway-service + port: + number: 8000 + - host: monitoring.bakery-ia.local + http: + paths: + - path: /grafana + pathType: Prefix + backend: + service: + name: grafana-service + port: + number: 3000 + - path: /prometheus + pathType: Prefix + backend: + service: + name: prometheus-service + port: + number: 9090 \ No newline at end of file diff --git a/infrastructure/kubernetes/overlays/dev/dev-patches.yaml b/infrastructure/kubernetes/overlays/dev/dev-patches.yaml index 1acf4b02..19be5c2c 100644 --- a/infrastructure/kubernetes/overlays/dev/dev-patches.yaml +++ b/infrastructure/kubernetes/overlays/dev/dev-patches.yaml @@ -27,15 +27,18 @@ metadata: name: bakery-ingress namespace: bakery-ia annotations: - nginx.ingress.kubernetes.io/rewrite-target: / nginx.ingress.kubernetes.io/ssl-redirect: "false" nginx.ingress.kubernetes.io/force-ssl-redirect: "false" nginx.ingress.kubernetes.io/cors-allow-origin: "*" nginx.ingress.kubernetes.io/cors-allow-methods: "GET, POST, PUT, DELETE, OPTIONS" nginx.ingress.kubernetes.io/cors-allow-headers: "Content-Type, Authorization" + nginx.ingress.kubernetes.io/cors-allow-credentials: "true" + nginx.ingress.kubernetes.io/enable-cors: "true" # Development specific annotations nginx.ingress.kubernetes.io/proxy-read-timeout: "300" nginx.ingress.kubernetes.io/proxy-connect-timeout: "300" + nginx.ingress.kubernetes.io/proxy-body-size: "10m" + nginx.ingress.kubernetes.io/proxy-send-timeout: "600" spec: ingressClassName: nginx rules: diff --git a/infrastructure/kubernetes/overlays/dev/https-kustomization.yaml b/infrastructure/kubernetes/overlays/dev/https-kustomization.yaml new file mode 100644 index 00000000..263bc73b --- /dev/null +++ b/infrastructure/kubernetes/overlays/dev/https-kustomization.yaml @@ -0,0 +1,62 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +metadata: + name: bakery-ia-https-dev + +# Base configuration +resources: + - ../../base + - ../../base/components/cert-manager/cluster-issuer-staging.yaml + - ../../base/components/cert-manager/cluster-issuer-production.yaml + - ../../base/components/cert-manager/local-ca-issuer.yaml + +# Patches +patches: + - path: dev-patches.yaml + - target: + kind: Ingress + name: bakery-ingress + path: ingress-https-patch.yaml + +labels: + - includeSelectors: true + pairs: + app.kubernetes.io/part-of: bakery-ia + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/environment: dev-https + +# Set image tags for development +images: + - name: bakery/auth-service + newTag: latest + - name: bakery/tenant-service + newTag: latest + - name: bakery/training-service + newTag: latest + - name: bakery/forecasting-service + newTag: latest + - name: bakery/sales-service + newTag: latest + - name: bakery/external-service + newTag: latest + - name: bakery/notification-service + newTag: latest + - name: bakery/inventory-service + newTag: latest + - name: bakery/recipes-service + newTag: latest + - name: bakery/suppliers-service + newTag: latest + - name: bakery/pos-service + newTag: latest + - name: bakery/orders-service + newTag: latest + - name: bakery/production-service + newTag: latest + - name: bakery/alert-processor + newTag: latest + - name: bakery/gateway + newTag: latest + - name: bakery/dashboard + newTag: latest \ No newline at end of file diff --git a/infrastructure/kubernetes/overlays/dev/ingress-https-patch.yaml b/infrastructure/kubernetes/overlays/dev/ingress-https-patch.yaml new file mode 100644 index 00000000..d2cc8e82 --- /dev/null +++ b/infrastructure/kubernetes/overlays/dev/ingress-https-patch.yaml @@ -0,0 +1,20 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: bakery-ingress + namespace: bakery-ia + annotations: + # Enable HTTPS redirect + nginx.ingress.kubernetes.io/ssl-redirect: "true" + nginx.ingress.kubernetes.io/force-ssl-redirect: "true" + # Update CORS for HTTPS + nginx.ingress.kubernetes.io/cors-allow-origin: "https://bakery-ia.local,https://api.bakery-ia.local,https://monitoring.bakery-ia.local" + # Cert-manager annotations - using local CA for development + cert-manager.io/cluster-issuer: "local-ca-issuer" +spec: + tls: + - hosts: + - bakery-ia.local + - api.bakery-ia.local + - monitoring.bakery-ia.local + secretName: bakery-ia-tls-cert \ No newline at end of file diff --git a/infrastructure/kubernetes/overlays/dev/kustomization.yaml b/infrastructure/kubernetes/overlays/dev/kustomization.yaml index a9419be8..a68ed613 100644 --- a/infrastructure/kubernetes/overlays/dev/kustomization.yaml +++ b/infrastructure/kubernetes/overlays/dev/kustomization.yaml @@ -9,10 +9,8 @@ namespace: bakery-ia resources: - ../../base -patchesStrategicMerge: - - dev-patches.yaml - -patchesJson6902: +patches: + - path: dev-patches.yaml - target: group: apps version: v1 @@ -24,9 +22,9 @@ patchesJson6902: value: requests: memory: "64Mi" - cpu: "50m" + cpu: "25m" limits: - memory: "128Mi" + memory: "256Mi" cpu: "200m" - target: group: apps @@ -39,9 +37,9 @@ patchesJson6902: value: requests: memory: "64Mi" - cpu: "50m" + cpu: "25m" limits: - memory: "128Mi" + memory: "256Mi" cpu: "200m" - target: group: apps @@ -119,11 +117,452 @@ patchesJson6902: path: /spec/template/spec/containers/0/resources value: requests: - memory: "128Mi" - cpu: "50m" + memory: "64Mi" + cpu: "25m" limits: memory: "256Mi" cpu: "200m" + # Database patches + - target: + group: apps + version: v1 + kind: Deployment + name: external-db + patch: |- + - op: replace + path: /spec/template/spec/containers/0/resources + value: + requests: + memory: "64Mi" + cpu: "25m" + limits: + memory: "256Mi" + cpu: "200m" + - target: + group: apps + version: v1 + kind: Deployment + name: forecasting-db + patch: |- + - op: replace + path: /spec/template/spec/containers/0/resources + value: + requests: + memory: "64Mi" + cpu: "25m" + limits: + memory: "256Mi" + cpu: "200m" + - target: + group: apps + version: v1 + kind: Deployment + name: inventory-db + patch: |- + - op: replace + path: /spec/template/spec/containers/0/resources + value: + requests: + memory: "64Mi" + cpu: "25m" + limits: + memory: "256Mi" + cpu: "200m" + - target: + group: apps + version: v1 + kind: Deployment + name: notification-db + patch: |- + - op: replace + path: /spec/template/spec/containers/0/resources + value: + requests: + memory: "64Mi" + cpu: "25m" + limits: + memory: "256Mi" + cpu: "200m" + - target: + group: apps + version: v1 + kind: Deployment + name: orders-db + patch: |- + - op: replace + path: /spec/template/spec/containers/0/resources + value: + requests: + memory: "64Mi" + cpu: "25m" + limits: + memory: "256Mi" + cpu: "200m" + - target: + group: apps + version: v1 + kind: Deployment + name: pos-db + patch: |- + - op: replace + path: /spec/template/spec/containers/0/resources + value: + requests: + memory: "64Mi" + cpu: "25m" + limits: + memory: "256Mi" + cpu: "200m" + - target: + group: apps + version: v1 + kind: Deployment + name: production-db + patch: |- + - op: replace + path: /spec/template/spec/containers/0/resources + value: + requests: + memory: "64Mi" + cpu: "25m" + limits: + memory: "256Mi" + cpu: "200m" + - target: + group: apps + version: v1 + kind: Deployment + name: recipes-db + patch: |- + - op: replace + path: /spec/template/spec/containers/0/resources + value: + requests: + memory: "64Mi" + cpu: "25m" + limits: + memory: "256Mi" + cpu: "200m" + - target: + group: apps + version: v1 + kind: Deployment + name: sales-db + patch: |- + - op: replace + path: /spec/template/spec/containers/0/resources + value: + requests: + memory: "64Mi" + cpu: "25m" + limits: + memory: "256Mi" + cpu: "200m" + - target: + group: apps + version: v1 + kind: Deployment + name: suppliers-db + patch: |- + - op: replace + path: /spec/template/spec/containers/0/resources + value: + requests: + memory: "64Mi" + cpu: "25m" + limits: + memory: "256Mi" + cpu: "200m" + - target: + group: apps + version: v1 + kind: Deployment + name: tenant-db + patch: |- + - op: replace + path: /spec/template/spec/containers/0/resources + value: + requests: + memory: "64Mi" + cpu: "25m" + limits: + memory: "256Mi" + cpu: "200m" + - target: + group: apps + version: v1 + kind: Deployment + name: training-db + patch: |- + - op: replace + path: /spec/template/spec/containers/0/resources + value: + requests: + memory: "64Mi" + cpu: "25m" + limits: + memory: "256Mi" + cpu: "200m" + # Service patches + - target: + group: apps + version: v1 + kind: Deployment + name: external-service + patch: |- + - op: add + path: /spec/template/spec/initContainers + value: + - name: wait-for-external-db + image: postgres:13-alpine + command: + - sh + - -c + - | + until pg_isready -h $EXTERNAL_DB_HOST -p $EXTERNAL_DB_PORT -U $EXTERNAL_DB_USER; do + echo "Waiting for external database..." + sleep 2 + done + echo "External database is ready!" + env: + - name: EXTERNAL_DB_HOST + valueFrom: + configMapKeyRef: + name: bakery-config + key: EXTERNAL_DB_HOST + - name: EXTERNAL_DB_PORT + valueFrom: + configMapKeyRef: + name: bakery-config + key: DB_PORT + - name: EXTERNAL_DB_USER + valueFrom: + secretKeyRef: + name: database-secrets + key: EXTERNAL_DB_USER + - name: PGPASSWORD + valueFrom: + secretKeyRef: + name: database-secrets + key: EXTERNAL_DB_PASSWORD + - name: wait-for-rabbitmq + image: busybox:1.35 + command: + - sh + - -c + - | + until nc -z $RABBITMQ_HOST $RABBITMQ_PORT; do + echo "Waiting for RabbitMQ..." + sleep 2 + done + echo "RabbitMQ is ready!" + env: + - name: RABBITMQ_HOST + valueFrom: + configMapKeyRef: + name: bakery-config + key: RABBITMQ_HOST + - name: RABBITMQ_PORT + valueFrom: + configMapKeyRef: + name: bakery-config + key: RABBITMQ_PORT + - name: wait-for-redis + image: redis:7-alpine + command: + - sh + - -c + - | + until redis-cli -h $REDIS_HOST -p $REDIS_PORT ping; do + echo "Waiting for Redis..." + sleep 2 + done + echo "Redis is ready!" + env: + - name: REDIS_HOST + valueFrom: + configMapKeyRef: + name: bakery-config + key: REDIS_HOST + - name: REDIS_PORT + valueFrom: + configMapKeyRef: + name: bakery-config + key: REDIS_PORT + - op: replace + path: /spec/template/spec/containers/0/resources + value: + requests: + memory: "64Mi" + cpu: "25m" + limits: + memory: "256Mi" + cpu: "200m" + - target: + group: apps + version: v1 + kind: Deployment + name: forecasting-service + patch: |- + - op: replace + path: /spec/template/spec/containers/0/resources + value: + requests: + memory: "64Mi" + cpu: "25m" + limits: + memory: "256Mi" + cpu: "200m" + - target: + group: apps + version: v1 + kind: Deployment + name: inventory-service + patch: |- + - op: replace + path: /spec/template/spec/containers/0/resources + value: + requests: + memory: "64Mi" + cpu: "25m" + limits: + memory: "256Mi" + cpu: "200m" + - target: + group: apps + version: v1 + kind: Deployment + name: notification-service + patch: |- + - op: replace + path: /spec/template/spec/containers/0/resources + value: + requests: + memory: "64Mi" + cpu: "25m" + limits: + memory: "256Mi" + cpu: "200m" + - target: + group: apps + version: v1 + kind: Deployment + name: orders-service + patch: |- + - op: replace + path: /spec/template/spec/containers/0/resources + value: + requests: + memory: "64Mi" + cpu: "25m" + limits: + memory: "256Mi" + cpu: "200m" + - target: + group: apps + version: v1 + kind: Deployment + name: pos-service + patch: |- + - op: replace + path: /spec/template/spec/containers/0/resources + value: + requests: + memory: "64Mi" + cpu: "25m" + limits: + memory: "256Mi" + cpu: "200m" + - target: + group: apps + version: v1 + kind: Deployment + name: production-service + patch: |- + - op: replace + path: /spec/template/spec/containers/0/resources + value: + requests: + memory: "64Mi" + cpu: "25m" + limits: + memory: "256Mi" + cpu: "200m" + - target: + group: apps + version: v1 + kind: Deployment + name: recipes-service + patch: |- + - op: replace + path: /spec/template/spec/containers/0/resources + value: + requests: + memory: "64Mi" + cpu: "25m" + limits: + memory: "256Mi" + cpu: "200m" + - target: + group: apps + version: v1 + kind: Deployment + name: sales-service + patch: |- + - op: replace + path: /spec/template/spec/containers/0/resources + value: + requests: + memory: "64Mi" + cpu: "25m" + limits: + memory: "256Mi" + cpu: "200m" + - target: + group: apps + version: v1 + kind: Deployment + name: suppliers-service + patch: |- + - op: replace + path: /spec/template/spec/containers/0/resources + value: + requests: + memory: "64Mi" + cpu: "25m" + limits: + memory: "256Mi" + cpu: "200m" + - target: + group: apps + version: v1 + kind: Deployment + name: tenant-service + patch: |- + - op: replace + path: /spec/template/spec/containers/0/resources + value: + requests: + memory: "64Mi" + cpu: "25m" + limits: + memory: "256Mi" + cpu: "200m" + - target: + group: apps + version: v1 + kind: Deployment + name: training-service + patch: |- + - op: replace + path: /spec/template/spec/containers/0/resources + value: + requests: + memory: "256Mi" + cpu: "100m" + limits: + memory: "1Gi" + cpu: "500m" configMapGenerator: - name: bakery-dev-config diff --git a/infrastructure/monitoring/prometheus/prometheus.yml b/infrastructure/monitoring/prometheus/prometheus.yml index 9f1582c0..2d46e41a 100644 --- a/infrastructure/monitoring/prometheus/prometheus.yml +++ b/infrastructure/monitoring/prometheus/prometheus.yml @@ -21,7 +21,7 @@ scrape_configs: # Service discovery for microservices - job_name: 'gateway' static_configs: - - targets: ['gateway:8000'] + - targets: ['gateway-service:8000'] metrics_path: '/metrics' scrape_interval: 30s scrape_timeout: 10s diff --git a/kind-config.yaml b/kind-config.yaml index b6540047..29a29f07 100644 --- a/kind-config.yaml +++ b/kind-config.yaml @@ -3,7 +3,6 @@ apiVersion: kind.x-k8s.io/v1alpha4 name: bakery-ia-local nodes: - role: control-plane - image: kindest/node:v1.29.0 kubeadmConfigPatches: - | kind: InitConfiguration @@ -11,16 +10,19 @@ nodes: kubeletExtraArgs: node-labels: "ingress-ready=true" extraPortMappings: - - containerPort: 80 + # HTTP ingress + - containerPort: 30080 hostPort: 80 protocol: TCP - - containerPort: 443 + # HTTPS ingress + - containerPort: 30443 hostPort: 443 protocol: TCP - - containerPort: 30080 - hostPort: 30080 + # Direct frontend access (backup) + - containerPort: 30300 + hostPort: 3000 + protocol: TCP + # Direct gateway access (backup) + - containerPort: 30800 + hostPort: 8000 protocol: TCP -- role: worker - image: kindest/node:v1.29.0 -- role: worker - image: kindest/node:v1.29.0 \ No newline at end of file diff --git a/services/production/app/core/config.py b/services/production/app/core/config.py index 898c0e2c..9d1abe0d 100644 --- a/services/production/app/core/config.py +++ b/services/production/app/core/config.py @@ -42,12 +42,12 @@ class ProductionSettings(BaseServiceSettings): REDIS_DB: int = 3 # Service URLs for communication - GATEWAY_URL: str = os.getenv("GATEWAY_URL", "http://gateway:8080") - ORDERS_SERVICE_URL: str = os.getenv("ORDERS_SERVICE_URL", "http://orders:8000") - INVENTORY_SERVICE_URL: str = os.getenv("INVENTORY_SERVICE_URL", "http://inventory:8000") - RECIPES_SERVICE_URL: str = os.getenv("RECIPES_SERVICE_URL", "http://recipes:8000") - SALES_SERVICE_URL: str = os.getenv("SALES_SERVICE_URL", "http://sales:8000") - FORECASTING_SERVICE_URL: str = os.getenv("FORECASTING_SERVICE_URL", "http://forecasting:8000") + GATEWAY_URL: str = os.getenv("GATEWAY_URL", "http://gateway-service:8000") + ORDERS_SERVICE_URL: str = os.getenv("ORDERS_SERVICE_URL", "http://orders-service:8000") + INVENTORY_SERVICE_URL: str = os.getenv("INVENTORY_SERVICE_URL", "http://inventory-service:8000") + RECIPES_SERVICE_URL: str = os.getenv("RECIPES_SERVICE_URL", "http://recipes-service:8000") + SALES_SERVICE_URL: str = os.getenv("SALES_SERVICE_URL", "http://sales-service:8000") + FORECASTING_SERVICE_URL: str = os.getenv("FORECASTING_SERVICE_URL", "http://forecasting-service:8000") # Production Planning Configuration PLANNING_HORIZON_DAYS: int = int(os.getenv("PLANNING_HORIZON_DAYS", "7")) diff --git a/services/recipes/app/core/config.py b/services/recipes/app/core/config.py index 33b0c1dd..30d54083 100644 --- a/services/recipes/app/core/config.py +++ b/services/recipes/app/core/config.py @@ -39,14 +39,14 @@ class Settings: REDIS_URL: str = os.getenv("REDIS_URL", "redis://localhost:6379/0") # External service URLs - GATEWAY_URL: str = os.getenv("GATEWAY_URL", "http://gateway:8000") + GATEWAY_URL: str = os.getenv("GATEWAY_URL", "http://gateway-service:8000") INVENTORY_SERVICE_URL: str = os.getenv( "INVENTORY_SERVICE_URL", - "http://inventory:8000" + "http://inventory-service:8000" ) SALES_SERVICE_URL: str = os.getenv( "SALES_SERVICE_URL", - "http://sales:8000" + "http://sales-service:8000" ) # Authentication diff --git a/setup-https.sh b/setup-https.sh new file mode 100755 index 00000000..2052c3a2 --- /dev/null +++ b/setup-https.sh @@ -0,0 +1,256 @@ +#!/bin/bash + +# Bakery IA HTTPS Setup Script +# This script sets up HTTPS with cert-manager and Let's Encrypt for local development + +set -e + +echo "πŸ”’ Setting up HTTPS for Bakery IA with cert-manager and Let's Encrypt" +echo "===============================================================" + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Function to print colored output +print_status() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +print_success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +print_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# Check prerequisites +check_prerequisites() { + print_status "Checking prerequisites..." + + # Check required tools + local missing_tools=() + + if ! command -v kubectl &> /dev/null; then + missing_tools+=("kubectl") + fi + + if ! command -v kind &> /dev/null; then + missing_tools+=("kind") + fi + + if ! command -v skaffold &> /dev/null; then + missing_tools+=("skaffold") + fi + + if ! command -v colima &> /dev/null; then + missing_tools+=("colima") + fi + + # Report missing tools + if [ ${#missing_tools[@]} -ne 0 ]; then + print_error "Missing required tools: ${missing_tools[*]}" + print_error "Please install them with: brew install ${missing_tools[*]}" + exit 1 + fi + + # Check if Colima is running + if ! colima status --profile k8s-local &> /dev/null; then + print_error "Colima is not running. Please start it with:" + print_error "colima start --cpu 4 --memory 8 --disk 50 --runtime docker --profile k8s-local" + exit 1 + fi + + # Check if cluster is running + if ! kubectl cluster-info &> /dev/null; then + print_error "No Kubernetes cluster found. Please create your Kind cluster first:" + print_error "kind create cluster --name bakery-ia-local" + exit 1 + fi + + print_success "Prerequisites check passed" +} + +# Install cert-manager +install_cert_manager() { + print_status "Installing cert-manager..." + + # Install cert-manager + kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.2/cert-manager.yaml + + # Wait for cert-manager to be ready + print_status "Waiting for cert-manager pods to be ready..." + kubectl wait --for=condition=ready pod -l app.kubernetes.io/instance=cert-manager -n cert-manager --timeout=300s + + print_success "cert-manager installed successfully" +} + +# Install NGINX Ingress Controller +install_nginx_ingress() { + print_status "Installing NGINX Ingress Controller for Kind..." + + # Install NGINX Ingress Controller for Kind (correct URL) + kubectl apply -f https://kind.sigs.k8s.io/examples/ingress/deploy-ingress-nginx.yaml + + # Wait for ingress controller to be ready + print_status "Waiting for NGINX Ingress Controller to be ready..." + kubectl wait --namespace ingress-nginx \ + --for=condition=ready pod \ + --selector=app.kubernetes.io/component=controller \ + --timeout=300s + + print_success "NGINX Ingress Controller installed successfully" +} + +# Setup cluster issuers +setup_cluster_issuers() { + print_status "Setting up cluster issuers..." + + # Apply cluster issuers + kubectl apply -f infrastructure/kubernetes/base/components/cert-manager/cluster-issuer-staging.yaml + kubectl apply -f infrastructure/kubernetes/base/components/cert-manager/local-ca-issuer.yaml + kubectl apply -f infrastructure/kubernetes/base/components/cert-manager/cluster-issuer-production.yaml + + # Wait a bit for the issuers to be created + sleep 10 + + # Check if issuers are ready + print_status "Checking cluster issuer status..." + kubectl get clusterissuers + + print_success "Cluster issuers configured successfully" +} + +# Deploy the application with HTTPS using Skaffold +deploy_with_https() { + print_status "Deploying Bakery IA with HTTPS support using Skaffold..." + + # Check if Skaffold is available + if ! command -v skaffold &> /dev/null; then + print_error "Skaffold is not installed. Please install skaffold first:" + print_error "brew install skaffold" + exit 1 + fi + + # Deploy with Skaffold (builds and deploys automatically) + print_status "Building and deploying with Skaffold..." + skaffold run --profile=dev + + # Apply the HTTPS ingress patch + print_status "Applying HTTPS configuration..." + kubectl patch ingress bakery-ingress -n bakery-ia --patch-file infrastructure/kubernetes/overlays/dev/ingress-https-patch.yaml + + print_status "Waiting for deployments to be ready..." + kubectl wait --for=condition=available --timeout=300s deployment --all -n bakery-ia + + print_success "Application deployed with HTTPS support using Skaffold" +} + +# Check certificate status +check_certificates() { + print_status "Checking certificate status..." + + # Wait for certificate to be issued + sleep 30 + + echo "" + echo "Certificate status:" + kubectl get certificates -n bakery-ia + + echo "" + echo "Certificate details:" + kubectl describe certificate bakery-ia-tls-cert -n bakery-ia + + echo "" + echo "TLS secret status:" + kubectl get secret bakery-ia-tls-cert -n bakery-ia +} + +# Update hosts file +update_hosts_file() { + print_status "Checking hosts file configuration..." + + # Get the external IP for Kind + EXTERNAL_IP="127.0.0.1" + + # Check if entries exist in hosts file + if ! grep -q "bakery-ia.local" /etc/hosts; then + print_warning "Please add the following entries to your /etc/hosts file:" + echo "" + echo "sudo tee -a /etc/hosts << EOF" + echo "$EXTERNAL_IP bakery-ia.local" + echo "$EXTERNAL_IP api.bakery-ia.local" + echo "$EXTERNAL_IP monitoring.bakery-ia.local" + echo "EOF" + echo "" + else + print_success "Hosts file entries already exist" + fi +} + +# Export CA certificate for browser trust +export_ca_certificate() { + print_status "Exporting CA certificate for browser trust..." + + # Wait for CA certificate to be created + sleep 10 + + # Extract the CA certificate + kubectl get secret local-ca-key-pair -n cert-manager -o jsonpath='{.data.tls\.crt}' | base64 -d > bakery-ia-ca.crt + + print_success "CA certificate exported as 'bakery-ia-ca.crt'" + print_warning "To trust this certificate in your browser:" + echo " 1. Import 'bakery-ia-ca.crt' into your browser's certificate store" + echo " 2. Mark it as trusted for website authentication" + echo "" + print_warning "For macOS: Add to Keychain Access and set to 'Always Trust'" + print_warning "For Linux: Add to /usr/local/share/ca-certificates/ and run 'sudo update-ca-certificates'" +} + +# Display access information +display_access_info() { + print_success "πŸŽ‰ HTTPS setup completed!" + echo "" + echo "Access your application at:" + echo " 🌐 Frontend: https://bakery-ia.local" + echo " πŸ”— API: https://api.bakery-ia.local" + echo " πŸ“Š Monitoring: https://monitoring.bakery-ia.local" + echo "" + echo "Useful commands:" + echo " πŸ“‹ Check pods: kubectl get pods -n bakery-ia" + echo " πŸ” Check ingress: kubectl get ingress -n bakery-ia" + echo " πŸ“œ Check certificates: kubectl get certificates -n bakery-ia" + echo " πŸ“ View logs: kubectl logs -f deployment/ -n bakery-ia" + echo " πŸš€ Run Skaffold dev mode: skaffold dev --profile=dev" + echo " 🧹 Clean up: skaffold delete" + echo "" + print_warning "Note: You may see certificate warnings until you import the CA certificate into your browser" +} + +# Main execution +main() { + echo "Starting HTTPS setup for Bakery IA..." + + check_prerequisites + install_cert_manager + install_nginx_ingress + setup_cluster_issuers + deploy_with_https + check_certificates + update_hosts_file + export_ca_certificate + display_access_info + + print_success "Setup completed successfully! πŸš€" +} + +# Run main function +main "$@" \ No newline at end of file diff --git a/shared/config/base.py b/shared/config/base.py index 8e628162..4ade07ed 100644 --- a/shared/config/base.py +++ b/shared/config/base.py @@ -110,7 +110,7 @@ class BaseServiceSettings(BaseSettings): # Service-to-Service Authentication SERVICE_API_KEY: str = os.getenv("SERVICE_API_KEY", "service-api-key-change-in-production") ENABLE_SERVICE_AUTH: bool = os.getenv("ENABLE_SERVICE_AUTH", "false").lower() == "true" - API_GATEWAY_URL: str = os.getenv("API_GATEWAY_URL", "http://gateway:8000") + API_GATEWAY_URL: str = os.getenv("API_GATEWAY_URL", "http://gateway-service:8000") # Password Requirements PASSWORD_MIN_LENGTH: int = int(os.getenv("PASSWORD_MIN_LENGTH", "8")) @@ -129,7 +129,7 @@ class BaseServiceSettings(BaseSettings): # ================================================================ # Service URLs (can be overridden by environment variables) - GATEWAY_URL: str = os.getenv("GATEWAY_URL", "http://gateway:8000") + GATEWAY_URL: str = os.getenv("GATEWAY_URL", "http://gateway-service:8000") AUTH_SERVICE_URL: str = os.getenv("AUTH_SERVICE_URL", "http://auth-service:8000") TRAINING_SERVICE_URL: str = os.getenv("TRAINING_SERVICE_URL", "http://training-service:8000") FORECASTING_SERVICE_URL: str = os.getenv("FORECASTING_SERVICE_URL", "http://forecasting-service:8000") diff --git a/skaffold-dev.sh b/skaffold-dev.sh new file mode 100755 index 00000000..cac0c8f7 --- /dev/null +++ b/skaffold-dev.sh @@ -0,0 +1,152 @@ +#!/bin/bash + +# Bakery IA Skaffold Development Script +# Quick setup script for Skaffold development workflow + +set -e + +echo "πŸš€ Starting Bakery IA Development Environment with Skaffold" +echo "==========================================================" + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Function to print colored output +print_status() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +print_success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +print_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# Check prerequisites +check_prerequisites() { + print_status "Checking prerequisites..." + + local missing_tools=() + + if ! command -v skaffold &> /dev/null; then + missing_tools+=("skaffold") + fi + + if ! command -v kubectl &> /dev/null; then + missing_tools+=("kubectl") + fi + + if ! command -v colima &> /dev/null; then + missing_tools+=("colima") + fi + + if ! command -v kind &> /dev/null; then + missing_tools+=("kind") + fi + + if [ ${#missing_tools[@]} -ne 0 ]; then + print_error "Missing required tools: ${missing_tools[*]}" + print_error "Install with: brew install ${missing_tools[*]}" + exit 1 + fi + + # Check if Colima is running + if ! colima status --profile k8s-local &> /dev/null; then + print_warning "Colima is not running. Starting it now..." + colima start --cpu 4 --memory 8 --disk 50 --runtime docker --profile k8s-local + fi + + # Check if Kind cluster exists + if ! kind get clusters | grep -q "bakery-ia-local"; then + print_warning "Kind cluster not found. Creating it now..." + kind create cluster --name bakery-ia-local + fi + + # Verify cluster is accessible + if ! kubectl cluster-info &> /dev/null; then + print_error "Cannot connect to Kubernetes cluster" + exit 1 + fi + + print_success "Prerequisites check passed" +} + +# Setup development environment +setup_dev_environment() { + print_status "Setting up development environment..." + + # Check if NGINX Ingress is installed + if ! kubectl get namespace ingress-nginx &> /dev/null; then + print_status "Installing NGINX Ingress Controller..." + kubectl apply -f https://kind.sigs.k8s.io/examples/ingress/deploy-ingress-nginx.yaml + kubectl wait --namespace ingress-nginx \ + --for=condition=ready pod \ + --selector=app.kubernetes.io/component=controller \ + --timeout=300s + fi + + print_success "Development environment ready" +} + +# Start Skaffold development mode +start_skaffold_dev() { + print_status "Starting Skaffold development mode..." + + print_warning "Starting continuous development mode with Skaffold..." + print_warning "This will:" + echo " - Build all Docker images automatically" + echo " - Deploy to your Kind cluster" + echo " - Watch for file changes and auto-rebuild" + echo " - Stream logs from all services" + echo "" + print_warning "Press Ctrl+C to stop and clean up" + echo "" + + # Start Skaffold in development mode + skaffold dev --profile=dev +} + +# Display information +display_info() { + print_success "πŸŽ‰ Skaffold development environment ready!" + echo "" + echo "Next steps:" + echo " 1. Add hosts entries (if not done already):" + echo " sudo tee -a /etc/hosts << EOF" + echo " 127.0.0.1 bakery-ia.local" + echo " 127.0.0.1 api.bakery-ia.local" + echo " 127.0.0.1 monitoring.bakery-ia.local" + echo " EOF" + echo "" + echo " 2. Access your application:" + echo " 🌐 Frontend: http://bakery-ia.local" + echo " πŸ”— API: http://api.bakery-ia.local" + echo "" + echo " 3. For HTTPS support, run: ./setup-https.sh" + echo "" + echo "Useful commands:" + echo " πŸ“‹ Check pods: kubectl get pods -n bakery-ia" + echo " πŸ“ View logs: kubectl logs -f deployment/ -n bakery-ia" + echo " 🧹 Clean up: skaffold delete" +} + +# Main execution +main() { + check_prerequisites + setup_dev_environment + display_info + start_skaffold_dev +} + +# Run main function +main "$@" \ No newline at end of file diff --git a/skaffold.yaml b/skaffold.yaml index d57d8cf1..96f7c4f3 100644 --- a/skaffold.yaml +++ b/skaffold.yaml @@ -6,6 +6,9 @@ metadata: build: local: push: false + tagPolicy: + envTemplate: + template: "dev" artifacts: # Gateway - image: bakery/gateway @@ -95,17 +98,8 @@ deploy: paths: - infrastructure/kubernetes/overlays/dev -portForward: - - resourceType: service - resourceName: frontend-service - namespace: bakery-ia - port: 3000 - localPort: 3000 - - resourceType: service - resourceName: gateway-service - namespace: bakery-ia - port: 8000 - localPort: 8000 +# Port forwarding removed - using ingress with direct port mapping +# Access via: https://localhost (or http://localhost) profiles: - name: dev @@ -113,7 +107,8 @@ profiles: local: push: false tagPolicy: - gitCommit: {} + envTemplate: + template: "dev" deploy: kustomize: paths: