Some checks failed
Dev CI / Security gate (push) Successful in 31s
Dev CI / Backend — Lint (push) Successful in 1m8s
Dev CI / Frontend — Lint & Type-check (push) Successful in 1m14s
Dev CI / Backend — Unit Tests (push) Successful in 1m10s
Dev CI / Frontend — Unit Tests (push) Successful in 46s
Dev CI / Notify Failure (push) Has been skipped
CD Preprod / Security gate (push) Successful in 29s
CD Preprod / Backend — Lint (push) Successful in 1m7s
CD Preprod / Frontend — Lint & Type-check (push) Successful in 1m13s
CD Preprod / Backend — Unit Tests (push) Successful in 1m6s
CD Preprod / Frontend — Unit Tests (push) Successful in 44s
CD Preprod / Backend — Integration Tests (push) Failing after 37s
CD Preprod / Build Log Exporter (push) Has been skipped
CD Preprod / Image security (${{ matrix.service }}, ${{ matrix.arch }}) (amd64, backend) (push) Has been skipped
CD Preprod / Build Backend (push) Has been skipped
CD Preprod / Build Frontend (push) Has been skipped
CD Preprod / Image security (${{ matrix.service }}, ${{ matrix.arch }}) (amd64, frontend) (push) Has been skipped
CD Preprod / Image security (${{ matrix.service }}, ${{ matrix.arch }}) (amd64, log-exporter) (push) Has been skipped
CD Preprod / Image security (${{ matrix.service }}, ${{ matrix.arch }}) (arm64, backend) (push) Has been skipped
CD Preprod / Image security (${{ matrix.service }}, ${{ matrix.arch }}) (arm64, frontend) (push) Has been skipped
CD Preprod / Image security (${{ matrix.service }}, ${{ matrix.arch }}) (arm64, log-exporter) (push) Has been skipped
CD Preprod / Deploy to Preprod (push) Has been skipped
CD Preprod / Notify Success (push) Has been skipped
CD Preprod / Notify Failure (push) Has been skipped
246 lines
7.7 KiB
YAML
246 lines
7.7 KiB
YAML
# =============================================================================
|
|
# Backend NestJS
|
|
# =============================================================================
|
|
---
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: xpeditis-backend
|
|
namespace: xpeditis-prod
|
|
labels:
|
|
app.kubernetes.io/name: xpeditis-backend
|
|
app.kubernetes.io/component: api
|
|
app.kubernetes.io/part-of: xpeditis
|
|
spec:
|
|
replicas: 2
|
|
revisionHistoryLimit: 5
|
|
strategy:
|
|
type: RollingUpdate
|
|
rollingUpdate:
|
|
# Aucun pod retire avant qu'un remplacant ne soit pret : zero coupure.
|
|
maxUnavailable: 0
|
|
maxSurge: 1
|
|
selector:
|
|
matchLabels:
|
|
app.kubernetes.io/name: xpeditis-backend
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app.kubernetes.io/name: xpeditis-backend
|
|
app.kubernetes.io/component: api
|
|
app.kubernetes.io/part-of: xpeditis
|
|
annotations:
|
|
# Force le redemarrage des pods quand la configuration change : sans
|
|
# cela, modifier le ConfigMap ne produit aucun effet visible.
|
|
# La valeur est recalculee par scripts/deploy.sh.
|
|
xpeditis.com/config-checksum: "PLACEHOLDER"
|
|
spec:
|
|
imagePullSecrets:
|
|
- name: regcred
|
|
# 2 replicas sur 1 noeud : la contrainte est "preferred", sinon le second
|
|
# pod resterait indefiniment en Pending. Elle deviendra effective le jour
|
|
# ou un second noeud sera ajoute (phase 2 du plan de charge).
|
|
topologySpreadConstraints:
|
|
- maxSkew: 1
|
|
topologyKey: kubernetes.io/hostname
|
|
whenUnsatisfiable: ScheduleAnyway
|
|
labelSelector:
|
|
matchLabels:
|
|
app.kubernetes.io/name: xpeditis-backend
|
|
securityContext:
|
|
runAsNonRoot: true
|
|
runAsUser: 1001
|
|
runAsGroup: 1001
|
|
fsGroup: 1001
|
|
seccompProfile:
|
|
type: RuntimeDefault
|
|
# 60 s : laisse le temps aux requetes en cours et aux connexions
|
|
# WebSocket de se fermer proprement.
|
|
terminationGracePeriodSeconds: 60
|
|
initContainers:
|
|
- name: seed-rates
|
|
image: rg.fr-par.scw.cloud/weworkstudio/xpeditis-backend:latest
|
|
command: [sh, -ec, 'cp -R /app/src/infrastructure/storage/csv-storage/rates/. /rates/']
|
|
securityContext:
|
|
allowPrivilegeEscalation: false
|
|
readOnlyRootFilesystem: true
|
|
capabilities:
|
|
drop: ["ALL"]
|
|
resources:
|
|
requests: { cpu: 50m, memory: 64Mi }
|
|
limits: { cpu: 200m, memory: 128Mi }
|
|
volumeMounts:
|
|
- name: rates
|
|
mountPath: /rates
|
|
containers:
|
|
- name: backend
|
|
# Le tag est remplace au deploiement (kubectl set image).
|
|
image: rg.fr-par.scw.cloud/weworkstudio/xpeditis-backend:latest
|
|
imagePullPolicy: IfNotPresent
|
|
ports:
|
|
- name: http
|
|
containerPort: 4000
|
|
protocol: TCP
|
|
envFrom:
|
|
- configMapRef:
|
|
name: xpeditis-backend-config
|
|
- secretRef:
|
|
name: xpeditis-backend-secrets
|
|
env:
|
|
- name: POD_NAME
|
|
valueFrom:
|
|
fieldRef:
|
|
fieldPath: metadata.name
|
|
|
|
# Le demarrage inclut l'attente de PostgreSQL puis la verification
|
|
# des migrations : la sonde de demarrage laisse jusqu'a 150 s avant
|
|
# de declarer le pod perdu, sans penaliser les redemarrages rapides.
|
|
startupProbe:
|
|
httpGet:
|
|
path: /api/v1/health/live
|
|
port: http
|
|
initialDelaySeconds: 10
|
|
periodSeconds: 5
|
|
failureThreshold: 30
|
|
timeoutSeconds: 3
|
|
|
|
livenessProbe:
|
|
httpGet:
|
|
path: /api/v1/health/live
|
|
port: http
|
|
periodSeconds: 20
|
|
timeoutSeconds: 5
|
|
failureThreshold: 3
|
|
|
|
# LIMITE CONNUE : /health/ready renvoie toujours "ready" sans tester
|
|
# PostgreSQL ni Redis (health.controller.ts). Un pod incapable de
|
|
# joindre la base sera donc declare pret. Correctif recommande apres
|
|
# la mise en ligne : @nestjs/terminus avec des indicateurs reels.
|
|
readinessProbe:
|
|
httpGet:
|
|
path: /api/v1/health/ready
|
|
port: http
|
|
initialDelaySeconds: 5
|
|
periodSeconds: 10
|
|
timeoutSeconds: 3
|
|
failureThreshold: 3
|
|
|
|
resources:
|
|
requests:
|
|
cpu: 300m
|
|
memory: 512Mi
|
|
limits:
|
|
cpu: 1500m
|
|
memory: 1536Mi
|
|
|
|
securityContext:
|
|
allowPrivilegeEscalation: false
|
|
capabilities:
|
|
drop: ["ALL"]
|
|
readOnlyRootFilesystem: true
|
|
|
|
volumeMounts:
|
|
- name: rates
|
|
mountPath: /app/src/infrastructure/storage/csv-storage/rates
|
|
- name: logs
|
|
mountPath: /app/logs
|
|
- name: tmp
|
|
mountPath: /tmp
|
|
lifecycle:
|
|
preStop:
|
|
exec:
|
|
# Laisse Traefik retirer le pod de son pool avant que le
|
|
# processus ne commence a refuser des connexions.
|
|
command: ["sh", "-c", "sleep 10"]
|
|
|
|
volumes:
|
|
- name: rates
|
|
emptyDir:
|
|
sizeLimit: 1Gi
|
|
- name: logs
|
|
emptyDir:
|
|
sizeLimit: 512Mi
|
|
- name: tmp
|
|
emptyDir:
|
|
sizeLimit: 256Mi
|
|
|
|
---
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: xpeditis-backend
|
|
namespace: xpeditis-prod
|
|
labels:
|
|
app.kubernetes.io/name: xpeditis-backend
|
|
annotations:
|
|
# Sessions collantes : obligatoires pour Socket.IO. La negociation
|
|
# long-polling echoue si deux requetes d'un meme handshake atterrissent sur
|
|
# des replicas differents.
|
|
#
|
|
# ATTENTION -- limite non resolue par ce reglage : le gateway
|
|
# (notifications.gateway.ts) garde la carte userId -> sockets EN MEMOIRE et
|
|
# n'utilise pas @socket.io/redis-adapter. Une notification emise par le
|
|
# replica A n'atteint donc pas un utilisateur connecte au replica B.
|
|
# Cf. docs/mise-en-prod/15-exploitation-incidents.md, "Points de vigilance".
|
|
traefik.ingress.kubernetes.io/service.sticky.cookie: "true"
|
|
traefik.ingress.kubernetes.io/service.sticky.cookie.name: "xpd_be"
|
|
traefik.ingress.kubernetes.io/service.sticky.cookie.secure: "true"
|
|
traefik.ingress.kubernetes.io/service.sticky.cookie.httponly: "true"
|
|
traefik.ingress.kubernetes.io/service.sticky.cookie.samesite: "lax"
|
|
spec:
|
|
type: ClusterIP
|
|
selector:
|
|
app.kubernetes.io/name: xpeditis-backend
|
|
ports:
|
|
- name: http
|
|
port: 4000
|
|
targetPort: http
|
|
protocol: TCP
|
|
|
|
---
|
|
apiVersion: policy/v1
|
|
kind: PodDisruptionBudget
|
|
metadata:
|
|
name: xpeditis-backend
|
|
namespace: xpeditis-prod
|
|
spec:
|
|
minAvailable: 1
|
|
selector:
|
|
matchLabels:
|
|
app.kubernetes.io/name: xpeditis-backend
|
|
|
|
---
|
|
apiVersion: autoscaling/v2
|
|
kind: HorizontalPodAutoscaler
|
|
metadata:
|
|
name: xpeditis-backend
|
|
namespace: xpeditis-prod
|
|
spec:
|
|
scaleTargetRef:
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
name: xpeditis-backend
|
|
minReplicas: 2
|
|
# Plafond a 4 : au-dela, le CPX41 sature. Passer a 3 noeuds avant d'augmenter
|
|
# (cf. 15-exploitation-incidents.md, section montee en charge).
|
|
maxReplicas: 4
|
|
metrics:
|
|
- type: Resource
|
|
resource:
|
|
name: cpu
|
|
target:
|
|
type: Utilization
|
|
averageUtilization: 70
|
|
- type: Resource
|
|
resource:
|
|
name: memory
|
|
target:
|
|
type: Utilization
|
|
averageUtilization: 80
|
|
behavior:
|
|
scaleUp:
|
|
stabilizationWindowSeconds: 60
|
|
scaleDown:
|
|
# Descente lente : evite de retirer un pod juste avant un nouveau pic.
|
|
stabilizationWindowSeconds: 600
|