first commit
This commit is contained in:
commit
dc9da64778
145
k8s/backend.yaml
Normal file
145
k8s/backend.yaml
Normal file
@ -0,0 +1,145 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: backend-secret
|
||||
namespace: xpeditis
|
||||
type: Opaque
|
||||
data:
|
||||
# Base64 encoded JWT secret
|
||||
JWT_SECRET: eHBlZGl0aXMtcHJvZC1zZWNyZXQta2V5LWNoYW5nZS1pbi1wcm9kdWN0aW9u
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: backend-config
|
||||
namespace: xpeditis
|
||||
data:
|
||||
SPRING_PROFILES_ACTIVE: "prod"
|
||||
SPRING_DATASOURCE_URL: "jdbc:postgresql://postgres-service:5432/xpeditis_prod"
|
||||
CORS_ALLOWED_ORIGINS: "https://xpeditis.fr,https://www.xpeditis.fr"
|
||||
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: backend
|
||||
namespace: xpeditis
|
||||
labels:
|
||||
app: backend
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: backend
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: backend
|
||||
spec:
|
||||
containers:
|
||||
- name: backend
|
||||
image: ghcr.io/your-username/xpeditis/backend:latest
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
env:
|
||||
- name: SPRING_PROFILES_ACTIVE
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: backend-config
|
||||
key: SPRING_PROFILES_ACTIVE
|
||||
- name: SPRING_DATASOURCE_URL
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: backend-config
|
||||
key: SPRING_DATASOURCE_URL
|
||||
- name: SPRING_DATASOURCE_USERNAME
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: postgres-secret
|
||||
key: POSTGRES_USER
|
||||
- name: SPRING_DATASOURCE_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: postgres-secret
|
||||
key: POSTGRES_PASSWORD
|
||||
- name: JWT_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: backend-secret
|
||||
key: JWT_SECRET
|
||||
- name: CORS_ALLOWED_ORIGINS
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: backend-config
|
||||
key: CORS_ALLOWED_ORIGINS
|
||||
resources:
|
||||
requests:
|
||||
memory: "512Mi"
|
||||
cpu: "250m"
|
||||
limits:
|
||||
memory: "1Gi"
|
||||
cpu: "500m"
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /api/actuator/health
|
||||
port: 8080
|
||||
initialDelaySeconds: 60
|
||||
periodSeconds: 30
|
||||
timeoutSeconds: 10
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /api/actuator/health/readiness
|
||||
port: 8080
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
volumeMounts:
|
||||
- name: logs-volume
|
||||
mountPath: /app/logs
|
||||
volumes:
|
||||
- name: logs-volume
|
||||
emptyDir: {}
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: backend-service
|
||||
namespace: xpeditis
|
||||
labels:
|
||||
app: backend
|
||||
spec:
|
||||
selector:
|
||||
app: backend
|
||||
ports:
|
||||
- port: 8080
|
||||
targetPort: 8080
|
||||
type: ClusterIP
|
||||
|
||||
---
|
||||
apiVersion: autoscaling/v2
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: backend-hpa
|
||||
namespace: xpeditis
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: backend
|
||||
minReplicas: 2
|
||||
maxReplicas: 10
|
||||
metrics:
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: 70
|
||||
- type: Resource
|
||||
resource:
|
||||
name: memory
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: 80
|
||||
78
k8s/frontend.yaml
Normal file
78
k8s/frontend.yaml
Normal file
@ -0,0 +1,78 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: frontend
|
||||
namespace: xpeditis
|
||||
labels:
|
||||
app: frontend
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: frontend
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: frontend
|
||||
spec:
|
||||
containers:
|
||||
- name: frontend
|
||||
image: ghcr.io/your-username/xpeditis/frontend:latest
|
||||
ports:
|
||||
- containerPort: 80
|
||||
resources:
|
||||
requests:
|
||||
memory: "128Mi"
|
||||
cpu: "100m"
|
||||
limits:
|
||||
memory: "256Mi"
|
||||
cpu: "200m"
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 80
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 30
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 80
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: frontend-service
|
||||
namespace: xpeditis
|
||||
labels:
|
||||
app: frontend
|
||||
spec:
|
||||
selector:
|
||||
app: frontend
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
type: ClusterIP
|
||||
|
||||
---
|
||||
apiVersion: autoscaling/v2
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: frontend-hpa
|
||||
namespace: xpeditis
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: frontend
|
||||
minReplicas: 2
|
||||
maxReplicas: 5
|
||||
metrics:
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
target:
|
||||
type: Utilization
|
||||
averageUtilization: 70
|
||||
73
k8s/ingress.yaml
Normal file
73
k8s/ingress.yaml
Normal file
@ -0,0 +1,73 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: xpeditis-ingress
|
||||
namespace: xpeditis
|
||||
annotations:
|
||||
kubernetes.io/ingress.class: "nginx"
|
||||
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
||||
nginx.ingress.kubernetes.io/ssl-redirect: "true"
|
||||
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
|
||||
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
|
||||
nginx.ingress.kubernetes.io/rate-limit: "100"
|
||||
nginx.ingress.kubernetes.io/rate-limit-window: "1m"
|
||||
spec:
|
||||
tls:
|
||||
- hosts:
|
||||
- xpeditis.fr
|
||||
- www.xpeditis.fr
|
||||
- api.xpeditis.fr
|
||||
secretName: xpeditis-tls
|
||||
rules:
|
||||
# Frontend principal
|
||||
- host: xpeditis.fr
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: frontend-service
|
||||
port:
|
||||
number: 80
|
||||
|
||||
# Redirection www vers domaine principal
|
||||
- host: www.xpeditis.fr
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: frontend-service
|
||||
port:
|
||||
number: 80
|
||||
|
||||
# API Backend
|
||||
- host: api.xpeditis.fr
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: backend-service
|
||||
port:
|
||||
number: 8080
|
||||
|
||||
---
|
||||
# Certificat SSL automatique avec cert-manager
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: ClusterIssuer
|
||||
metadata:
|
||||
name: letsencrypt-prod
|
||||
spec:
|
||||
acme:
|
||||
server: https://acme-v02.api.letsencrypt.org/directory
|
||||
email: admin@xpeditis.fr
|
||||
privateKeySecretRef:
|
||||
name: letsencrypt-prod
|
||||
solvers:
|
||||
- http01:
|
||||
ingress:
|
||||
class: nginx
|
||||
7
k8s/namespace.yaml
Normal file
7
k8s/namespace.yaml
Normal file
@ -0,0 +1,7 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: xpeditis
|
||||
labels:
|
||||
name: xpeditis
|
||||
environment: production
|
||||
115
k8s/postgres.yaml
Normal file
115
k8s/postgres.yaml
Normal file
@ -0,0 +1,115 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: postgres-secret
|
||||
namespace: xpeditis
|
||||
type: Opaque
|
||||
data:
|
||||
# Base64 encoded values
|
||||
POSTGRES_DB: eHBlZGl0aXNfcHJvZA== # xpeditis_prod
|
||||
POSTGRES_USER: eHBlZGl0aXNfdXNlcg== # xpeditis_user
|
||||
POSTGRES_PASSWORD: eHBlZGl0aXNfcGFzc3dvcmQ= # xpeditis_password
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: postgres-pvc
|
||||
namespace: xpeditis
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 10Gi
|
||||
storageClassName: standard
|
||||
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: postgres
|
||||
namespace: xpeditis
|
||||
labels:
|
||||
app: postgres
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: postgres
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: postgres
|
||||
spec:
|
||||
containers:
|
||||
- name: postgres
|
||||
image: postgres:15-alpine
|
||||
ports:
|
||||
- containerPort: 5432
|
||||
env:
|
||||
- name: POSTGRES_DB
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: postgres-secret
|
||||
key: POSTGRES_DB
|
||||
- name: POSTGRES_USER
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: postgres-secret
|
||||
key: POSTGRES_USER
|
||||
- name: POSTGRES_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: postgres-secret
|
||||
key: POSTGRES_PASSWORD
|
||||
volumeMounts:
|
||||
- name: postgres-storage
|
||||
mountPath: /var/lib/postgresql/data
|
||||
resources:
|
||||
requests:
|
||||
memory: "256Mi"
|
||||
cpu: "250m"
|
||||
limits:
|
||||
memory: "512Mi"
|
||||
cpu: "500m"
|
||||
livenessProbe:
|
||||
exec:
|
||||
command:
|
||||
- pg_isready
|
||||
- -U
|
||||
- xpeditis_user
|
||||
- -d
|
||||
- xpeditis_prod
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
- pg_isready
|
||||
- -U
|
||||
- xpeditis_user
|
||||
- -d
|
||||
- xpeditis_prod
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 5
|
||||
volumes:
|
||||
- name: postgres-storage
|
||||
persistentVolumeClaim:
|
||||
claimName: postgres-pvc
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: postgres-service
|
||||
namespace: xpeditis
|
||||
labels:
|
||||
app: postgres
|
||||
spec:
|
||||
selector:
|
||||
app: postgres
|
||||
ports:
|
||||
- port: 5432
|
||||
targetPort: 5432
|
||||
type: ClusterIP
|
||||
242
scripts/deploy.sh
Executable file
242
scripts/deploy.sh
Executable file
@ -0,0 +1,242 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Script de déploiement Xpeditis
|
||||
# Usage: ./deploy.sh [environment] [component]
|
||||
# Environments: dev, staging, prod
|
||||
# Components: all, backend, frontend, database
|
||||
|
||||
set -e
|
||||
|
||||
ENVIRONMENT=${1:-dev}
|
||||
COMPONENT=${2:-all}
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
||||
|
||||
# Couleurs pour les logs
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
log_info() {
|
||||
echo -e "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
log_success() {
|
||||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||
}
|
||||
|
||||
log_warning() {
|
||||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# Vérifier les prérequis
|
||||
check_prerequisites() {
|
||||
log_info "Vérification des prérequis..."
|
||||
|
||||
if ! command -v docker &> /dev/null; then
|
||||
log_error "Docker n'est pas installé"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v docker-compose &> /dev/null; then
|
||||
log_error "Docker Compose n'est pas installé"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$ENVIRONMENT" == "prod" ]] && ! command -v kubectl &> /dev/null; then
|
||||
log_error "kubectl n'est pas installé (requis pour la production)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log_success "Prérequis vérifiés"
|
||||
}
|
||||
|
||||
# Déploiement en développement
|
||||
deploy_dev() {
|
||||
log_info "Déploiement en environnement de développement..."
|
||||
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
case $COMPONENT in
|
||||
"all")
|
||||
docker-compose down
|
||||
docker-compose up --build -d
|
||||
;;
|
||||
"backend")
|
||||
docker-compose up --build -d backend
|
||||
;;
|
||||
"frontend")
|
||||
docker-compose up --build -d frontend
|
||||
;;
|
||||
"database")
|
||||
docker-compose up -d postgres
|
||||
;;
|
||||
*)
|
||||
log_error "Composant inconnu: $COMPONENT"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
log_success "Déploiement dev terminé"
|
||||
log_info "Frontend: http://localhost:3000"
|
||||
log_info "Backend: http://localhost:8080"
|
||||
log_info "Base de données: localhost:5432"
|
||||
}
|
||||
|
||||
# Déploiement en staging
|
||||
deploy_staging() {
|
||||
log_info "Déploiement en environnement de staging..."
|
||||
|
||||
# Build et push des images
|
||||
build_and_push_images "staging"
|
||||
|
||||
# Déploiement Kubernetes
|
||||
kubectl apply -f "$PROJECT_ROOT/k8s/namespace.yaml"
|
||||
kubectl apply -f "$PROJECT_ROOT/k8s/" -n xpeditis-staging
|
||||
|
||||
log_success "Déploiement staging terminé"
|
||||
}
|
||||
|
||||
# Déploiement en production
|
||||
deploy_prod() {
|
||||
log_info "Déploiement en environnement de production..."
|
||||
|
||||
# Confirmation utilisateur
|
||||
read -p "Êtes-vous sûr de vouloir déployer en production? (y/N): " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
log_info "Déploiement annulé"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Build et push des images
|
||||
build_and_push_images "prod"
|
||||
|
||||
# Déploiement Kubernetes
|
||||
kubectl apply -f "$PROJECT_ROOT/k8s/namespace.yaml"
|
||||
kubectl apply -f "$PROJECT_ROOT/k8s/" -n xpeditis
|
||||
|
||||
# Attendre que les pods soient prêts
|
||||
kubectl wait --for=condition=ready pod -l app=backend -n xpeditis --timeout=300s
|
||||
kubectl wait --for=condition=ready pod -l app=frontend -n xpeditis --timeout=300s
|
||||
|
||||
log_success "Déploiement production terminé"
|
||||
log_info "Site web: https://xpeditis.fr"
|
||||
log_info "API: https://api.xpeditis.fr"
|
||||
}
|
||||
|
||||
# Build et push des images Docker
|
||||
build_and_push_images() {
|
||||
local env=$1
|
||||
log_info "Build et push des images Docker pour $env..."
|
||||
|
||||
# Backend
|
||||
if [[ "$COMPONENT" == "all" || "$COMPONENT" == "backend" ]]; then
|
||||
log_info "Build de l'image backend..."
|
||||
docker build -t "xpeditis/backend:$env" "$PROJECT_ROOT/backend"
|
||||
docker tag "xpeditis/backend:$env" "ghcr.io/your-username/xpeditis/backend:$env"
|
||||
docker push "ghcr.io/your-username/xpeditis/backend:$env"
|
||||
fi
|
||||
|
||||
# Frontend
|
||||
if [[ "$COMPONENT" == "all" || "$COMPONENT" == "frontend" ]]; then
|
||||
log_info "Build de l'image frontend..."
|
||||
docker build -t "xpeditis/frontend:$env" \
|
||||
--build-arg VITE_API_URL="https://api.xpeditis.fr" \
|
||||
--target production \
|
||||
"$PROJECT_ROOT/frontend"
|
||||
docker tag "xpeditis/frontend:$env" "ghcr.io/your-username/xpeditis/frontend:$env"
|
||||
docker push "ghcr.io/your-username/xpeditis/frontend:$env"
|
||||
fi
|
||||
|
||||
log_success "Images Docker buildées et pushées"
|
||||
}
|
||||
|
||||
# Fonction de rollback
|
||||
rollback() {
|
||||
log_warning "Rollback en cours..."
|
||||
|
||||
if [[ "$ENVIRONMENT" == "dev" ]]; then
|
||||
docker-compose down
|
||||
docker-compose up -d
|
||||
else
|
||||
kubectl rollout undo deployment/backend -n xpeditis
|
||||
kubectl rollout undo deployment/frontend -n xpeditis
|
||||
fi
|
||||
|
||||
log_success "Rollback terminé"
|
||||
}
|
||||
|
||||
# Afficher l'aide
|
||||
show_help() {
|
||||
echo "Usage: $0 [environment] [component]"
|
||||
echo ""
|
||||
echo "Environments:"
|
||||
echo " dev - Environnement de développement (défaut)"
|
||||
echo " staging - Environnement de staging"
|
||||
echo " prod - Environnement de production"
|
||||
echo ""
|
||||
echo "Components:"
|
||||
echo " all - Tous les composants (défaut)"
|
||||
echo " backend - Backend Spring Boot uniquement"
|
||||
echo " frontend - Frontend React uniquement"
|
||||
echo " database - Base de données uniquement"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --rollback - Effectuer un rollback"
|
||||
echo " --help - Afficher cette aide"
|
||||
echo ""
|
||||
echo "Exemples:"
|
||||
echo " $0 # Déploiement dev complet"
|
||||
echo " $0 prod all # Déploiement production complet"
|
||||
echo " $0 staging backend # Déploiement staging backend uniquement"
|
||||
echo " $0 --rollback # Rollback"
|
||||
}
|
||||
|
||||
# Point d'entrée principal
|
||||
main() {
|
||||
case "${1:-}" in
|
||||
"--help"|"-h")
|
||||
show_help
|
||||
exit 0
|
||||
;;
|
||||
"--rollback")
|
||||
rollback
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
log_info "Démarrage du déploiement Xpeditis"
|
||||
log_info "Environnement: $ENVIRONMENT"
|
||||
log_info "Composant: $COMPONENT"
|
||||
|
||||
check_prerequisites
|
||||
|
||||
case $ENVIRONMENT in
|
||||
"dev")
|
||||
deploy_dev
|
||||
;;
|
||||
"staging")
|
||||
deploy_staging
|
||||
;;
|
||||
"prod")
|
||||
deploy_prod
|
||||
;;
|
||||
*)
|
||||
log_error "Environnement inconnu: $ENVIRONMENT"
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
log_success "Déploiement terminé avec succès!"
|
||||
}
|
||||
|
||||
# Exécuter le script principal
|
||||
main "$@"
|
||||
Loading…
Reference in New Issue
Block a user