ldc-ovoteam/manifest.yaml
Jérémy Munsch 669ee7d736
feat(deployment): enhance deployment configuration with health checks and resource limits
Added readiness, liveness, and startup probes for improved application health monitoring.
Configured resource requests and limits for better resource management.
2026-11-06 12:23:21 +01:00

330 lines
9.8 KiB
YAML

apiVersion: v1
kind: ConfigMap
metadata:
name: ${CI_PROJECT_PATH_SLUG}-config-map
data:
APP_DEBUG: "${APP_APP_DEBUG}"
APP_ENV: "${APP_APP_ENV}"
APP_KEY: "${APP_APP_KEY}"
APP_MAINTENANCE_DRIVER: "cache"
APP_MAINTENANCE_STORE: "redis"
APP_NAME: "${APP_APP_NAME}"
APP_URL: "https://${APP_DOMAIN}"
AWS_ACCESS_KEY_ID: ${APP_OVH_S3_ACCESS_KEY_ID}
AWS_BUCKET: ${APP_OVH_S3_BUCKET}
AWS_DEFAULT_REGION: ${APP_GLOBAL_OVH_S3_REGION}
AWS_ENDPOINT: ${APP_GLOBAL_OVH_S3_ENDPOINT}
AWS_SECRET_ACCESS_KEY: ${APP_OVH_S3_SECRET_ACCESS_KEY}
AWS_URL: "${APP_OVH_S3_URL}"
AWS_USE_PATH_STYLE_ENDPOINT: "true"
CACHE_PREFIX: ""
CACHE_STORE: "${APP_CACHE_STORE}"
DB_CONNECTION: "mysql"
DB_DATABASE: "${APP_DB_DATABASE}"
DB_HOST: "${APP_GLOBAL_OVH_MYSQL_HOST}"
DB_PASSWORD: "${APP_DB_PASSWORD}"
DB_PORT: "${APP_GLOBAL_OVH_MYSQL_PORT}"
DB_USERNAME: "${APP_DB_USERNAME}"
FILESYSTEM_DISK: "${APP_FILESYSTEM_DISK}"
GOOGLE_RECAPTCHA_PRIVATE: "${APP_GOOGLE_RECAPTCHA_PRIVATE}"
GOOGLE_RECAPTCHA_PUBLIC: "${APP_GOOGLE_RECAPTCHA_PUBLIC}"
GOOGLE_RECAPTCHA_VERSION: "${APP_GOOGLE_RECAPTCHA_VERSION}"
LOG_CHANNEL: "k8s"
MAIL_ENCRYPTION: "${APP_MAIL_ENCRYPTION}"
MAIL_FROM_NAME: "${APP_APP_NAME}"
MAIL_HOST: "${APP_MAIL_HOST}"
MAIL_PASSWORD: "${APP_MAIL_PASSWORD}"
MAIL_PORT: "${APP_MAIL_PORT}"
MAIL_USERNAME: "${APP_MAIL_USERNAME}"
MATOMO_SITE_ID: "${APP_MATOMO_SITE_ID}"
QUEUE_CONNECTION: "database"
REDIS_CLIENT: "phpredis"
REDIS_HOST: "${APP_GLOBAL_OVH_REDIS_HOST}"
REDIS_PASSWORD: "${APP_REDIS_PASSWORD}"
REDIS_PORT: "${APP_GLOBAL_OVH_REDIS_PORT}"
REDIS_PREFIX: "${APP_REDIS_PREFIX}"
REDIS_SCHEME: "${APP_GLOBAL_OVH_REDIS_SCHEME}"
REDIS_USERNAME: "${APP_REDIS_USERNAME}"
SAML2_CONTACT_SUPPORT_EMAIL: "${APP_SAML2_CONTACT_SUPPORT_EMAIL}"
SAML2_CONTACT_TECHNICAL_EMAIL: "${APP_SAML2_CONTACT_TECHNICAL_EMAIL}"
SAML2_DEFAULT_TENANT_UUID: "${APP_SAML2_DEFAULT_TENANT_UUID}"
SAML2_SP_CERT_PRIVATEKEY: "${APP_SAML2_SP_CERT_PRIVATEKEY}"
SAML2_SP_CERT_x509: "${APP_SAML2_SP_CERT_x509}"
SENTRY_LARAVEL_DSN: "${APP_SENTRY_LARAVEL_DSN}"
SESSION_CONNECTION: "${APP_SESSION_CONNECTION}"
SESSION_DRIVER: "${APP_SESSION_DRIVER}"
TELESCOPE_ENABLED: "${APP_TELESCOPE_ENABLED}"
UWIL_ADMIN_SECURE_CIDR_LIST: "${APP_GLOBAL_UWIL_ADMIN_SECURE_CIDR_LIST}"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ${CI_PROJECT_PATH_SLUG}-deployment
labels:
app: ${CI_PROJECT_PATH_SLUG}-app
spec:
selector:
matchLabels:
app: ${CI_PROJECT_PATH_SLUG}-app
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
template:
metadata:
labels:
app: ${CI_PROJECT_PATH_SLUG}-app
spec:
securityContext:
runAsUser: 82
runAsGroup: 82
fsGroup: 82
fsGroupChangePolicy: OnRootMismatch
terminationGracePeriodSeconds: 30
imagePullSecrets:
- name: docker-registry-credentials
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- ${CI_PROJECT_PATH_SLUG}-app
topologyKey: kubernetes.io/hostname
namespaces:
- ${KUBE_NAMESPACE}
volumes:
- name: laravel-cache
emptyDir: {}
- name: laravel-views
emptyDir: {}
containers:
- name: ${CI_PROJECT_PATH_SLUG}-container
image: $IMAGE_TAG
imagePullPolicy: IfNotPresent
env:
- name: XDG_CONFIG_HOME # For tinker
value: /tmp
envFrom:
- configMapRef:
name: ${CI_PROJECT_PATH_SLUG}-config-map
ports:
- name: http
containerPort: 80
protocol: TCP
volumeMounts:
- name: laravel-cache
mountPath: /app/srcs/bootstrap/cache
- name: laravel-views
mountPath: /app/srcs/storage/framework/views
readinessProbe:
httpGet:
path: /up
port: http
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
livenessProbe:
httpGet:
path: /up
port: http
initialDelaySeconds: 30
periodSeconds: 20
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /up
port: http
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 24
resources:
limits:
cpu: "${APP_CI_CPU_LIMIT}"
memory: "${APP_CI_MEMORY_LIMIT}"
requests:
cpu: "${APP_CI_CPU_REQUEST}"
memory: "${APP_CI_MEMORY_REQUEST}"
securityContext:
# TODO : valider le POC
# readOnlyRootFilesystem: true
# TODO : a priori incompatible avec PVC
# allowPrivilegeEscalation: false
- name: ${CI_PROJECT_PATH_SLUG}-queue-worker
image: $IMAGE_TAG
lifecycle:
preStop:
exec:
command: [ "/bin/sh", "-c", "kill -s TERM 1; while test $(ps ax | grep -v grep | grep bash | wc -l) -gt 0; do sleep 2s; done" ]
resources:
limits:
cpu: "${APP_CI_CPU_LIMIT}"
memory: "${APP_CI_MEMORY_LIMIT}"
requests:
cpu: "${APP_CI_CPU_REQUEST}"
memory: "${APP_CI_MEMORY_REQUEST}"
command:
- "bash"
args:
- "k8s-queues.sh"
envFrom:
- configMapRef:
name: ${CI_PROJECT_PATH_SLUG}-config-map
securityContext:
# TODO : valider le POC
# readOnlyRootFilesystem: true
# TODO : a priori incompatible avec PVC
# allowPrivilegeEscalation: false
---
apiVersion: v1
kind: Service
metadata:
name: ${CI_PROJECT_PATH_SLUG}-service
spec:
selector:
app: ${CI_PROJECT_PATH_SLUG}-app
ports:
- name: http
port: 80
targetPort: http
protocol: TCP
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: ${CI_PROJECT_PATH_SLUG}-ingress-route
spec:
entryPoints:
- web
- websecure
routes:
- match: Host(`${APP_DOMAIN}`) || Host(`www.${APP_DOMAIN}`)
kind: Rule
services:
- name: ${CI_PROJECT_PATH_SLUG}-service
port: 80
middlewares:
- name: redirect-no-www-to-www
tls:
secretName: ${CRT_TLS_NAME}
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: ${CI_PROJECT_PATH_SLUG}-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: ${CI_PROJECT_PATH_SLUG}-deployment
minReplicas: 1
maxReplicas: 2
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 75
behavior:
scaleUp:
stabilizationWindowSeconds: 0
selectPolicy: Max
policies:
- type: Percent
value: 100
periodSeconds: 60
- type: Pods
value: 2
periodSeconds: 60
scaleDown:
stabilizationWindowSeconds: 300
selectPolicy: Min
policies:
- type: Percent
value: 25
periodSeconds: 60
- type: Pods
value: 1
periodSeconds: 60
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: ${CI_PROJECT_PATH_SLUG}-cronjob
spec:
schedule: "* * * * *"
successfulJobsHistoryLimit: 1
failedJobsHistoryLimit: 1
concurrencyPolicy: Forbid
jobTemplate:
spec:
template:
spec:
restartPolicy: OnFailure
securityContext:
runAsUser: 82
runAsGroup: 82
fsGroup: 82
fsGroupChangePolicy: OnRootMismatch
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- ${CI_PROJECT_PATH_SLUG}-app
topologyKey: kubernetes.io/hostname
namespaces:
- ${KUBE_NAMESPACE}
imagePullSecrets:
- name: docker-registry-credentials
volumes:
- name: laravel-cache
emptyDir: {}
- name: laravel-views
emptyDir: {}
containers:
- name: ${CI_PROJECT_PATH_SLUG}-scheduled
image: $IMAGE_TAG
imagePullPolicy: IfNotPresent
workingDir: /app/srcs
command:
- php
args:
- artisan
- schedule:run
envFrom:
- configMapRef:
name: ${CI_PROJECT_PATH_SLUG}-config-map
volumeMounts:
- name: laravel-cache
mountPath: /app/srcs/bootstrap/cache
- name: laravel-views
mountPath: /app/srcs/storage/framework/views
resources:
requests:
cpu: "${APP_CI_CPU_REQUEST}"
memory: "${APP_CI_MEMORY_REQUEST}"
limits:
cpu: "${APP_CI_CPU_LIMIT}"
memory: "${APP_CI_MEMORY_LIMIT}"
securityContext:
# TODO : valider le POC
# readOnlyRootFilesystem: true
# TODO : a priori incompatible avec PVC
# allowPrivilegeEscalation: false