iT邦幫忙

2023 iThome 鐵人賽

DAY 14
0
Cloud Native

AWS AI交易室實戰系列 第 14

Day 14 - AWS Lambda Extensions 實作

  • 分享至 

  • xImage
  •  

~ 靈異體附身 ~

相關程式碼:https://github.com/slindevel/modern-aws-marathon

AWS Lambda Function執行環境介紹

AWS Lambda Function運行在一個被稱為執行環境(execution environment)的受隔離環境中。這使它們與其他Lambda Function隔離開來,並提供了在函數配置中指定的資源,例如記憶體。

AWS Lambda Service會自動管理計算使用Lambda Function資源的生命週期,以便讓您僅支付實際使用的部分。在函數調用之間,AWS Lambda Service會凍結執行環境。如果 AWS Lambda Service需要執行環境來進行後續的調用,它會解凍執行環境。

以前,只有運行時程序能夠影響執行環境的生命週期。它會與Runtime API 進行通信,該 API 在執行環境中提供了一個 HTTP API 端點(HTTP API endpoing),用於與 Lambda 服務進行通信。

lambda & runtime api

運行時(runtime) 使用API從Lambda請求調用事件並將其傳遞給函數代碼。然後,它在完成處理事件時通知Lambda服務。Lambda服務隨後凍結執行環境。

運行時進程以前公開了Lambda執行環境的兩個不同階段:初始化(Init)和調用(Invoke)。

初始化(Init):在初始化階段期間,Lambda服務初始化運行時,然後運行函數的初始化代碼(即主處理程序之外的代碼)。初始化階段在第一次調用時發生,或者如果啟用了預配置並發性能(Provisioned Concurrency),則提前進行。

調用(Invoke):在調用階段期間,運行時通過運行時API向Lambda服務請求調用事件,並調用函數處理程序。然後,它將函數響應返回給運行時API。

函數運行後,Lambda服務凍結執行環境並保持一段時間,以預測是否會有另一個函數調用。

如果Lambda函數在一段時間內未收到任何調用,Lambda服務將關閉並刪除該環境。

previous lambda lifecycle

AWS Lambda Extension執行環境介紹

Lambda Extensions在Lambda Function運行初始化之前進行初始化。它們在函數執行期間與函數並行運行,並在關閉期間可以執行邏輯。
Lambda Extension通過對Lambda生命週期進行以下更改,實現與Lambda服務的整合:
New Lambda lifecycle with extension

導入 Lambda Extension 後的 Lambda 生命週期

  • 初始化階段(Init phase):現在有三個獨立的初始化任務:extensions初始化(extensions Init)、運行時初始化(runtime Init)和函數初始化(function Init)。這樣可以創建一個順序,使得extension和runtime能夠在function代碼運行之前執行設置任務。
  • 調用期間獲得更大的控制權:在調用階段期間,運行時如前所述,請求調用事件並調用函數處理程序。此外,擴展現在可以向Lambda服務請求生命週期事件。它們可以根據這些生命週期事件執行邏輯,並在完成後向Lambda服務響應。當運行時和所有extensions回應給Lambda服務時,Lambda服務凍結執行環境。通過這種方式,extension可以影響凍結/解凍行為。
  • 關閉階段(Shutdown phase):我們現在公開了關閉階段的相關訊息(透過Runtime API) ,以使extension在執行環境關閉時能夠正常停止。Lambda服務會發送一個關閉事件,告知runtime和extension執行環境即將關閉。

extension在function執行期間可以與Lambda Service進行更緊密的集成,並具有更大的控制權以滿足特定的需求。

Lambda lifecycle details

Lambda Extension執行過程(External Extension)

您可以將external extension部署為 Lambda Layer,這些層是包含共享庫或其他依賴項的.zip存檔,或者將它們包含在以容器映像方式部署的function的映像中。

要新增Lambda Layer,可以使用AWS管理控制台、AWS命令行界面 (AWS CLI) 或基礎設施即代碼工具 (如AWS CloudFormationAWS Serverless Application Model(AWS SAM)Terraform)。

當Lambda服務為.zip存檔函數啟動函數執行環境時,它會從Lambda層中提取extension檔案並將其放在/opt目錄下。對於容器映像function,extension檔案將作為容器映像的一部分打包到/opt目錄下。然後,Lambda會查找/opt/extensions目錄中的任何可執行程序並開始執行它們。extension需要作為二進制文件或腳本可執行。由於函數代碼目錄是只讀的,extension不能修改函數代碼。

放到Lambda Layer的extension zip檔案內容如下(以”extension.zip"為例子)

├── marathon-lambda-extension-project (隨意名稱,沒用到)
    ├── extensions (固定名稱)
    |    └── logs_api_http_extension
    |          └── __init__.py
    |          └── extensions_api_client.py
    |          └── http_listener.py
    |          └── logs_api_client.py
    └── marathon-lambda-extension.py (與Lambda Layers Layer Name一致)
  • extensions_api_client.py: 工具類負責extension的註冊、獲取下一個事件、初始化和處理錯誤的操作。
  • marathon-lambda-extension: external extension的程式進入點(Entry Point)
  • marathon-lambda-extension.py: AWS Lambda Extension的執行程式,在 AWS Lambda Runtime 會直接執行這個 py 檔案

部署 extension 到 Day7 建立的 lambda function:(注意最後 layer-arn 參數要帶版號)

# in Day15/
$ cd marathon-lambda-extension-project
# step 1 - make marathon-lambda-extension.py executable
$ chmod +x extensions/marathon-lambda-extension.py
# step 2 - zip
$ zip -r extension.zip ./extensions
# step 3 - deploy to lambda layers
$ aws lambda publish-layer-version \              
 --layer-name "marathon-lambda-extension" \
 --zip-file  "fileb://extension.zip"
{
    "Content": {
       ...
    },
    "LayerArn": "arn:aws:lambda:ap-northeast-1:<account_id>:layer:marathon-lambda-extension",
    "LayerVersionArn": "arn:aws:lambda:ap-northeast-1:<account_id>:layer:marathon-lambda-extension:1",
    "Description": "",
    "CreatedDate": "2023-09-18T16:03:08.052+0000",
    "Version": 1
}
# step 4 - attach layer to lambda function
$ aws lambda update-function-configuration \
--function-name marathon-function \
--layers <layer-arn-with-version>

開新 terminal 使用指令,記得要切換到正確的 AWS Profile

$ export AWS_PROFILE=<your_profile>
# check user
$ aws iam get-user
$ aws logs tail /aws/lambda/marathon-function --follow

回到原本的 terminal,invoke 剛剛 attach 的 lambda

$ aws lambda invoke --function-name marathon-function out.log --log-type Tail

可以看到 aws logs 指令的那個 teminal 顯示以下訊息(在接收 request 之前):

Starting Extensions {'events': ['INVOKE', 'SHUTDOWN']} {'destination': {'protocol': 'HTTP', 'URI': 'http://sandbox:4243'}, 'types': ['platform', 'function'], 'buffering': {'timeoutMs': 1000, 'maxBytes': 262144, 'maxItems': 10000}}
Initializing LogsAPIExternalExtension marathon-lambda-extension.py
Registering to ExtensionsAPIClient on http://127.0.0.1:9001/2020-01-01/extension
Initializing HTTP Server on sandbox:4243
Subscribing to Logs API on http://127.0.0.1:9001/2020-08-15
Serving HTTP Server on sandbox:4243
LOGS	Name: marathon-lambda-extension.py	State: Subscribed	Types: [Platform, Function]
Successfully subscribed to Logs API: b'"OK"'
Serving LogsAPIHTTPExternalExtension marathon-lambda-extension.py
EXTENSION	Name: marathon-lambda-extension.py	State: Ready	Events: [INVOKE, SHUTDOWN]

程式碼說明:

  • extensions_api_client.py:

    • register: 使用Restful POST 向Extension API註冊,使其可以收到關於Runtime時INVOKE, SHUTDOWN的訊息

    • next: 讀取下一個進來的訊息

    • register payload如下:

      {"events":["INVOKE","SHUTDOWN"]}
      
      
  • marathon-lambda-extension.py 執行步驟解說:

    1. extensions_api_client registration
    2. while loop 接收 extensions_api_client.next()傳來的訊息執行相關的動作(handleInvoke&handleShutdown)

總結

Lambda externel extension 給了我們多一點額外資源可以搜集一些 init/terminate stage 方面的資訊,一般來說第三方的監控軟體都是利用此功能來實作對 AWS Lambda 的監控的
最後,如果是使用 docker image 部署的話,只要把 extension.zip 的內容放到 image 的 /opt/ 目錄下即可(ex. /opt/marathon-lambda-extension.py ...)

參考資料

https://github.com/aws-samples/aws-lambda-extension
https://docs.aws.amazon.com/lambda/latest/dg/lambda-extensions.html
https://aws.amazon.com/tw/blogs/compute/introducing-aws-lambda-extensions-in-preview/
https://aws.amazon.com/tw/blogs/compute/building-extensions-for-aws-lambda-in-preview/


上一篇
Day 13 - AWS Lambda Extension 介紹
下一篇
Day 15 - AWS ECS & Fargate
系列文
AWS AI交易室實戰30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言