Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Migration d’un hébergement classique à une infra cloud PaaS, retour d'expérience

Migration d’un hébergement classique à une infra cloud PaaS, retour d'expérience

Beaucoup d’hébergements sont encore à base de serveur dédié car c'est ce que tout le monde fait et que c'est souvent le meilleur rapport puissance / prix. Et on peut aussi faire ce que l'on veut dessus.

Mais cette liberté a un coût : c'est à nous de gérer beaucoup de choses : sécurité, migration de version, log, monitoring. Comme c'est un métier à part entière, on le fait souvent mal ou on le délègue, perdant ainsi pas mal de souplesse et de réactivité.

Cette conférence est un retour d'expérience d'une migration vers un hébergement Platform as a Service (PaaS) avec plein de conseils sur la performance et sur le process d'arriver à un hébergement de qualité clair et reproductible.

Vous ne verrez plus votre hébergement du même œil !

Bastien Jaillot

October 13, 2022
Tweet

More Decks by Bastien Jaillot

Other Decks in Programming

Transcript

  1. Retour d’expérience
    Migration d’un hébergement
    classique à une infra cloud
    PaaS
    Bastien Jaillot, architecte @JoliCode – @bastnic

    View Slide

  2. View Slide

  3. « Les nuits blanches passées
    sur le site planté nous
    empêchaient d'envisager toute
    croissance car le serveur ne
    tiendrait pas »

    View Slide

  4. Bastien, cofondateur et architecte logiciel

    View Slide

  5. (Du coup on m’appelle pour des situations qui puent 💩)
    Les situations
    complexes sont
    mon dada

    View Slide

  6. On s’adresse à qui ?
    - À ceux qui subissent leurs hébergements
    - À ceux qui veulent scaler “facilement” leur application.
    - À ceux qui connaissent déjà ces galères et sont là pour écouter une bonne histoire.
    - Plus généralement à tous ceux qui déploient un site en production.

    View Slide

  7. Bonjour, je voudrais un
    hébergement pour mon site PHP
    / MySQL
    Ça va me coûter combien ?

    View Slide

  8. Ce que l’on vous demande
    Version de PHP ? MySQL ?
    Combien de CPU / RAM / Espace disque ?

    View Slide

  9. Ce que l’on DEVRAIT vous demander
    - Je dois mettre à jour X pour des raisons de sécurité, quand puis-je le faire pour éviter un downtime ?
    - Quelle stratégie de backup / restore ?
    - Comment ça se passe si besoin de plus de puissance ?
    - On sait que l’on va devoir mettre à jour les versions logicielles, comment on planifie ça ?
    - Comment déployer ?
    - Comment rollback ?
    - Comment ajouter un worker ?
    - Comment configurer un cron ?
    - Comment ajouter une dépendance ?

    View Slide

  10. Ce que l’on DEVRAIT vous demander
    - Je dois mettre à jour XX pour des raisons de sécurité, quand puis-je le faire pour éviter un downtime
    - Quelle stratégie de backup / restore ?
    - Comment ça se passe si besoin de plus de puissance ?
    - On sait que l’on va devoir mettre à jour les versions logicielles, comment on planifie ça ?
    - Comment déployer ?
    - Comment rollback ?
    - Comment ajouter un worker ?
    - Comment configurer un cron ?
    - Comment ajouter une dépendance ?
    -
    Comment améliorer le process de build ?
    -
    Comment gérer les environnements ?
    -
    Où sont les logs ?
    -
    Tu veux un APM ?
    -
    Tu as pensé à faire un tir de charge pour que l’on finetune les process et la mémoire ?
    -
    Comment on rotate les logs ?
    -
    Combien de releases on garde
    -
    Quelles sondes poser ?
    -
    Qui gère quoi quand ça plante ? HNO ?
    -

    View Slide

  11. Observabilité ? Je dois auditer mais ???
    - SSH bloqué => il faut que l’ancien administrateur système m’ajoute
    - Aucune documentation
    - Script custom pour déployer
    - Instances Docker mais routing custom
    - Ni LOG ni APM, les développeurs sont aveugles de fait
    - RIEN DE STANDARD
    ouaip, non, on ne va PAS toucher à ça

    View Slide

  12. Serveur qui n’en peut plus

    View Slide

  13. API
    www
    Clients apps
    BDD
    cache local des réponses API
    Tout sur un serveur
    Users
    Contributors backoffice
    cache local des réponses API

    View Slide

  14. Architecture du code ?
    - API / BO : code bien legacy et très très très très très très très lent
    - FRONT : Symfony nickel mais un énorme cache fichier de l’API (??)
    - Applications mobiles et tierces ne bénéficient pas du cache calculé par le front
    - la performance n’a jamais été prise en compte à la base, ce sont des rustines
    pour que le front ne tombe pas
    => c’est propre, on va pouvoir bosser !

    View Slide

  15. Le cache HTTP
    vous connaissez ?

    View Slide

  16. Cache HTTP (avec Varnish)
    - Ça s’interpose entre le client et le site PHP
    - Ça répond en <1ms, et consomme 0,0000001% CPU
    - Ça se configure via des en-têtes HTTP
    - Ça se scripte via du VCL
    - C’est bon, mangez-en !
    J’ai déjà bloggé sur le sujet :
    https://jolicode.com/blog/scaling-the-symfony-demo-app-to-the-extreme-with-varnish

    View Slide

  17. API
    www
    Clients apps
    BDD
    Tout sur un serveur
    Users
    Contributors backoffice
    Proxy
    cache

    View Slide

  18. On va proxifier l’API de l’extérieur
    Il nous faut donc un nouvel hébergement :
    - aucune idée des futures performances de la plateforme
    - le trafic n’étant pas lisse, on veut du scaling
    - j’ai 0 temps et le client n’a pas un énorme budget
    - le site est planté très régulièrement, on va pouvoir prendre nos gros sabots
    - plein de solutions (cluster kubernetes, plusieurs serveurs dédiés, lambdas, …)
    (si vous partez sur Kubernetes pour cette taille de site, on se rappelle quand vous aurez échoué)

    View Slide

  19. PaaS ? Platform as a Service

    View Slide

  20. PaaS chez Clever Cloud ?
    - on décrit ce que l’on veut (une application PHP 8.1 liée à un MySQL 8.0)
    - c’est tout
    - ah si, on paie à la ressource consommée.
    - tout se configure via des variables d’environnement documentées
    - beaucoup plus cher à CPU égal par rapport à un dédié et plus de latence
    - mais ça va nous permettre d’optimiser donc ce sera PEUT-ÊTRE dans le même
    range de prix => pour le moment on n’en sait rien
    - Clever Cloud = ils sont Français et sympas, pourquoi pas ?

    View Slide

  21. API
    www
    Clients apps
    BDD
    Tout sur un serveur
    Users
    Contributors backoffice
    Proxy
    cache
    Infrastructure
    Clever Cloud

    View Slide

  22. On récupère tout
    - Clever Cloud : création de l'organisation par le client, ajout des comptes admin
    - New Relic : création par le client d’un compte gratuit
    - DNS : accès à la config ("oui oui il faut bien saisir le point à la fin") => TTL à 300s
    - GitHub : accès à tous les repositories de code
    - Backups : accès aux sauvegardes de bases de données et des fichiers statiques

    View Slide

  23. 1. Proxy

    View Slide

  24. # Proxy tentative 1, Varnish appelle le legacy
    mkdir -p proxy-varnish/clevercloud && cd proxy-varnish
    touch clevercloud/varnish.vcl # avec du code VCL pas sympa
    git init && git add . && git commit -m 'Proxy: add varnish config'
    clever create -t php "proxy-varnish" -o "Conf AFUP"
    clever deploy
    clever open # ouvre l’url en cleverapps.io dans votre navigateur

    View Slide

  25. 2022-01-18T22:04:05+01:00 VCL compilation failed
    2022-01-18T22:04:05+01:00 #######------------
    2022-01-18T22:04:05+01:00 Only one IPv4 and one IPv6 are allowed.
    2022-01-18T22:04:05+01:00 **Backend host "api.XXX.com": resolves to
    too many addresses**.

    View Slide

  26. # on n’oublie pas de nettoyer
    # derrière nous #boyscoutRule
    clever delete

    View Slide

  27. # Proxy tentative 2, Varnish appelle une app PHP
    mkdir -p proxy-php/clevercloud && cd proxy-php
    touch clevercloud/varnish.vcl # avec du code VCL pas sympa
    symfony create <...>
    git init && git add . && git commit -m 'Proxy: add code'
    clever create -t php "proxy-php" -o "Conf AFUP"
    clever deploy
    clever open # ouvre l’url en cleverapps.io dans votre navigateur

    View Slide

  28. clever env set CC_PHP_VERSION 8.1
    clever env set APP_ENV prod

    View Slide

  29. # nginx != apache, .htaccess… 🤦
    composer require symfony/apache-pack
    git add .
    git commit -m "Fix apache config"
    clever deploy

    View Slide

  30. C’est en prod !
    En DEUX minutes nous avons une application PHP en production et accessible.
    Sans AUCUNE compétence en administration système !

    View Slide

  31. #[Route('/{anything}', name: 'proxy', requirements: ['anything' => '.+'])]
    public function index(Request $request,
    HttpClientInterface $httpClient): Response
    {
    $originResponse = $httpClient->request($request->getMethod(),
    $request->getRequestUri());
    return new Response(
    $originResponse->getContent(false),
    $originResponse->getStatusCode(false),
    [
    'content-type' => $originResponse->getHeaders(false)['content-type'],
    ]
    );
    }

    View Slide

  32. # ça proxifie, maintenant, ajoutons du monitoring
    clever env set NEWRELIC_APPNAME "prod - api proxy php"
    clever env set NEWRELIC_LICENSE xxxxx

    View Slide

  33. HEIN ?

    View Slide

  34. # imaginez la discussion avec l'infogérant pour
    # lui dire de downgrade PHP. Mieux comme ça non ?
    clever env set CC_PHP_VERSION 8.0
    clever restart

    View Slide

  35. // on n'oublie pas les tests, pas grand chose, mais on itérera au besoin
    public function testProxyGet()
    {
    $client = static::createClient();
    $crawler = $client->request('GET', '/secretUrl');
    $response = $client->getResponse();
    $data = json_decode($response->getContent());
    $headers = $response->headers;
    $this->assertIsArray($data);
    $this->assertTrue($response->isCacheable());
    }

    View Slide

  36. TEST EN ÉCHEC

    View Slide

  37. public function index(Request $request,
    HttpClientInterface $httpClient): Response
    {
    // ...
    $response->setPublic();
    $response->setSharedMaxAge(3600);
    return $response;
    }

    View Slide

  38. Et le build ???
    Clever Cloud lance tout seul un composer install s’il détecte un
    composer.json

    View Slide

  39. // le code n'étant pas structuré (une action répond à 100% des appels), New Relic
    // regroupe toutes les transactions sous /index.php, on corrige ça
    $action = parse_url($request->getRequestUri(), PHP_URL_PATH);
    if (extension_loaded('newrelic')) {
    newrelic_name_transaction($action . ' - ' . $request->query->get('client'));
    }

    View Slide

  40. View Slide

  41. View Slide

  42. On modifie les apps clientes pour
    utiliser le proxy…

    View Slide

  43. # Hit rate trop faible vu avec
    varnishstat -1 | grep MAIN.n_lru_nuked
    # on augmente sa taille allouée (1go par défaut)
    # cette variable d'environnement a été créée exprès pour moi, merci Clever <3
    clever env set CC_VARNISH_STORAGE_SIZE "13G"
    # fuite mémoire car métadonnées sur un trop grand nombre d'objets
    # on passe d'une instance nano (512M) à S (2go)
    clever scale --flavor S

    View Slide

  44. 2. Front

    View Slide

  45. API
    www
    Clients apps
    BDD
    Tout sur un serveur
    Users
    Contributors backoffice
    Proxy
    cache
    Infrastructure
    Clever Cloud

    View Slide

  46. # Mise en ligne du site front
    git clone [email protected]:pouet.git
    clever create -t php "front" -o "Conf AFUP"
    clever env set CC_PHP_VERSION 8.0
    clever env set APP_ENV prod
    clever env set NEWRELIC_APPNAME "prod - front php"
    clever env set NEWRELIC_LICENSE xxxxx
    clever env set API_URL https://...
    clever domain add www.j-ai-signé-un-nda.com
    clever deploy

    View Slide

  47. # nginx != apache, .htaccess… 🤦
    composer require symfony/apache-pack
    git add .
    git commit -m "Fix apache config"
    clever deploy

    View Slide

  48. # application/config/packages/monolog.yaml
    when@prod:
    monolog:
    handler:
    # ...
    nested:
    - type: stream
    - path: php://stderr
    + type: error_log

    View Slide

  49. DEUX minutes
    pour générer
    le menu ?

    View Slide

  50. # ESI (Edge Side Include), merci Varnish
    {# base.html.twig #}
    {{ render_esi(
    controller(
    'App\\Controller\\MenuController::index',
    {'_locale': app.request.get('_locale')}
    )
    ) }}

    View Slide

  51. /**
    * @Cache(smaxage="3600", public=true)
    */
    class MenuController extends AbstractController
    {
    public function index()
    {
    // les gros calculs étaient dans du routing
    return $this->render('_menu.html.twig');
    }
    }

    View Slide

  52. Prêt pour une mise en
    prod via migration
    DNS ?

    View Slide

  53. View Slide

  54. Rollback après 30s
    Pas merci les médias en absolute qui ont masqué le souci.

    View Slide

  55. /**
    * @Route("/media/{anything}", name="media_proxy", methods={"GET"}, requirements={"anything":".+"})
    */
    public function proxy(Request $request, HttpClientInterface $httpClient): Response
    {
    $originalResponse = $httpClient->request($request->getMethod(), $request->getRequestUri());
    $response = new Response(
    $originalResponse->getContent(),
    $originalResponse->getStatusCode(),
    ['content-type' => $originalResponse->getHeaders()['content-type']]
    );
    $response->setPublic();
    $response->setSharedMaxAge(3600);
    return $response;
    }

    View Slide

  56. Re MEP… OK ! 🎉
    (on s’occupera de synchroniser les fichiers hein ⌛⌛⌛)

    View Slide

  57. 3. API & BO

    View Slide

  58. API
    www
    Clients apps
    BDD
    Un serveur
    Users
    Contributors backoffice
    Proxy
    cache
    Infrastructure
    Clever Cloud
    BDD
    jetable
    API
    test

    View Slide

  59. # nginx != apache, .htaccess… 🤦
    composer require symfony/apache-pack (et non, legacy…)
    touch .htaccess
    git add .
    git commit -m "Fix apache config"
    clever deploy

    View Slide

  60. Performance SQL ?
    - Malgré des ajouts d’index… Performances horribles comparées au legacy
    - Dans notre bonheur, j’étais passé direct de MySQL 5.7 à MySQL 8, mais PERTE
    DES QUERY CACHE.
    - Legacy qui fait 500x la même requête SQL dans une boucle => on va éviter de
    fixer le code, on fixe MySQL
    - => on jette l’instance v8 et on lance v5.7

    View Slide

  61. www
    Clients apps
    One server
    Users
    Contributors backoffice
    Proxy
    cache
    Infrastructure
    Clever Cloud
    BDD
    API
    KTHXBYE
    Uploaded
    data

    View Slide

  62. Bug marrant 1/2
    Constat : des énormes pics bases de données sans cause visible dans l’APM API.
    Que faut-il faire ? augmenter la puissance BDD ?
    Sont nuls ces serveurs, on va repasser sur un dédié

    View Slide

  63. Bug marrant 2/2
    On regardait la mauvaise application…
    Un contributeur ouvrait 40 onglets d’un coup
    404 favicon.ico => chargement par défaut de la page d'accueil du BO
    Page d’accueil avec plein de métriques, plein de calculs : écroulement de la BDD
    Solution : ajouter un favicon 🙄

    View Slide

  64. 1
    2
    3
    4
    5
    6

    View Slide

  65. 4. Mais encore

    View Slide

  66. PaaS : gestion des fichiers contribués
    Pas de stockage local sur du cloud, car les machines meurent 💀.
    Deux solutions : stockage objet “S3” (cellar) ou point de montage distant “NFS” (fsbucket)

    View Slide

  67. PaaS : gestion des mails
    - SMTP local ne fonctionne évidemment pas
    - On peut utiliser un SMTP distant en configurant des variables d'environnement
    (mais ça ne fonctionne pas)
    - On utilise symfony/mailer

    View Slide

  68. PaaS : gestion des crontab
    C’est documenté https://www.clever-cloud.com/doc/administrate/cron/

    View Slide

  69. PaaS : gestion des workers
    C’est documenté https://www.clever-cloud.com/doc/develop/workers/

    View Slide

  70. PaaS : gestion des logs
    C’est documenté https://www.clever-cloud.com/doc/administrate/log-management/

    View Slide

  71. PaaS : et si on veut quand même scripter ?
    C’est documenté https://www.clever-cloud.com/doc/develop/build-hooks/
    - hooks sur le déploiement : Avant / après build, avant lancement, lancement ok,
    lancement planté
    - déclaration par… variable d’environnement

    View Slide

  72. www
    Clients apps
    Users
    Contributors backoffice
    Proxy
    cache
    Infrastructure
    Clever Cloud
    BDD
    API
    7.4
    API
    8.1
    Uploaded
    data

    View Slide

  73. DivisionByZeroErro
    r

    View Slide

  74. Différence sur le déploiement ?
    Avant ?
    - SSH sur la machine
    - Lancement commande inconnue
    - Pull du code
    - Composer install
    - Npm build
    - Pendant ce temps là le site est down
    Après ?
    $ clever deploy
    Une nouvelle instance se lance quand le
    build est prêt.
    0 downtime, 0 code custom

    View Slide

  75. Mais est-ce que
    ça scale
    vraiment ?
    Horizontalement
    ET/OU
    Verticalement

    View Slide

  76. Clients apps
    Users
    Contributors backoffice
    Proxy
    cache
    Infrastructure
    Clever Cloud
    BDD
    API
    API
    API
    API
    API
    API
    www
    www
    www
    www

    View Slide

  77. Tout n’est pas magique : pas libre de tout faire…
    - RabbitMQ, Cassandra ? => demander au support
    - Extension Apache ou PHP exotique ? => demander au support
    - Réplication SQL ? => demander au support
    - DataDog à la place New Relic ? ben non ! Mais tu peux tester Elastic APM
    - https://redirection.io/ ? ben non (enfin si, en hackant beaucoup, article à venir)
    - Un mauvais signal : zone New Yorkaise qui ferme 10j après que je l’utilise

    View Slide

  78. Tout n’est pas magique :(
    - Pas de support d’HTTP/2 => faut demander un accès béta
    un comble quand on sait que le CEO en parlait en conférence en 2014
    - Pas de réseau privé par organisation (ça arrive)
    - Pas de healthcheck applicatif (je fais du lobying)
    - Vim a le mouse support activé. Mais qui fait ça ?

    View Slide

  79. Cependant <3… rétrospective
    - Soucis de version de PHP : changer une variable d’environnement
    - Soucis de MySQL trop lent : lancer les deux versions et comparer
    - Vous avez souvent eu ce degré de liberté / réactivité avec vos scripts ansible /
    bash / infogérant ?
    - Grande agilité => on peut TESTER des choses sans un gros investissement

    View Slide

  80. - Le client a la main sur tout : il peut vous donner les mêmes accès que moi
    - Depuis la console PaaS : identifier 4 applications PHP, une base MySQL et 2
    dossiers partagés (fsbucket).
    - Dans chaque app : identifier les contrats (les variables d'environnements)
    - Déployer: clever deploy
    - Ça ralentit ou ça plante ? regarder New Relic ou clever logs
    C’est bon vous pouvez me virer

    View Slide

  81. C’en est tellement simple que
    ça en serait presque ennuyeux
    (et c’est tant mieux) #boringTech

    View Slide

  82. > Quelques bons chiffres pour vous illustrer les
    avancées toujours positives de notre projet.
    > +70% par rapport à la même période l'année
    précédente
    > et le tout SANS NUITS BLANCHES liées aux serveurs !

    View Slide

  83. Agilité dans l’infogérance
    Observabilité

    View Slide

  84. Conclusion
    - Architecture moins chère, scalable et évolutive.
    - Déploiement standardisé et sans code custom.
    - Applications bien cloisonnées sans container ni VM à gérer.
    - Pas nécessaire d’avoir de connaissances en administration système.
    - C’est souvent plus simple et moins coûteux de se faire accompagner par un expert.
    - J’ai mis plus de temps à préparer cette présentation qu’à effectuer cette migration

    View Slide

  85. Commentaires ?
    Feedbacks ?
    https://openfeedback.io/forumphp2022/
    https://joind.in/event/forum-php-2022

    View Slide

  86. Merci.
    ForumPHP 2022 – Bastien Jaillot – @bastnic

    View Slide