π Project Architecture
Private AKS Β· Flask + PostgreSQL Β· Full stack overview
Internet / Client
β
βΌ
βββββββββββββββββββββββββ
β DNS / Azure DNS β
β (public hostname) β
βββββββββββββ¬ββββββββββββ
β HTTPS
βΌ
βββββββββββββββββββββββββ
β Azure Load Balancer β
β (public front door) β
βββββββββββββ¬ββββββββββββ
β
βΌ
βββββββββββββββββββββββββ
β Traefik Ingress β
β + cert-manager TLS β
β (Let's Encrypt) β
βββββββββββββ¬ββββββββββββ
β
βΌ
βββββββββββββββββββββββββ
β Flask App (Pods) β
β Gunicorn Β· Deploymentβ
β Service: ClusterIP β
βββββββββββββ¬ββββββββββββ
β
βΌ
βββββββββββββββββββββββββ
β PostgreSQL β
β StatefulSet + PVC β
β Service: postgres β
βββββββββββββββββββββββββ
CI/CD path (side channel):
Azure DevOps β Self-hosted Agent (private VNet)
β Build image β Azure ACR
β Helm upgrade β AKS (private API)
Layers
1. Edge & Ingress
Public traffic hits Azure Load Balancer, then Traefik. cert-manager issues and renews Let's Encrypt certificates so all external traffic is HTTPS.
Azure LB
Traefik
cert-manager
Let's Encrypt
2. Application
Flask app runs under Gunicorn in Deployment pods. ClusterIP Service fronts the pods. Liveness uses /health; readiness can include DB checks via /api/db-status.
Flask
Gunicorn
Deployment
ClusterIP
3. Data
PostgreSQL runs as a StatefulSet with persistent volume claims. The app reaches it via the in-cluster service name postgres.
StatefulSet
PVC
Service: postgres
4. Platform & Networking
Private AKS cluster β control plane is not publicly reachable. Workloads live in a private VNet. Images come from Azure Container Registry.
Private AKS
Private VNet
Azure ACR
Kubernetes
5. CI/CD
Azure DevOps pipelines run on a self-hosted agent inside the private VNet. Pipeline builds the image, pushes to ACR, and deploys via Helm without exposing the cluster API publicly.
Azure DevOps
Self-hosted agent
Helm
ACR