iT邦幫忙

2023 iThome 鐵人賽

DAY 4
0
DevOps

CDK 從 0 開始打造靈活自如的 IaC系列 第 4

04 - 使用 CDK 定義 AWS 存儲資源

  • 分享至 

  • xImage
  •  

本篇文章內有:

  • 使用 AWS CDK 定義 Amazon S3 儲存貯體 (Bucket)
  • 自訂 Amazon S3 儲存貯體

使用 AWS CDK 定義 Amazon S3 儲存貯體 (Bucket)

在之前的文章中,我們都是用 sample-app 這個模板所生成的程式碼,在這篇文章中,我們終於要來親手寫 AWS CDK 了。

先建立一個新資料夾,透過下面的指令,在裡面生成一個空的 AWS CDK 專案。

npm exec --package=aws-cdk -- cdk init app --language=typescript

一樣用 Visual Studio Code 開啟專案後,我們要來編輯 lib 資料夾下的 app-stack.ts ,檔案名字可能會不同,但在 lib 之下也只有一個檔案,不會迷路,他應該會長得像這個樣子。
Visual Studio Code project app

這邊建議大家可以開啟 Format On Save ,點選左下角的齒輪開啟設定 (Settings) ,或是按快捷鍵 macOS: cmd (⌘) + , , Windows: ctrl + ,
Visual Studio Code Menu

在上方搜尋欄輸入 editor.formatOnSave ,並勾選下方出現的 Format On Save ,這樣在儲存的時候, Visual Studio Code 就會試著幫你把程式碼變整齊。
Visual Studio Code Settings

回歸正題,先將空的 AWS CDK App 部署上去,如此一來我們比較好知道接下來新增的程式碼有甚麼效果。

npm run cdk -- deploy

接下來要做的是,在中間的部分, 建構子 (constructor) 裡面, super 下面,貼上以下的程式碼。

new cdk.aws_s3.Bucket(this, 'bucket');

是的,就一行,如此一來我們就已經告訴了 AWS CDK 去建立一個 Amazon S3 。

馬上來看一下跟 AWS 上面的資源差異。

npm run cdk -- diff

出現了我們想要的 Amazon S3 儲存貯體。

Resources
[+] AWS::S3::Bucket bucket bucket43879C71

現在剩餘的事情就是將這個變更更新到 AWS 上面,更新的指令跟部署的指令是一樣的。

npm run cdk -- deploy

自訂 Amazon S3 儲存貯體

如果就這樣結束這篇文章也太便宜作者了,所以我們要來客製化這個Amazon S3 儲存貯體。

針對剛才貼上的程式碼,我們改成下面的內容。

new cdk.aws_s3.Bucket(this, 'bucket', {
  encryption: cdk.aws_s3.BucketEncryption.KMS_MANAGED,
  bucketKeyEnabled: true,
});

這邊是更改了加密行為,這將使用 Bucket Key 做加密,這是個可以節省 KMS API 呼叫次數,是個省錢的方式,來看一下差異變更。

Resources
[~] AWS::S3::Bucket bucket bucket43879C71
 └─ [+] BucketEncryption
     └─ {"ServerSideEncryptionConfiguration":[{"BucketKeyEnabled":true,"ServerSideEncryptionByDefault":{"SSEAlgorithm":"aws:kms"}}]}

發現這次的資源變更,從 [+] 變成了 [~] ,這是因為資源已經存在,只是針對其中的參數進行更新。
還有 [-] 這個符號,這是代表該資源將被刪除。

除了直接在物件建立時給予屬性,也有些參數是支援用物件方法進行設定或更新,我們將程式碼改成以下的內容。

const bucket = new cdk.aws_s3.Bucket(this, 'bucket', {
  encryption: cdk.aws_s3.BucketEncryption.KMS_MANAGED,
  bucketKeyEnabled: true,
});

bucket.addLifecycleRule({
  expiration: cdk.Duration.days(7),
});

這次的差異也很清楚地列表出來,這個變更會讓 Amazon S3 自動刪除存放了 7 天以上的物件 (Object) 。

Resources
[~] AWS::S3::Bucket bucket bucket43879C71
 └─ [+] LifecycleConfiguration
     └─ {"Rules":[{"ExpirationInDays":7,"Status":"Enabled"}]}

我們可以進到 AWS Console 上面看剛才所有的變更,一樣在上方搜尋欄輸入 S3 進入服務頁面。
AWS Console Search S3

會發現這個 Amazon S3 儲存貯體的名稱實在是不和藹,甚至可以說很醜,這是因為 AWS CDK 在沒有特別指示的情況下,會自動為資源產生名字,而 AWS CloudFormation 會在資源後再加上亂數後綴,確保資源不會衝突。
AWS Console S3 Buckets

其實,可以在建立物件時,加上這個屬性,讓 Amazon S3 儲存貯體的名字清楚明瞭。

bucketName: 'app-bucket'

這時如果看差異變更,會發現有點不一樣,後面多出了 Replace

Resources
[~] AWS::S3::Bucket bucket bucket43879C71 replace
 └─ [+] BucketName (requires replacement)
     └─ app-bucket

看了一下,原來更改名稱這個屬性會需要做資源替換 (requires replacement) , AWS CDK CLI 也在差異變更中指出這件事情。

但這回在部署的時候,好像不妙,出現了 UPDATE_FAILED ,我們的變更沒有被成功的執行,但同時,既有的 Amazon S3 儲存貯體也沒有受到影響。

AppStack: deploying... [1/1]
AppStack: creating CloudFormation changeset...
AppStack | 0/3 | 12:00:04 AM | UPDATE_IN_PROGRESS   | AWS::CloudFormation::Stack | AppStack User Initiated
AppStack | 0/3 | 12:00:07 AM | UPDATE_IN_PROGRESS   | AWS::S3::Bucket    | bucket (bucket43879C71) Requested update requires the creation of a new physical resource; hence creating one.
AppStack | 0/3 | 12:00:08 AM | UPDATE_FAILED        | AWS::S3::Bucket    | bucket (bucket43879C71) app-bucket already exists
AppStack | 0/3 | 12:00:08 AM | UPDATE_ROLLBACK_IN_P | AWS::CloudFormation::Stack | AppStack The following resource(s) failed to update: [bucket43879C71]. 
AppStack | 1/3 | 12:00:11 AM | UPDATE_COMPLETE      | AWS::S3::Bucket    | bucket (bucket43879C71)
AppStack | 2/3 | 12:00:11 AM | UPDATE_ROLLBACK_COMP | AWS::CloudFormation::Stack | AppStack
AppStack | 2/3 | 12:00:12 AM | DELETE_SKIPPED       | AWS::S3::Bucket    | bucket (bucket43879C71)
AppStack | 3/3 | 12:00:12 AM | UPDATE_ROLLBACK_COMP | AWS::CloudFormation::Stack | AppStack

熟悉的綠色勾勾不見了,變成兩個紅色的叉叉。

Failed resources:
AppStack | 12:00:08 AM | UPDATE_FAILED        | AWS::S3::Bucket    | bucket (bucket43879C71) app-bucket already exists

 ❌  AppStack failed: Error: The stack named AppStack failed to deploy: UPDATE_ROLLBACK_COMPLETE: app-bucket already exists
    at FullCloudFormationDeployment.monitorDeployment (/tmp/app/node_modules/aws-cdk/lib/index.js:443:10232)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Object.deployStack2 [as deployStack] (/tmp/app/node_modules/aws-cdk/lib/index.js:446:153546)
    at async /tmp/app/node_modules/aws-cdk/lib/index.js:446:136809     

 ❌ Deployment failed: Error: The stack named AppStack failed to deploy: UPDATE_ROLLBACK_COMPLETE: app-bucket already exists
    at FullCloudFormationDeployment.monitorDeployment (/tmp/app/node_modules/aws-cdk/lib/index.js:443:10232)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Object.deployStack2 [as deployStack] (/tmp/app/node_modules/aws-cdk/lib/index.js:446:153546)
    at async /tmp/app/node_modules/aws-cdk/lib/index.js:446:136809     

The stack named AppStack failed to deploy: UPDATE_ROLLBACK_COMPLETE: app-bucket already exists

AWS CDK CLI 把錯誤訊息也列了出來,原來是已經有人佔用了 app-bucket 這個沒創意的名稱,果然亂數產生名字還是有一定的道理在的。

寫完這 8 行程式碼之後,如果有進去 AWS CloudFormation 看一下,會發現產生出來的模板超過 250行呢。


透過親自寫程式碼,雖然可能都是複製貼上,但應該有更了解如何透過 AWS CDK 建立 AWS 資源,也體驗到部署失敗的滋味,緊接著要來嘗試資源之間的互相參照。


上一篇
03 - CDK App 部署流程
下一篇
05 - 使用 CDK 定義 AWS 計算資源
系列文
CDK 從 0 開始打造靈活自如的 IaC7
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言