iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 6
1
DevOps

用 CDK 定義 AWS 架構系列 第 6

Day 6 - AWS CDK 部署 Lambda 與 API Gateway 服務 (上)

今天我們來部署一個 API Gateway 串接 Lambda 的服務,讓我們直接來 serverless 一下!

https://ithelp.ithome.com.tw/upload/images/20201024/20117701QzNO37YYln.jpg

建立 Lambda

創建新的 CDK Project

我們這次的專案叫它 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!

與之前的 CDK Project 創建方法做比較

可以看到這次沒有加入 template 指令,所以在 cdk-lambda.stack.ts 裡面沒有內容只有一行註解,移除註解就可以開始我們今天的主題了!

https://ithelp.ithome.com.tw/upload/images/20200919/20117701GbnkomaadV.png

創建 Lambda function 主程式

  • 接下來我們創建一個放 lambda function 的資料夾
$ mkdir lambda
  • 放入 lambda/index.js 測試檔案
exports.handler = async function (event) {
  console.log("request:", JSON.stringify(event, undefined, 2));
  return;
};
  • 加入 cdk-lambda.stack.ts 放入 lambda
import * 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
  • 開啟 AWS Console 檢查一下看一下我們的 Lambda 是否有成功部署上去!
    https://ithelp.ithome.com.tw/upload/images/20200920/20117701o9dCUQzGvW.png

準備 API Gateway 要用的 Lambda Function

第一次使用 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 看看吧!
https://ithelp.ithome.com.tw/upload/images/20200920/201177010v7nnBdvdN.png

加入 API Gateway

修改 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 了來修正一下程式
https://ithelp.ithome.com.tw/upload/images/20200920/2011770168RYYmfbLl.png

修正網頁

其實這邊的問題主要是在 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>`,
  };
};

再部署一次就正常了
https://ithelp.ithome.com.tw/upload/images/20200920/201177018WFxePIQre.png

讓 API Gateway 支援 customer domain

目前使用的網址是 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 看一下是否設定完成
https://ithelp.ithome.com.tw/upload/images/20200920/20117701HnnsTzBIuz.png

確定完成後到我們的 DNS 設定一下 Domain 的 CNAME,接下來就可以使用新的網址打開網站拉!
是不是變得比較美觀 ~
https://ithelp.ithome.com.tw/upload/images/20200920/20117701cOXKj3bPP0.png

以上是今天的 CDK 使用 Lambda、API Gateway 與 ACM 解說,目前的排版可能有點亂我還在思考要怎麼做會比較好看請大家見諒 QQ

想要看更多嗎?歡迎到我的部落格參觀

文章內容主要是網路或是程式開發類型的文章

本文同步刊載於 Clarence 部落格:Day 6 - AWS CDK 部署 Lambda 與 API Gateway 服務 (上)


「AWS CDK 完全學習手冊:打造雲端基礎架構程式碼 IaC」
本書改編並延伸自第 12 屆 iT 邦幫忙鐵人賽獲得 DevOps 組冠軍的《用 CDK 定義 AWS 架構》系列文章,以簡單、好讀的行文風格詳述技術細節,並提供完整的程式碼範例與說明,一步一步帶領新手從零開始踏上 AWS CDK 技術達人之路。

有興趣的朋友歡迎至天瓏書局選購!

購書連結 https://bit.ly/2ZMAebE

https://ithelp.ithome.com.tw/upload/images/20211103/20117701W7l6fQnn2L.jpg


上一篇
Day 5 - 執行 AWS CDK sample-app
下一篇
Day 7 - AWS CDK 部署 Lambda 與 API Gateway 服務 (下)
系列文
用 CDK 定義 AWS 架構30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
t628x7600
iT邦新手 5 級 ‧ 2021-09-03 17:45:24

可以請教一下~domain name 你是有先用Route 53跟註冊嗎?

Clarence iT邦新手 3 級 ‧ 2021-09-04 12:46:30 檢舉

我這邊不是用 Route53 不過先使用 Route53 註冊這樣比較方便,如果不想用 Route53 註冊有兩個方法可以做

  1. 可以先到 ACM 設定一次先把 CNAME 設定到自己的 Domain 上面,這個部分因為每次都一樣所以下次執行就會直接成功
  2. 在跑 CDK 的過程中到 ACM 看需要設鄧的 CNAME 是什麼然後到在設定到自己的 Domain 上面

我要留言

立即登入留言