

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 使用 部署 Lambda 函數 AWS CDK
<a name="lambda-cdk-tutorial"></a>

 AWS Cloud Development Kit (AWS CDK) 是基礎設施即程式碼 (IaC) 架構，您可以使用您選擇的程式設計語言來定義 AWS 雲端基礎設施。若要定義您自己的雲端基礎設施，要先編寫包含一個或更多堆疊的應用程式 (使用 CDK 支援的其中一種語言)。然後，您將它合成到 CloudFormation 範本，並將您的 資源部署到 AWS 帳戶。按照本主題中的步驟部署一個 Lambda 函數，從 Amazon API Gateway 端點傳回事件。

隨附於 CDK 的 AWS 建構程式庫提供模組，可讓您用來建立 AWS 服務 所提供資源的模型。針對熱門服務，程式庫會提供具有智能預設和最佳實務的彙整建構。您可以使用 [aws\$1lambda](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda-readme.html) 模組來定義函數和相關資源，幾行程式碼即可完成。

## 先決條件
<a name="lambda-cdk-prerequisites"></a>

開始本教學課程之前，請執行下列命令 AWS CDK 來安裝 。

```
npm install -g aws-cdk
```

## 步驟 1：設定您的 AWS CDK 專案
<a name="lambda-cdk-step-1"></a>

為您的新 AWS CDK 應用程式建立目錄並初始化專案。

------
#### [ JavaScript ]

```
mkdir hello-lambda
cd hello-lambda
cdk init --language javascript
```

------
#### [ TypeScript ]

```
mkdir hello-lambda
cd hello-lambda
cdk init --language typescript
```

------
#### [ Python ]

```
mkdir hello-lambda
cd hello-lambda
cdk init --language python
```

專案開始後，啟用專案的虛擬環境，並安裝 AWS CDK的基準相依項。

```
source .venv/bin/activate
python -m pip install -r requirements.txt
```

------
#### [ Java ]

```
mkdir hello-lambda
cd hello-lambda
cdk init --language java
```

將此 Maven 專案匯入 Java 整合式開發環境 (IDE)。例如，在 Eclipse 中，依次選擇**檔案** > **匯入** > **Maven** > **現有的 Maven 專案**。

------
#### [ C\$1 ]

```
mkdir hello-lambda
cd hello-lambda
cdk init --language csharp
```

------

**注意**  
 AWS CDK 應用程式範本使用專案目錄的名稱來產生來源檔案和類別的名稱。在此範例中，目錄名為 `hello-lambda`。若使用不同的專案目錄名稱，您的應用程式將與這些說明不相符。

AWS CDK v2 包含名為 的單一套件 AWS 服務 中所有 的穩定建構`aws-cdk-lib`。在初始化專案時，此套件會安裝為相依性套件。使用某些程式設計語言時，套件會在您第一次建置專案時安裝。

## 步驟 2：定義 AWS CDK 堆疊
<a name="lambda-cdk-step-2"></a>

CDK *堆疊*是一或多個建構的集合，可定義 AWS 資源。每個 CDK 堆疊代表您 CDK 應用程式中的 CloudFormation 堆疊。

若要定義 CDK 堆疊，請遵循您偏好之程式設計語言的指示。此堆疊定義下列項目：
+ 函數的邏輯名稱：`MyFunction`
+ 函數程式碼的位置 (在 `code` 屬性中指定)。如需詳細資訊，請參閱 *AWS Cloud Development Kit (AWS CDK) API Reference* 中的 [Handler code](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda-readme.html#handler-code) 一節。
+ REST API 的邏輯名稱：`HelloApi`
+ API Gateway 端點的邏輯名稱：`ApiGwEndpoint`

請注意，本教學課程中的所有 CDK 堆疊都會使用 Lambda 函數的 Node.js [執行時期](lambda-runtimes.md)。您可以針對此 CDK 堆疊和 Lambda 函數使用不同的程式設計語言，以利用每種語言的優勢。例如，您可以針對 CDK 堆疊使用 TypeScript，以利用基礎設施程式碼靜態輸入的優勢。您可以針對 Lambda 函數使用 JavaScript，以利用動態類型語言的彈性和快速開發優勢。

------
#### [ JavaScript ]

開啟 `lib/hello-lambda-stack.js` 檔案並將內容替換如下：

```
const { Stack } = require('aws-cdk-lib');
const lambda = require('aws-cdk-lib/aws-lambda');
const apigw = require('aws-cdk-lib/aws-apigateway');

class HelloLambdaStack extends Stack {
  /**
   *
   * @param {Construct} scope
   * @param {string} id
   * @param {StackProps=} props
   */
  constructor(scope, id, props) {
    super(scope, id, props);
    const fn = new lambda.Function(this, 'MyFunction', {
      code: lambda.Code.fromAsset('lib/lambda-handler'),
      runtime: lambda.Runtime.NODEJS_LATEST,
      handler: 'index.handler'
    });

    const endpoint = new apigw.LambdaRestApi(this, 'MyEndpoint', {
      handler: fn,
      restApiName: "HelloApi"
    });

  }
}

module.exports = { HelloLambdaStack }
```

------
#### [ TypeScript ]

開啟 `lib/hello-lambda-stack.ts` 檔案並將內容替換如下：

```
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as apigw from "aws-cdk-lib/aws-apigateway";
import * as lambda from "aws-cdk-lib/aws-lambda";
import * as path from 'node:path';

export class HelloLambdaStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps){
    super(scope, id, props)
    const fn = new lambda.Function(this, 'MyFunction', {
      runtime: lambda.Runtime.NODEJS_LATEST,
      handler: 'index.handler',
      code: lambda.Code.fromAsset(path.join(__dirname, 'lambda-handler')),
    });

    const endpoint = new apigw.LambdaRestApi(this, `ApiGwEndpoint`, {
      handler: fn,
      restApiName: `HelloApi`,
    });

  }
}
```

------
#### [ Python ]

開啟 `/hello-lambda/hello_lambda/hello_lambda_stack.py` 檔案並將內容替換如下：

```
from aws_cdk import (
    Stack,
    aws_apigateway as apigw,
    aws_lambda as _lambda
)
from constructs import Construct

class HelloLambdaStack(Stack):

    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        fn = _lambda.Function(
            self,
            "MyFunction",
            runtime=_lambda.Runtime.NODEJS_LATEST,
            handler="index.handler",
            code=_lambda.Code.from_asset("lib/lambda-handler")
        )

        endpoint = apigw.LambdaRestApi(
            self,
            "ApiGwEndpoint",
            handler=fn,
            rest_api_name="HelloApi"
        )
```

------
#### [ Java ]

開啟 `/hello-lambda/src/main/java/com/myorg/HelloLambdaStack.java` 檔案並將內容替換如下：

```
package com.myorg;

import software.constructs.Construct;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
import software.amazon.awscdk.services.apigateway.LambdaRestApi;
import software.amazon.awscdk.services.lambda.Function;

public class HelloLambdaStack extends Stack {
    public HelloLambdaStack(final Construct scope, final String id) {
        this(scope, id, null);
    }

    public HelloLambdaStack(final Construct scope, final String id, final StackProps props) {
        super(scope, id, props);

        Function hello = Function.Builder.create(this, "MyFunction")
                            .runtime(software.amazon.awscdk.services.lambda.Runtime.NODEJS_LATEST)
                            .code(software.amazon.awscdk.services.lambda.Code.fromAsset("lib/lambda-handler"))
                            .handler("index.handler")
                            .build();

        LambdaRestApi api = LambdaRestApi.Builder.create(this, "ApiGwEndpoint")
                                .restApiName("HelloApi")
                                .handler(hello)
                                .build();

    }
}
```

------
#### [ C\$1 ]

開啟 `src/HelloLambda/HelloLambdaStack.cs` 檔案並將內容替換如下：

```
using Amazon.CDK;
using Amazon.CDK.AWS.APIGateway;
using Amazon.CDK.AWS.Lambda;
using Constructs;

namespace HelloLambda
{
    public class HelloLambdaStack : Stack
    {
        internal HelloLambdaStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            var fn = new Function(this, "MyFunction", new FunctionProps
            {
                Runtime = Runtime.NODEJS_LATEST,
                Code = Code.FromAsset("lib/lambda-handler"),
                Handler = "index.handler"
            });

            var api = new LambdaRestApi(this, "ApiGwEndpoint", new LambdaRestApiProps
            {
                Handler = fn
            });
        }
    }
}
```

------

## 步驟 3：建立 Lambda 函數程式碼
<a name="lambda-cdk-step-3"></a>

1. 從專案 (`hello-lambda`) 的根目錄建立 Lambda 函數程式碼的 `/lib/lambda-handler` 目錄。此目錄是在 AWS CDK 堆疊的 `code` 屬性中指定。

1. 在 `/lib/lambda-handler` 目錄中，建立名為 `index.js` 的新檔案。將以下程式碼貼到檔案。該函數會從 API 請求擷取特定屬性，並將其傳回為 JSON 回應。

   ```
   exports.handler = async (event) => {
     // Extract specific properties from the event object
     const { resource, path, httpMethod, headers, queryStringParameters, body } = event;
     const response = {
       resource,
       path,
       httpMethod,
       headers,
       queryStringParameters,
       body,
     };
     return {
       body: JSON.stringify(response, null, 2),
       statusCode: 200,
     };
   };
   ```

## 步驟 4：部署 AWS CDK 堆疊
<a name="lambda-cdk-step-4"></a>

1. 從專案根目錄執行 [cdk synth](https://docs.aws.amazon.com/cdk/v2/guide/ref-cli-cmd-synth.html) 命令：

   ```
   cdk synth
   ```

   此命令會從 CDK 堆疊合成 AWS CloudFormation 範本。該範本是大約為 400 行的 YAML 檔案，與下面的內容相似：
**注意**  
如果您遇到以下錯誤，請確定您位於專案目錄的根目錄。  

   ```
   --app is required either in command-line, in cdk.json or in ~/.cdk.json
   ```  
**Example CloudFormation 範本**  

   ```
   Resources:
     MyFunctionServiceRole3C357FF2:
       Type: AWS::IAM::Role
       Properties:
         AssumeRolePolicyDocument:
           Statement:
             - Action: sts:AssumeRole
               Effect: Allow
               Principal:
                 Service: lambda.amazonaws.com
           Version: "2012-10-17"		 	 	 
         ManagedPolicyArns:
           - Fn::Join:
               - ""
               - - "arn:"
                 - Ref: AWS::Partition
                 - :iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
       Metadata:
         aws:cdk:path: HelloLambdaStack/MyFunction/ServiceRole/Resource
     MyFunction1BAA52E7:
       Type: AWS::Lambda::Function
       Properties:
         Code:
           S3Bucket:
             Fn::Sub: cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}
           S3Key: ab1111111cd32708dc4b83e81a21c296d607ff2cdef00f1d7f48338782f92l3901.zip
         Handler: index.handler
         Role:
           Fn::GetAtt:
             - MyFunctionServiceRole3C357FF2
             - Arn
         Runtime: nodejs24.x
         ...
   ```

1. 執行 [cdk deploy](https://docs.aws.amazon.com/cdk/v2/guide/ref-cli-cmd-deploy.html) 命令：

   ```
   cdk deploy
   ```

   等待資源建立完畢。最終輸出包含 API Gateway 端點的 URL。範例：

   ```
   Outputs:
   HelloLambdaStack.ApiGwEndpoint77F417B1 = https://abcd1234.execute-api.us-east-1.amazonaws.com/prod/
   ```

## 步驟 5：測試函數
<a name="lambda-cdk-step-5"></a>

若要調用該 Lambda 函數，請複製 API Gateway 端點並將其貼到 Web 瀏覽器或執行 `curl` 命令：

```
curl -s https://abcd1234.execute-api.us-east-1.amazonaws.com/prod/
```

回應是從原始事件物件所選取屬性的 JSON 表示，其中包含對 API Gateway 端點提出之請求的相關資訊。範例：

```
{
  "resource": "/",
  "path": "/",
  "httpMethod": "GET",
  "headers": {
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
    "Accept-Encoding": "gzip, deflate, br, zstd",
    "Accept-Language": "en-US,en;q=0.9",
    "CloudFront-Forwarded-Proto": "https",
    "CloudFront-Is-Desktop-Viewer": "true",
    "CloudFront-Is-Mobile-Viewer": "false",
    "CloudFront-Is-SmartTV-Viewer": "false",
    "CloudFront-Is-Tablet-Viewer": "false",
    "CloudFront-Viewer-ASN": "16509",
    "CloudFront-Viewer-Country": "US",
    "Host": "abcd1234.execute-api.us-east-1.amazonaws.com",
     ...
```

## 步驟 6：清除您的資源
<a name="lambda-cdk-step-6"></a>

API Gateway 端點可公開存取。為了避免意外產生費用，請執行 [cdk destroy](https://docs.aws.amazon.com/cdk/v2/guide/ref-cli-cmd-destroy.html) 命令來刪除堆疊和所有相關聯的資源。

```
cdk destroy
```

## 後續步驟
<a name="lambda-cdk-next-steps"></a>

如需以您選擇的語言撰寫 AWS CDK 應用程式的資訊，請參閱下列內容：

------
#### [ TypeScript ]

[以 TypeScript 使用 AWS CDK](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-typescript.html)

------
#### [ JavaScript ]

[以 JavaScript 使用 AWS CDK](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-javascript.html)

------
#### [ Python ]

[在 Python AWS CDK 中使用](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-python.html)

------
#### [ Java ]

[在 Java AWS CDK 中使用](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-java.html)

------
#### [ C\$1 ]

[在 C\$1 AWS CDK 中使用](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-csharp.html)

------
#### [ Go ]

[在 Go AWS CDK 中使用](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-go.html)

------