Forzar la distribución de CloudFront / actualización de archivos

146

Estoy usando Amazon CloudFront para servir archivos estáticos de mis aplicaciones web.

¿No hay forma de decirle a una distribución en la nube que necesita actualizar su archivo o señalar un solo archivo que debería actualizarse?

Amazon recomienda que versione sus archivos como logo_1.gif, logo_2.gif y así sucesivamente como una solución para este problema, pero eso parece una solución bastante estúpida. ¿No hay absolutamente otra manera?

Martín
fuente
Como nota al margen, no creo que sea estúpido nombrar archivos estáticos como ese. Lo hemos estado usando mucho y tener un cambio de nombre automático según la versión del archivo en el control de versiones nos ha ahorrado muchos dolores de cabeza.
eis
1
@eis a menos que el archivo que necesita reemplazar se haya vinculado a 1000 lugares diferentes en línea. Buena suerte al actualizar todos esos enlaces.
Jake Wilson
@Jakobud ¿por qué deberían actualizarse los enlaces en ese caso? se refieren a una versión específica, que no es la última, si el archivo ha cambiado. Si el archivo no se ha cambiado, funcionará como lo hizo antes.
eis
66
En algunos casos, una empresa puede cometer un error al publicar la imagen incorrecta para algo o algún otro tipo de artículo cuando recibe un aviso de eliminación de una firma de abogados y tiene que reemplazar el archivo. Simplemente cargar un nuevo archivo con un nuevo nombre no solucionará ese tipo de problema, que desafortunadamente es un problema que es cada vez más común en estos días.
Jake Wilson el

Respuestas:

134

Buenas noticias. Amazon finalmente agregó una función de invalidación. Ver la referencia de la API .

Esta es una solicitud de muestra de la Referencia de 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>
James Lawruk
fuente
9
Tenga en cuenta que la invalidación llevará algún tiempo (aparentemente 5-30 minutos según algunas publicaciones de blog que he leído).
Michael Warkentin
37
Si no desea realizar una solicitud de API usted mismo, también puede iniciar sesión en la consola de Amazon y crear una solicitud de invalidación
j0nes
Para aquellos de ustedes que usan la API para hacer la invalidación, ¿aproximadamente cuánto tiempo tarda en surtir efecto la invalidación?
ill_always_be_a_warriors
20
Recuerde que esto cuesta $ 0.005 por archivo después de sus primeras 1,000 solicitudes de invalidación por mes aws.amazon.com/cloudfront/pricing
TimS
1
@MichaelWarkentin Después de realizar una createInvalidationsolicitud de API , sigo viendo que la actualización tarda entre 5 y 10 minutos en invalidarse. Observe que escribo este comentario 4 años después del suyo.
Tim Peterson
19

A partir del 19 de marzo, Amazon ahora permite que el TTL de caché de Cloudfront sea de 0 segundos, por lo que (en teoría) nunca debería ver objetos obsoletos. Entonces, si tiene sus activos en S3, simplemente puede ir a AWS Web Panel => S3 => Editar propiedades => Metadatos, luego configure su valor "Cache-Control" en "max-age = 0".

Esto es directamente de la documentación de la API :

Para controlar si CloudFront almacena en caché un objeto y durante cuánto tiempo, le recomendamos que use el encabezado Cache-Control con la directiva max-age =. CloudFront almacena en caché el objeto durante el número de segundos especificado. (El valor mínimo es de 0 segundos).

John K. Chow
fuente
¿Dónde está esta configuración en la nueva interfaz de usuario de la consola de AWS? No puedo encontrarlo
ill_always_be_a_warriors
1
Encontré la configuración para un archivo individual, pero ¿hay alguna configuración para que todo lo que se cargue en mi bucket tenga un TTL de 0?
ill_always_be_a_warriors
Si bien definitivamente también estaría interesado en una configuración de cubeta, encontré que esta es una solución más rápida / mejor. Las solicitudes de invalidación (junto con el resto de la API) son muy confusas y están mal documentadas, y hice girar mis ruedas durante 3 horas antes de que esto funcionara instantáneamente.
Two-Bit Alchemist
33
Llámame loco, pero establecer TTL en 0 y max-age en 0 realmente está usando CloudFront sin almacenamiento en caché, ¿eso no reenviaría todas las solicitudes al origen constantemente buscando actualizaciones? ¿Esencialmente hacer que la CDN sea inútil?
acidjazz
66
Si solo usa Cloudfront como mecanismo para tener un sitio S3 habilitado para SSL estático con un dominio personalizado, entonces el almacenamiento en caché no importa. Además, estos problemas que estamos discutiendo es que en las fases de desarrollo el almacenamiento en caché de 0 tiempos es bueno.
Dan G
10

Con la API de invalidación, se actualiza en unos minutos.
Echa un vistazo a PHP Invalidator .

anjanesh
fuente
Esto es exactamente lo que estaba buscando. ¡Voy a conectar esto en los web-hook de Beanstalkapp cuando se implemente automáticamente desde git! Gracias por el enlace!
cointilt
10

Configuración de actualización automatizada en 5 minutos

Ok muchachos. La mejor manera posible por ahora de realizar una actualización automática de CloudFront (invalidación) es crear la función Lambda que se activará cada vez que se cargue cualquier archivo en el depósito S3 (uno nuevo o reescrito).

Incluso si nunca antes usó las funciones lambda, es realmente fácil: solo siga mis instrucciones paso a paso y tomará solo 5 minutos:

Paso 1

Vaya a https://console.aws.amazon.com/lambda/home y haga clic en Crear una función lambda

Paso 2

Haga clic en Función en blanco (personalizada)

Paso 3

Haga clic en el cuadro vacío (con trazos) y seleccione S3 del combo

Paso 4

Seleccione su Bucket (igual que para la distribución CloudFront)

Paso 5

Establezca un Tipo de evento en "Objeto creado (todo)"

Paso 6

Establezca Prefijo y Sufijo o déjelo vacío si no sabe qué es.

Paso 7

Marque la casilla de verificación Activar activador y haga clic en Siguiente

Paso 8

Asigne un nombre a su función (algo así como: YourBucketNameS3ToCloudFrontOnCreateAll )

Paso 9

Seleccione Python 2.7 (o posterior) como tiempo de ejecución

Paso 10

Pegue el siguiente código en lugar del código predeterminado de Python:

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())
            })

Paso 11

Abra https://console.aws.amazon.com/cloudfront/home en una nueva pestaña del navegador y copie su ID de distribución de CloudFront para usar en el siguiente paso.

Paso 12

Regrese a la pestaña lambda y pegue su identificación de distribución en lugar de _YOUR_DISTRIBUTION_ID_ en el código de Python. Mantenga las citas circundantes.

Paso 13

Establecer controlador : lambda_function.lambda_handler

Paso 14

Haga clic en el cuadro combinado de roles y seleccione Crear un rol personalizado . Se abrirá una nueva pestaña en el navegador.

Paso 15

Haga clic en ver documento de política , haga clic en editar , haga clic en Aceptar y reemplace la definición de rol con lo siguiente (como está):

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

Paso 16

Haga clic en permitir . Esto te devolverá a una lambda. Verifique que el nombre del rol que acaba de crear esté seleccionado en el cuadro combinado de roles existentes .

Paso 17

Establezca Memoria (MB) en 128 y Tiempo de espera en 5 segundos.

Paso 18

Haga clic en Siguiente , luego haga clic en Crear función

Paso 19

tú eres bueno para irte. Ahora, cada vez que cargue / vuelva a cargar cualquier archivo en S3, se evaluará en todas las ubicaciones de CloudFront Edge.

PD: cuando esté probando, asegúrese de que su navegador esté cargando imágenes desde CloudFront, no desde la memoria caché local.

PSS: tenga en cuenta que solo los primeros 1000 archivos de invalidación por mes son gratuitos, cada invalidación por encima del límite cuesta $ 0.005 USD. También se pueden aplicar cargos adicionales por la función Lambda, pero es extremadamente barato.

Kainax
fuente
¿Solo el último artículo de cada lote S3?
Phil
@Phil El código está escrito de esa manera, por lo que solo se invalidarán los archivos recién cargados, no un paquete completo. En caso de que se carguen varios archivos, cada uno de ellos se invalidará por separado. Funciona de maravilla.
Kainax
La única razón por la que este código funciona como se espera es porque S3 actualmente solo incluye un elemento por notificación, es decir, la longitud de la matriz siempre es feliz 1 y, en consecuencia, incluso si carga varios archivos de una vez, recibe una notificación completamente nueva por archivo No recibe una notificación para todo el depósito en ningún caso. No obstante, este código tal como está escrito no está listo si AWS cambia ese comportamiento. Es mucho más seguro escribir código que maneje toda la matriz, independientemente de la longitud, que era mi punto original (lamentablemente perdido).
Phil
La única razón por la que AWS agrega controladores de eventos es ... bueno ... para manejar eventos. ¿Por qué lo quitarían? No importa cómo se haya agregado un nuevo archivo, debería desencadenar un evento para API y así es como funciona ahora y seguirá funcionando. Estoy usando AWS durante 4 años y nunca cambiaron algo, por lo que el código anterior dejó de funcionar. Incluso si cambian la API, cambian una nueva versión independiente, pero todas las versiones anteriores siempre son compatibles. En ese caso particular, simplemente no creo que el evento de archivo personal se elimine nunca. Probablemente ya sea utilizado por millones de proyectos en todo el mundo.
Kainax
En caso de que malinterprete su primer comentario y quiera decir que 'Cantidad': 1 agregará solo el último elemento: hay un bucle FOR para cada elemento de la matriz.
Kainax
9

Bucket Explorer tiene una interfaz de usuario que hace que esto sea bastante fácil ahora. Así es cómo:

Haz clic derecho en tu cubo. Seleccione "Administrar distribuciones".
Haga clic derecho en su distribución. Seleccione "Obtener lista de invalidación de Cloudfront" Luego seleccione "Crear" para crear una nueva lista de invalidación. Seleccione los archivos para invalidar y haga clic en "Invalidar". Espera de 5 a 15 minutos.

Leopd
fuente
4

Si tiene instalado boto (que no es solo para Python, sino que también instala un montón de útiles utilidades de línea de comando), ofrece una utilidad de línea de comando específicamente llamada cfadmino 'administrador frontal de nube' que ofrece la siguiente funcionalidad:

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

Usted invalia las cosas ejecutando:

$sam# cfadmin invalidate <distribution> <path>
samuraisam
fuente
En realidad, cfadmin es una herramienta muy útil, especialmente si necesita restablecer el caché de CloudFront desde el script de implementación de consola \ bash \ travis ci. Por cierto, aquí está la publicación sobre cómo restablecer \ invalidar la memoria caché de CoudFront durante el despliegue de travis a aws
Mikita Manko
3

Simplemente publique para informar a cualquiera que visite esta página (primer resultado en 'Actualización de archivo de Cloudfront') que hay un acceso + fácil de usar invalidante en línea disponible en swook.net

Este nuevo invalidador es:

  • Totalmente en línea (sin instalación)
  • Disponible 24x7 (alojado por Google) y no requiere ninguna membresía.
  • Hay soporte de historial y verificación de ruta para permitirle invalidar sus archivos con facilidad. (¡A menudo con solo unos pocos clics después de invalidar por primera vez!)
  • También es muy seguro, como descubrirá al leer su publicación de lanzamiento .

Divulgación completa: hice esto. ¡Que te diviertas!

se desmayó
fuente
2
lo siento, pero incluso "usted dice" las credenciales no almacenadas o filtradas ... uno nunca debe dar su credencial a un tercero. ¿Se puede implementar una autenticación remota de Amazon o algo así?
d.raev
Deberías poner esto detrás de https como mínimo.
Oliver Tynes
Las herramientas en línea son generalmente buenas, pero proporcionar credenciales a herramientas de terceros será una preocupación de seguridad válida. Sugeriría usar la consola web oficial o la herramienta oficial de CLI .
RayLuo
2
Por la seguridad de los demás, estoy rechazando esta respuesta. Nunca debes pedirle a la gente sus credenciales
Moataz Elmasry
3

Una forma muy fácil de hacerlo es el versionado de CARPETA.

Entonces, si sus archivos estáticos son cientos, por ejemplo, simplemente colóquelos en una carpeta llamada por año + versiones.

por ejemplo, uso una carpeta llamada 2014_v1 donde dentro tengo todos mis archivos estáticos ...

Entonces, dentro de mi HTML, siempre pongo la referencia a la carpeta. (por supuesto, tengo un PHP incluido donde configuré el nombre de la carpeta). Entonces, al cambiar en 1 archivo, en realidad cambia en todos mis archivos PHP ...

Si quiero una actualización completa, simplemente cambio el nombre de la carpeta a 2014_v2 en mi fuente y cambio dentro de php include a 2014_v2

todos los HTML cambian automáticamente y solicitan la nueva ruta, el caché MISS frente a la nube y lo solicitan a la fuente.

Ejemplo: SOURCE.mydomain.com es mi fuente, cloudfront.mydomain.com es CNAME para la distribución de cloudfront.

Entonces, PHP llamó a este archivo cloudfront.mydomain.com/2014_v1/javascript.js y cuando quiero una actualización completa, simplemente cambio el nombre de la carpeta a la fuente a "2014_v2" y cambio la inclusión de PHP configurando la carpeta a "2014_v2" .

¡Así no hay demora por invalidación y SIN COSTO!

Esta es mi primera publicación en stackoverflow, ¡espero que lo haya hecho bien!

MarcoP
fuente
2

En rubí, usando la gema de niebla

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

incluso en caso de invalidación, la invalidación demora entre 5 y 10 minutos en procesarse y actualizarse en todos los servidores amazon edge

raycchan
fuente
¡Acabas de salvarme la vida!
Fábio Batista
2

Invalidación de soporte de AWS CLI actual en modo de vista previa. Ejecute lo siguiente en su consola una vez:

aws configure set preview.cloudfront true

Implemento mi proyecto web usando npm. Tengo los siguientes scripts en mi 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"
}

Con las secuencias de comandos anteriores, puede implementar su sitio con:

npm run deploy
Dmitry Efimenko
fuente
1
Creo que necesita el asterisco en su comando 'aws.invalidate', cambie --paths /a --paths /*. el mío también era como el tuyo y no invalidaba la distribución ...
Herald Smit
1

Si está utilizando AWS, probablemente también use su herramienta oficial de CLI (tarde o temprano). AWS CLI versión 1.9.12 o superior admite la invalidación de una lista de nombres de archivo.

Divulgación completa: hice esto. ¡Que te diviertas!

RayLuo
fuente
Enlace inactivo: conduce a un 404 :( y no puedo actualizarlo ya que falta la versión 1.9.12 en las notas de la versión ( aws.amazon.com/releasenotes/?tag=releasenotes%23keywords%23cli )
SlyDave
Amigo, thtat era una versión lanzada hace casi 3 años. Pruebe la última versión y es probable que la función todavía esté allí. (
Divulgación
oh, lo sé, me pareció extraño que de todas las notas de lanzamiento, solo 1.9.12 no exista: D (que es a lo que me refería sobre no poder actualizar el enlace). El comentario fue más una pista para cualquiera que haya encontrado el camino hasta aquí, como yo lo hice y necesitaba encontrar las notas de liberación de AWS CLI. sin daño, sin falta.
SlyDave
0

Ve a CloudFront.

Haga clic en su ID / Distribuciones.

Haga clic en invalidaciones.

Haga clic en crear invalidación.

En el cuadro de ejemplo gigante, escriba * y haga clic en invalidar

Hecho

ingrese la descripción de la imagen aquí

Arrendajo
fuente