Serverless - 層建立



什麼是層?

層是一種隔離程式碼塊的方法。假設您想在應用程式中匯入 NumPy 庫。您信任該庫,並且幾乎沒有機會更改該庫的原始碼。因此,如果您不希望 NumPy 的原始碼弄亂您的應用程式工作區,您會怎麼做呢?簡單來說,您只需要 NumPy 放在其他地方,與您的應用程式程式碼隔離。層允許您完全做到這一點。您可以簡單地將所有依賴項(NumPy、Pandas、SciPy 等)捆綁到一個單獨的層中,然後在 serverless 中的 lambda 函式中簡單地引用該層。就是這樣!捆綁在該層中的所有庫現在都可以匯入到您的應用程式中。同時,您的應用程式工作區保持完全整潔。您只需檢視應用程式程式碼進行編輯。

Layer ARN

照片由 Iva Rajovic 拍攝於 Unsplash,表示程式碼在層中的分離

層真正酷的一點是它們可以在函式之間共享。假設您部署了一個帶有包含 NumPy 和 Pandas 的 python-requirements 層的 lambda 函式。現在,如果另一個 lambda 函式需要 NumPy,您無需為此函式部署單獨的層。您可以簡單地使用前一個函式的層,它也可以與新函式一起正常工作。

這將節省您在部署期間的大量寶貴時間。畢竟,您只需要部署應用程式程式碼。依賴項已存在於現有層中。因此,許多開發人員將依賴項層保留在單獨的堆疊中。然後,他們在所有其他應用程式中使用此層。這樣,他們就不需要一遍又一遍地部署依賴項。畢竟,依賴項相當龐大。僅 NumPy 庫本身就大約 80 MB。每次更改應用程式程式碼(可能只有幾 KB)時都部署依賴項將非常不方便。

新增依賴項層只是一個例子。還有其他幾個用例。例如,serverless.com 上提供的示例涉及使用 FFmpeg 工具建立 GIF。在該示例中,他們將 FFmpeg 工具儲存在一個層中。總而言之,AWS Lambda 允許我們為每個函式最多新增 5 個層。唯一的條件是 5 個層和應用程式的總大小應小於 250 MB。

建立 python-requirements 層

現在讓我們看看如何使用 serverless 建立和部署包含所有依賴項的層。為此,我們需要 serverless-python-requirements 外掛。此外掛僅適用於 Serverless 1.34 及更高版本。因此,如果您使用的是 <1.34 版本,則可能需要升級您的 Serverless 版本。您可以使用以下命令安裝外掛:

sls plugin install -n serverless-python-requirements

接下來,您將此外掛新增到 serverless.yml 檔案的 plugins 部分,並在 custom 部分提及其配置:

plugins:
   - serverless-python-requirements
custom:
   pythonRequirements:
      dockerizePip: true
      layer: true

在這裡,dockerizePip - true 啟用 docker 的使用,並允許您在 docker 容器中打包所有依賴項。我們在上一章討論了使用 docker 打包。layer - true 告訴 serverless python 依賴項應儲存在單獨的層中。現在,在這一點上,您可能想知道 serverless 如何理解要打包哪些依賴項?答案如外掛章節所述,在於 requirements.txt 檔案中。

定義層外掛和自定義配置後,您可以按如下方式將層新增到 serverless 中的各個函式中:

functions:
   hello:
      handler: handler.hello
      layers:
         - { Ref: PythonRequirementsLambdaLayer }

關鍵字 PythonRequirementsLambdaLayer 來自 CloudFormation 參考。通常,它源自層的名稱。語法為 'LayerNameLambdaLayer'(標題大小寫,無空格)。在我們的例子中,由於層名稱是 python 需求,因此引用變為 PythonRequirementsLambdaLayer。如果您不確定 lambda 層的名稱,可以透過以下步驟獲取:

  • 執行 sls package

  • 開啟 .serverless/cloudformation-template-update-stack.json

  • 搜尋 'LambdaLayer'

在同一區域中的另一個函式中使用現有層

正如我在開頭提到的,層真正酷的一點是能夠在您的函式中使用現有層。這可以透過使用現有層的 ARN 輕鬆完成。使用 ARN 將現有層新增到函式的語法非常簡單:

functions:
   hello:
      handler: handler.hello
      layers:
         - arn:aws:lambda:region:XXXXXX:layer:LayerName:Y

就是這樣。現在,具有指定 ARN 的層將與您的函式一起工作。如果層包含 NumPy 庫,您可以繼續在您的“hello”函式中呼叫 import numpy。它將執行而不會出現任何錯誤。

如果您想知道從哪裡可以獲取 ARN,實際上非常簡單。只需導航到 AWS 控制檯中包含該層的函式,然後單擊“層”。

Layer ARN

當然,如果層不屬於您的賬戶,則需要公開共享或專門與您的賬戶共享。稍後將詳細介紹。

此外,請記住,層應與您的應用程式相容。不要期望與 node.js 執行時相容的層能夠與在 python3.6 執行時中建立的函式一起執行。

非需求/通用層

如開頭所述,層的主要功能是隔離程式碼塊。因此,它們不需要僅包含依賴項。它們可以包含您指定的任何程式碼段。在 custom 中的 pythonRequirements 中呼叫 layer: trueserverless-python-requirements 外掛實現的一種快捷方式。但是,要建立通用層,serverless.yml 中的語法(如 serverless 文件 中所述)如下:

layers:
   hello:
      path: layer-dir # required, path to layer contents on disk
      name: ${opt:stage, self:provider.stage, 'dev'}-layerName # optional, Deployed Lambda layer name
      description: Description of what the lambda layer does # optional, Description to publish to AWS
      compatibleRuntimes: # optional, a list of runtimes this layer is compatible with
         - python3.8
      licenseInfo: GPLv3 # optional, a string specifying license information
      # allowedAccounts: # optional, a list of AWS account IDs allowed to access this layer.
      #   - '*'
      # note: uncommenting this will give all AWS users access to this layer unconditionally.
      retain: false # optional, false by default. If true, layer versions are not deleted as new ones are created

由於提供了註釋,因此各種配置引數不言而喻。除了“path”之外,所有其他屬性都是可選的。path 屬性是您希望從應用程式程式碼中隔離的任意目錄的路徑。它將被壓縮併發布為您的層。例如,在 serverless 上的示例專案 中,他們將 FFmpeg 工具託管在一個層中,他們在名為“layer”的單獨資料夾中下載該工具,並在 path 屬性中指定該資料夾。

layers:
   ffmpeg:
      path: layer

如前所述,我們可以在 layers 屬性中新增最多 5 個層。

要將這些通用層用於您的函式,您可以再次使用 CloudFormation 參考或指定 ARN。

允許其他賬戶訪問層

只需在 'allowedAccounts' 屬性中提及賬戶編號,即可為更多賬戶提供對您的層的訪問許可權。例如:

layers:
   testLayer:
      path: testLayer
      allowedAccounts:
         - 999999999999 # a specific account ID
         - 000123456789 # a different specific account ID

如果要使層可公開訪問,可以在 allowedAccounts 中新增 '*':

layers:
   testLayer:
      path: testLayer
      allowedAccounts:
      - '*'

參考資料

廣告