在 AWS 環境下,網站託管可以透過 S3、Route53 和 CloudFront 的整合來實作。首先,將靜態網站內容儲存於 S3 儲存桶中,並設定適當的儲存桶政策。接著,使用 CloudFront 作為內容傳遞網路 (CDN),提升網站效能和可用性。最後,透過 Route53 設定 DNS,將網域名稱指向 CloudFront 分佈,讓使用者可以透過自訂網域名稱存取網站。為了確保網站安全,我們可以使用 AWS Certificate Manager (ACM) 申請 SSL/TLS 憑證,並將其設定於 CloudFront 分佈上,讓網站可以透過 HTTPS 提供服務。此外,本文也示範如何使用 CloudFormation 以程式碼化的方式自動化佈署和設定這些資源,簡化網站託管的流程並提高效率。
使用 S3、Route53 和 CloudFront 進行網站託管
介紹
本章節將介紹如何使用 Amazon S3、Route53 和 CloudFront 進行網站託管。我們將探討如何設定 S3 靜態網站、如何使用 CloudFront 進行內容傳遞,以及如何使用 Route53 進行 DNS 設定。
使用 S3 進行靜態網站託管
設定 S3 靜態網站
要使用 S3 進行靜態網站託管,首先需要建立一個 S3 儲存桶,並將其設定為靜態網站。儲存桶的名稱必須與網域名稱完全相符,例如 qnatime.com。
新增檔案和儲存桶政策
新增 index.html 和 error.html 檔案到儲存桶中,並新增一個儲存桶政策,允許所有人讀取儲存桶中的內容。
設定 Route53
在 Route53 中建立別名記錄,將網域名稱指向 S3 儲存桶。
程式碼範例
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::qnatime.com/*"
}
]
}
內容解密:
上述程式碼範例是一個 S3 儲存桶政策,允許所有人讀取儲存桶中的物件。其中,Version 指定了政策的版本,Statement 指定了政策的陳述式。Sid 是陳述式的 ID,Effect 指定了陳述式的作用(允許或拒絕),Principal 指定了陳述式的主體(誰可以執行此動作),Action 指定了陳述式的動作(讀取物件),Resource 指定了陳述式的資源(儲存桶中的物件)。
使用 CloudFront 進行內容傳遞
建立 CloudFront 分佈
要使用 CloudFront 進行內容傳遞,首先需要建立一個 CloudFront 分佈。在建立分佈時,需要指定來源(S3 儲存桶)和別名(網域名稱)。
設定別名和預設根物件
在 CloudFront 分佈中設定別名和預設根物件。別名是指向 CloudFront 分佈的網域名稱,預設根物件是指當使用者存取網域名稱時,CloudFront 傳遞的預設物件。
程式碼範例
{
"CallerReference": "qnatime-distribution-2019-01-12-07-45",
"Aliases": {
"Quantity": 2,
"Items": ["qnatime.net", "www.qnatime.net"]
},
"DefaultRootObject": "index.html",
"Origins": {
"Quantity": 1,
"Items": [
{
"Id": "my-origin",
"DomainName": "qnatime.com.s3.amazonaws.com",
"S3OriginConfig": {
"OriginAccessIdentity": ""
}
}
]
}
}
內容解密:
上述程式碼範例是一個 CloudFront 分佈設定檔。其中,CallerReference 指定了分佈的參考 ID,Aliases 指定了分佈的別名,DefaultRootObject 指定了預設根物件,Origins 指定了分佈的來源(S3 儲存桶)。
使用 Route53 進行 DNS 設定
建立別名記錄
在 Route53 中建立別名記錄,將網域名稱指向 CloudFront 分佈。
程式碼範例
{
"Comment": "change batch request for qnatime.net",
"Changes": [
{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "qnatime.net",
"Type": "A",
"AliasTarget": {
"HostedZoneId": "Z2FDTNDATAQYW2",
"DNSName": "d1obzjrl8ac1no.cloudfront.net",
"EvaluateTargetHealth": false
}
}
}
]
}
內容解密:
上述程式碼範例是一個 Route53 變更請求檔。其中,Comment 指定了變更請求的註解,Changes 指定了變更請求的內容。Action 指定了變更請求的動作(建立或刪除),ResourceRecordSet 指定了變更請求的資源記錄集。Name 指定了記錄集的名稱,Type 指定了記錄集的型別,AliasTarget 指定了記錄集的別名目標。
使用 S3、Route53 和 CloudFront 進行網頁託管的 CloudFormation 設定
本章節將詳細介紹如何使用 AWS CloudFormation 來設定 CloudFront 分發(Distribution)以及 Route53 的 RecordSet,以實作網頁託管。
CloudFront 分發堆積疊(Distribution Stack)的建立
首先,我們需要準備一個 CloudFormation 範本,該範本包含以下幾個主要部分:
範本版本和描述:首先定義範本的版本和描述(可選)。
引數(Parameters):定義一個引數區段,用於接受以逗號分隔的網域名稱別名列表。
Parameters: DomainNameAliases: Description: 網站的網域名稱別名(例如:quizzercloud.com, www.quizzercloud.com) Type: CommaDelimitedList資源(Resources):在資源區段中,我們定義 CloudFront 分發。
Resources: MyCloudFrontDistribution: Type: AWS::CloudFront::Distribution Properties: DistributionConfig: Origins: - DomainName: quizzer.cloud.s3.amazonaws.com Id: myS3Origin S3OriginConfig: OriginAccessIdentity: '' Enabled: 'true' Comment: '具有網域的 CloudFront 分發' DefaultRootObject: index.html Aliases: !Ref DomainNameAliases DefaultCacheBehavior: TargetOriginId: myS3Origin ForwardedValues: QueryString: 'false' Cookies: Forward: none ViewerProtocolPolicy: allow-all輸出(Outputs):建立一個輸出區段,以傳回 CloudFront 分發 ID 和網域名稱。同時,我們也會匯出網域名稱,以便稍後在 RecordSet 堆積疊中使用。
Outputs: CloudFrontDistributionId: Value: !Ref MyCloudFrontDistribution Description: 'CloudFront 分發 ID' CloudFrontDomain: Value: !GetAtt MyCloudFrontDistribution.DomainName Description: 'CloudFront 分發網域名稱' Export: Name: CloudFrontDomainName
接著,我們需要建立一個 JSON 檔案來傳遞引數值給 aws cloudformation create-stack 命令,然後執行該命令來建立堆積疊。
RecordSet 堆積疊的建立
RecordSet 堆積疊用於在 Route53 中建立記錄集。範本如下:
引數定義:定義根網域名稱、子網域名稱和 S3 託管區域 ID 的引數。
資源定義:建立一個
AWS::Route53::RecordSetGroup型別的資源,為網域新增 A 記錄。Resources: QuizzerCloudDNS: Type: AWS::Route53::RecordSetGroup Properties: HostedZoneName: !Sub - ${DomainName}. - DomainName: !Ref RootDomainName Comment: Zone apex alias. RecordSets: - Name: !Ref RootDomainName Type: A AliasTarget: HostedZoneId: !Ref RecordHostedZoneId DNSName: !ImportValue CloudFrontDomainName - Name: !Ref SubDomainName Type: A AliasTarget: HostedZoneId: !Ref RecordHostedZoneId DNSName: !ImportValue CloudFrontDomainName
內容解密:
HostedZoneName指定了託管區域的名稱,後面跟著一個點(.)。RecordHostedZoneId是 CloudFront 分發的託管區域 ID,這是一個固定值。
- 輸出定義(可選):定義輸出區段以傳回 URL。
執行 aws cloudformation create-stack 命令,並傳遞必要的引數,然後使用 describe-stacks 子命令檢查狀態。
使用 HTTPS 保護網域 URL
在實際應用中,應該盡量使用 HTTPS 而不是 HTTP。由於目前尚未組態有效的證書,直接存取 HTTPS 網址會顯示「Not Secure」警告。下一章節將介紹如何建立和匯入有效的證書來解決這個問題。
停用和刪除 CloudFront 分發
要刪除 CloudFront 分發,首先需要停用它。停用分發需要使用 update-distribution 命令,並指定一個包含所有現有屬性的分發組態 JSON 檔案,但需將 Enabled 設定為 false。
程式碼範例:
aws cloudfront get-distribution-config --id <Distribution_ID> --output json > distribution-config.json
# 編輯 distribution-config.json,將 "Enabled" 改為 false
aws cloudfront update-distribution --id <Distribution_ID> --distribution-config file://distribution-config.json
aws cloudfront delete-distribution --id <Distribution_ID>
內容解密:
- 首先,使用
get-distribution-config命令取得當前分發組態的 JSON 檔案。 - 編輯該 JSON 檔案,將
Enabled的值改為false,然後儲存。 - 使用
update-distribution命令更新分發組態,指定編輯後的 JSON 檔案。 - 等待分發狀態變為
Disabled後,即可使用delete-distribution命令刪除分發。
使用 S3、Route53 和 CloudFront 進行網頁託管的 SSL/TLS 設定
在前面的章節中,我們已經瞭解如何使用 Amazon S3、Amazon Route 53 和 Amazon CloudFront 來託管靜態網站。然而,當我們使用自訂網域名稱時,直接透過 HTTPS 存取網站會出現「Not Secure」警告。本章節將指導如何為 CloudFront 分佈設定 SSL/TLS 證書,以啟用 HTTPS 存取並自動將 HTTP 請求重新導向至 HTTPS。
準備工作
在開始之前,請確保您已經:
- 按照「Chapter 9, Serverless Architecture Patterns and Practices」中的「Creating SSL certificates with ACM」配方取得了 ACM(AWS Certificate Manager)SSL/TLS 證書。
- 熟悉前述章節中關於 S3、CloudFront 和 Route 53 的設定步驟。
使用 AWS CLI 指令為 CloudFront 分佈設定 SSL/TLS 證書
步驟一:取得 ACM SSL/TLS 證書 ARN
首先,您需要取得與您的網域名稱(例如 www.qnatime.net)相關聯的 ACM SSL/TLS 證書 ARN。
步驟二:更新 CloudFront 分佈設定
建立或更新 CloudFront 分佈的設定檔(JSON 格式),加入 ViewerCertificate 屬性,範例如下:
"ViewerCertificate": {
"ACMCertificateArn": "arn:aws:acm:us-east-1:<account_id>:certificate/42b3ba99-66e9-4e71-8c1c-4239c1e81c84",
"SSLSupportMethod": "sni-only",
"MinimumProtocolVersion": "TLSv1.1_2016",
"Certificate": "arn:aws:acm:us-east-1:<account_id>:certificate/42b3ba99-66e9-4e71-8c1c-4239c1e81c84",
"CertificateSource": "acm"
}
#### 內容解密:
此段 JSON 設定用於指定 CloudFront 分佈所使用的 SSL/TLS 證書。其中:
ACMCertificateArn指定了 ACM 中 SSL/TLS 證書的 ARN。SSLSupportMethod設定為sni-only,表示 CloudFront 只會對支援 SNI(Server Name Identification)的客戶端提供 HTTPS 服務。MinimumProtocolVersion設定了最低的 TLS 版本,以確保安全性。Certificate和CertificateSource進一步確認了證書來源和 ARN。
步驟三:更新或建立 CloudFront 分佈
使用更新後的設定檔來建立或更新 CloudFront 分佈。如果是新分佈,請記得在 Route 53 中建立別名記錄,指向新的 CloudFront 分佈網域名稱。
步驟四:驗證 HTTPS 連線
更新完成後,嘗試透過 HTTPS 存取您的網站網域名稱。您應該不再看到「Not Secure」警告。點選瀏覽器中的鎖定按鈕,可以檢視證書詳情。
使用 CloudFormation 範本為 CloudFront 分佈設定 SSL/TLS 證書
範本結構概述
您可以更新現有的 CloudFormation Stack 或建立新的 Stack。以下概述了範本的關鍵部分:
- 引數定義:接受逗號分隔的網域名稱別名和證書 ARN。
- 資源定義:在
DistributionConfig中定義必要的屬性,包括Origins、Enabled、Comment、DefaultRootObject、Aliases、DefaultCacheBehavior和ViewerCertificate。
DistributionConfig:
Origins:
- DomainName: quizzer.cloud.s3.amazonaws.com
Id: myS3Origin
S3OriginConfig:
OriginAccessIdentity: ''
Enabled: 'true'
Comment: 'CloudFront Distribution with Domain'
DefaultRootObject: index.html
Aliases: !Ref DomainNameAliases
DefaultCacheBehavior:
TargetOriginId: myS3Origin
ForwardedValues:
QueryString: 'false'
Cookies:
Forward: none
ViewerProtocolPolicy: redirect-to-https
ViewerCertificate:
AcmCertificateArn: !Ref DomainNameCert
SslSupportMethod: sni-only
#### 內容解密:
此段 CloudFormation 範本定義了 CloudFront 分佈的設定。其中:
ViewerCertificate部分指定了 ACM 證書 ARN 和 SSL 支援方法。ViewerProtocolPolicy設定為redirect-to-https,使得任何 HTTP 請求都會被重新導向至 HTTPS,傳回 HTTP 狀態碼 301(永久移動)。
重要步驟回顧
- 建立CloudFront分配:指定根網域、WWW子網域以及ACM憑證ARN。
- 建立A記錄:為根網域和WWW子網域建立A記錄,指向CloudFront分配。
- 測試網域:透過HTTPS存取根網域和WWW子網域,確認能夠安全地接收來自S3儲存桶的回應。
運作原理
- CloudFront支援三種方式的SSL/TLS憑證:預設的CloudFront憑證、ACM憑證和IAM憑證。優先使用ACM憑證。
- 伺服器名稱指示(SNI):允許多個憑證執行在單一IP上,提高了靈活性。