# Enhanced Ingress Example with Detailed Comments # This example shows how to expose your applications externally with SSL/TLS # # 🎯 What this does: Creates an Ingress that: # - Routes traffic from external domains to your services # - Automatically handles SSL/TLS certificates # - Provides load balancing across multiple pods # - Supports path-based routing (different URLs to different services) # - Includes security features like rate limiting and CORS # πŸ“Š ASCII Diagram: How Ingress Works in Your Cluster # # β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” # β”‚ INTERNET β”‚ # β”‚ β”‚ # β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ # β”‚ β”‚ Browser β”‚ β”‚ Mobile β”‚ β”‚ API β”‚ β”‚ Other β”‚ β”‚ # β”‚ β”‚ β”‚ β”‚ App β”‚ β”‚ Client β”‚ β”‚ Clients β”‚ β”‚ # β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ # β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ # β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ # β”‚ β”‚ β”‚ β”‚ # β”‚ β–Ό β–Ό β”‚ # β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ # β”‚ β”‚ AZURE LOAD BALANCER β”‚ β”‚ # β”‚ β”‚ IP: 4.155.160.32 (prod-usw2-k8s-freeleaps-lb-fe-ip) β”‚ β”‚ # β”‚ β”‚ Port: 80/443 β”‚ β”‚ # β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ # β”‚ β”‚ β”‚ # β”‚ β–Ό β”‚ # β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ # β”‚ β”‚ NGINX INGRESS CONTROLLER β”‚ β”‚ # β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ # β”‚ β”‚ β”‚ Pod: ingress-nginx-controller-abc123 β”‚ β”‚ β”‚ # β”‚ β”‚ β”‚ IP: 10.0.1.100 Port: 80/443 β”‚ β”‚ β”‚ # β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ # β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ # β”‚ β”‚ β”‚ # β”‚ β–Ό β”‚ # β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ # β”‚ β”‚ INGRESS RULES β”‚ β”‚ # β”‚ β”‚ β”‚ β”‚ # β”‚ β”‚ argo.mathmast.com β†’ argo-cd-server:80 β”‚ β”‚ # β”‚ β”‚ gitea.freeleaps.mathmast.com β†’ gitea-http:3000 β”‚ β”‚ # β”‚ β”‚ magicleaps.mathmast.com β†’ magicleaps-frontend-service:80 β”‚ β”‚ # β”‚ β”‚ alpha.magicleaps.mathmast.com β†’ magicleaps-frontend-service:80 β”‚ β”‚ # β”‚ β”‚ β”‚ β”‚ # β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ # β”‚ β”‚ β”‚ # β”‚ β–Ό β”‚ # β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ # β”‚ β”‚ KUBERNETES SERVICES β”‚ β”‚ # β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ # β”‚ β”‚ β”‚argo-cd-svc β”‚ β”‚gitea-http β”‚ β”‚magic-front β”‚ β”‚magic-api β”‚ β”‚ β”‚ # β”‚ β”‚ β”‚ClusterIP β”‚ β”‚ClusterIP β”‚ β”‚ClusterIP β”‚ β”‚ClusterIP β”‚ β”‚ β”‚ # β”‚ β”‚ β”‚10.0.1.10 β”‚ β”‚10.0.1.11 β”‚ β”‚10.0.1.12 β”‚ β”‚10.0.1.13 β”‚ β”‚ β”‚ # β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ # β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ # β”‚ β”‚ β”‚ # β”‚ β–Ό β”‚ # β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ # β”‚ β”‚ APPLICATION PODS β”‚ β”‚ # β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ # β”‚ β”‚ β”‚argo-cd-pod β”‚ β”‚gitea-pod β”‚ β”‚magic-front β”‚ β”‚magic-api β”‚ β”‚ β”‚ # β”‚ β”‚ β”‚10.0.1.101 β”‚ β”‚10.0.1.102 β”‚ β”‚10.0.1.103 β”‚ β”‚10.0.1.104 β”‚ β”‚ β”‚ # β”‚ β”‚ β”‚argo-cd:v2.8 β”‚ β”‚gitea:1.20 β”‚ β”‚nginx:latest β”‚ β”‚api:v1.2 β”‚ β”‚ β”‚ # β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ # β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ # β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ # # πŸ”„ Request Flow Example: # 1. User visits: https://magicleaps.mathmast.com/ # 2. DNS resolves to Azure Load Balancer IP (4.155.160.32) # 3. Load Balancer forwards to nginx-ingress-controller # 4. Ingress controller checks rules: # - Host: magicleaps.mathmast.com βœ“ # - Path: / matches /* prefix βœ“ # 5. Routes to magicleaps-frontend-service:80 # 6. Service load balances to magicleaps-frontend pods # 7. Pod returns response through same path # πŸ” SSL/TLS Certificate Flow: # β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” # β”‚ Browser β”‚ β”‚ Ingress β”‚ β”‚cert-manager β”‚ β”‚Let's Encryptβ”‚ # β”‚ β”‚ β”‚ Controller β”‚ β”‚ β”‚ β”‚ β”‚ # β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ # β”‚ β”‚ β”‚ β”‚ # β”‚ HTTPS Request β”‚ β”‚ β”‚ # │───────────────▢│ β”‚ β”‚ # β”‚ β”‚ Check Cert β”‚ β”‚ # β”‚ │───────────────▢│ β”‚ # β”‚ β”‚ β”‚ Request Cert β”‚ # β”‚ β”‚ │───────────────▢│ # β”‚ β”‚ β”‚ β”‚ DNS Challenge # β”‚ β”‚ β”‚ │◀───────────────│ # β”‚ β”‚ β”‚ Cert Ready β”‚ # β”‚ β”‚ │◀───────────────│ # β”‚ β”‚ Cert Ready β”‚ β”‚ # β”‚ │◀───────────────│ β”‚ # β”‚ HTTPS Response β”‚ β”‚ β”‚ # │◀───────────────│ β”‚ β”‚ # 🏭 YOUR ACTUAL PRODUCTION SETUP # # Based on your codebase, here are your actual production values: # # Load Balancer IP: 4.155.160.32 (prod-usw2-k8s-freeleaps-lb-fe-ip) # # Current Applications: # 1. ArgoCD: argo.mathmast.com β†’ argo-cd-server:80 (freeleaps-devops-system) # 2. Gitea: gitea.freeleaps.mathmast.com β†’ gitea-http:3000 (freeleaps-prod) # 3. Magicleaps Prod: magicleaps.mathmast.com β†’ magicleaps-frontend-service:80 (magicleaps) # 4. Magicleaps Alpha: alpha.magicleaps.mathmast.com β†’ magicleaps-frontend-service:80 (magicleaps) # # Certificate Issuer: mathmast-dot-com (Let's Encrypt + GoDaddy DNS01) # Ingress Controller: nginx-ingress-controller:v1.12.0 (freeleaps-controls-system) # # Commands to check your actual setup: # kubectl get ingress --all-namespaces # kubectl get certificates --all-namespaces # kubectl get pods -n freeleaps-controls-system -l app.kubernetes.io/name=ingress-nginx # curl -I http://4.155.160.32 # nslookup argo.mathmast.com # nslookup gitea.freeleaps.mathmast.com # nslookup magicleaps.mathmast.com # πŸ“š EDUCATIONAL EXAMPLE BELOW # This is a generic example for learning purposes. Your actual setup is above. # Ingress for external access and routing apiVersion: networking.k8s.io/v1 # ← Kubernetes API version for Ingress resources kind: Ingress # ← Resource type: Ingress (external access layer) metadata: # ← Metadata section: describes the ingress name: web-app-ingress # ← Unique name for this ingress namespace: my-app # ← Namespace where ingress will be created labels: # ← Labels for organizing and selecting ingresses app: web-app # ← Label: identifies this as a web application ingress environment: production # ← Label: environment this runs in annotations: # ← Annotations: configuration for ingress controller # πŸ”§ Nginx Ingress Controller Annotations # These tell the nginx-ingress-controller how to behave nginx.ingress.kubernetes.io/rewrite-target: / # ← Rewrite URL paths (remove /api prefix) nginx.ingress.kubernetes.io/ssl-redirect: "true" # ← Redirect HTTP to HTTPS nginx.ingress.kubernetes.io/force-ssl-redirect: "true" # ← Force HTTPS redirect # πŸ” Cert-Manager Integration # This tells cert-manager to automatically get SSL certificates cert-manager.io/cluster-issuer: "letsencrypt-prod" # ← Use Let's Encrypt for certificates # πŸ›‘οΈ Rate Limiting # Prevent abuse by limiting requests per time window nginx.ingress.kubernetes.io/rate-limit: "100" # ← 100 requests per window nginx.ingress.kubernetes.io/rate-limit-window: "1m" # ← 1 minute window # 🌐 CORS (Cross-Origin Resource Sharing) # Allow web browsers to make requests from different domains nginx.ingress.kubernetes.io/enable-cors: "true" # ← Enable CORS nginx.ingress.kubernetes.io/cors-allow-origin: "*" # ← Allow all origins (customize for production) nginx.ingress.kubernetes.io/cors-allow-methods: "GET, POST, PUT, DELETE, OPTIONS" # ← Allowed HTTP methods nginx.ingress.kubernetes.io/cors-allow-headers: "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization" # ← Allowed headers # ⚑ Performance Optimizations # These improve performance for your applications nginx.ingress.kubernetes.io/proxy-body-size: "0" # ← No limit on request body size nginx.ingress.kubernetes.io/proxy-read-timeout: "600" # ← 10 minute read timeout nginx.ingress.kubernetes.io/proxy-send-timeout: "600" # ← 10 minute send timeout spec: # ← Specification: defines routing rules # πŸ” TLS Configuration # This defines SSL/TLS certificates for secure HTTPS connections tls: # ← TLS (Transport Layer Security) configuration - hosts: # ← List of hostnames this certificate covers - myapp.example.com # ← Main application domain - api.myapp.example.com # ← API subdomain secretName: myapp-tls # ← Name of the secret containing the certificate # cert-manager will automatically create this secret with the SSL certificate # πŸ›£οΈ Routing Rules # These define how traffic is routed to different services rules: # ← List of routing rules # Rule 1: Main application (myapp.example.com) - host: myapp.example.com # ← Hostname to match (like a domain name) http: # ← HTTP traffic configuration paths: # ← List of URL paths and their destinations # Path 1: Root path (/) β†’ web application - path: / # ← URL path to match (root path) pathType: Prefix # ← How to match the path (Prefix = starts with) backend: # ← Where to send the traffic service: # ← Backend service configuration name: web-app-service # ← Service name to route to port: # ← Service port number: 80 # ← Port number (80 = HTTP) # Path 2: Static files (/static) β†’ static file server - path: /static # ← URL path to match (static files) pathType: Prefix # ← Match paths starting with /static backend: # ← Where to send the traffic service: # ← Backend service configuration name: static-service # ← Service name for static files port: # ← Service port number: 80 # ← Port number # Rule 2: API subdomain (api.myapp.example.com) - host: api.myapp.example.com # ← Different hostname for API http: # ← HTTP traffic configuration paths: # ← List of URL paths and their destinations # Path 1: Root path (/) β†’ main API service - path: / # ← URL path to match (root path) pathType: Prefix # ← How to match the path backend: # ← Where to send the traffic service: # ← Backend service configuration name: api-service # ← Service name for main API port: # ← Service port number: 8080 # ← Port number (8080 = common API port) # Path 2: Version 1 API (/v1) β†’ v1 API service - path: /v1 # ← URL path to match (v1 API) pathType: Prefix # ← Match paths starting with /v1 backend: # ← Where to send the traffic service: # ← Backend service configuration name: api-v1-service # ← Service name for v1 API port: # ← Service port number: 8080 # ← Port number # Path 3: Version 2 API (/v2) β†’ v2 API service - path: /v2 # ← URL path to match (v2 API) pathType: Prefix # ← Match paths starting with /v2 backend: # ← Where to send the traffic service: # ← Backend service configuration name: api-v2-service # ← Service name for v2 API port: # ← Service port number: 8080 # ← Port number # πŸš€ How to use this: # kubectl apply -f ingress-example.yaml # kubectl get ingress # Check ingress status # kubectl describe ingress web-app-ingress # See detailed ingress info # kubectl get certificates # Check SSL certificate status # curl -H "Host: myapp.example.com" http://your-cluster-ip/ # Test routing # πŸ“Š What happens when you apply this: # 1. Kubernetes creates the Ingress resource # 2. nginx-ingress-controller reads the Ingress and configures nginx # 3. cert-manager sees the cert-manager.io/cluster-issuer annotation # 4. cert-manager requests SSL certificate from Let's Encrypt # 5. Let's Encrypt validates domain ownership via DNS challenge # 6. Certificate is stored in Kubernetes secret # 7. nginx-ingress-controller uses the certificate for HTTPS # 8. Traffic flows: Internet β†’ Load Balancer β†’ nginx β†’ Services β†’ Pods # πŸ” Your Current Setup Analysis: # Based on your codebase, you're using: # - nginx-ingress-controller in freeleaps-controls-system namespace # - cert-manager with Let's Encrypt for SSL certificates # - Custom ingress manager that automatically creates ingresses # - Annotations for SSL redirect, rate limiting, and CORS # - DNS-based certificate validation (DNS01 challenge) # πŸ“š Learn more: # - Ingress: https://kubernetes.io/docs/concepts/services-networking/ingress/ # - nginx-ingress: https://kubernetes.github.io/ingress-nginx/ # - cert-manager: https://cert-manager.io/docs/ # - SSL/TLS: https://kubernetes.io/docs/concepts/services-networking/ingress/#tls # - Rate Limiting: https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#rate-limiting # - CORS: https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#enable-cors