On a testé Amazon Elastic File System (EFS)

MAJ le 29 juin 2016

Amazon EFS

Qu'est-ce que Amazon Elastic File System (Amazon EFS) ?

Annoncé cet été par Andy Jassy lors du sommet AWS de San Francisco, Amazon Elastic File System (EFS) est un nouveau service permettant de partager un système de fichier entre plusieurs instances EC2 en NFSv4.

Reposant sur des disques SSD, ce service est managé par AWS qui s'occupe de répliquer les données entre différentes zones de disponbilités et de provisionner de manière transparente le nombre d'instances nécéssaires à son bon fonctionnement. Enfin, la tarification repose uniquement sur la quantité d'espace de stockage utilisée à raison de 0,30 USD/Go/mois.

Le services est disponible dans trois régions depuis le 28 juin 2016 : US East (Northern Virginia), US West (Oregon), and Europe (Ireland).

Pourquoi utiliser Amazon EFS ?

Nous avons déjà S3 non ? Oui, mais S3 n'est pas un filesystem. C'est du stockage objet. Et malheureusement bien peu d'applications savent parler nativement avec S3. Il n'est par exemple pas trivial de rendre cloud-compatible des logiciels aussi fréquents que WordPress, Magento ou encore Drupal.

Amazon EFS partage les fichiers

Création d'un site WordPress scalable

Nous allons ici monter une plateforme WordPress scalable complète basée sur EFS.

On va en profiter pour revoir en détail comment monter un VPC from scratch, avec ses subnets, et route-table. Ça ne fait jamais de mal de reprendre les bases, en suivant les best-practices.


Contactez des Experts AWS certifiés !

Création des ressources de base

VPC

On commence par créer le VPC :

$ aws ec2 create-vpc \
    --cidr-block 10.1.0.0/16
vpc-8fe172ea

Puis on active le support du DNS :

$ aws ec2 modify-vpc-attribute \
    --vpc-id vpc-8fe172ea \
    --enable-dns-support
$ aws ec2 modify-vpc-attribute \
    --vpc-id vpc-8fe172ea \
    --enable-dns-hostnames

Etape fondamentale, on nomme notre VPC :

$ aws ec2 create-tags \
    --resources vpc-8fe172ea \
    --tags Key=Name,Value=efs

Le VPC doit pouvoir accéder à Internet. Il faut donc lui attacher une Internet Gateway :

$ aws ec2 create-internet-gateway
igw-744efa11

On nomme notre Internet Gateway :

$ aws ec2 create-tags \
    --resources igw-744efa11 \
    --tags Key=Name,Value=efs

Puis enfin, on attache l'attache au VPC :

$ aws ec2 attach-internet-gateway \
    --internet-gateway-id igw-744efa11 \
    --vpc-id vpc-8fe172ea

Subnets

On va créer deux subnets publics:

1 subnet public en zone A :

$ aws ec2 create-subnet \
    --vpc-id vpc-8fe172ea \
    --cidr-block 10.1.0.0/24 \
    --availability-zone us-west-2a
subnet-d2f890b7

$ aws ec2 create-tags \
    --resources subnet-d2f890b7 \
    --tags Key=Name,Value=efs-public-subnet-A
$ aws ec2 modify-subnet-attribute \
    --subnet-id subnet-d2f890b7 \
    --map-public-ip-on-launch

1 subnet public en zone B :

$ aws ec2 create-subnet \
    --vpc-id vpc-8fe172ea \
    --cidr-block 10.1.1.0/24 \
    --availability-zone us-west-2b
subnet-8cc049fb

$ aws ec2 create-tags \
    --resources subnet-8cc049fb \
    --tags Key=Name,Value=efs-public-subnet-B
$ aws ec2 modify-subnet-attribute \
    --subnet-id subnet-8cc049fb \
    --map-public-ip-on-launch

Amazon EFS

Routage

Création et nommage de la table de routage publique

$ aws ec2 create-route-table \
    --vpc-id vpc-8fe172ea
rtb-21751244

$ aws ec2 create-tags \
    --resources rtb-21751244 \
    --tags Key=Name,Value=efs-public-route-table

Ajout de la route par défaut via l'internet gateway, et association de la table de routage aux deux subnets publics

$ aws ec2 create-route \
    --route-table-id rtb-21751244 \
    --destination-cidr-block 0.0.0.0/0 \
    --gateway-id igw-744efa11
$ aws ec2 associate-route-table \
    --subnet-id subnet-d2f890b7 \
    --route-table-id rtb-21751244
$ aws ec2 associate-route-table \
    --subnet-id subnet-8cc049fb \
    --route-table-id rtb-21751244

Security Groups

Comme d'habitude, on va créer un groupe par ensemble logique. Dans notre cas :

  • Un groupe par defaut pour tout le projet
  • Un groupe pour les frontaux PHP
  • Un groupe pour la base de données
  • Un groupe pour EFS
$ aws ec2 create-security-group \
    --group-name efs-default \
    --description 'groupe par defaut pour tout le projet' \
    --vpc-id vpc-8fe172ea
sg-0b4bb66f

$ aws ec2 create-tags \
    --resources sg-0b4bb66f \
    --tags Key=Name,Value=efs-default

etc. On répète cette même opération pour les trois autres groupes.

Amazon EFS

Frontaux et base de données

Base MysQL RDS

On va déployer une instance RDS MySQL single-AZ (pour notre exemple), dans le VPC efs.

DB subnet group

$ aws rds create-db-subnet-group \
    --db-subnet-group-name efs \
    --db-subnet-group-description efs \
    --subnet-ids subnet-d2f890b7 subnet-8cc049fb

Paramètres

$ aws rds create-db-parameter-group \
    --db-parameter-group-name efs \
    --db-parameter-group-family MySQL5.6 \
    --description efs

Démarrage de l'instance RDS

$ aws rds create-db-instance \
    --db-instance-identifier efs-mysql \
    --db-instance-class db.t2.micro \
    --storage-type gp2 \
    --engine MySQL \
    --allocated-storage 10 \
    --db-parameter-group-name efs \
    --master-username root \
    --master-user-password ************ \
    --backup-retention-period 1 \
    --no-publicly-accessible \
    --region us-west-2 \
    --availability-zone us-west-2a \
    --vpc-security-group-ids sg-d04bb6b4 \
    --db-subnet-group-name efs

Frontaux PHP

On l'a vu, l'usage d'EFS ici va être de pouvoir scaler horizontalement notre WordPress. Qui dit scaler dit donc AutoScaling Group.

Launch configuration

Avant de commencer, il nous faut créer un fichier temporaire contenant les user-data qui seront attachés aux instances de notre groupe d'autoscaling :

$ cat > /tmp/userdata << EOF
#!/bin/bash
wget https://s3-us-west-2.amazonaws.com/test-efs/init-www.sh
chmod +x ./init-www.sh
./init-www.sh
EOF

On va commencer par créer une launch configuration pour nos WordPress a partir d'une image Amazon Linux de base, dans les security groups efs-default, efs-www et, nous verrons plus loin pourquoi, également dans efs-nfs

$ aws autoscaling create-launch-configuration \
    --launch-configuration-name efs-www \
    --image-id ami-e7527ed7 \
    --key-name efs \
    --security-groups sg-0b4bb66f sg-cc4bb6a8 sg-da4bb6be \
    --instance-type t2.micro \
    --user-data file:///tmp/userdata

Préparation des User-Data

On l'a vu, les user-data appelés par la launch config font eux-même référence à un script stocké dans S3. C'est ce script, très simple, qui va installer tout ce qu'il faut pour faire tourner WordPress.

$ cat > /tmp/init-www.sh << EOF
#!/bin/bash
yum -y update
yum -y install httpd24 mysql php56 php56-mysqlnd
chkconfig httpd on
service httpd start

cd /var/www/html
wget https://wordpress.org/latest.tar.gz
tar xf latest.tar.gz
rm latest.tar.gz
chown -R apache:apache /var/www/html

service httpd restart
EOF

Puis on envoie ce fichier dans S3 :

$ aws s3 cp /tmp/init-www.sh s3://test-efs/ --acl public-read

Elastic Load Balancer

Avant de pouvoir lancer nos instances, il nous faut un ELB :

$ aws elb create-load-balancer \
    --load-balancer-name efs-www \
    --listeners Protocol=HTTP,LoadBalancerPort=80,InstanceProtocol=HTTP,InstancePort=80 \
    --subnets subnet-d2f890b7 subnet-8cc049fb \
    --security-groups sg-3246bb56
efs-www-464796227.us-west-2.elb.amazonaws.com

AutoScaling Group

On va pouvoir maintenant démarrer notre premier frontal, configurer WordPress et EFS... et voir la magie opérer.

$ aws autoscaling create-auto-scaling-group \
    --auto-scaling-group-name efs-www \
    --launch-configuration-name efs-www \
    --min-size 1 \
    --desired-capacity 1 \
    --max-size 10 \
    --load-balancer-names efs-www \
    --vpc-zone-identifier subnet-d2f890b7,subnet-8cc049fb \
    --health-check-type ELB \
    --health-check-grace-period 300 \
    --tags ResourceId=efs-www,ResourceType=auto-scaling-group,Key=Name,Value=efs-www,PropagateAtLaunch=true

Installation et configuration de WordPress

Base de données

on commence tout de suite par configurer la base de données MySQL :

mysql -uroot -hefs-mysql.czpll9qoxxxd.us-west-2.rds.amazonaws.com -p
mysql> CREATE USER "wordpress-user"@"%" IDENTIFIED BY "*************"; 
mysql> CREATE DATABASE "wordpress-db";
mysql> GRANT ALL PRIVILEGES ON "wordpress-db".* TO "wordpress-user"@"%";
mysql> exit

Configuration de WordPress

Rendez vous à l'adresse de votre ELB /wordpress. dans notre cas : http://efs-www-464796227.us-west-2.elb.amazonaws.com/wordpress

Vous devriez voir aparaître l'assistant de configuration. Faites ce qu'il faut. (nous ne sommes pas ici dans un tutorial WordPress).

C'est parfait, nous avons maitenant notre WordPress fonctionnel !

Et maintenant ?

Et oui ? et maintenant ? On vient de passer tout ce temps pour juste avoir un WordPress qui marche ? Quel était le sujet initial déjà ? Ah oui, Elastic File System.

Et si on scalait ?

Autrement dit, que se passe-t-il si on ajoute un second frontal parce que subitement notre superbe blog se met a avoir un succès fou ?

Il suffit de passer notre --desired-capacity a 2 au niveau de l'autoscaling group, et puis voilà ! Oui... mais non. Oui, ça fonctionnera, on aura bien un second frontal avec WordPress fonctionnel... Sauf que... les données ne seront pas partagées entre les deux frontaux. Typiquement, si vous envoyez une photo depuis l'interface d'administration, celle-ci sera stockée sur un des deux frontal. Si un visiteur arrive et tombe sur l'autre frontal, il ne verra pas l'image. Dommage.

Il faut donc trouver un moyen fiable d'avoir un système de fichier partagé, étant donné que WordPress n'est pas nativement Cloud-Ready. (Exemple, il n'est pas capable nativement de stocker ces medias dans S3...)

C'est là qu'EFS arrive à notre secours (on ne s'en doutait pas...).

EFS va nous permettre de monter un système de fichier partagé (NFS) fiable, scalable et... pas trop cher.

Amazon EFS

EFS, nous voilà

Avant de commencer, il nous faut générer une chaîne aléatoire :

$ uuidgen
7fd8f05d-1841-4f5d-b0a9-a5c539048f4c

On peut donc maitenant créer notre EFS :

$ aws efs create-file-system \
    --creation-token 7fd8f05d-1841-4f5d-b0a9-a5c539048f4c
fs-aee10d07

Comme d'habitude, on respecte les bonnes pratiques, et on nomme notre EFS :

$ aws efs create-tags \
    --file-system-id fs-aee10d07 \
--tags Key=Name,Value=efs-www

Maintenant, il nous faut créer une cible de montage (horrible traduction de mount target)

$ aws efs create-mount-target \
    --file-system-id fs-aee10d07 \
    --subnet-id subnet-d2f890b7 \
    --security-groups sg-da4bb6be
$ aws efs create-mount-target \
    --file-system-id fs-aee10d07 \
    --subnet-id subnet-8cc049fb \
    --security-groups sg-da4bb6be

Pour que tout fonctionne, il faut autoriser le port tcp/2049 au niveau du security group efs-nfs en provenance du groupe efs-www. Et voilà ! Nous avons maintenant un superbe système de fichier NFS disponible sur nos frontaux wordpress. Allons voir ça.

Montage de l'EFS sur les frontaux

On se connecte à notre pour le moment unique frontal, et on va tester que tout fonctionne.

On commence par installer le client NFS :

$ sudo yum install -y nfs-utils

puis on va créer un dossier partagé :

$ sudo mkdir /efs
$ sudo mount -t nfs4 $(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone).fs-aee10d07.efs.us-west-2.amazonaws.com:/ /efs

copions maintenant tout le contenu de /var/www/html/wordpress dans /efs

$ sudo mv /var/www/html/wordpress /efs

et, même si ce n'est pas la plus belle façon de faire, faisons rapidement un lien symbolique :

$ sudo mv /var/www/html /var/www/html.SAV
$ sudo ln -s /efs /var/www/html

et redémarrons Apache

$ sudo service httpd restart

Amazon EFS

Testons

On peut maintenant visiter notre superbe blog en se rendant sur l'adresse de notre ELB. Dans notre cas : http://efs-www-464796227.us-west-2.elb.amazonaws.com/wordpress

C'est parfait, nous avons un WordPress qui semble fonctionner à merveille. Oui et ? Tout ça pour ça ?

Non ! Car maintenant notre blog est scalable ! Si nous souhaitons avoir non plus un frontal, mais deux, dix, trente-six, c'est possible ! Et nous allons le prouver.

Mise à jour des user-data

Avant tout, il faut un peu modifier notre script d'init appelé lors du premier démarrage des instances. Rappelez-vous, c'est le script que nous avons poussé dans S3.

$ cat > /tmp/init-www.sh << EOF
#!/bin/bash
yum -y update
yum -y install httpd24 mysql php56 php56-mysqlnd nfs-utils

mkdir /efs

mount -t nfs4 $(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone).fs-aee10d07.efs.us-west-2.amazonaws.com:/ /efs

mv /var/www/html /var/www/html.SAV
ln -s /efs /var/www/html

service httpd start
chkconfig httpd on
EOF

Il nous faut maintenant envoyer ce script dans S3 :

$ aws s3 cp /tmp/init-www.sh s3://test-efs/ --acl public-read

Scale-up

Voilà, tout est prêt, nous pouvons maintenant passer de 1 frontal à 2. Pour cela, il suffit de changer le desired-capacity de l'autoscaling group :

$ aws autoscaling set-desired-capacity \
    --auto-scaling-group-name efs-www \
    --desired-capacity 2

Conclusion

Alors, EFS, bien ? pas bien ?

Les deux mon capitaine !

Techniquement, il faut bien avouer qu'EFS est un petit bijou. Un NFSaaS (As a Service), multi-AZ, à un coût raisonnable manquait cruellement à l'offre Amazon. Où est donc le problème ? Et bien le NFS, c'est bien, mais ce n'est vraiment pas cloud. Dans l'idéal, dans du vrai cloud, les instances ne devraient jamais avoir comme pré-requis un système de fichier partagé. Malheureusement, nos amis les développeurs n'ont pour beaucoup toujours pas intégré ce problème.

Il est dommage que WordPress ne sache pas nativement communiquer avec S3 pour y stocker les fichiers partagés (les médias, les thèmes, etc.). Ce problème n'est malheureusement pas propre à WordPress. Rares sont en fait les outils (Magento, Drupal, etc.) réellement cloud-ready. Le problème d'EFS peut donc, paradoxalement être sa trop grande simplicité. Maintenant qu'EFS existe, pourquoi les développeurs s'embêteraient-ils à dépenser temps et argent pour modifier leurs logiciels pour les rendre cloud-friendly ? ...

Si le Cloud a réussi à prouver ses nombreux avantages, force est de constater que les applications - et notamment les CMS les plus connus - nécessitent encore des aménagements pour en tirer le meilleur profit. Avec Amazon EFS, cet effort de "cloudification" de l'applicatif se réduit un peu plus, le reste du chemin pouvant être confié aux équipes d'Osones qui travaillent aux côtés de vos développeurs pour s'assurer du bon respect des best practices. Et une fois que vous profiterez de la même infrastructure que le géant mondial du e-commerce, qui vous arrêtera ?



Alexis GÜNST HORN

C'est à vous de jouer !

Questions, remarques, suggestions... Contactez-nous directement sur Twitter sur @osones !

Pour discuter avec nous de vos projets, nous restons disponibles directement via contact@osones.com ou via le chat !

- Encore un peu de temps ? Parcourez nos dossiers :

A la découverte d'AWS Lambda

AWS Lambda


A la découverte d'Amazon DynamoDB Streams

Amazon DynamoDB


Container as a Service avec Amazon EC2 Container Service (ECS)

Amazon ECS


On a testé Amazon Elastic File System (EFS)

Amazon EFS


Rejoignez VOTRE groupe LinkedIn dès maintenant : Utilisateurs Francophones d'Amazon Web Services (AWS).

AWS user group FR

La discussion continue !

Nous attendons vos questions, remarques & mots doux sur notre Twitter :