Forcer la mise à jour de la distribution / du fichier CloudFront


146

J'utilise CloudFront d'Amazon pour servir des fichiers statiques de mes applications Web.

N'existe-t-il aucun moyen d'indiquer à une distribution cloudfront qu'elle doit actualiser son fichier ou de signaler un seul fichier à actualiser?

Amazon vous recommande de version vos fichiers comme logo_1.gif, logo_2.gif et ainsi de suite pour contourner ce problème, mais cela semble être une solution assez stupide. N'y a-t-il absolument pas d'autre moyen?



en passant, je ne pense pas que ce soit stupide de nommer des fichiers statiques comme ça. Nous l'avons beaucoup utilisé et le changement de nom automatisé selon la version du fichier dans le contrôle de version nous a évité beaucoup de maux de tête.
eis

1
@eis sauf si le fichier que vous devez remplacer a été lié à 1000 emplacements différents en ligne. Bonne chance pour mettre à jour tous ces liens.
Jake Wilson

@Jakobud pourquoi les liens devraient-ils être mis à jour dans ce cas? ils font référence à une version spécifique, qui n'est pas la dernière, si le fichier a été modifié. Si le fichier n'a pas été modifié, il fonctionnera comme avant.
eis le

6
Dans certains cas, une entreprise peut commettre une erreur en affichant la mauvaise image pour quelque chose ou un autre type d'article où elle reçoit un avis de retrait d'un cabinet d'avocats et doit remplacer le fichier. Le simple téléchargement d'un nouveau fichier avec un nouveau nom ne résoudra pas ce genre de problème, qui est malheureusement un problème de plus en plus courant de nos jours.
Jake Wilson

Réponses:


134

Bonnes nouvelles. Amazon a finalement ajouté une fonctionnalité d'invalidation. Consultez la référence API .

Voici un exemple de demande de la référence API:

POST /2010-08-01/distribution/[distribution ID]/invalidation HTTP/1.0
Host: cloudfront.amazonaws.com
Authorization: [AWS authentication string]
Content-Type: text/xml

<InvalidationBatch>
   <Path>/image1.jpg</Path>
   <Path>/image2.jpg</Path>
   <Path>/videos/movie.flv</Path>
   <CallerReference>my-batch</CallerReference>
</InvalidationBatch>

9
Veuillez noter que l'invalidation prendra un certain temps (apparemment 5 à 30 minutes selon certains articles de blog que j'ai lus).
Michael Warkentin

37
Si vous ne souhaitez pas faire de demande d'API vous-même, vous pouvez également vous connecter à Amazon Console et y créer une demande d'invalidation: docs.amazonwebservices.com/AmazonCloudFront/latest/…
j0nes

Pour ceux d'entre vous qui utilisent l'API pour faire l'invalidation, combien de temps environ faut-il pour que l'invalidation prenne effet?
ill_always_be_a_warriors

20
N'oubliez pas que cela coûte 0,005 USD par fichier après vos 1000 premières demandes d'invalidation par mois aws.amazon.com/cloudfront/pricing
TimS

1
@MichaelWarkentin Après avoir fait une createInvalidationrequête API , je vois toujours que la mise à jour prend 5 à 10 minutes environ pour être invalidée. Remarquez que j'écris ce commentaire 4 ans après le vôtre.
tim peterson

19

Depuis le 19 mars, Amazon autorise désormais la durée de vie du cache de Cloudfront à 0 seconde, vous ne devriez donc (théoriquement) jamais voir d'objets périmés. Donc, si vous avez vos actifs dans S3, vous pouvez simplement accéder à AWS Web Panel => S3 => Modifier les propriétés => Métadonnées, puis définir votre valeur "Cache-Control" sur "max-age = 0".

Cela vient directement de la documentation de l' API :

Pour contrôler si CloudFront met en cache un objet et pendant combien de temps, nous vous recommandons d'utiliser l'en-tête Cache-Control avec la directive max-age =. CloudFront met en cache l'objet pendant le nombre de secondes spécifié. (La valeur minimale est de 0 seconde.)


Où se trouve ce paramètre dans la nouvelle interface utilisateur de la console AWS? Je ne peux pas le trouver.
ill_always_be_a_warriors

1
J'ai trouvé le paramètre pour un fichier individuel, mais y a-t-il un paramètre pour que tout ce qui est téléchargé dans mon compartiment ait un TTL de 0?
ill_always_be_a_warriors

Bien que je serais également certainement intéressé par un paramètre à l'échelle du seau, j'ai trouvé que c'était une solution plus rapide / meilleure. Les demandes d'invalidation (ainsi que le reste de l'API) sont très déroutantes et mal documentées, et j'ai fait tourner mes roues pendant 3 heures avant que cela ne fonctionne instantanément.
Two-Bit Alchemist

33
Appelez-moi fou, mais définir le TTL sur 0 et l'âge max sur 0 utilise vraiment CloudFront sans mise en cache, cela ne transmettrait-il pas toutes les demandes à l'origine en vérifiant constamment les mises à jour? Rendant essentiellement le CDN inutile?
acidjazz

6
Si vous utilisez simplement cloudfront comme mécanisme pour avoir un site S3 statique compatible SSL avec un domaine personnalisé, la mise en cache n'a pas d'importance. En outre, ces problèmes dont nous discutons sont que dans les phases de développement, la mise en cache à 0 temps est bonne.
Dan G

10

Avec l'API d'invalidation, il est mis à jour en quelques minutes.
Découvrez PHP Invalidator .


Ceci est exactement ce que je cherchais. Je vais accrocher cela dans les web-hooks de Beanstalkapp lors du déploiement automatique à partir de git! Merci pour le lien!
cointilt

10

Configuration de la mise à jour automatisée en 5 minutes

Ok les gars. Le meilleur moyen pour l'instant d'effectuer une mise à jour automatique de CloudFront (invalidation) est de créer une fonction Lambda qui sera déclenchée à chaque fois qu'un fichier est téléchargé dans le compartiment S3 (un nouveau ou une réécriture).

Même si vous n'avez jamais utilisé les fonctions lambda auparavant, c'est vraiment facile - suivez simplement mes instructions étape par étape et cela ne prendra que 5 minutes:

Étape 1

Accédez à https://console.aws.amazon.com/lambda/home et cliquez sur Créer une fonction lambda

Étape 2

Cliquez sur Fonction vide (personnalisé)

Étape 3

Cliquez sur la case vide (barrée) et sélectionnez S3 dans le combo

Étape 4

Sélectionnez votre bucket (comme pour la distribution CloudFront)

Étape 5

Définissez un type d'événement sur "Objet créé (tout)"

Étape 6

Définissez le préfixe et le suffixe ou laissez-le vide si vous ne savez pas ce que c'est.

Étape 7

Cochez la case Activer le déclencheur et cliquez sur Suivant

Étape 8

Nommez votre fonction (quelque chose comme: YourBucketNameS3ToCloudFrontOnCreateAll )

Étape 9

Sélectionnez Python 2.7 (ou version ultérieure) comme Runtime

Étape 10

Collez le code suivant au lieu du code Python par défaut:

from __future__ import print_function

import boto3
import time

def lambda_handler(event, context):
    for items in event["Records"]:
        path = "/" + items["s3"]["object"]["key"]
        print(path)
        client = boto3.client('cloudfront')
        invalidation = client.create_invalidation(DistributionId='_YOUR_DISTRIBUTION_ID_',
            InvalidationBatch={
            'Paths': {
            'Quantity': 1,
            'Items': [path]
            },
            'CallerReference': str(time.time())
            })

Étape 11

Ouvrez https://console.aws.amazon.com/cloudfront/home dans un nouvel onglet de navigateur et copiez votre ID de distribution CloudFront pour l'utiliser à l'étape suivante.

Étape 12

Revenez à l'onglet lambda et collez votre ID de distribution au lieu de _VOTRE_DISTRIBUTION_ID_ dans le code Python. Gardez les citations environnantes.

Étape 13

Définir le gestionnaire : lambda_function.lambda_handler

Étape 14

Cliquez sur la liste déroulante des rôles et sélectionnez Créer un rôle personnalisé . Un nouvel onglet dans le navigateur sera ouvert.

Étape 15

Cliquez sur afficher le document de stratégie , cliquez sur modifier , cliquez sur OK et remplacez la définition de rôle par ce qui suit (tel quel):

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws:logs:*:*:*"
    },
    {
      "Effect": "Allow",
      "Action": [
          "cloudfront:CreateInvalidation"
      ],
      "Resource": [
          "*"
      ]
    }
  ]
}

Étape 16

Cliquez sur autoriser . Cela vous ramènera à un lambda. Vérifiez que le nom de rôle que vous venez de créer est sélectionné dans la zone de liste déroulante Rôle existant .

Étape 17

Réglez la mémoire (Mo) sur 128 et le délai d' expiration sur 5 sec.

Étape 18

Cliquez sur Suivant , puis sur Créer une fonction

Étape 19

Tu es prêt! Désormais, chaque fois que vous téléchargerez / remettez en ligne un fichier sur S3, il sera évalué dans tous les emplacements CloudFront Edge.

PS - Lorsque vous testez, assurez-vous que votre navigateur charge des images depuis CloudFront, et non depuis le cache local.

PSS - Veuillez noter que seules les 1000 premières invalidation de fichiers par mois sont gratuites, chaque invalidation dépassant la limite coûte 0,005 USD. Des frais supplémentaires pour la fonction Lambda peuvent également s'appliquer, mais c'est extrêmement bon marché.


Juste le dernier élément de chaque lot S3?
Phil

@Phil Le code est écrit de cette façon, donc seuls les fichiers nouvellement téléchargés seront invalides, pas un compartiment entier. En cas de téléchargement de plusieurs fichiers, chacun d'eux sera invalidé séparément. Fonctionne comme un charme.
Kainax le

La seule raison pour laquelle ce code fonctionne comme prévu est que S3 n'incluait actuellement qu'un seul élément par notification, c'est-à-dire que la longueur du tableau est heureusement toujours 1, et par conséquent, même si vous téléchargez plusieurs fichiers en une seule fois, vous obtenez une notification entièrement nouvelle par fichier. Vous ne recevez en aucun cas une notification pour l'ensemble du bucket. Néanmoins, ce code tel qu'il est écrit n'est pas prêt si AWS modifie ce comportement. Il est beaucoup plus sûr d'écrire du code qui gère tout le tableau, quelle que soit la longueur, ce qui était mon point d'origine (malheureusement manqué).
Phil

La seule raison pour laquelle AWS ajoute des gestionnaires d'événements est ... enfin ... de gérer les événements. Pourquoi le supprimeraient-ils? Quelle que soit la façon dont un nouveau fichier a été ajouté, il devrait déclencher un événement pour l'API et c'est ainsi que cela fonctionne maintenant et continuera de fonctionner. J'utilise AWS depuis 4 ans et ils n'ont jamais changé quelque chose, donc le code précédent a cessé de fonctionner. Même s'ils changent d'API, ils en font une nouvelle version autonome, mais toutes les versions précédentes restent toujours prises en charge. Dans ce cas particulier, je ne crois tout simplement pas que l'événement de fichier personnel sera jamais supprimé. Il est probablement déjà utilisé par des millions de projets dans le monde.
Kainax

Au cas où je ne comprends pas votre premier commentaire et que vous voulez dire que «Quantité»: 1 n'ajoutera que le dernier élément - il y a une boucle FOR pour chaque élément du tableau.
Kainax

9

Bucket Explorer a une interface utilisateur qui rend cela assez facile maintenant. Voici comment:

Faites un clic droit sur votre seau. Sélectionnez «Gérer les distributions».
Cliquez avec le bouton droit sur votre distribution. Sélectionnez «Obtenir la liste d'invalidation Cloudfront», puis sélectionnez «Créer» pour créer une nouvelle liste d'invalidation. Sélectionnez les fichiers à invalider, puis cliquez sur «Invalider». Attendez 5 à 15 minutes.


4

Si vous avez installé boto (ce qui n'est pas seulement pour python, mais installe également un tas d'utilitaires de ligne de commande utiles), il propose un utilitaire de ligne de commande spécifiquement appelé cfadminou `` cloud front admin '' qui offre les fonctionnalités suivantes:

Usage: cfadmin [command]
cmd - Print help message, optionally about a specific function
help - Print help message, optionally about a specific function
invalidate - Create a cloudfront invalidation request
ls - List all distributions and streaming distributions

Vous invalidez des choses en exécutant:

$sam# cfadmin invalidate <distribution> <path>

En fait, cfadmin est un outil très utile, surtout si vous avez besoin de réinitialiser le cache CloudFront à partir du script de déploiement console \ bash \ travis ci. BTW voici le post comment réinitialiser \ invalider le cache CoudFront pendant le déploiement de travis sur aws
Mikita Manko

3

Il suffit de poster pour informer toute personne visitant cette page (premier résultat sur 'Cloudfront File Refresh') qu'il existe un invalidateur en ligne facile à utiliser + accessible disponible sur swook.net

Ce nouvel invalidateur est:

  • Entièrement en ligne (pas d'installation)
  • Disponible 24h / 24 et 7j / 7 (hébergé par Google) et ne nécessite aucun abonnement.
  • Il existe une prise en charge de l'historique et une vérification du chemin pour vous permettre d'invalider facilement vos fichiers. (Souvent en quelques clics seulement après l'invalidation pour la première fois!)
  • Il est également très sécurisé, comme vous le découvrirez en lisant sa publication .

Divulgation complète: j'ai fait ça. S'amuser!


2
désolé, mais même "vous dites" les informations d'identification ne sont pas stockées ou poirées ... il ne faut jamais donner ses informations d'identification à un tiers. Peut-être implémenter une authentification Amazon à distance ou quelque chose?
d.raev

Vous devriez au moins mettre cela derrière https.
Oliver Tynes

Les outils en ligne sont généralement bien, mais fournir des informations d'identification à un outil tiers sera un problème de sécurité valide. Je suggérerais d'utiliser la console Web officielle ou l' outil CLI officiel .
RayLuo

2
Pour la sécurité des autres, je vote contre cette réponse. Vous ne devriez jamais demander aux gens leurs informations d'identification
Moataz Elmasry

3

un moyen très simple de le faire est le contrôle de version FOLDER.

Donc, si vos fichiers statiques sont des centaines par exemple, placez-les simplement tous dans un dossier appelé par année + versioning.

par exemple, j'utilise un dossier appelé 2014_v1 où à l'intérieur j'ai tous mes fichiers statiques ...

Donc, dans mon HTML, je mets toujours la référence au dossier. (bien sûr, j'ai un PHP include où j'ai défini le nom du dossier.) Donc, en changeant dans 1 fichier, il change réellement dans tous mes fichiers PHP.

Si je veux une actualisation complète, je renomme simplement le dossier en 2014_v2 dans ma source et change à l'intérieur du php include en 2014_v2

tout le HTML change automatiquement et demande le nouveau chemin, le cache cloudfront MISS et le demande à la source.

Exemple: SOURCE.mydomain.com est ma source, cloudfront.mydomain.com est CNAME vers la distribution cloudfront.

Donc, le PHP a appelé ce fichier cloudfront.mydomain.com/2014_v1/javascript.js et quand je veux une actualisation complète, je renomme simplement le dossier dans la source en "2014_v2" et je change l'inclusion PHP en définissant le dossier sur "2014_v2" .

Comme ça, il n'y a aucun délai pour l'invalidation et AUCUN FRAIS!

C'est mon premier article dans stackoverflow, j'espère que je l'ai bien fait!



2

En rubis, en utilisant la gemme de brouillard

AWS_ACCESS_KEY = ENV['AWS_ACCESS_KEY_ID']
AWS_SECRET_KEY = ENV['AWS_SECRET_ACCESS_KEY']
AWS_DISTRIBUTION_ID = ENV['AWS_DISTRIBUTION_ID']

conn = Fog::CDN.new(
    :provider => 'AWS',
    :aws_access_key_id => AWS_ACCESS_KEY,
    :aws_secret_access_key => AWS_SECRET_KEY
)

images = ['/path/to/image1.jpg', '/path/to/another/image2.jpg']

conn.post_invalidation AWS_DISTRIBUTION_ID, images

même en cas d'invalidation, il faut encore 5 à 10 minutes pour que l'invalidation soit traitée et actualisée sur tous les serveurs périphériques Amazon


Vous venez de me sauver la vie!
Fábio Batista

2

l'actuelle AWS CLI prend en charge l'invalidation en mode aperçu. Exécutez une fois ce qui suit dans votre console:

aws configure set preview.cloudfront true

Je déploie mon projet Web en utilisant npm. J'ai les scripts suivants dans mon package.json:

{
    "build.prod": "ng build --prod --aot",
    "aws.deploy": "aws s3 sync dist/ s3://www.mywebsite.com --delete --region us-east-1",
    "aws.invalidate": "aws cloudfront create-invalidation --distribution-id [MY_DISTRIBUTION_ID] --paths /",
    "deploy": "npm run build.prod && npm run aws.deploy && npm run aws.invalidate"
}

Après avoir mis en place les scripts ci-dessus, vous pouvez déployer votre site avec:

npm run deploy

1
Je pense que vous avez besoin de l'astérisque dans votre commande 'aws.invalidate', passez --paths /à --paths /*. le mien était aussi comme le vôtre et il n'a pas invalidé la distribution ...
Herald Smit

1

Si vous utilisez AWS, vous utilisez probablement également son outil CLI officiel (tôt ou tard). AWS CLI version 1.9.12 ou supérieure prend en charge l'invalidation d'une liste de noms de fichiers.

Divulgation complète: j'ai fait ça. S'amuser!


Lien mort - mène à un 404: (et je ne peux pas le mettre à jour car la version 1.9.12 est absente des notes de publication ( aws.amazon.com/releasenotes/?tag=releasenotes%23keywords%23cli )
SlyDave

Mec, thtat était une version sortie il y a presque 3 ans. Essayez la dernière version et la fonctionnalité est probablement toujours là. (Divulgation complète: je ne travaille plus sur AWS CLI.)
RayLuo

oh je sais, juste trouvé étrange que de toutes les notes de publication, seulement 1.9.12 n'existe pas: D (c'est ce à quoi je voulais en venir à propos de ne pas pouvoir mettre à jour le lien). Le commentaire était plus un indice pour tous ceux qui s'y trouvaient, comme je l'ai fait et qui avaient besoin de trouver les notes de publication pour l'AWS CLI. pas de mal, pas de faute.
SlyDave

0

Accédez à CloudFront.

Cliquez sur votre ID / Distributions.

Cliquez sur Invalidations.

Cliquez sur créer une invalidation.

Dans la boîte d'exemple géante, tapez * et cliquez sur invalider

Terminé

entrez la description de l'image ici

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.