

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

# 教學課程：建置自訂執行期
<a name="runtimes-walkthrough"></a>

在本教學課程中，您將建立具有自訂執行時間的 Lambda 函數。首先，您要將執行時間納入函式的部署套件中。接著再將其遷移到與函式分開而單獨管理的 Layer。最後，您要透過更新該執行時間 Layer 以資源為基礎的許可政策，將其與世界各地的人共享。

## 必要條件
<a name="runtimes-walkthrough-prereqs"></a>

此教學課程假設您具備基本的 Lambda 操作知識並了解 Lambda 主控台。若您尚未了解，請遵循 [使用主控台建立一個 Lambda 函數](getting-started.md#getting-started-create-function) 中的指示，建立您的第一個 Lambda 函數。

若要完成下列步驟，您需要 [AWS CLI 版本 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)。命令和預期的輸出會列在不同的區塊中：

```
aws --version
```

您應該會看到下列輸出：

```
aws-cli/2.13.27 Python/3.11.6 Linux/4.14.328-248.540.amzn2.x86_64 exe/x86_64.amzn.2
```

對於長命令，逸出字元 (`\`) 用於將命令分割為多行。

在 Linux 和 macOS 上，使用您偏好的 shell 和套件軟體管理工具。

**注意**  
在 Windows 中，作業系統的內建終端不支援您常與 Lambda 搭配使用的某些 Bash CLI 命令 (例如 `zip`)。若要取得 Ubuntu 和 Bash 的 Windows 整合版本，請[安裝適用於 Linux 的 Windows 子系統](https://docs.microsoft.com/en-us/windows/wsl/install-win10)。本指南中的 CLI 命令範例使用 Linux 格式。如果您使用的是 Windows CLI，必須重新格式化包含內嵌 JSON 文件的命令。

您需要 IAM 角色來建立 Lambda 函數。該角色需要許可，才能將日誌傳送至 CloudWatch Logs，並存取您的函數使用的 AWS 服務。如果您還沒有函數開發角色，請立即建立一個。

**若要建立執行角色**

1. 在 IAM 主控台中開啟[角色頁面](https://console.aws.amazon.com/iam/home#/roles)。

1. 選擇建**立角色**。

1. 建立具備下列屬性的角色。
   + **信任實體** - **Lambda**。
   + **許可** - **AWSLambdaBasicExecutionRole**。
   + **角色名稱** - **lambda-role**。

   **AWSLambdaBasicExecutionRole** 政策具備函數將日誌寫入到 CloudWatch Logs 時所需的許可。

## 建立函數
<a name="runtimes-walkthrough-function"></a>

建立具有自訂執行時間的 Lambda 函數。本範例包括兩個檔案：執行期 `bootstrap` 檔案以及函數處理常式。兩個檔案都是以 Bash 實作。

1. 建立專案的目錄，然後切換至該目錄。

   ```
   mkdir runtime-tutorial
   cd runtime-tutorial
   ```

1. 建立稱為 `bootstrap` 的新檔案。這是自訂執行期。  
**Example 引導**  

   ```
   #!/bin/sh
   
   set -euo pipefail
   
   # Initialization - load function handler
   source $LAMBDA_TASK_ROOT/"$(echo $_HANDLER | cut -d. -f1).sh"
   
   # Processing
   while true
   do
     HEADERS="$(mktemp)"
     # Get an event. The HTTP request will block until one is received
     EVENT_DATA=$(curl -sS -LD "$HEADERS" "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/next")
   
     # Extract request ID by scraping response headers received above
     REQUEST_ID=$(grep -Fi Lambda-Runtime-Aws-Request-Id "$HEADERS" | tr -d '[:space:]' | cut -d: -f2)
   
     # Run the handler function from the script
     RESPONSE=$($(echo "$_HANDLER" | cut -d. -f2) "$EVENT_DATA")
   
     # Send the response
     curl "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/$REQUEST_ID/response"  -d "$RESPONSE"
   done
   ```

   執行時間將從部署套件載入函式指令碼。其使用了兩個變數以找出指令碼。`LAMBDA_TASK_ROOT` 將告知套件解壓縮的位置，而 `_HANDLER` 則包含指令碼的名稱。

   在執行期載入函數指令碼之後，它將使用執行期 API 從 Lambda 中擷取調用事件、傳遞事件至處理常式，並將回應發布回 Lambda。為了取得請求 ID，執行時間將 API 回應中的各標頭儲存至暫時檔案，然後從該檔案讀取 `Lambda-Runtime-Aws-Request-Id` 標頭。
**注意**  
執行時間另還負責其他任務，包括錯誤處理以及向處理常式提供內容資訊。如需詳細資訊，請參閱 [要求](runtimes-custom.md#runtimes-custom-build)。

1. 為函數建立指令碼。以下範例指令碼定義了一個接受事件資料的處理常式函數，會將該資料記錄到 `stderr` 並予以傳回。  
**Example function.sh**  

   ```
   function handler () {
     EVENT_DATA=$1
     echo "$EVENT_DATA" 1>&2;
     RESPONSE="Echoing request: '$EVENT_DATA'"
   
     echo $RESPONSE
   }
   ```

   `runtime-tutorial` 目錄現在應該看起來像這樣：

   ```
   runtime-tutorial
   ├ bootstrap
   └ function.sh
   ```

1. 將檔案轉成可執行檔並加入至 .zip 封存檔。這是部署套件。

   ```
   chmod 755 function.sh bootstrap
   zip function.zip function.sh bootstrap
   ```

1. 建立名為的函數 `bash-runtime`。對於 `--role`，輸入 Lambda [執行角色](lambda-intro-execution-role.md)的 ARN。

   ```
   aws lambda create-function --function-name bash-runtime \
   --zip-file fileb://function.zip --handler function.handler --runtime provided.al2023 \
   --role arn:aws:iam::123456789012:role/lambda-role
   ```

1. 調用函數。

   ```
   aws lambda invoke --function-name bash-runtime --payload '{"text":"Hello"}' response.txt --cli-binary-format raw-in-base64-out
   ```

   如果您使用 AWS CLI 第 2 版，則需要 **cli-binary-format** 選項。若要讓此成為預設的設定，請執行 `aws configure set cli-binary-format raw-in-base64-out`。若要取得更多資訊，請參閱*《AWS Command Line Interface 使用者指南第 2 版》*中 [AWS CLI 支援的全域命令列選項](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list)。

   您應該看到如下回應：

   ```
   {
       "StatusCode": 200,
       "ExecutedVersion": "$LATEST"
   }
   ```

1. 確認回應。

   ```
   cat response.txt
   ```

   您應該看到如下回應：

   ```
   Echoing request: '{"text":"Hello"}'
   ```

## 建立 Layer
<a name="runtimes-walkthrough-layer"></a>

為了將執行時間程式碼與函式程式碼分開，您要建立一個僅包含執行時間的 Layer。Layer 讓您能夠單獨開發函式的依存項目，且若搭配多個函式使用同一 Layer 還可減少儲存空間用量。如需更多詳細資訊，請參閱 [使用層管理 Lambda 相依項](chapter-layers.md)。

1. 建立包含 `bootstrap` 檔案的 .zip 檔案。

   ```
   zip runtime.zip bootstrap
   ```

1. 使用 [publish-layer-version](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/publish-layer-version.html?highlight=nodejs16%20x) 命令來建立 layer。

   ```
   aws lambda publish-layer-version --layer-name bash-runtime --zip-file fileb://runtime.zip
   ```

   如此即建立了 Layer 的第一個版本。

## 更新函數
<a name="runtimes-walkthrough-update"></a>

若要搭配函式使用執行期 Layer，請將函式設定成使用 Layer，並且移除函式中的執行期程式碼。

1. 更新函式組態以提取 Layer。

   ```
   aws lambda update-function-configuration --function-name bash-runtime \
   --layers arn:aws:lambda:us-east-1:123456789012:layer:bash-runtime:1
   ```

   這會將執行時間新增至 `/opt` 目錄中的函數。若要確保 Lambda 使用層中的執行期，您必須將 `boostrap` 從函數的部署套件中移除，如接下來兩個步驟所示。

1. 建立包含函數程式碼的 .zip 檔案。

   ```
   zip function-only.zip function.sh
   ```

1. 更新函式程式碼，使之僅包含處理常式指令碼。

   ```
   aws lambda update-function-code --function-name bash-runtime --zip-file fileb://function-only.zip
   ```

1. 調用函數以確認其是否可搭配執行期 layer 運作。

   ```
   aws lambda invoke --function-name bash-runtime --payload '{"text":"Hello"}' response.txt --cli-binary-format raw-in-base64-out
   ```

   如果您使用 AWS CLI 第 2 版，則需要 **cli-binary-format** 選項。若要讓此成為預設的設定，請執行 `aws configure set cli-binary-format raw-in-base64-out`。若要取得更多資訊，請參閱*《AWS Command Line Interface 使用者指南第 2 版》*中 [AWS CLI 支援的全域命令列選項](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list)。

   您應該看到如下回應：

   ```
   {
       "StatusCode": 200,
       "ExecutedVersion": "$LATEST"
   }
   ```

1. 確認回應。

   ```
   cat response.txt
   ```

   您應該看到如下回應：

   ```
   Echoing request: '{"text":"Hello"}'
   ```

## 更新執行時間
<a name="runtimes-walkthrough-runtime"></a>

1. 若要記錄執行環境的相關資訊，請更新執行時間指令碼使其輸出環境變數。  
**Example 引導**  

   ```
   #!/bin/sh
   
   set -euo pipefail
   
   # Configure runtime to output environment variables
   echo "##  Environment variables:"
   env
   
   # Load function handler
   source $LAMBDA_TASK_ROOT/"$(echo $_HANDLER | cut -d. -f1).sh"
   
   # Processing
   while true
   do
     HEADERS="$(mktemp)"
     # Get an event. The HTTP request will block until one is received
     EVENT_DATA=$(curl -sS -LD "$HEADERS" "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/next")
   
     # Extract request ID by scraping response headers received above
     REQUEST_ID=$(grep -Fi Lambda-Runtime-Aws-Request-Id "$HEADERS" | tr -d '[:space:]' | cut -d: -f2)
   
     # Run the handler function from the script
     RESPONSE=$($(echo "$_HANDLER" | cut -d. -f2) "$EVENT_DATA")
   
     # Send the response
     curl "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/$REQUEST_ID/response"  -d "$RESPONSE"
   done
   ```

1. 建立包含新版本 `bootstrap` 檔案的 .zip 檔案。

   ```
   zip runtime.zip bootstrap
   ```

1. 建立 `bash-runtime` 層的新版本。

   ```
   aws lambda publish-layer-version --layer-name bash-runtime --zip-file fileb://runtime.zip
   ```

1. 設定函式以使用新版本的 Layer。

   ```
   aws lambda update-function-configuration --function-name bash-runtime \
   --layers arn:aws:lambda:us-east-1:123456789012:layer:bash-runtime:2
   ```

## 共享 Layer
<a name="runtimes-walkthrough-share"></a>

若要與其他 AWS 帳戶共用層，請將跨帳戶許可陳述式新增至層的[資源型政策](access-control-resource-based.md)。執行 [add-layer-version-permission](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/add-layer-version-permission.html) 命令，並將帳戶 ID 指定為 `principal`。在各陳述式中，您可將許可授予單一帳戶、所有帳戶或 [AWS Organizations](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_introduction.html) 中的某個組織。

以下列範例會授予帳戶 111122223333 存取 `bash-runtime` layer 第 2 版的許可。

```
aws lambda add-layer-version-permission \
  --layer-name bash-runtime \
  --version-number 2 \  
  --statement-id xaccount \
  --action lambda:GetLayerVersion \
  --principal 111122223333 \
  --output text
```

您應該會看到類似下列的輸出：

```
{"Sid":"xaccount","Effect":"Allow","Principal":{"AWS":"arn:aws:iam::111122223333:root"},"Action":"lambda:GetLayerVersion","Resource":"arn:aws:lambda:us-east-1:123456789012:layer:bash-runtime:2"}
```

許可僅適用於單一層版本。每次建立新的層版本時均需重複此程序。

## 清除
<a name="runtimes-walkthrough-cleanup"></a>

刪除各個版本的 Layer。

```
aws lambda delete-layer-version --layer-name bash-runtime --version-number 1
aws lambda delete-layer-version --layer-name bash-runtime --version-number 2
```

由於函數持有對該層的第 2 版的參考，所以它仍存在於 Lambda 中。本函式將繼續運作，但無法再設定各函式使用已刪除的版本。若您修改了函數的 layer 清單，則必須指定新的版本或略去已刪除的 layer。

使用 [delete-function](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/delete-function.html) 命令刪除函數。

```
aws lambda delete-function --function-name bash-runtime
```