1. 简介

Terraform 是一个基础设施即代码(Infrastructure as Code)工具,可以用于创建、修改和管理基础设施。而 AWS Lambda 是一项无服务器计算服务,允许你在无需预置或管理服务器的情况下运行代码。它会根据工作负载自动扩展应用,响应每个触发事件执行代码。

将 Lambda 的无服务器特性与 Terraform 的基础设施即代码(IaC)方法结合,开发者可以获得以下优势:

✅ 版本化的基础设施配置
✅ 与应用代码一起维护
✅ 复制相同配置的环境
✅ 自动化 CI/CD 流程中的基础设施变更
✅ 跟踪基础设施状态

本教程将讲解如何使用 Terraform 配置 AWS Lambda 函数。所有命令均在 Ubuntu 22.04 上测试通过,AWS CLI 版本为 1.37.11。


2. 前提条件

在开始使用 Terraform 配置 AWS Lambda 之前,需要确保满足以下条件:

  • 有效的 AWS 账户,并具有适当的权限
  • Terraform 已安装在本地:
$ terraform --version
Terraform v1.9.8
on linux_amd64
  • AWS CLI 已安装并配置了管理员权限:
$ aws --version
aws-cli/1.37.11 Python/3.10.12 Linux/5.15.0-82-generic botocore/1.36.11

此外,建议具备基本的 AWS 云平台和 Terraform 使用经验。


3. IAM 角色配置

虽然可以使用 AWS CLI 中已配置的管理员凭据,但遵循最小权限原则并使用专用 IAM 用户是 AWS 的最佳实践

我们创建一个名为 terraform-user 的专用 IAM 用户,并赋予其管理 AWS Lambda 的有限权限:

$ aws iam create-user --user-name terraform-user
{
    "User": {
        "Path": "/",
        "UserName": "terraform-user",
        "UserId": "AIDA4T4OCLX5W42FFGY62",
        "Arn": "arn:aws:iam::<ACCOUNT_ID>:user/terraform-user",
        "CreateDate": "2025-02-14T15:49:05Z"
    }
}

接下来,创建一个名为 aws-lambda-terraform 的目录用于存放示例文件:

$ mkdir ~/aws-lambda-terraform && cd ~/aws-lambda-terraform

在该目录下创建一个名为 terraform-policy.json 的 JSON 文件,用于定义 terraform-user 所需权限:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "lambda:CreateFunction",
                "lambda:UpdateFunctionCode",
                "lambda:DeleteFunction",
                "lambda:AddPermission",
                "lambda:RemovePermission",
                "lambda:GetFunction",
                "lambda:ListVersionsByFunction",
                "lambda:GetFunctionCodeSigningConfig",
                "lambda:GetPolicy",
                "lambda:InvokeFunction",
                "events:PutRule",
                "events:PutTargets",
                "events:DeleteRule",
                "events:RemoveTargets",
                "events:DescribeRule",
                "events:ListRules",
                "events:ListTagsForResource",
                "events:ListTargetsByRule",
                "iam:CreateRole",
                "iam:PutRolePolicy",
                "iam:AttachRolePolicy",
                "iam:DeleteRole",
                "iam:DetachRolePolicy",
                "iam:GetRole",
                "iam:PassRole",
                "iam:ListRolePolicies",
                "iam:ListAttachedRolePolicies",
                "iam:ListInstanceProfilesForRole",
                "logs:CreateLogGroup",
                "logs:DescribeLogGroups"
            ],
            "Resource": [
                "arn:aws:lambda:us-east-1:<ACCOUNT_ID>:function:hello_lambda",
                "arn:aws:events:us-east-1:<ACCOUNT_ID>:rule/*",
                "arn:aws:iam::<ACCOUNT_ID>:role/lambda_exec_role",
                "arn:aws:logs:us-east-1:<ACCOUNT_ID>:log-group:*"
            ]
        }
    ]
}

使用 AWS CLI 创建策略并绑定到 terraform-user

$ aws iam create-policy \
  --policy-name TerraformLambdaPolicy \
  --policy-document file://terraform-policy.json
$ aws iam attach-user-policy \
  --user-name terraform-user \
  --policy-arn "arn:aws:iam::<ACCOUNT_ID>:policy/TerraformLambdaPolicy"

创建访问密钥并配置默认凭据:

$ aws iam create-access-key --user-name terraform-user
{
    "AccessKey": {
        "UserName": "terraform-user",
        "AccessKeyId": "AKIA4T4OCLX5VF63ZO4K",
        "Status": "Active",
        "SecretAccessKey": <SECRET_ACCESS_KEY>,
        "CreateDate": "2025-02-14T15:58:24Z"
    }
}

配置 AWS CLI:

$ aws configure
AWS Access Key ID [****************ZO4K]: 
AWS Secret Access Key [****************LRvO]: 
Default region name [us-east-1]: 
Default output format [json]:

至此,我们已完成 Terraform 操作 AWS Lambda 所需的最小权限配置。


4. 项目结构与初始化

项目结构如下:

aws-lambda-terraform/
├── main.tf         # Terraform 主配置
├── outputs.tf      # 输出定义
└── lambda/
    └── hello_lambda.py  # Lambda 函数代码

main.tf 中配置 AWS Terraform 提供商:

terraform {
  required_providers {
    aws = {
        source = "hashicorp/aws"
        version = "~> 5.0"
    }
  }
}
provider "aws" {
  region = "us-east-1"
}

该配置将 AWS 作为基础设施提供商,并指定所有资源部署在 us-east-1 区域。


5. Lambda 函数配置

5.1. Lambda 函数代码

Lambda 函数代码保存在 lambda/hello_lambda.py 中:

import json
import os

def lambda_handler(event, context):
    return {
        'statusCode': 200,
        'body': json.dumps({
            'message': 'Hello from Lambda!',
            'environment': os.getenv('ENV', 'default')
        })
    }

该函数接收 event 和 context 参数,返回一个兼容 API Gateway 的 JSON 响应。

5.2. Lambda IAM 角色配置

为 Lambda 函数创建执行角色:

resource "aws_iam_role" "lambda_exec" {
    name = "lambda_exec_role"

    assume_role_policy = jsonencode({
        Version = "2012-10-17"
        Statement = [{
            Action = "sts:AssumeRole"
            Effect = "Allow"
            Principal = {
                Service = "lambda.amazonaws.com"
            }
        }]
    })
}

resource "aws_iam_role_policy_attachment" "lambda_basic" {
    role = aws_iam_role.lambda_exec.name
    policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}

⚠️ 没有这个 IAM 配置,Lambda 将无法执行或写入日志

5.3. 资源定义

使用 archive_file 将 Lambda 函数打包为 ZIP 文件:

data "archive_file" "lambda_zip" {
  type = "zip"
  source_dir = "${path.module}/lambda"
  output_path = "${path.module}/lambda/lambda_function.zip"
}

创建 Lambda 函数资源:

resource "aws_lambda_function" "hello_lambda" {
  filename = data.archive_file.lambda_zip.output_path
  function_name = "hello_lambda"
  role = aws_iam_role.lambda_exec.arn
  handler = "hello_lambda.lambda_handler"
  runtime = "python3.9"
  source_code_hash = data.archive_file.lambda_zip.output_base64sha256

  environment {
    variables = {
      ENV = "test"
    }
  }
}

outputs.tf 中输出函数名称和 ARN:

output "lambda_function_name" {
  value = aws_lambda_function.hello_lambda.function_name
}

output "lambda_arn" {
  value = aws_lambda_function.hello_lambda.arn
}

5.4. 部署与测试

初始化 Terraform 并部署:

$ terraform init
$ terraform plan
$ terraform apply

测试 Lambda 函数:

$ aws lambda invoke \
  --function-name hello_lambda \
  --region us-east-1 \
  output.txt

查看输出:

$ cat output.txt
{"statusCode": 200, "body": "{\"message\": \"Hello from Lambda!\", \"environment\": \"test\"}"}

查看日志:

$ aws lambda invoke \
  --function-name hello_lambda \
  --region us-east-1 \
  --log-type Tail \
  output.txt | jq -r .LogResult | base64 --decode

6. Lambda 触发器配置

Lambda 的一大用途是响应特定事件(触发器)执行代码。常见的触发服务包括:

✅ Amazon S3(对象创建/删除)
✅ Amazon DynamoDB(表更新)
✅ Amazon API Gateway(API 调用)
✅ Amazon SNS(消息发布)
✅ Amazon EventBridge(定时事件)

6.1. 使用 EventBridge 配置定时触发器

添加定时规则:

resource "aws_cloudwatch_event_rule" "schedule_lambda" { 
  name = "scheduled_lambda_trigger"
  description = "Triggers Lambda every 5 minutes"
  schedule_expression = "rate(5 minutes)"
}

绑定 Lambda 函数作为目标:

resource "aws_cloudwatch_event_target" "lambda_target" {
  rule = aws_cloudwatch_event_rule.schedule_lambda.name
  target_id = "lambda_target"
  arn = aws_lambda_function.hello_lambda.arn
}

授予 EventBridge 调用 Lambda 的权限:

resource "aws_lambda_permission" "allow_cloudwatch" {
  statement_id = "AllowExecutionFromCloudWatch"
  action = "lambda:InvokeFunction"
  function_name = aws_lambda_function.hello_lambda.function_name
  principal = "events.amazonaws.com"
  source_arn = aws_cloudwatch_event_rule.schedule_lambda.arn
}

6.2. 测试触发器

应用配置:

$ terraform apply

验证规则状态:

$ aws events describe-rule --name scheduled_lambda_trigger

验证目标是否正确:

$ aws events list-targets-by-rule --rule scheduled_lambda_trigger

查看 AWS 控制台中的 Lambda 调用记录:

Lambda's recent invocations caused by the trigger set to run every 5 minutes.


7. 总结

本文介绍了如何使用 Terraform 配置 AWS Lambda 函数,包括:

✅ 部署 Python Lambda 函数
✅ 创建 IAM 角色与权限
✅ 配置定时触发器(EventBridge)
✅ 部署、测试与日志查看

通过 Terraform 实现了完整的 Lambda 基础设施管理,为构建可复用、可版本控制的 Serverless 架构打下基础。


原始标题:How To Set Up AWS Lambda Function in Terraform