Einführung
Eine Version kann korrekt in S3 gespeichert sein, während die Distribution noch eine ältere Kopie liefert. Steuere die Cache-Dauer, beobachte Wiederverwendung und Ablauf und invalidiere nur den Pfad der aktualisierten Seite. Behalte den Cache eines zweiten Objekts und den privaten Ursprung bei.
Schließe zuerst das Labor zur Bereitstellung privater S3-Inhalte ab. Diese unabhängige VM stellt einen neuen privaten Bucket, OAC, eine Distribution und die passende Bucket-Richtlinie bereit. Ressourcen früherer VMs werden nicht wiederverwendet. Anfangs ist Caching deaktiviert; es gibt keine Viewer-Anfragen oder Invalidierungen. Vorbereitete Dateien lassen dich auf das Cache-Verhalten konzentrieren. Beobachte den tatsächlichen Zustand oben in AWS View und führe unten in Terminal Befehle aus. Ein persönliches AWS-Konto oder eine öffentliche Domain ist nicht erforderlich.
Zertifizierungsziele
| Zertifizierung | Prüfungsaufgabe | Übung |
|---|---|---|
| Solutions Architect – Associate (SAA-C03) | Aufgabe 3.4 | CloudFront-Inhaltsbereitstellung und den Einfluss der Cache-Dauer auf Lesezugriffe am Ursprung üben. |
Laborübersicht

Wiederverwendung und Ablauf des Caches beobachten
In diesem Schritt legst du eine kurze Cache-Dauer fest, um einen Cache-Treffer von einem erneuten Lesezugriff am Ursprung zu unterscheiden.
Ein Cache speichert eine Kopie für spätere Anfragen. Die TTL ist ihre Gültigkeitsdauer in Sekunden. Cache-Control: max-age des Objekts gibt die Dauer vor. Minimale und maximale TTL der Distribution begrenzen sie; die Standard-TTL gilt, wenn der Ursprung keine Dauer angibt. Hier verwendest du die normalen Distributionseinstellungen ohne separate Cache-Richtlinie.
Ermittle die vorbereitete Distribution. --query wählt die Distribution mit dem Laborkommentar aus; $(...) speichert ID oder Domain in einer Shell-Variablen. Halte Terminal geöffnet. Sieh dir den unabhängigen Referenz-Bucket an, ohne ihn zu verändern:
cd /home/labex/project
DIST_ID=$(aws cloudfront list-distributions \
--query "DistributionList.Items[?Comment=='labex-n03:private-content'].Id | [0]" \
--output text)
DIST_DOMAIN=$(aws cloudfront get-distribution \
--id "$DIST_ID" \
--query Distribution.DomainName \
--output text)
aws s3api list-buckets \
--query 'Buckets[].Name'
Lies die aktuelle Konfiguration und ihren ETag, die Versionskennung für eine sichere Aktualisierung. > schreibt die Ausgabe in eine Datei. sed ändert nur die beiden TTL-Eigenschaften, die in der vorbereiteten Konfiguration null sind; die minimale TTL bleibt null. Der neue Maximalwert erlaubt später längere Dauern:
aws cloudfront get-distribution-config \
--id "$DIST_ID" \
--query DistributionConfig > current-config.json
ETAG=$(aws cloudfront get-distribution-config \
--id "$DIST_ID" \
--query ETag \
--output text)
sed -e 's/"DefaultTTL": 0/"DefaultTTL": 6/' -e 's/"MaxTTL": 0/"MaxTTL": 3600/' current-config.json > cached-config.json
aws cloudfront update-distribution \
--id "$DIST_ID" \
--if-match "$ETAG" \
--distribution-config file://cached-config.json
aws cloudfront wait distribution-deployed \
--id "$DIST_ID"
Lade die vorbereitete erste Version mit sechs Sekunden Gültigkeit hoch. Behalte den Inhaltstyp text/html bei:
aws s3api put-object \
--bucket labex-n03-content \
--key index.html \
--body index.html \
--content-type text/html \
--cache-control 'max-age=6'
curl --include zeigt Header und Antwortinhalt. --resolve leitet den tatsächlichen Distributionsnamen zum Viewer-Endpunkt dieser VM, ohne das System-DNS zu verändern. Führe beide Anfragen direkt hintereinander aus, damit die zweite vor Ablauf der sechs Sekunden eintrifft:
curl --fail --include --noproxy '*' --resolve "${DIST_DOMAIN}:8082:127.0.0.1" "http://${DIST_DOMAIN}:8082/index.html"
curl --fail --include --noproxy '*' --resolve "${DIST_DOMAIN}:8082:127.0.0.1" "http://${DIST_DOMAIN}:8082/index.html"
Die erste zeigt X-Cache: Miss from cloudfront, die zweite Hit from cloudfront; beide liefern Release one. Ein Treffer verwendet gespeicherte Bytes ohne erneuten Ursprungszugriff. Age zeigt das Alter der Kopie; unmittelbar aufeinanderfolgende Anfragen können beide null Sekunden anzeigen.
sleep 7 lässt die sechs Sekunden gültige Kopie ablaufen. Frage danach erneut an:
sleep 7
curl --fail --include --noproxy '*' --resolve "${DIST_DOMAIN}:8082:127.0.0.1" "http://${DIST_DOMAIN}:8082/index.html"
Erwarte einen weiteren Cache-Miss mit derselben Seite. Der Ablauf führt bei der nächsten Anfrage zum erneuten Ursprungszugriff; er löscht nicht das S3-Objekt. AWS View zeigt tatsächliche Anfragen und Ursprungszugriffe. Führe die Prüfung aus, bevor du fortfährst.

Eine Aktualisierung hinter einer Cache-Kopie beobachten
In diesem Schritt lädst du eine neue Version hoch und beobachtest, warum ein bestehender Cache weiterhin alte Inhalte liefert.
Längere Dauern erleichtern die Beobachtung. Lade die erste Seite erneut mit max-age=900 und das unabhängige Objekt stable.txt mit max-age=3600 hoch. Die maximale TTL von 3600 erlaubt beide Werte:
aws s3api put-object \
--bucket labex-n03-content \
--key index.html \
--body index.html \
--content-type text/html \
--cache-control 'max-age=900'
aws s3api put-object \
--bucket labex-n03-content \
--key stable.txt \
--body stable.txt \
--content-type text/plain \
--cache-control 'max-age=3600'
Geänderte Ursprungsmetadaten ändern eine bereits gespeicherte Antwort nicht rückwirkend. Warte auf den Ablauf der alten Sechs-Sekunden-Kopie und fülle anschließend den Cache beider Pfade:
sleep 7
curl --fail --include --noproxy '*' --resolve "${DIST_DOMAIN}:8082:127.0.0.1" "http://${DIST_DOMAIN}:8082/index.html"
curl --fail --include --noproxy '*' --resolve "${DIST_DOMAIN}:8082:127.0.0.1" "http://${DIST_DOMAIN}:8082/stable.txt"
Beide Anfragen zeigen einen Miss und lesen die aktuellen Ursprungsobjekte. Die Seite enthält nun Cache-Control: max-age=900. Schließe die nächsten beiden Schritte innerhalb dieser fünfzehn Minuten ab.
Die vorbereitete Datei release-two.html enthält die geänderte Seite. Lade sie unter demselben Objektschlüssel hoch und behalte Inhaltstyp und Dauer bei. Lies das Objekt mit der authentifizierten S3-CLI in origin-release.html, um die tatsächlichen Bytes zu sehen:
cat release-two.html
aws s3api put-object \
--bucket labex-n03-content \
--key index.html \
--body release-two.html \
--content-type text/html \
--cache-control 'max-age=900'
aws s3api get-object \
--bucket labex-n03-content \
--key index.html origin-release.html
cat origin-release.html
Der Ursprung enthält Release two. Rufe denselben Pfad über die Distribution ab:
curl --fail --include --noproxy '*' --resolve "${DIST_DOMAIN}:8082:127.0.0.1" "http://${DIST_DOMAIN}:8082/index.html"
Erwarte einen Hit mit Release one. Der Upload war erfolgreich, aber die Viewer-Kopie bleibt gemäß ihrer eigenen TTL gültig. Das unterscheidet sich von einem Berechtigungsfehler am Ursprung. Führe die Prüfung der alten Kopie aus.

Nur die aktualisierte Seite invalidieren
In diesem Schritt machst du die neue Version vor Ablauf sichtbar, ohne den Cache des unabhängigen Objekts zu leeren.
Eine Invalidierung entfernt passende Objekte aus dem Distributionscache. Der Pfad ist der mit / beginnende Viewer-Pfad, kein Bucket-Name oder lokaler Dateipfad. Verwende genau /index.html; /* würde auch das unabhängige Objekt unnötig entfernen.
Erstelle die Anfrage. Die CLI-Kurzform --paths liefert den Invalidierungsbatch; die Abfrage speichert seine erzeugte ID in einer Variablen:
INVALIDATION_ID=$(aws cloudfront create-invalidation \
--distribution-id "$DIST_ID" \
--paths '/index.html' \
--query Invalidation.Id \
--output text)
aws cloudfront wait invalidation-completed \
--distribution-id "$DIST_ID" \
--id "$INVALIDATION_ID"
aws cloudfront get-invalidation \
--distribution-id "$DIST_ID" \
--id "$INVALIDATION_ID" \
--query 'Invalidation.{Status:Status,Paths:InvalidationBatch.Paths.Items}'
Bestätige Completed und /index.html. Ein abgeschlossener Batch allein beweist nicht, welche Bytes beim Nutzer ankommen. Rufe die Seite zweimal ab, um neuen Inhalt und Wiederverwendung zu belegen:
curl --fail --include --noproxy '*' --resolve "${DIST_DOMAIN}:8082:127.0.0.1" "http://${DIST_DOMAIN}:8082/index.html"
curl --fail --include --noproxy '*' --resolve "${DIST_DOMAIN}:8082:127.0.0.1" "http://${DIST_DOMAIN}:8082/index.html"
Erwarte einen Miss mit Release two und danach einen Hit mit derselben neuen Seite. Die erste Anfrage liest aktuelle Ursprungsbytes, die zweite verwendet die neue Kopie.
Rufe das unabhängige Objekt ab und wiederhole den anonymen direkten Ursprungstest:
curl --fail --include --noproxy '*' --resolve "${DIST_DOMAIN}:8082:127.0.0.1" "http://${DIST_DOMAIN}:8082/stable.txt"
curl --noproxy '*' --output /dev/null --write-out 'Anonymous origin: HTTP %{http_code}\n' http://127.0.0.1:5000/labex-n03-content/index.html
stable.txt muss weiterhin einen Hit mit unverändertem Inhalt liefern, ohne zusätzlichen Ursprungszugriff. Anonymer S3-Zugriff muss weiterhin HTTP 403 liefern. Invalidierung ändert den Cache, nicht die Ursprungsberechtigungen. Führe die Prüfung der gezielten Aktualisierung aus.

Nur deine Bereitstellungsressourcen entfernen
In diesem Schritt deaktivierst und löschst du zuerst die Distribution, anschließend OAC und S3-Inhalte. Behalte den Referenz-Bucket bei.
CloudFront verwendet ETag als Versionstoken der Konfiguration. Lies aktuelle Konfiguration und ETag; rate das Token nicht.
Lies vor dem Löschen der Distribution ihre OAC-ID. Diese Variable bewahrt die Kennung des genau zu entfernenden Controls:
OAC_ID=$(aws cloudfront get-distribution-config \
--id "$DIST_ID" \
--query 'DistributionConfig.Origins.Items[0].OriginAccessControlId' \
--output text)
Speichere nun die aktuelle Konfiguration und ermittle ihren ETag:
aws cloudfront get-distribution-config \
--id "$DIST_ID" \
--query DistributionConfig \
--output json > distribution-current.json
DIST_ETAG=$(aws cloudfront get-distribution-config \
--id "$DIST_ID" \
--query ETag \
--output text)
In der aktuellen Laborkonfiguration ist Enabled der Distribution das einzige gleichnamige Attribut mit dem Wert true. Diese normale sed-Ersetzung erstellt eine deaktivierte Kopie und behält die Ursprungseinstellungen bei:
sed 's/"Enabled": true/"Enabled": false/' distribution-current.json > distribution-disabled.json
aws cloudfront update-distribution \
--id "$DIST_ID" \
--if-match "$DIST_ETAG" \
--distribution-config file://distribution-disabled.json
Warte auf die Bereitstellung der deaktivierten Konfiguration. AWS-Änderungen können Zeit benötigen; dieses Labor misst keine weltweite Bereitstellungsverzögerung:
aws cloudfront wait distribution-deployed \
--id "$DIST_ID"
Das Update ändert den ETag. Lies vor dem Löschen der deaktivierten Distribution das neueste Token:
DIST_ETAG=$(aws cloudfront get-distribution-config \
--id "$DIST_ID" \
--query ETag \
--output text)
aws cloudfront delete-distribution \
--id "$DIST_ID" \
--if-match "$DIST_ETAG"
Lösche OAC mit seinem eigenen ETag. Distributions-ID und OAC-ID bezeichnen unterschiedliche Ressourcen:
OAC_ETAG=$(aws cloudfront get-origin-access-control \
--id "$OAC_ID" \
--query ETag \
--output text)
aws cloudfront delete-origin-access-control \
--id "$OAC_ID" \
--if-match "$OAC_ETAG"
Lösche nur die beiden Laborobjekte und ihren Bucket:
aws s3api delete-object \
--bucket labex-n03-content \
--key index.html
aws s3api delete-object \
--bucket labex-n03-content \
--key stable.txt
aws s3api delete-bucket \
--bucket labex-n03-content
aws s3api list-buckets \
--query 'Buckets[].Name'
Der Referenz-Bucket muss erhalten und der Inhalts-Bucket verschwunden sein. AWS View sollte keine Inhaltsdistribution und nur das Referenzobjekt zeigen. Führe die Bereinigungsprüfung aus. Eine fehlgeschlagene API-Anfrage beweist keine Löschung.

Zusammenfassung
Du hast TTL-Grenzen und Cache-Control eingestellt, Cache-Treffer ohne zusätzliche Ursprungszugriffe beobachtet und eine kurzlebige Kopie ablaufen lassen. Ein neuer Upload am Ursprung ersetzt keine noch gültige Viewer-Kopie. Die Invalidierung des genauen Pfads lieferte die neue Seite und erhielt den unabhängigen Cache sowie den privaten Ursprung. Anschließend hast du nur eigene Ressourcen gelöscht. Bei häufigen Veröffentlichungen ermöglichen auch versionierte Objektnamen die Auswahl neuer Inhalte; hier hast du einen bestehenden Pfad aktualisiert.



