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 full-size slide

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

    View full-size slide

  3. Bastien, cofondateur et architecte logiciel

    View full-size slide

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

    View full-size slide

  5. 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 full-size slide

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

    View full-size slide

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

    View full-size slide

  8. 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 full-size slide

  9. 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 full-size slide

  10. 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 full-size slide

  11. Serveur qui n’en peut plus

    View full-size slide

  12. 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 full-size slide

  13. 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 full-size slide

  14. Le cache HTTP
    vous connaissez ?

    View full-size slide

  15. 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 full-size slide

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

    View full-size slide

  17. 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 full-size slide

  18. PaaS ? Platform as a Service

    View full-size slide

  19. 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 full-size slide

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

    View full-size slide

  21. 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 full-size slide

  22. # 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 full-size slide

  23. 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 full-size slide

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

    View full-size slide

  25. # 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 full-size slide

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

    View full-size slide

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

    View full-size slide

  28. 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 full-size slide

  29. #[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 full-size slide

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

    View full-size slide

  31. # 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 full-size slide

  32. // 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 full-size slide

  33. TEST EN ÉCHEC

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  36. // 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 full-size slide

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

    View full-size slide

  38. # 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 full-size slide

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

    View full-size slide

  40. # 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 full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  45. /**
    * @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 full-size slide

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

    View full-size slide

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

    View full-size slide

  48. /**
    * @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 full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  52. 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 full-size slide

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

    View full-size slide

  54. 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 full-size slide

  55. 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 full-size slide

  56. 4. Mais encore

    View full-size slide

  57. 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 full-size slide

  58. 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 full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  62. 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 full-size slide

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

    View full-size slide

  64. DivisionByZeroErro
    r

    View full-size slide

  65. 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 full-size slide

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

    View full-size slide

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

    View full-size slide

  68. 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 full-size slide

  69. 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 full-size slide

  70. 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 full-size slide

  71. - 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 full-size slide

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

    View full-size slide

  73. > 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 full-size slide

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

    View full-size slide

  75. 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 full-size slide

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

    View full-size slide

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

    View full-size slide