Deploying Static Website to AWS CloudFront with AWS CDK

相信有很多人有疑問為甚麼要使用AWS CDK來使用AWS? 而我目前也是剛開始學習,對於他們最明顯的差異就是便利性 這篇文章就是寫一下如何使用python撰寫CDK腳本,最後deploy 靜態網頁到s3與CloudFront 還有幫CloudFront上certificate

Deploying Static Website to AWS CloudFront with AWS CDK

目錄:


前言

相信有很多人有疑問為甚麼要使用AWS CDK來使用AWS?
而我目前也是剛開始學習,對於他們最明顯的差異就是 便利性

在AWS panel上點點點 vs CDK stack寫好生成CloudFormation幫你deploy
免去像是設定IAM等等的行為,且方便deploy與destroy

這篇文章就是寫一下如何使用python撰寫CDK腳本,最後deploy 靜態網頁到s3與CloudFront
還有幫CloudFront上certificate


Prepare enviroment

Install aws-cli && python3 && python3-venv && nodejs && npm on Ubuntu 20.04
nodejs有版本限制要注意一下 node -v 的版本

$ sudo apt update && sudo apt install -y awscli python3 python3-venv nodejs npm
$ node -v
v10.19.0

After that, please install aws-cdk

$ sudo npm install -g aws-cdk
$ cdk --version 
1.93.0 (build c506d3b) 

設置aws configuration
這邊不推薦使用root的金鑰,建議去IAM建立一個新User。

$ aws configure


Create an app

$ mkdir cdk-static-website && cd cdk-static-website
$ cdk init app --language python
$ source .venv/bin/activate

新增需要使用到的套件並安裝

$ cat << EOF >> requirements.txt
yapf
flake8
aws-cdk.aws-s3
aws-cdk.aws-s3-deployment
aws-cdk.aws-cloudfront
aws-cdk.aws-cloudfront-origins
aws-cdk.aws-certificatemanager
EOF

$ pip install -r requirements.txt

以上全部做完之後,目錄應該長這樣

cdk_static_website_stack.py 就是我們要修改的檔案

完成上面步驟後,對於第一次使用CDK的朋友們,記得要bootstrap

$ cdk bootstrap

這個指令會在當前的region創建一個s3 bucket來儲存cdk所使用的到的CloudFormation
完成之後就可以進行下一步囉


Prepare certificate

如果這邊你沒有個人域名可以跳過

關於CloudFront的certificate有個特殊要求就是Region必須得在 us-east-1
這邊假定你都已經簽發好了
ACM(Amazon Certificate Manager)要求三樣東西

  • Certificate
  • CertificateKey
  • CA_Certificate

如果你都有了,那就可以直接用aws-cli上傳

# Note: fileb://PATH_TO_YOUR_CERTIFICATE
$ AWS_DEFAULT_REGION=us-east-1 aws acm import-certificate --certificate fileb://certification/cloudfront.mino.tw.pem \
--certificate-chain fileb://certification/ca.pem \
--private-key fileb://certification/cloudfront.mino.tw.key.pem

# 成功的話會回傳certificate的arn
{
    "CertificateArn": "arn:aws:acm:us-east-1:914017757250:certificate/325a19c2-26ba-4c81-9c08-919d03bb9b4e"
}

或者你可以去AWS的ACM console(region: us-east-1)手動request一個憑證

或者你可以使用外部DNS驗證


CDK在deploy的時候會給你一組DNS驗證需要設定的CNAME,
等你設定完再等幾分鐘才會繼續跑,
而new出來的certificate可以直接取代掉之後在example中的
cert_mgr.Certificate.from_certificate_arn(self, 'Certificate', arn)

以上說的都是Domain給外面管理的情況

如果你的Domain給AWS Route 53管的話那就可以直接透過CDK來request,
不過我沒錢沒實驗過,就甭談了。
有興趣可以去看API Reference

總之只要把certificate的ARN記錄下來就行了。


Modifying python code


CDK Synth && Deploy

Before starting synth and deploy, 我們得先創建website-dist的資料夾與檔案

$ mkdir website-dist
$ cat << EOF > website-dist/index.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>CloudFront</title>
</head>
<body>
    <p>用 CDK 定義 AWS 架構!</p>
</body>
</html>
EOF

$ cat << EOF > website-dist/error.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>CloudFront Error page</title>
</head>
<body>
    <p>ERROR PAGE</p>
</body>
</html>
EOF

完成後,那就來試試看 synth 吧

$ cdk synth

如果你步驟都沒問題的話,他會自己生成CloudFormation

然後將其deploy

$ cdk deploy

等待幾分鐘後,就可以在CloudFront上看到service的domain name了

可以看到已經成功了,再來就是在自己的DNS服務商上將自訂的domain name CNAME到cloudfront上的domain name就行了

大功告成

如果這時候我們想把域名拿掉呢?
回到我們的cdk_static_website_stack.py
將有背後有 # 如果沒有域名,請將這行註解 的程式碼都註解掉

然後看diff的差別

$ cdk diff

deploy again

$ cdk deploy

然後自訂域名就不能用了

最後我們這次實作完成了

直接下指令就可以把它全部清光囉

$ cdk destroy

最後會留下來的東西就只有cdk的CloudFormation與儲存他的S3 bucket


結語

最近我學長來找我,來幫忙建構他們公司的架構,打算用AWS的全家桶,
在此之前的我只有用免費的EC2玩了12個月,還有摸一摸s3之類的AWS比較常用的服務,
而真的深入了解AWS之後才知道為甚麼這麼多公司會選擇使用AWS(or Azure/GCP...),
解決方案真的太多了,只要有錢甚麼都能搞定,
像筆者之前與同學的Side project 網頁同接人數快2000人,DB就不行了,
最後是optimize 程式與DB setting才解決,
如果能用RDS或許就不用這麼麻煩了(還是要optimize程式),
最後唯一的缺點就是貴了,個人的services還是找便宜的VPS廠商比較好


References

  1. https://docs.aws.amazon.com/cdk/latest/guide/hello_world.html
  2. https://ithelp.ithome.com.tw/articles/10241696
  3. https://docs.aws.amazon.com/cdk/api/latest/docs/aws-cloudfront-readme.html