In diesem Artikel wird es um die Konfiguration von Amazons S3 und Cloudfront gehen. Außerdem wird ein SSL-Zertifikat über den AWS Certificate Manager erstellt und in Cloudfront eingebunden.
Das Ziel ist es, statische Inhalte, die in der S3 liegen, von der Cloudfront über eine eigene Domain-URL aufzurufen.
Wer seine Webseite beschleunigen oder aber einfach Platz auf dem eigenen Server einsparen möchte, der kommt schnell auf den Gedanken, einen Teil seiner Daten in die Cloud auszulagern. Insbesondere Images (Bilder, Grafiken) und digitale Downloads wie z.B. PDFs eignen sich dafür sehr gut.
Test-Setup
Für meinen Test habe ich ca. 100 Images in die S3 hochgeladen. Dabei handelt es sich um Grafiken, die Teil einer Webseite sind. So ist auf jeder Unterseite dieser Webseite eine große Grafik eingebunden, die beim Aufruf der Seite vom Server meines Hosters geladen wurde. Um den Pageload durch parallele Requests zu beschleunigen, hatte ich die Images früher bereits auf eine Subdomain ausgelagert. Wie ich das gemacht habe, habe ich in diesem Artikel beschrieben.
Nun wollte ich erreichen, dass die Images nicht mehr vom eigenen Server geladen werden, sondern von Amazons CDN Cloudfront. Der Request für den Abruf der Images sollte aber nach wie vor über die Subdomain geroutet werden. Da meine Webseite unter https:// läuft, müssen die Images auch über https:// zur Verfügung gestellt werden.
Soweit zu den Anforderungen.
Inhalte auf AWS S3 auslagern und Public machen
Um die Amazon Webservices nutzen zu können, muss man sich im ersten Schritt dafür anmelden. Dafür ist eine Kreditkarte für die Abrechnung der Services zu hinterlegen. Dann wird der Service S3 ausgewählt und ein Bucket (Eimer) eingerichtet. In dem Bucket können dann für eine bessere Übersichtlichkeit wieder Verzeichnisse angelegt werden. Ich habe ein Verzeichnis „Images“ angelegt und meine Daten hochgeladen. Das Hochladen der Daten soll hier aber nicht Inhalt des Artikels sein, dafür gibt es diverse Möglichkeiten, die teilweise auch von der Backend-Sprache und/oder dem eingesetzen CMS abhängen. Einfach mal nach googlen.
Als nächstes muss der Zugriff auf die hochgeladenen Daten geregelt werden. Per Default können die abgelegten Daten von außen nicht aufgerufen werden. Für meinen Anwendungsfall ist dies aber zwingend notwendig, da die Images ja Teil meiner Webseite sind. Hier gibt es mindestens zwei Möglichkeiten, die Inhalte „Public“ zu machen. Entweder für jedes Objekt einzeln, was mir aber bei +100 Images zu viel Arbeit wäre. Oder mit einer „Bucket Policy“, die den Zugriff für alle Elemente in dem Bucket regelt.
Um die Bucket Policy editieren zu können,
- den entsprechenden Bucket aufrufen
- das Tab „Permissions“ anwählen
- Sub-Tab „Bucket Policy“ wählen und dort den folgenden JSON-Code eingeben
{
„Version“: „2012-10-17“,
„Statement“: [
{
„Sid“: „PublicReadGetObject“,
„Effect“: „Allow“,
„Principal“: {
„AWS“: „*“
},
„Action“: „s3:GetObject“,
„Resource“: „arn:aws:s3:::bucket/*“
}
]
}
Hinweis: wenn Du das für Deinen Bucket übernehmen willst, musst Du unter dem Item „Ressource“ das Wort „bucket“ durch den Namen Deines Buckets ersetzen. Wenn der Name Deines Buckets z.B. „meine-webseite“ lautet, dann schaut die Zeile hinterher so aus
„Resource“: „arn:aws:s3:::meine-webseite/*“
Wenn es funktioniert hat, steht nun unter „Access“ das Wort „Public“ in orange. Du kannst es nicht übersehen.
Ungecachtes Abrufen von S3 Inhalten nicht kosteneffizient
Eigentlich könnte man an der Stelle schon innehalten. Nun können Deine Inhalte von jedem Browser, der die Bucket-URL kennt, aufgerufen werden. Wenn Du die Image-URLs mit dem Code Deiner Webseite verknüpfst, können die Inhalte schon asynchron von dem S3-Speicher geladen werden.
Das ist an der Stelle aber noch nicht optimal. Zum einen würdest Du in Deinem Code die Klar-URLs zu Deinen Bucket-Inhalten offenbaren, das ist zwar per se nicht schlimm, aber schaut nicht so schön aus. Der zweite Punkt ist aber sehr viel gewichtiger, Amazon rechnet seine AWS Dienstleistungen nach dem Umfang der Nutzung ab. Im Falle der S3 zählt zur Nutzung das Herunterladen von dort gespeicherten Inhalten. Da die Daten in der S3 per Default nicht gecached sind, wird bei jedem Browseraufruf die Bilddatei erneut von der S3 abgerufen.
Um das zu verhindern, sollten die Daten mit einem CDN (Content Delievery Network) gecached werden. Praktischerweise stellt Amazon AWS mit Cloudfront dafür ein weiteres Produkt zur Verfügung.
SSL-Zertifikat über AWS Certificate Manager generieren
Bevor wir uns Cloutfront zuwenden, generieren wir zunächst ein neues SSL-Zertifikat.
Weil unsere Webseite mit https:// verschlüsselt ist, sollten die Images auch über https:// erreichbar sein. In der S3 sind sie das auch und über Cloudfront kann der Abruf auch über https:// erfolgen. Wenn der Aufruf aber über eine per CNAME weitergeleitete Domain/Subdomain erfolgen soll, dann (nur dann!) muss ein weiteres SSL-Zertifikat erstellt werden. Da ich die Images über https://images.meinedomain.de aufrufen möchte, generiere ich in der AWS über den Service Certificate Manager ein kostenloses SSL-Zertifikat.
- den Certificate Manager findet Ihr unter „Security, Identity & Compliance„
- Klick „Request a certificate„
- hier den Domain Namen oder die Sub-Domain eingeben. Ich hatte meine Images ja bereits auf eine Subdomain images.meinewebseite.de ausgelagert. Daher habe ich diese Sub-Domain an der Stelle eingegeben.
- Bestätigen
Nun wird Amazon die Domain verifizieren. Hierfür gibt es zwei Methoden
- Verifizierung per DNS via CNAME
- Verifizierung per Mail
Ich habe die erste Möglichkeit gewählt und einen neuen DNS-Eintrag für die Domain generiert. Wenn alles geklappt hat, dann schaut es so aus
Es dauert ein Weilchen, bis der Status auf „Issued“ wechselt.
Cloudfront Distribution erstellen
Als vorletzten Schritt erstellen wir eine neue Cloudfront-Distribution. Die findet Ihr ganz unten unter „Networking & Content Delivery„.
- Create Distribusion
- dann das obere „Get started“ von „Web“ auswählen
Nun kommen die Settings
Origin-Settings
- Origin Domain Name: hier werden Deine S3 Buckets angezeigt, sobald Du lostippst. Du solltest dann den Bucket auswählen, in dem Deine Images oder Inhalte abgelegt sind
- Origin Path: wenn Du Deine Inhalte in Verzeichnissen gegliedert hast, dann wähle hier Dein Verzeichnis aus. Keinen Slash am Ende setzen
- Restrict Bucket Access: Steht schon per Default auf „No“. Kann übernommen werden
Default Cache Behavior Settings
- Object Caching: habe ich auf „Customize“ gestellt
- bis auf „Default TTL“ habe ich alles wie vorgegeben belassen. Hier habe ich „7776000“ eingetragen. Es handelt sich dabei um einen Sekunden-Wert. Solange sollen Dateien im Cache belassen werden, bevor sie wieder bei der S3 angefragt werden. In meinem Fall entspricht die Zahl 3 Monaten.
- Alternate Domain Names (CNAMEs): hier Deine Domain oder Sub-Domain eintragen, über die die Inhalte abgerufen werden sollen
- SSL Certificate: wenn Du vorher das SSL-Zerifikat über die AWS Certificate Manager erstellt hast, kannst Du es hier unter „Custom SSL Certificat“ auswählen
- Custom SSL Support: Das kostenlose SSL-Zertifikat kommt mit der Einschränkung daher, das es „nur“ „Server Name Indication (SNI)“ unterstützt. Es gibt einige wenige Browser/Betriebssystem-Konstellationen, in denen das SSL-Zertifikat nicht angezeigt wird. Amazon bietet auch noch eine dedizierte IP Adresse für das Zertifikat an, lässt sich das aber mit 600 $ / Jahr bezahlen.
Wer zu diesen Einstellungen etwas googelt, wird feststellen, dass es hier noch sehr viel mehr Möglichkeiten gibt. Andere User bevorzugen es zum Beispiel, den Objekten in der S3 einen eigenen Cache Header mitzugeben. Das kann vorteilhaft sein, wenn Du wiederkehrende Besucher hast, bei denen dann das Image direkt im Browser vorgehalten wird. Davon habe ich jetzt mit meinen Einstellungen keinen Gebrauch gemacht.
Distribution Settings
Dies ist der letzte größere Punkt beim Erstellen der Cloudfront-Distribution. Weil ich ja gerne meine Images über die Sub-Domain images.meinedomain.de aufrufen möchte, muss ich hier die Default-Einstellungen etwas anpassen.
Für wen es OK ist, wenn die gecachten Inhalte über die Cloudfront-URL abgerufen werden, also z.B. über https://d111111abcdef8.cloudfront.net/image-1.jpg der braucht hier natürlich kein Custom SSL Zertifikat auswählen und kann sich den Schritt mit dem AWS Certificate Manager gänzlich sparen.
Unabhängig davon dauert es eine Weile, bis nach dem Klick auf „Create Distribution“ die Distribution fertig erstellt ist („Status: Deployed“). Je mehr Inhalte aus der S3 in die Distribution geladen werden müssen, umso längert dauert der Vorgang.
CNAME auf Cloudfront Weiterleiten
Wer seine Images nicht über seinen eigenen (Sub)-Domainnamen aufrufen möchte, der ist an der Stelle eigentlich schon fertig. Ab sofort können die Inhalte aus der S3 über die Cloudfront-URL aufgerufen werden. Die Cloudfront-URL findet Ihr unter „Domain Name“ und schaut in etwa so aus https://d111111abcdef8.cloudfront.net
Um Eure Images aufrufen zu können, müsst Ihr nun nur noch den Pfad des Images an die URL anhängen, also z.B. https://d111111abcdef8.cloudfront.net/image-1.jpg
Wenn ihr an dieser Stelle folgende Meldung erhaltet
dann habt ihr nicht unbedingt etwas falsch gemacht. Ihr müsst wahrschinlich nur noch den Pfad sauber angeben.
Nehmen wir an, Ihr habt Eure Images innerhalb des Buckets in einem Unterverzeichnis „Images“ angelegt. In dem Fall lautet die korrekte Cloudfront-URL
https://d111111abcdef8.cloudfront.net/images/image-1.jpg
Für den Fall aber, dass Ihr in den oben beschriebenen „Origin-Settings“ das Verzeichnis schon mit angegeben habt, sollte die Cloudfront-URL ohne die Verzeichnis-Angabe zum Ziel führen
https://d111111abcdef8.cloudfront.net/image-1.jpg
Für diejenigen, die statt der Cloudfront-URL die eigene Domain zum Aufruf nutzen möchten:
In dem Fall müsst Ihr bei Eurem Registrar noch einen neuen DNS-Eintrag generieren. Der schaut dann so aus, dass Ihr für die Domain oder Subdomain einen CNAME Eintrag mit der Cloudfront-URL generiert.
Nun seid Ihr fertig und Eure Inhalte sollten über die folgenden drei Möglichkeiten aufrufbar sein:
https://s3-eu-west-1.amazonaws.com/bucketname/images/image-1.jpg
https://d111111abcdef8.cloudfront.net/image-1.jpg
https://images.meinedomain.com/image-1.jpg
Bei den letzten beiden URLs könnt Ihr die Header Werte mit redbot.org noch prüfen, ob die Daten auch wirklich über Cloudfront ausgeliefert werden und der Request nicht an den S3 Bucket weitergereicht wird.
Im Idealfall schaut es dann so aus:
Falls dort unter „X-Cache“ -> „Miss from cloudfront“ stehen sollte, ist das aber noch kein Grund zur Beunruhigung. Das bedeutet nur, dass die Datei noch nicht im Cloudfront-CDN gespeichert war. Beim zweiten Request sollte es dann aber „Hit from cloudfront“ sein.
Ich hoffe, dass Euch diese Anleitung beim Einrichten Eurer Cloudfront-Instanz hilft. Postet doch gerne Eure Erfahrungen mit Cloudfront und S3 in den Kommentaren!