Architecture FitConnect
Architecture détaillée de la plateforme avec diagrammes et composants
Architecture FitConnect
Architecture complète de la plateforme FitConnect déployée sur Google Kubernetes Engine avec une approche microservices.
Diagramme Global
┌─────────────────────────────────────────────────────────────────┐
│ INTERNET │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Google Cloud DNS │ │
│ │ fitnessconnect.fr │ │
│ └─────────────────────┬───────────────────────────────────┘ │
└────────────────────────┼─────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Google Kubernetes Engine │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ GCE Load Balancer │ │
│ │ (Ingress) │ │
│ │ 34.118.xxx.xxx │ │
│ └─────────────────────┬───────────────────────────────────┘ │
│ │ │
│ ┌─────────────────────┴───────────────────────────────────┐ │
│ │ Traefik Ingress │ │
│ │ SSL Termination │ │
│ └─────┬──────────────────────────────────────────────┬────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌──────────┐ │
│ │ Frontend │ │ Backend │ │ Keycloak │ │ Adminer │ │
│ │ (React) │ │ (NestJS) │ │ SSO │ │ DB │ │
│ │ 2 replicas │ │ 1 replica │ │ 1 replica │ │ Admin │ │
│ └─────────────┘ └─────┬───────┘ └─────────────┘ └──────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ PostgreSQL │ │
│ │ 1 replica + PVC │ │
│ │ fitness_platform_db │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Uptime Kuma Monitoring │ │
│ │ 1 replica + PVC │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
Composants Principaux
Service | Technologie | Replicas | Rôle |
---|---|---|---|
Frontend | React + TypeScript | 2 | Interface utilisateur |
Backend API | NestJS + TypeScript | 1 | Logique métier |
PostgreSQL | PostgreSQL 14 | 1 | Persistance données |
Keycloak | Keycloak 24 | 1 | Authentification SSO |
Adminer | Adminer Latest | 1 | Administration DB |
Uptime Kuma | Uptime Kuma | 1 | Monitoring |
🔁 Ingress Controller GKE
Nous utilisons Ingress GCE (Google Cloud Load Balancer) comme point d'entrée unique vers les services de la plateforme. Ce composant route les requêtes vers les services exposés, selon le nom de domaine et le port.
🌐 Hôtes configurés
Domaine | Service routé | Port |
---|---|---|
fitnessconnect.fr | frontend-service | 80 |
api.fitnessconnect.fr | api-service | 3000 |
login.fitnessconnect.fr | keycloak-service | 8080 |
adminer.fitnessconnect.fr | adminer-service | 8080 |
uptimekuma.fitnessconnect.fr | uptime-kuma-service | 3001 |
L'accès via HTTP est désactivé (kubernetes.io/ingress.allow-http: "false") pour forcer le HTTPS sur tous les endpoints.
🔐 Certificats SSL Automatiques (HTTPS)
Les certificats sont provisionnés automatiquement via la ressource ManagedCertificate de GKE, sans intervention manuelle. Cela permet un renouvellement automatique, une conformité HTTPS globale, et une configuration centralisée.
kind: ManagedCertificate metadata: name: fitnessconnect-cert spec: domains:
- fitnessconnect.fr
- www.fitnessconnect.fr
- api.fitnessconnect.fr
- login.fitnessconnect.fr
- adminer.fitnessconnect.fr
- uptimekuma.fitnessconnect.fr
Toutes les URLs publiques sont donc servies via HTTPS sécurisé avec des certificats Google valides.
Sécurité Réseau (Network Policies)
Des Network Policies Kubernetes ont été mises en place pour restreindre les flux entre pods et services internes. Cela permet de s’assurer que chaque composant ne peut communiquer qu’avec les services autorisés.
🔄 Règles Implémentées
Pod cible | Accès autorisé depuis | Port(s) |
---|---|---|
postgres | api , keycloak , adminer | 5432 |
api | frontend , uptime-kuma | 3000 |
keycloak | frontend , api | 8080 |
frontend | Ouvert à tous (accès Ingress GCE) | 80 |
✅ Résumé Sécurité
🔒 HTTPS activé pour tous les domaines via certificats managés GKE
📌 Ingress GCE centralise le routage du trafic web
Network Policies assurent une isolation stricte entre composants
🔁 Aucun service critique n’est exposé directement à l’extérieur
Flux de Communication
Utilisateur
│
▼ HTTPS (443)
GCE Load Balancer
│
▼ HTTP (80/8080)
Traefik Ingress Controller
│
├─▶ Frontend Service ──▶ Frontend Pods (2x)
│ │
│ ▼ API Calls (3000)
├─▶ Backend Service ──▶ Backend Pod (1x)
│ │
│ ▼ SQL (5432)
│ PostgreSQL Service ──▶ PostgreSQL Pod (1x)
│
├─▶ Keycloak Service ──▶ Keycloak Pod (1x)
│
├─▶ Adminer Service ──▶ Adminer Pod (1x)
│
└─▶ Uptime-Kuma Service ──▶ Uptime-Kuma Pod (1x)
Frontend React + TypeScript
# Configuration Frontend
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
namespace: annual-project
spec:
replicas: 2
selector:
matchLabels:
app: frontend
template:
spec:
containers:
- name: frontend
image: europe-west1-docker.pkg.dev/k8s-frist-test/annual-project-repo/frontend:latest
ports:
- containerPort: 80
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "200m"
Technologies Frontend :
- React.js 18 avec TypeScript strict
- Tailwind CSS pour le styling
- Vite pour le bundling
- Nginx pour servir les assets statiques
Backend NestJS + TypeScript
# Configuration API NestJS
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
namespace: annual-project
spec:
replicas: 1
selector:
matchLabels:
app: api
template:
spec:
initContainers:
- name: wait-for-postgres
image: postgres:14
command: ["sh", "-c", "until pg_isready -h postgres-service -p 5432 -U postgres; do sleep 5; done"]
containers:
- name: api
image: europe-west1-docker.pkg.dev/k8s-frist-test/annual-project-repo/api:latest
ports:
- containerPort: 3000
env:
- name: DATABASE_HOST
value: "postgres-service"
- name: KEYCLOAK_URL
value: "https://login.fitnessconnect.fr"
Technologies Backend :
- NestJS 10 avec TypeScript
- PostgreSQL avec TypeORM
- JWT + Keycloak pour l'authentification
- Stripe pour les paiements
- Validation avec class-validator
- Swagger pour l'API documentation
Base de Données PostgreSQL
# Configuration PostgreSQL
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
namespace: annual-project
spec:
replicas: 1
template:
spec:
containers:
- name: postgres
image: postgres:14
env:
- name: POSTGRES_DB
value: "fitness_platform_db"
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: postgres-secret
key: POSTGRES_USER
volumeMounts:
- name: postgres-storage
mountPath: /var/lib/postgresql/data
volumes:
- name: postgres-storage
persistentVolumeClaim:
claimName: postgres-pvc
Keycloak – Gestion Centralisée de l’Authentification
Keycloak est une solution open-source de gestion des identités et des accès (IAM) conçue pour permettre une authentification centralisée, sécurisée et moderne pour les applications web et mobiles.
Dans notre projet FitConnect, Keycloak joue un rôle essentiel dans l’authentification SSO (Single Sign-On) des utilisateurs, qu’ils soient coach ou client.
🔧 Rôles et responsabilités de Keycloak
Fonction | Description |
---|---|
SSO OAuth2 / OpenID Connect | Un seul login pour accéder à toutes les applications (API, frontend) |
Intégration Login Google | Connexion rapide via compte Google |
Gestion des utilisateurs | Interface d’administration web pour gérer utilisateurs, groupes, rôles |
Attribution de rôles | Rôles client , coach , admin utilisés côté API pour restreindre l’accès |
Vérification des tokens | Chaque requête backend sécurisée par des tokens émis par Keycloak |
Sécurité centralisée | Plus besoin de gérer mots de passe dans nos microservices |
Grâce à Keycloak, toute la gestion de la sécurité utilisateur est externalisée et centralisée, ce qui simplifie et renforce l’architecture de notre application.
Persistance :
- PersistentVolume de 10Gi sur GKE
- Backup automatique via scripts
- Réplication possible pour la haute disponibilité
Flux d'Authentification Keycloak
┌─────────────┐ 1. Login Request ┌─────────────┐
│ │ ──────────────────────▶ │ │
│ Frontend │ │ Keycloak │
│ (React) │ ◀────────────────────── │ SSO │
│ │ 2. Redirect to SSO │ │
└─────────────┘ └─────────────┘
│ │
│ 3. User Credentials │
└───────────────────────────────────────┘
│
▼ 4. Authentication
┌─────────────┐ 5. JWT Token ┌─────────────┐
│ │ ◀────────────────────── │ │
│ Frontend │ │ Keycloak │
│ │ │ │
└─────────────┘ └─────────────┘
│
│ 6. API Calls with JWT
▼
┌─────────────┐ 7. Token Validation ┌─────────────┐
│ │ ──────────────────────▶ │ │
│ Backend │ │ Keycloak │
│ (NestJS) │ ◀────────────────────── │ SSO │
│ │ 8. User Info │ │
└─────────────┘ └─────────────┘
Network Policies - Isolation Réseau
┌─────────────────────────────────────────────────────────────────┐
│ Network Segmentation │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌──────────┐ │
│ │ Internet │ ✅ │ Frontend │ ✅ │ Backend │ │
│ │ Traffic │ ────────▶│ Pods │ ────────▶│ Pod │ │
│ └─────────────┘ └─────────────┘ └─────┬────┘ │
│ │ │ │
│ │ ❌ (Blocked) │ ✅ │
│ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ ┌──────────┐ │
│ │ Uptime-Kuma │ ✅ │ PostgreSQL │ ✅ │ Keycloak │ │
│ │ Pod │ ────────▶│ Pod │ ◀────────│ Pod │ │
│ └─────────────┘ └─────────────┘ └──────────┘ │
│ ▲ │
│ │ ✅ │
│ ┌─────────────┐ │
│ │ Adminer │ │
│ │ Pod │ │
│ └─────────────┘ │
└─────────────────────────────────────────────────────────────────┘
# Isolation Réseau PostgreSQL
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: postgres-network-policy
namespace: annual-project
spec:
podSelector:
matchLabels:
app: postgres
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: api
- podSelector:
matchLabels:
app: keycloak
- podSelector:
matchLabels:
app: adminer
ports:
- protocol: TCP
port: 5432
Secrets Management
Secret | Contenu | Usage |
---|---|---|
postgres-secret | User/Password DB | Connexion PostgreSQL |
keycloak-secret | Admin credentials | Administration Keycloak |
api-secret | JWT, Stripe, Email | Configuration API |
┌─────────────────────────────────────────────────────────────────┐
│ Kubernetes Secrets │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │postgres- │ │keycloak- │ │ api- │ │
│ │secret │ │secret │ │ secret │ │
│ │ │ │ │ │ │ │
│ │• USER │ │• ADMIN │ │• JWT_SECRET │ │
│ │• PASSWORD │ │• PASSWORD │ │• STRIPE_KEY │ │
│ │• DATABASE │ │ │ │• MAIL_PASS │ │
│ └─────┬───────┘ └─────┬───────┘ └─────┬───────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │PostgreSQL │ │ Keycloak │ │ Backend │ │
│ │ Pod │ │ Pod │ │ Pod │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────────┘
Pipeline CI/CD GitLab
┌─────────────────────────────────────────────────────────────────┐
│ GitLab CI/CD Pipeline │
│ │
│ 🌿 BRANCHES feature/* │
│ ┌─────────────┐ │
│ │ TEST │ │
│ │ │ │
│ │• Frontend │ │
│ │• API Tests │ │
│ │• PostgreSQL │ │
│ │• Coverage │ │
│ └─────────────┘ │
│ │
│ 🔄 BRANCH develop │
│ ┌─────────────┐ │
│ │ TEST │ │
│ │ │ │
│ │• Frontend │ │
│ │• API Tests │ │
│ │• PostgreSQL │ │
│ │• Integration│ │
│ └─────────────┘ │
│ │
│ 🚀 BRANCH main (PRODUCTION) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ BUILD │ │ DEPLOY │ │ VERIFY │ │
│ │ │ │ │ │ │ │
│ │• Frontend │ │• GKE Apply │ │• Health │ │
│ │• API │ │• PostgreSQL │ │ Checks │ │
│ │• Docker │ │• Keycloak │ │• Services │ │
│ │ Images │ │• Ingress │ │• Monitoring │ │
│ │• Registry │ │• SSL Certs │ │• Uptime │ │
│ └─────┬───────┘ └─────┬───────┘ └─────────────┘ │
│ │ │ │
│ └────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
Volumes Persistants
┌─────────────────────────────────────────────────────────────────┐
│ Google Cloud Storage │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ GKE Persistent Disks │ │
│ │ │ │
│ │ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │PostgreSQL │ │ Uptime-Kuma │ │ │
│ │ │ PVC │ │ PVC │ │ │
│ │ │ 10Gi │ │ 2Gi │ │ │
│ │ │ │ │ │ │ │
│ │ │• Database │ │• Config │ │ │
│ │ │ Files │ │• Logs │ │ │
│ │ │• WAL Logs │ │• SQLite DB │ │ │
│ │ │• Backups │ │ │ │ │
│ │ └─────┬───────┘ └─────┬───────┘ │ │
│ └────────┼────────────────────────────┼───────────────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │PostgreSQL │ │ Uptime-Kuma │ │
│ │ Pod │ │ Pod │ │
│ │ │ │ │ │
│ │Mount: │ │Mount: │ │
│ │/var/lib/ │ │/app/data │ │
│ │postgresql/ │ │ │ │
│ │data │ │ │ │
│ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────────┘
# PersistentVolume PostgreSQL
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-pvc
namespace: annual-project
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: standard-rwo
---
# PersistentVolume Uptime Kuma
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: uptime-kuma-pvc
namespace: annual-project
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
storageClassName: standard-rwo
Configuration Ingress
┌─────────────────────────────────────────────────────────────────┐
│ DNS Resolution │
│ │
│ fitnessconnect.fr ──────▶ 34.118.xxx.xxx │
│ api.fitnessconnect.fr ──────▶ 34.118.xxx.xxx │
│ login.fitnessconnect.fr ──────▶ 34.118.xxx.xxx │
│ adminer.fitnessconnect.fr ──────▶ 34.118.xxx.xxx │
│ uptimekuma.fitnessconnect.fr ────▶ 34.118.xxx.xxx │
│ │
└─────────────────────┬───────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ GCE Load Balancer │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ SSL Termination │ │
│ │ (Google Managed Certificates) │ │
│ └─────────────────────┬───────────────────────────────────┘ │
│ │ │
│ ┌─────────────────────▼───────────────────────────────────┐ │
│ │ Ingress Controller │ │
│ │ │ │
│ │ Route by Host Header: │ │
│ │ • fitnessconnect.fr ──▶ frontend-service │ │
│ │ • api.fitnessconnect.fr ──▶ api-service │ │
│ │ • login.fitnessconnect.fr ──▶ keycloak-service │ │
│ │ • adminer.fitnessconnect.fr──▶ adminer-service │ │
│ │ • uptimekuma.fitnessconnect.fr▶ uptime-kuma-service │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: project-ingress
namespace: annual-project
annotations:
kubernetes.io/ingress.class: "gce"
networking.gke.io/managed-certificates: "fitnessconnect-cert"
kubernetes.io/ingress.allow-http: "false"
spec:
rules:
- host: fitnessconnect.fr
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend-service
port:
number: 80
- host: api.fitnessconnect.fr
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-service
port:
number: 3000
Certificats SSL
apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
name: fitnessconnect-cert
namespace: annual-project
spec:
domains:
- fitnessconnect.fr
- www.fitnessconnect.fr
- api.fitnessconnect.fr
- login.fitnessconnect.fr
- adminer.fitnessconnect.fr
- uptimekuma.fitnessconnect.fr
Architecture de Monitoring
┌─────────────────────────────────────────────────────────────────┐
│ Monitoring Stack │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Uptime-Kuma │ │ Kubernetes │ │ Google │ │
│ │ │ │ Metrics │ │ Cloud │ │
│ │• HTTP Checks│ │ │ │ Monitoring │ │
│ │• DB Checks │ │• Pod Status │ │ │ │
│ │• SSL Checks │ │• Resources │ │• Node Stats │ │
│ │• Alerts │ │• Events │ │• Network │ │
│ └─────┬───────┘ └─────┬───────┘ └─────┬───────┘ │
│ │ │ │ │
│ └────────────────┼────────────────┘ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Alert Manager │ │
│ │ │ │
│ │ • Slack Notifications │ │
│ │ • Email Alerts │ │
│ │ • Webhook Integrations │ │
│ │ • Escalation Policies │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘