S3
Concepts
S3
Amazon Simple Storage Service (Amazon S3) est l'un des premiers services d'AWS.
C'est un service de stockage objet. On stocke nos objets dans des Buckets. Un objet est un fichier plus ses méta-données.
Note
Les noms de buckets sont uniques de façon globale, pas uniquement pour un compte AWS mais bien pour tous les comptes.
Un bucket nommé mon-bucket
aura pour api mon-bucket.s3.amazonaws.com
qui est bien globale.
C'est une des raisons qui font que S3 est un service global, mais attention un bucket et ses objets sont bien dans une région.
D'ailleurs AWS privilégie voire force l'usage de endpoints régionaux comme mon-bucket.s3.eu-west-3.amazonaws.com
Chaque objet a une clé qui est son identifiant unique au sein du bucket.
Par exemple, si assets/logo.png
est une clé d'un objet dans un bucket mon-bucket
dans la région de Paris,
on peut accéder à l'objet en question sur l'URL https://mon-bucket.s3.eu-west-3.amazonaws.com/assets/logo.png
On peut activer sur un bucket le versioning qui permet de prévenir d'éventuelles suppressions involontaires et de
conserver des versions de l'objet pour potentiellement y revenir. On peut dans ce cas avoir un delete marker
qui
indique pour une clé que l'objet est supprimé, mais permet de conserver ses versions.
Avec ses fonctionnalités s3 peut couvrir beaucoup d'usages, du simple stockage/archivage pour des contenus applicatifs web jusqu'au Big Data/datalake.
Storage class
S3 dispose de multiples Storage class
permettant de répondre à plusieurs besoins.
Chaque storage class est définie par plusieurs critères :
- Durabilité
- Disponibilité
- Redondance
- Temps de récupération
- Prix
La storage class d'un objet se choisi en fonction de ces critères et le pattern d'usage de l'objet. On part de la classe standard pour aller vers celles Glacier. La classe standard a une durabilité de 99,999999999% (11 9s) et une disponibilité de 99,99 % des objets sur une année donnée. Plus de détails sur les classes ici
Note
Il y a des classes Glacier mais Glacier est aussi un autre service AWS pour faire de l'archivage objet long terme.
On peut définir des lifecycle configurations
permettant de soit supprimer des groupes d'objets ou les faire passer
d'une classe à l'autre en fonctions de leur âge, taille, version, etc.
Cela permet d'optimiser les coûts de notre bucket.
On peut par exemple faire automatiquement "expirer" notre objet après 30 jours puis le supprimer après 1an, ou encore archiver un rapport après 30 jours, etc.
Voici liste des classes et leurs transitions possibles.
Plus de détails sur le pricing ici
Consistence des données
Par le passé s3 avait une consistence éventuelle, mais désormais l'API offre ce que l'on appelle une forte consistence
read-after-write
pour les PUT et DELETE d'objets.
Cela implique qu'après un ajout, changement ou suppression les lectures LIST ou GET sont cohérentes.
Gestion d'accès
S3 est une API publique exposée sur internet. Il faut faire attention aux configurations d'accès des objets et respecter le principe de moindre privilège.
La gestion d'accès à nos bucket peut se faire de plusieurs façons différentes :
- Via des policies IAM
- Via une bucket policy, c'est-à-dire un
resourced based iam policy
- Via des ACLs sur les buckets ou objets
Note
S3 et ces ACLs existaient avant la création d'IAM, le service de gestion de droits d'AWS. Elles ont été gardées pour des raisons de rétrocompatibilité et pour des besoins très spécifiques.
Il est conseillé de façon générale d'utiliser de façon générale les policies IAM ou bucket policies et pas les ACLs. Cela simplifie également l'audit.
Plus de détails sur la gestion d'accès S3 sur la doc ou ce blog.
Notons également qu'il est possible de générer ce que l'on appelle des Pre-signed urls
qui permettent de générer des
url/liens pour les objets permettant d'inclure une authentification temporaire et dédié à l'objet en question.
Cela fonctionne pour un GET mais il est aussi possible de faire cela pour du PUT.
Ainsi, on peut via un microservice ou API pre-signer les url afin que les objets soient affichables dans un site
sans avoir à ouvrir tout le bucket.
Utiliser les Pre-signed urls
pour l'upload permet aussi que le client envoie directement son objet sans avoir à le
faire transiter sur notre backend, ce qui économise de la bande passante.
Website hosting
S3 permet de servir nos sites web statiques. C'est une option que l'on active et pour laquelle configure un document index qui sera la page par défault et potentiellement une page d'erreur et des règles de redirections.
Une fois l'option activée, nous pouvons visualiser notre site sur http://bucket-name.s3-website-Region.amazonaws.com
ou http://bucket-name.s3-website.Region.amazonaws.com
en fonction de la région.
On peut ensuite si l'on veut utiliser notre propre domaine en configurant un
CNAME. Par contre S3 ne supporte pas directement de servir en HTTPS, pour cela AWS recommande d'utiliser CloudFront.
AWS résume les différences entre utiliser l'API REST de S3 directement ou passer par les endpoint s3-website
ici.
Note
Il y a encore beaucoup de fonctionnalités et configurations que l'on ne mentionne pas ici:
- Multi-part upload
- Event notifications (SNS / SQS / Lambda / EventBridge)
- S3 Object Lock
- S3 Select
- S3 Replication
- S3 Access Points
- S3 Express One Zone
- S3 Transfer Acceleration
- S3 Gateway Endpoint pour optimiser les coûts
- Requester Pays
- Monitoring / analyse du bucket et de son usage
- Et beaucoup, plus
TP
À vous de jouer
Le but de cette étape est donc de se servir de la fonctionnalité de s3 de servir des sites statiques. Ça tombe bien notre frontend CDB en est un ! C'est même un SPA, single-page application, angular.
Commencez par copier votre dossier précédent en un nouveau dossier nommé Step5
On va ensuite récupérer le contenu du site web.
Pour cela, vous devez avoir docker
et faire un docker login
avec le mot de passe fourni et mis dans les user-data.
Pour éviter que chacun prenne un code source et fasse sa compilation angular, nous allons pull l'image et en extraire
le dossier contenant les fichiers web dans un dossier generated-templates
.
docker run -d --rm --name extract -e API_URL=extact registry.gitlab.com/takima-school/images/cdb/www:latest;
docker cp extract:/usr/share/nginx/html/ generated-templates;
docker stop extract
Nous allons nous servir du module
hashicorp/dir/template.
Celui-ci a pour gros avantage de nous extraire le content-type nécessaire afin que s3 serve correctement les objets pour
notre site web.
Ici ce que vous avez récupéré est déjà un template.
Jusqu'ici, c'était l'entry-point de l'image docker remplaçait dans le main.xxx.js
le @{API_URL}
par la valeur de la
variable d'environnement.
Déclarez votre bucket et ces différentes configurations :
- aws_s3_bucket
-
aws_s3_bucket_public_access_block
block_public_policy
etrestrict_public_buckets
désactivés car nous voulons ouvrir notre site web - aws_s3_bucket_policy (pas d'ACLs) avec la policy suivante
- aws_s3_bucket_website_configuration
- Vous pouvez supprimer vos anciennes resources ASG/ELB/security groups frontend !
Note
Le module hashicorp/dir/template
permet de résourdre des template terraform mais ici notre site n'en est pas un.
Pour remplacer l'API_URL et envoyer les objets dans le bucket voici le snipet :
module "template_files" {
source = "hashicorp/dir/template"
version = "1.0.2"
base_dir = "generated-templates"
}
resource "aws_s3_object" "site" {
for_each = module.template_files.files
bucket = aws_s3_bucket.frontend.id
key = each.key
content = endswith(each.key, ".js") ? replace(file(each.value.source_path), "@{API_URL}", local.backend_endpoint) : null
source = endswith(each.key, ".js") ? null : each.value.source_path
content_type = each.value.content_type
}
Success
Accédez au endpoint fourni par s3 en xxx.s3-website.eu-west-3.amazonaws.com
Vous avez découvert s3 et pu servir votre frontend avec et tout cela serverless !
Note
S3 tout seul a quelques soucis pour servir une SPA, single-page application. Cela peut se remarquer si on refresh une page par exemple. CloudFront aidera à résoudre ce soucis. Plus de détails sur ce thread.
Bonus
Nom de domaine
Certes notre site fonctionne avec l'endpoint fourni par s3 xxx.s3-website.eu-west-3.amazonaws.com
mais on préférait
y accéder avec notre joli www.xxx.formation.takima.school comme avant.
Note
Pour que s3 serve vos requêtes directement sur votre domaine il faut que le nom du bucket soit le FQDN de votre site et renvoyer votre record route53 vers S3.