你之前肯定寫過這段程式碼。當 S3 事件觸發時,你的 Lambda 函數被喚醒,它做的第一件事就是將一個檔案下載到/tmp目錄。處理該文件,上傳處理結果,然後清理/tmp目錄,以免空間不足。對管道中的每個檔案、每次呼叫、每個函數重複此過程。

S3 文件改變了這一切。你可以將 S3 儲存桶掛載為本機檔案系統,Lambda 程式碼只需使用open()函數即可。我建立了一組 AI 程式碼審查代理,它們透過掛載的 S3 儲存桶共享工作空間,並由一個持久化函數進行協調。文件存取程式碼是整個專案中最為枯燥的部分。這正是關鍵所在。

/tmp 稅

如果你曾經用 Lambda 建構過任何涉及 S3 資料的應用,你肯定知道其中的規律。你需要一個文件。但 S3 不直接提供文件,它提供的是物件。所以你需要將物件下載到/tmp目錄,進行處理,然後再將結果上傳回去。

# The old way: every Lambda developer has written this
import boto3

s3 = boto3.client("s3")

def lambda_handler(event, context):
    bucket = event["bucket"]
    key = event["key"]

    # Download to /tmp
    local_path = f"/tmp/{key.split('/')[-1]}"
    s3.download_file(bucket, key, local_path)

    # Do your actual work
    with open(local_path) as f:
        content = f.read()
    result = process(content)

    # Upload the result
    s3.put_object(Bucket=bucket, Key=f"output/{key}", Body=result)

    # Clean up so you don't fill /tmp
    os.remove(local_path)

對於「讀取檔案和寫入檔案」這樣的操作來說,這未免太繁瑣了。當多個函數需要處理同一份資料時,情況會變得更糟。每個函數都會下載自己的副本,各自管理自己的/tmp目錄。如果處理的是大型程式碼庫或資料集,那麼 10GB 的/tmp目錄空間很快就會被耗盡。

如果我不提那些能讓這個過程更輕鬆的庫,那就太失職了。像s3fssmart_open這樣的工具抽象化了其中的一些細節。但它們底層仍然會進行 API 呼叫。你的程式碼仍然是透過 SDK 與 S3 通信,而不是直接透過檔案系統。

Lambda 的 S3 文件

S3 Files 是一項新功能,它會將您的 S3 儲存桶掛載為 Lambda 函數上的本機檔案系統。您的程式碼可以讀取和寫入掛載路徑(例如/mnt/workspace上的文件,而 S3 Files 會負責將資料同步回儲存桶。您寫入的變更會在幾分鐘內反映到 S3 中。對 S3 物件所做的變更會在幾秒鐘內反映到檔案系統中。

# The new way: just file paths
from pathlib import Path

WORKSPACE = Path("/mnt/workspace")

def lambda_handler(event, context):
    # Read directly from the mount
    content = (WORKSPACE / "source" / "app.py").read_text()
    result = process(content)

    # Write directly to the mount
    (WORKSPACE / "output" / "result.json").write_text(result)

無需 boto3 進行文件存取。無需管理/tmp目錄。無需上傳步驟。檔案系統本身就是介面。

S3 Files 底層則是基於 Amazon EFS 建置。它透過將工作集快取到高效能儲存上,為活躍資料提供亞毫秒延遲。對於大型順序讀取操作,它直接從 S3 串流傳輸資料。您既能獲得文件系統語義,又能享受 S3 的持久性和經濟性優勢。

不過,要注意的是,S3 檔案服務需要一個 VPC。您的 Lambda 函數必須與掛載目標位於同一個 VPC 中,並且您需要一個 NAT 閘道才能存取外部網際網路。

說實話,身為無伺服器架構開發者,我通常不太喜歡 VPC。但 AWS 這些年來已經掃清了大部分障礙。連接到 VPC 的 Lambda 函數不再像以前那樣有冷啟動延遲。網路配置也簡化成了只需編寫一次的樣板程式碼。考慮到 S3 文件儲存帶來的諸多好處,這點犧牲是值得的。趕快取得一個可重複使用的網路模板,然後繼續你的專案吧!

我們正在建立什麼

我想用比「讀取 CSV 文件」更有趣的方式測試 S3 文件,所以我建立了一個無伺服器程式碼審查系統。你把它指向一個公開的 GitHub 程式碼庫,然後就會發生三件事:

  1. 持久編排器函數會將儲存庫複製到共用的 S3 檔案工作區。

  2. 安全審查代理和風格審查代理並行分析程式碼。

  3. 結果以 JSON 檔案的形式保存在同一個工作區中,並同步回 S3。

所有三個 Lambda 函數都掛載同一個 S3 儲存桶。編排器寫入文件,代理讀取文件。函數之間不傳遞 S3 金鑰,也不下載到/tmp目錄。文件系統充當協調層。

這些代理程式使用 Strands Agents SDK 和 Amazon Bedrock。每個代理程式都擁有自訂的檔案工具,這些工具操作掛載路徑,Claude 會決定讀取哪些檔案、分析哪些檔案以及寫入哪些檔案。編排器使用 Lambda 持久化函數來協調工作流程,並實作自動檢查點機制。

完整原始碼位於 GitHub: singledigit/lambda-s3-files-example

SAM模板

IaC(基礎設施即程式碼)部分迭代次數最多。 S3 檔案是全新的,CloudFormation 資源類型尚未納入程式碼檢查工具。以下是我總結的經驗教訓。

資源鏈

要讓 S3 檔案與 Lambda 協同工作,您需要以下五個資源:

  1. 已啟用版本控制的S3 儲存桶(必要)

  2. 用於存取 S3 檔案儲存桶的IAM 角色

  3. S3 檔案檔案系統,用於連接儲存桶和 NFS。

  4. 在每個可用區(網路端點)安裝目標

  5. 控制 Lambda 的 POSIX 身分的存取點

資源類型分別為AWS::S3Files::FileSystemAWS::S3Files::MountTargetAWS::S3Files::AccessPoint 。您的 IDE 的 CloudFormation 程式碼檢查器目前還無法辨識它們。請忽略紅色波浪線。

IAM角色陷阱

S3 檔案 IAM 角色信任的是elasticfilesystem.amazonaws.com ,而不是s3files.amazonaws.com 。這讓我很困惑。 S3 檔案建構於 EFS 之上,因此信任關係是透過 EFS 服務主體建立的。

S3FilesRole:
  Type: AWS::IAM::Role
  Properties:
    Path: /service-role/
    AssumeRolePolicyDocument:
      Version: '2012-10-17'
      Statement:
        - Sid: AllowS3FilesAssumeRole
          Effect: Allow
          Principal:
            Service: elasticfilesystem.amazonaws.com
          Action: sts:AssumeRole
          Condition:
            StringEquals:
              aws:SourceAccount: !Ref AWS::AccountId
            ArnLike:
              aws:SourceArn: !Sub 'arn:aws:s3files:${AWS::Region}:${AWS::AccountId}:file-system/*'

該角色需要具備讀取和寫入 S3 儲存桶的權限。使用aws:ResourceAccount條件將其範圍限定到您特定的儲存桶 ARN。

存取點

這是 Lambda 函數的關鍵部分。存取點控制函數執行所使用的 POSIX 身份,並建立一個可寫入的根目錄。如果沒有它,Lambda 可以掛載檔案系統,但無法寫入資料。

S3FilesAccessPoint:
  Type: AWS::S3Files::AccessPoint
  Properties:
    FileSystemId: !GetAtt S3FileSystem.FileSystemId
    PosixUser:
      Uid: '1000'
      Gid: '1000'
    RootDirectory:
      Path: /lambda
      CreationPermissions:
        OwnerUid: '1000'
        OwnerGid: '1000'
        Permissions: '755'

CreationPermissions屬性至關重要。它會在客戶端首次連接時自動建立具有正確所有權的/lambda目錄。如果沒有此屬性,根目錄的擁有者將是 root 使用者(UID 0),而 Lambda(透過存取點以 UID 1000 執行)將無法建立子目錄。

Lambda 設定

在 Lambda 函數端, FileSystemConfigs接受存取點 ARN(而不是檔案系統 ARN)和本機掛載路徑:

OrchestratorFunction:
  Type: AWS::Serverless::Function
  DependsOn:
    - MountTargetA
    - MountTargetB
  Properties:
    FileSystemConfigs:
      - Arn: !GetAtt S3FilesAccessPoint.AccessPointArn
        LocalMountPath: /mnt/workspace
    VpcConfig:
      SecurityGroupIds:
        - !GetAtt NetworkingStack.Outputs.LambdaSGId
      SubnetIds:
        - !GetAtt NetworkingStack.Outputs.PrivateSubnetAId
        - !GetAtt NetworkingStack.Outputs.PrivateSubnetBId

掛載目標上的DependsOn屬性非常重要。 Lambda 函數必須等到掛載目標可用後才能掛載檔案系統,而建立這些目標大約需要五分鐘。

我本來可以做得更好

S3 Files 非常適合這種使用情境。它允許 Lambda 函數之間共用文件,而無需呼叫 S3 API。但有幾點要注意:

一致性模型至關重要。 S3文件提供接近開放的一致性。如果函數 A 寫入一個文件,函數 B 立即讀取它,則 B 可能無法取得最新版本。在我的用例中,編排器先寫入,代理隨後執行,因此順序是自然的。如果您需要並發寫入者之間的即時協調,則需要不同的模式。

VPC 增加了一些複雜性。雖然不多,但確實存在。你需要子網路、安全群組以及用於網際網路存取的 NAT 閘道。最好一次性建立模板並重複使用。

冷啟動沒問題。以前掛載到 VPC 的 Lambda 函數冷啟動需要 10 秒以上,這個問題幾年前就解決了。現在掛載檔案系統後,我的函數冷啟動只需不到 2 秒。

完整程式碼位於github.com/singledigit/lambda-s3-files-example 。克隆、部署並指向一個程式碼倉庫。代理程式會告訴你它們的想法。


原文出處:https://dev.to/aws/lambda-just-got-a-file-system-i-put-ai-agents-on-it-1ej8


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝16   💬11   ❤️2
543
🥈
alicec
📝1   ❤️2
77
🥉
我愛JS
💬1  
4
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次
📢 贊助商廣告 · 我要刊登