Migration GCP → OVH : extranet Symfony
Migration d'un extranet Symfony et de son site vitrine de GCP vers un projet OVH Public Cloud dédié. Infra en Terraform, applicatif sous Docker Compose derrière Traefik, déploiement par GitHub Actions et bascule MySQL par réplication.
Le projet
L’extranet (Symfony) et son site vitrine tournaient sur GCP. Il fallait les passer sur OVH, dans une région française, sans casser la prod.
Tout le Terraform est écrit à la main, sans module tout fait, pour savoir exactement ce que chaque ressource crée.
Architecture
Un projet OVH dédié
Au départ, l’infra devait aller dans le projet Public Cloud existant de PharmaGDD. Elle a finalement été isolée dans son propre projet OVH : identifiants OpenStack et API séparés, facturation séparée, et une erreur sur ce projet ne peut pas toucher l’infra principale.
Ce choix a demandé un peu plus de travail au début : nouveaux identifiants, accès au registry et au S3 à refaire.
Réseau privé + bastion
La VM applicative est dans un réseau privé dédié (vRack/VLAN), séparé de celui de PharmaGDD. L’accès SSH passe uniquement par un bastion. Dans le security group, seuls le 80 et le 443 sont ouverts au public, et le 22 n’est ouvert que depuis le bastion.
Internet ──► Traefik (80/443) ──► FrankenPHP (extranet Symfony)
└─► conteneur SPA (site vitrine)
Admin ──► Bastion ──SSH──► VM app (réseau privé)
Terraform
Le Terraform est dans un repo à part. Le provider ovh gère le projet, le réseau et le DNS, OpenStack gère les instances et les security groups. Il faut respecter l’ordre réseau → sous-réseau → instance, et bien savoir ce qui dépend de l’API OVH et ce qui dépend d’OpenStack.
La VM est ensuite préparée (Docker, Compose, utilisateur, arborescence /opt/...) par un script lancé en SSH via le bastion.
Stack applicative
Tout tourne en Docker Compose sur la VM :
- Traefik pour le TLS et le routage par labels
- FrankenPHP pour servir l’extranet Symfony
- le site vitrine (SPA) dans son propre conteneur. Un bucket S3 mis à jour par la CI était prévu au départ, abandonné pour garder un seul point d’entrée.
- MySQL et Redis
- des sauvegardes vers un bucket S3 OVH
CI/CD
Le déploiement passe par GitHub Actions, avec un runner self-hosted partagé au niveau de l’organisation. Il n’y a aucun runner sur la VM de prod.
La bascule des données
La prod GCP écrit dans MySQL jusqu’au dernier jour, donc un simple dump/restore aurait imposé une longue coupure. La bascule passe par de la réplication :
- Copie initiale de la base (dump avec position GTID).
- La MySQL OVH devient réplique de la prod GCP. La connexion part d’OVH vers GCP, filtrée sur l’IP de sortie OVH et chiffrée en TLS. La base OVH reste en
super_read_onlypour qu’on ne puisse pas y écrire par erreur. - Le jour de la bascule : prod en lecture seule, on attend que le lag tombe à zéro, on promeut la réplique, puis on bascule le DNS (TTL baissé quelques jours avant).
La prod n’est coupée que le temps que la réplique rattrape son retard, soit quelques minutes.