3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

terraform-aws-modules/lambda/aws を利用してuv管理のPython Lambdaのデプロイ

Last updated at Posted at 2025-02-04

TerraformでLambdaをデプロイするときに、AWS Lambda Terraform moduleを使っていて、uvで管理しているPythonコードをLambdaでデプロイしたい人向けです。

現時点のバージョンである 7.20.1 を前提として書きます。

最初に

以下のIssueが対応されれば、公式で機能提供されるようになると思いますので、必要な人はウォッチしておくと良いかもです。

対応方針

現時点では対応されていないので commands を上手く使って実装することにしました。

image.png

それに伴い、裏の仕様も確認する必要あったのでコードを見ていたのですが、以下の package.py ファイルを読みながら検討すると commands に何を渡せば良いかわかりやすいです。

対応してみる

module以下のようなディレクトリ構成を想定しています。

ディレクトリ構成

uvを利用したシンプルな構成

module/lambda/
├── code
│   ├── .python-version
│   ├── pyproject.toml
│   ├── src
│   │   └── main.py
│   └── uv.lock
└── main.tf

Pythonコード

シンプルに requests を利用するコードです。

src/main.py
import requests


def handler(event: dict, context: dict) -> None:
    resp = requests.get("http://checkip.amazonaws.com/")
    print(f"{resp.text=}")
pyproject.toml
[project]
name = "code"
version = "0.1.0"
readme = "README.md"
requires-python = ">=3.11"
dependencies = ["requests>=2.32.3"]

[dependency-groups]
dev = ["types-requests>=2.32.0.20241016"]

Terraform

variable "s3_bucket" {
  type = string
}
variable "s3_lambda_package_prefix" {
  type = string
}

locals {
  function_name = "lambda-python-uv"
  role_name     = "lambda-python-uv"
  runtime       = "python3.11"
}

data "aws_iam_policy_document" "this" {
  statement {
    actions = ["sts:AssumeRole"]

    principals {
      type        = "Service"
      identifiers = ["lambda.amazonaws.com"]
    }
  }
}

resource "aws_iam_role" "this" {
  name               = local.role_name
  assume_role_policy = data.aws_iam_policy_document.this.json
}

# Lambda のベーシック実行ポリシー(AWS 管理ポリシー)をアタッチ
resource "aws_iam_role_policy_attachment" "this" {
  policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
  role       = aws_iam_role.this.name
}

# コードをLambda にデプロイするためのパッケージを作成
module "package" {
  source  = "terraform-aws-modules/lambda/aws"
  version = "7.20.1"


  runtime                  = local.runtime
  create_role              = false
  create_function          = false
  create_package           = true
  recreate_missing_package = false
  store_on_s3              = true
  s3_bucket                = var.s3_bucket


  source_path = [
    {
      path = "${path.module}/code"
      commands = [
        "mkdir -p ./dist/",
        "cp -a ./src/ ./dist/",
        "uv export --no-dev --format requirements-txt > ./dist/requirements.txt",
        "uv run pip install --no-compile --no-deps --prefix= --target=./dist --requirement=./dist/requirements.txt",
        ":zip ./dist/",
        "rm -fR ./dist/"
      ]
    }
  ]
}

# Lambda 関数を作成
module "lambda" {
  source  = "terraform-aws-modules/lambda/aws"
  version = "7.20.1"

  function_name            = local.function_name
  handler                  = "src.main.handler"
  runtime                  = local.runtime
  lambda_role              = aws_iam_role.this.arn
  create_role              = false
  create_function          = true
  create_package           = false
  s3_existing_package      = module.package.s3_object
  recreate_missing_package = false
  timeout                  = 60
  memory_size              = 256
}

ポイントとなっているのはこの部分です。

書いてあるとおりなのですが、dist というディレクトリを作成して、そこにソースコード入れて pip でモジュールも一緒に入れ込んでいます。ちなみにこの方法は ↑に書いた package.py の中の方法を参考にして、uv と組み合わせています。

      commands = [
        "mkdir -p ./dist/",
        "cp -a ./src/ ./dist/",
        "uv export --no-dev --format requirements-txt > ./dist/requirements.txt",
        "uv run pip install --no-compile --no-deps --prefix= --target=./dist --requirement=./dist/requirements.txt",
        ":zip ./dist/",
        "rm -fR ./dist/"
      ]

デプロイしてみる

AWS Lambda Terraform moduleを使って、pippoetry 使った時と同じようにPythonパッケージがフラットに入った状態でデプロイできています。

image.png

実行すると正常終了して、requests モジュールでGlobal IPが取得できています。

image.png

コードの構成によっては調整必要な場合もあるかもしれませんが、この方法を参考に package.py を参考に構成考えれば解決できると思います。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?