Aller au contenu

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.

docker login -u readregcred registry.gitlab.com

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 :

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.