今天我們來部署一個 API Gateway 串接 Lambda 的服務,讓我們直接來 serverless 一下!
我們這次的專案叫它 cdk-lambda
,首先我們先創建資料夾然後 init 一下專案
$ mkdir cdk-lambda && cd cdk-lambda
$ cdk init --language typescript
Applying project template app for typescript
# Welcome to your CDK TypeScript project!
This is a blank project for TypeScript development with CDK.
The `cdk.json` file tells the CDK Toolkit how to execute your app.
## Useful commands
* `npm run build` compile typescript to js
* `npm run watch` watch for changes and compile
* `npm run test` perform the jest unit tests
* `cdk deploy` deploy this stack to your default AWS account/region
* `cdk diff` compare deployed stack with current state
* `cdk synth` emits the synthesized CloudFormation template
Initializing a new git repository...
Executing npm install...
npm WARN deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142
npm WARN deprecated request-promise-native@1.0.9: request-promise-native has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142
npm WARN deprecated har-validator@5.1.5: this library is no longer supported
npm WARN deprecated resolve-url@0.2.1: https://github.com/lydell/resolve-url#deprecated
npm WARN deprecated urix@0.1.0: Please see https://github.com/lydell/urix#deprecated
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN cdk-lambda@0.1.0 No repository field.
npm WARN cdk-lambda@0.1.0 No license field.
✅ All done!
可以看到這次沒有加入 template
指令,所以在 cdk-lambda.stack.ts
裡面沒有內容只有一行註解,移除註解就可以開始我們今天的主題了!
$ mkdir lambda
lambda/index.js
測試檔案exports.handler = async function (event) {
console.log("request:", JSON.stringify(event, undefined, 2));
return;
};
cdk-lambda.stack.ts
放入 lambdaimport * as cdk from "@aws-cdk/core";
import * as lambda from "@aws-cdk/aws-lambda";
export class CdkLambdaStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const main = new lambda.Function(this, "lambda", {
runtime: lambda.Runtime.NODEJS_10_X,
handler: "index.handler",
code: lambda.Code.fromAsset("lambda"),
});
}
}
$ npm i @aws-cdk/aws-lambda
deploy
$ cdk deploy
第一次使用 CDK 部署 Lambda 來測試看看改變我們的 Lambda Function 會不會同步幫我們修改吧!
此次的修改內容因應要串接 API Gateway 做了一點改變
如果想要進一步知道其他的串接參數可以直接閱讀官方文件在 API Gateway 中設定整合回應
exports.handler = async function (event) {
console.log("request:", JSON.stringify(event, undefined, 2));
return {
statusCode: 200,
headers: { "Content-Type": "text/html" },
body: `<h1>第 12 屆 iT 邦幫忙鐵人賽 用 CDK 定義 AWS 架構 AWS Lambda!</h1>`,
};
};
在部署之前先查看一下 cdk diff
可以發現我們更新了 index.js
CDK 會幫我們重新上傳檔案到 S3 並且更新它
這段繁瑣的功能 CDK 完美的幫我們處理好了 ~~
可以從 Parameters 與 Resources 看到有 S3 的新增檔案與移除
$ cdk diff
因為剛開始使用我們還是重新整理一下 AWS Console 看看吧!
lib/cdk-lambda-stack.ts
我絕對不會說我本來是想要串 ALB 可是突然想到要先講 VPC 才可以創 ALB 因此決定還是先寫 API Gateway
要使用 API Gateway 串接 Lambda 可以直接使用 CDK 的 LambdaRestApi 來完成
是不是非常簡單又快速呢!這邊如果手動可是還要在 AWS Console 點個好幾下呢!
import * as cdk from "@aws-cdk/core";
import * as lambda from "@aws-cdk/aws-lambda";
import * as apigw from '@aws-cdk/aws-apigateway';
export class CdkLambdaStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const main = new lambda.Function(this, "lambda", {
runtime: lambda.Runtime.NODEJS_10_X,
handler: "index.handler",
code: lambda.Code.fromAsset("lambda"),
});
new apigw.LambdaRestApi(this, 'Endpoint', {
handler: main
});
}
}
檢查一下 diff 可以看到新增了 API Gateway 的 Resources
$ cdk diff
安裝套件
$ npm i @aws-cdk/aws-apigateway
使用部署指令完成後可以看到網頁了!
$ cdk deploy
我們來看一下網頁,哇!竟然是亂碼,其實是我們忘記指定它是 UTF-8
了來修正一下程式
其實這邊的問題主要是在 HTML 語法的部分跟 Lambda 比較沒有關係,不過還是介紹一下 XD
exports.handler = async function (event) {
console.log("request:", JSON.stringify(event, undefined, 2));
return {
statusCode: 200,
headers: { "Content-Type": "text/html" },
body: `<meta charset="utf-8"><h1>第 12 屆 iT 邦幫忙鐵人賽 用 CDK 定義 AWS 架構 AWS Lambda!</h1>`,
};
};
再部署一次就正常了
目前使用的網址是 API Gateway 的 domain 覺得不太美觀來幫它換一下!
首先我們先在 LambdaRestApi 指定 domain name 如 21-24 行使用 api.cdk.clarence.tw
在 API Gateway 使用 Customer Domain 需要使用 HTTPS 因此還需要設定 ACM 來新增 ACM 使用 *.cdk.clarence.tw
如 15-18 行
import * as cdk from "@aws-cdk/core";
import * as lambda from "@aws-cdk/aws-lambda";
import * as apigw from "@aws-cdk/aws-apigateway";
import * as acm from "@aws-cdk/aws-certificatemanager";
export class CdkLambdaStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const main = new lambda.Function(this, "lambda", {
runtime: lambda.Runtime.NODEJS_10_X,
handler: "index.handler",
code: lambda.Code.fromAsset("lambda"),
});
const cert = new acm.Certificate(this, "Certificate", {
domainName: "*.cdk.clarence.tw",
validation: acm.CertificateValidation.fromDns(),
});
new apigw.LambdaRestApi(this, "Endpoint", {
handler: main,
domainName: {
domainName: "api.cdk.clarence.tw",
certificate: cert,
},
});
}
}
安裝套件
$ npm i @aws-cdk/aws-certificatemanager
修改完程式後我們來更新一下
$ cdk deploy
執行完成後到 AWS Console 看 API Gateway/Custom domain names
看一下是否設定完成
確定完成後到我們的 DNS 設定一下 Domain 的 CNAME,接下來就可以使用新的網址打開網站拉!
是不是變得比較美觀 ~
以上是今天的 CDK 使用 Lambda、API Gateway 與 ACM 解說,目前的排版可能有點亂我還在思考要怎麼做會比較好看請大家見諒 QQ
文章內容主要是網路或是程式開發類型的文章
本文同步刊載於 Clarence 部落格:Day 6 - AWS CDK 部署 Lambda 與 API Gateway 服務 (上)
「AWS CDK 完全學習手冊:打造雲端基礎架構程式碼 IaC」
本書改編並延伸自第 12 屆 iT 邦幫忙鐵人賽獲得 DevOps 組冠軍的《用 CDK 定義 AWS 架構》系列文章,以簡單、好讀的行文風格詳述技術細節,並提供完整的程式碼範例與說明,一步一步帶領新手從零開始踏上 AWS CDK 技術達人之路。有興趣的朋友歡迎至天瓏書局選購!
可以請教一下~domain name 你是有先用Route 53跟註冊嗎?
我這邊不是用 Route53 不過先使用 Route53 註冊這樣比較方便,如果不想用 Route53 註冊有兩個方法可以做