Aucun des sites clients de cette agence ne ressemble à un autre : l’un tourne encore sur PHP 7.4 en attendant une refonte, un autre exploite PHP 8.3 avec JIT activé pour une boutique à fort trafic, un troisième nécessite une extension PHP native absente de la configuration standard. Mutualiser l’hébergement de cette flotte sur des serveurs classiques obligerait à multiplier les machines virtuelles au point de perdre tout l’intérêt économique de la mutualisation.
Kubernetes répond précisément à ce type d’hétérogénéité : chaque site s’exécute dans son propre pod, avec sa propre image de conteneur, sa propre version de PHP et ses propres limites de ressources, tout en partageant le même cluster physique sous-jacent.
Arborescence type d’un déploiement
cluster-agence/
├── namespaces/
│ ├── client-a/
│ │ ├── deployment.yaml
│ │ ├── service.yaml
│ │ └── configmap-php.yaml
│ └── client-b/
│ ├── deployment.yaml
│ └── ...
├── ingress/
│ └── ingress-controller.yaml
└── storage/
└── persistent-volumes.yaml
Chaque client dispose de son propre espace de noms (namespace), ce qui isole non seulement ses ressources de calcul mais aussi ses droits d’accès réseau internes au cluster, indépendamment des autres sites hébergés.
Une image de conteneur par version de PHP
L’hétérogénéité des versions PHP se résout en construisant une image de conteneur distincte pour chaque version requise, référencée dans le déploiement du client concerné :
apiVersion: apps/v1
kind: Deployment
metadata:
name: client-a
namespace: client-a
spec:
replicas: 2
template:
spec:
containers:
- name: php-fpm
image: registre-interne/wordpress-php74:latest
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"

Isoler les ressources sans surdimensionner
Le couple requests et limits garantit à chaque client une part minimale de ressources tout en l’empêchant de dépasser un plafond défini, ce qui protège les autres sites hébergés d’un pic de trafic imprévu chez un voisin de cluster. Cette finesse de réglage, propre à chaque déploiement, serait beaucoup plus lourde à maintenir sur des serveurs dédiés classiques.
Le stockage persistant : le point le plus délicat
Les médias WordPress posent un défi particulier sous Kubernetes, où les pods sont par nature éphémères et remplaçables. La solution consiste à monter un volume persistant (PersistentVolumeClaim) par client, indépendant du cycle de vie des pods eux-mêmes :
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: uploads-client-a
namespace: client-a
spec:
accessModes: [ReadWriteMany]
resources:
requests:
storage: 20Gi
Le mode ReadWriteMany est indispensable dès qu’un site fonctionne avec plusieurs répliques simultanées, pour que chaque pod accède aux mêmes fichiers physiques sans divergence.
Le seuil de rentabilité de cette architecture
Kubernetes impose une courbe d’apprentissage réelle et un coût d’exploitation du cluster lui-même, indépendant du nombre de sites hébergés. Cet investissement ne se justifie que lorsque l’hétérogénéité des besoins clients est suffisamment marquée pour que l’alternative, des serveurs dédiés par groupe de configuration similaire, coûte davantage en machines qu’en complexité opérationnelle.
Un repère utile sur ce type de décision : en dessous d’une dizaine de configurations vraiment distinctes, un parc de serveurs classiques reste souvent plus simple à exploiter qu’un cluster Kubernetes complet.
En résumé
Kubernetes trouve sa vraie justification pour un hébergement multi-clients lorsque l’hétérogénéité des besoins, versions de PHP, extensions natives, profils de charge, dépasse ce qu’une mutualisation classique peut absorber proprement. L’isolation par espace de noms et le couple requests/limits permettent alors de concilier mutualisation économique et isolation réelle entre clients.