Déployer Magento 2 sur AWS (Amazon Web Services)
CONTEXTE
J’ai récemment travaillé sur un projet magento 2 qui avait des besoins de scalabilité pour absorber les montées en charge. Nous avons donc opté pour AWS qui présente ces fonctionnalités et qui reste une valeur sure dans le domaine de l’hébergement. Le client ayant un budget hébergement approprié, nous avons pu exploré la piste.
J’ai trouvé peu d’informations sur comment déployer Magento 2 sur AWS donc je voulais vous présenter mon travail.
Ce post n’a pas comme ambition d’être un tutoriel de mise en place mais plutôt de présenter les différentes étapes par lesquelles je suis passé pour arriver à mon objectif.
MON OBJECTIF
Mon objectif était de proposer un environnement de recette iso-production avec un peu de magie. C’est à dire qu’on clique sur un bouton déployer et le code se déploie partout sans downtime.
Mon but est que l’infra doit vivre toute seule et on ne doit pas avoir à se connecter au serveur ou autre pour déployer.
POINT DE DÉPART
L’équipe AWS a réalisé un projet https://github.com/aws-quickstart/quickstart-magento qui est un “getting started” d’une infrastructure magento 2 sécurisée par de la redondance, autoscaling…
Voici l’infra :
En gros le principe est le suivant :
– On a un BASTION qui est le point d’entrée de notre infra (avec une ip publique donc accessible à partir de ma machine) et à partir de la, elle appartient aux sous réseaux privés ou se trouvent nos serveurs web. Cela présente une bonne option de sécurité car on peut facilement filtrer par ip qui peut accéder au bastion en SSH donc j’ai configuré mon ip fixe et celle du client. Toutes les autres seront interdites.
– On a un groupe d’autoscaling basé sur le pourcentage d’utilisation du processeur qui se charge de démarrer de nouvelles machines et de les éteindre lorsque le traffic diminue. On peut bien sur gérer les seuil et les limites afin de ne pas faire exploser les coûts.
– Redis (pour les sessions et le cache magento) + Mysql pour la base de donnée. Il est essentiel d’utiliser un serveur redis pour les sessions sinon on pourrait la perdre en cours de route selon si le load balancer nous envoie sur tel ou tel serveur web.
– Un disque réseau EFS monté sur tous les serveurs web afin de partager les medias (si on change une image produit, on veut que tous les serveurs web présentent la nouvelle)
LANCEMENT DE CE TEMPLATE
Alors le lancement devait se faire tout seul, on clique sur un bouton, on choisit ses configuration et hop!!!! on attend 30 minutes et tout est en place, la réalité a été tout autre.
Déjà je souhaitais déployer l’infrastructure sur les serveurs de Paris mais ce n’est pas possible car tous les services nécessaires, taille d’instance (EFS par exemple) n’existent pas, j’ai donc eu de nombreux échecs avant de comprendre cela.
J’ai donc ensuite choisi l’Irlande et là erreur mystérieuse vers la fin, au moment de l’installation de magento 2. Je me suis dis que cela venait peut être du fait que je tentais d’installer magento 2.2 alors que le template était prévu pour magento 2.1 et j’avais raison, c’était bien la source de l’erreur….
J’ai donc fini par arriver à installer l’infra en Irlande avec magento 2.1
!!! Attention, ce template crée une infra aux alentours de 750$ par mois !!!
Le template est lancé dans CloudFormation de aws. Si tout va bien, vous obtiendrez :
PERSONNALISATION
Déploiement
Maintenant j’ai un magento 2 vierge qui fonctionne sur une infra aws. Chic !!! Mais les nouvelles questions arrivent :
- Comment je déploie sur toutes les instances démarrées par l’autoscaling group
- Comment je mets à jour ces instances quand j’ai une nouvelle version de code
- J’utilise github, comment lier le projet sur mon infra aws
Première piste : Capistrano
Travaillant beaucoup avec Ruby on rails, je suis habitué à mettre en place Capistrano pour le déploiement de mes projets et en particulier https://github.com/davidalger/capistrano-magento2 sur mes projets magento 2.
Les ips tournent dans le cloud donc je ne peux pas les saisir en dur dans capistrano, j’avais donc trouvé la solution https://github.com/marcoschicote/capistrano3-autoscaling-deploy qui me semblait bien.
Mais comment je fais si de nouvelles machines démarrent et quelle version de code vont-elle prendre. Et bien en fait nos web serveur sont démarrés à partir d’une image AMIS (en gros un snapshot) cela signifie qu’à chaque déploiement, je dois faire une nouvelle AMIS à partir d’une instance sur laquelle j’ai correctement déployé => Trop lourd
Dans un environnement de préproduction Capistrano peut rester viable mais va s’avérer limité. Je devais trouver autre chose, il fallait que je cherche parmi les resources AWS.
Seconde piste : CodeDeploy
A force de lire sur internet, j’ai compris que amazon avait créé ses propres services d’intégration continue dont CodeDeploy qui est responsable de déployer une application web sur un auto scaling group par exemple. Pour se faire, il suffit de créer un fichier appspec.yml et d’orchestrer le déploiement par rapport au besoin de notre application.
Voici mes fichiers : appspec.yml
version: 0.0
os: linux
files:
- source: /
destination: /var/www/html/current
permissions:
- object: /
owner: ec2-user
group: nginx
hooks:
ApplicationStop:
- location: scripts/stop_server.sh
timeout: 300
runas: root
BeforeInstall:
- location: scripts/magento/prepare.sh
timeout: 300
runas: ec2-user
AfterInstall:
- location: scripts/magento/symlinks.sh
timeout: 300
runas: ec2-user
- location: scripts/magento/composer.sh
timeout: 300
runas: ec2-user
- location: scripts/magento/permissions.sh
timeout: 300
runas: ec2-user
- location: scripts/magento/compile.sh
timeout: 800
runas: ec2-user
- location: scripts/magento/database.sh
timeout: 300
runas: ec2-user
- location: scripts/start_server.sh
timeout: 300
runas: root
scripts/start_server.sh
#!/bin/bash
service nginx start
scripts/stop_server.sh
#!/bin/bash
isExistApp=`pgrep nginx`
if [[ -n $isExistApp ]]; then
service nginx stop
fi
scripts/magento/compile.sh
#!/bin/bash
#########################
# Go to right directory
#########################
m_path=/var/www/html/current
cd $m_path
#########################
# Set environment
#########################
php -f bin/magento -- deploy:mode:set production --skip-compilation
#########################
# Static assets
#########################
touch pub/static/deployed_version.txt
php -f bin/magento -- setup:static-content:deploy -f en_US -t VENDOR/THEME -t Magento/backend
php -f bin/magento -- setup:static-content:deploy -f fr_FR -t VENDOR/THEME -t Magento/backend
php -f bin/magento -- setup:static-content:deploy -f ja_JP -t VENDOR/THEME -t Magento/backend
php -f bin/magento -- setup:di:compile --no-ansi
#########################
# Composer
#########################
composer dump-autoload --no-dev --no-interaction --optimize 2>&1
scripts/magento/composer.sh
#!/bin/bash
#########################
# Go to right directory
#########################
m_path=/var/www/html/current
cd $m_path
#########################
# Composer
#########################
composer install --no-dev --prefer-dist --no-interaction --optimize-autoloader 2>&1
scripts/magento/database.sh
#!/bin/bash
#########################
# Go to right directory
#########################
m_path=/var/www/html/current
cd $m_path
#########################
# db update
#########################
php -f bin/magento -- setup:db-schema:upgrade
php -f bin/magento -- setup:db-data:upgrade
scripts/magento/permissions.sh
#!/bin/bash
#########################
# Go to right directory
#########################
m_path=/var/www/html/current
cd $m_path
#########################
# Permissions
#########################
find ./ -type d ! -perm 2775 -exec chmod 2775 {} +
find ./ -type f ! -perm 755 -exec chmod 755 {} +
chmod +x bin/magento
scripts/magento/prepare.sh
#!/bin/bash
#########################
# Keep last release
#########################
m_path=/var/www/html/current
rsync -a $m_path /var/www/html/last_deploy
rm -rf $m_path
scripts/magento/symlinks.sh
#!/bin/bash
#########################
# Go to right directory
#########################
m_path=/var/www/html/current
cd $m_path
#########################
# Symlinks
#########################
mkdir -p pub var
rm -rf pub/media
ln -s /var/www/html/shared/pub/media $m_path/pub/media
ln -s /var/www/html/shared/pub/sitemaps $m_path/pub/sitemaps
ln -s /var/www/html/shared/var/backups $m_path/var/backups
ln -s /var/www/html/shared/var/composer_home $m_path/var/composer_home
ln -s /var/www/html/shared/var/importexport $m_path/var/importexport
ln -s /var/www/html/shared/var/import_history $m_path/var/import_history
ln -s /var/www/html/shared/var/log $m_path/var/log
ln -s /var/www/html/shared/var/report $m_path/var/report
ln -s /var/www/html/shared/var/session $m_path/var/session
ln -s /var/www/html/shared/var/tmp $m_path/var/tmp
ln -s /var/www/html/shared/app/etc/env.php $m_path/app/etc/env.php
ln -s /var/www/html/shared/nginx.conf $m_path/nginx.conf
ln -s /var/www/html/shared/app/etc/config.local.php $m_path/app/etc/config.local.php
ln -s /var/www/html/shared/var/.setup_cronjob_status $m_path/var/.setup_cronjob_status
ln -s /var/www/html/shared/var/.update_cronjob_status $m_path/var/.update_cronjob_status
Les symlinks permettent de faire le lien entre nos répertoire locaux et le disque NFS monté sur toutes les instances ou on va stocker tous les medias afin de les partager entre les instances. Le template magento 2 a déjà créé ce disque dans le service EFS de AWS
Une fois cela tout bien configuré, CodeDeploy est capable de déployer l’application sur nos machines et même de le faire en blue/green déploiement.
Mais késako !!! ?
Et bien en fait voici les étapes d’un blue/green déploiement :
- Lancement de nouvelle(s) machine(s)
- Installation de l’application sur ces machines
- Routage du traffic sur ces machines si elles sont (healthy, c’est à dire elles répondent des 200)
- Suppression des anciennes machines
Avantage : Pas de downtime et ca ne publiera la nouvelle version que si l’application a été correctement déployée.
Désavantage : On se retrouve pendant 30min/1h avec le double de machines allumées donc on paie 1h de machines pour chaque déploiement (coût minime)
Conclusion
CodeDeploy est la bonne solution à utiliser avec AWS sans aucun doute. Le suivi des déploiements est bien fait, et on peut aussi relier des notifications slack, sms ou autre pour être notifié à chaque déploiement.
Déploiement automatique
J’ai l’habitude en travaillant avec Travis en intégration continue d’automatiser les déploiement en me basant sur git flow :
- Un commit sur develop déploie la version en preproduction
- Un commit sur master déploie la version en production
J’ai donc cherché comment faire cela avec AWS et j’ai trouvé : CodePipeline
En fait on relie le repository github associé au projet et on crée des “écouteurs” qui se déclenchent quand on commit sur telle ou telle branche. On peut alors lancé des commandes d’intégration continue (type tests rspec…) ou bien juste déployer en utilisant…CodeDeploy.
Avec ce composant je suis donc parvenu à la logique désirée : Un commit GITHUB sur la branche develop ou master déclenche un déploiement CodeDeploy sur l’environnement désirén respectivement staging ou production !
Nom de domaine
Le template magento 2 crée un LoadBalancer avec un DNS amazon, il suffit de créer un record CNAME sur votre domaine vers cette url pour accéder à votre site internet mais aussi de changer dans la table `core_config_data` de magento 2 l’url de votre site car magento 2 la stocke en base de donnée.
Par exemple :
www CNAME staging-MagentoStack-1R4POUP98-SecurityGroupStack-1X6QS47X-ELT6PU9G
Si votre nom de domaine est sebfie.com, alors l’adresse de votre site internet sera www.sebfie.com. C’est cette valeur qu’il faut mettre comme base_url dans la table `core_config_data` de magento 2.
Notifications de déploiement
Pour chaque déploiement, je souhaitais mettre en place des notifications slack qui m’indiquaient l’état du déploiement… pour être averti des erreurs mais aussi notifier le client lorsque le code se déploie.
Il suffit d’utiliser le service lambda de AWS et voici un tutoriel qui résume bien la procédure : http://4eva.net/posts/577
Et voici un peu un récapitulatif de ce que je suis arrivé à mettre en place. J’espère que cela donnera des idées à certains et si vous avez des besoins, n’hésitez pas à me contacter !
Bonjour,
Merci pour cette magnifique solution de déploiement continue!
Avez vous une idée comment utiliser Elastic Beanstalk pour rentabiliser les coups et éviter d’utiliser la quick start installation template ?
Merci
Bonjour,
Finalement le client pour qui j’avais mis en place cette solution n’a pas finalisé son site donc je n’ai pas pu explorer les autres parties mais comme Elastic Beanstalk n’est que la partie applicative, j’imagine qu’il suffit de connecter autour les services db…. pour que tout fonctionne.
Donc la réponse est non, je ne sais pas comment utiliser Elastic Beanstalk mais ca ne me semble pas du tout impossible ! Car derrière ce sont toujours les même objets Amazon qu’on va retrouver.
Bonjour
Bon article, c’est une base pour comprendre ce qu’il faut pour héberger un site Magento 2 dans AWS.
Pour moi c’est pour un but pédagogique et je souhaite savoir si vous avez une configuration type à choisir dans AWS pour un site Magento 2.
Je vais utiliser l’offre gratuit AWS pendant 12 mois pour installer Magento 2 chez AWS, je souhaite savoir si on peut installer la toute dernière version de Magento 2.
Cdt
Bonjour,
Oui on peut tout à faire installer la dernière version de Magento sauf qu’il faut maintenant rajouter un serveur elasticsearch.
Je ne suis pas certain que l’offre gratuite proposera de bonnes performances, je serai interessé par votre retour. Merci