在 AWS 上运行关键业务应用,却对谁在访问、性能瓶颈在哪、错误从何而来一无所知?启用 Application Load Balancer (ALB) 访问日志 是解决这些问题的第一步,也是实现可观测性、安全合规和性能优化的基石。

本文将基于 AWS 官方最新文档,为你提供一份超详细、零踩坑的 ALB 访问日志配置指南,涵盖所有 Region 的特殊要求和最佳实践。


一、为什么必须配置 ALB 访问日志?

ALB 访问日志会记录每一个经过负载均衡器的 HTTP/HTTPS 请求的完整生命周期,包括:

  • 客户端信息:IP 地址、端口、User-Agent。

  • 请求详情:时间戳、HTTP 方法、请求路径、协议。

  • 处理过程:请求处理时间、目标处理时间、响应时间。

  • 路由结果:目标组、目标实例/容器 IP、响应状态码。

  • 安全信息:TLS 版本、Cipher 套件、ALB 选择的路由规则。

核心价值

  • 故障排查:快速定位 5xx 错误来源,分析慢请求。

  • 安全审计:追踪可疑 IP,分析攻击模式。

  • 性能优化:识别瓶颈,优化后端服务。

  • 成本分析:了解流量模式,优化资源配置。

  • 合规要求:满足数据留存和审计的法规要求。


二、配置前的核心准备:S3 存储桶

ALB 访问日志只能存储在 Amazon S3 中。配置前,你必须先创建或准备好一个 S3 存储桶,并满足以下硬性要求

1. 创建 S3 存储桶

  1. 登录 AWS S3 控制台

  2. 点击 “Create bucket”

  3. Bucket name: 输入一个全局唯一的名称(如 my-company-alb-logs-prod-us-east-1)。

  4. AWS Region: 必须选择与你的 ALB 相同的区域。跨区域会导致配置失败。

  5. Default encryption: 必须选择 “Amazon S3-managed keys (SSE-S3)”。这是目前 ALB 访问日志唯一支持的服务端加密方式。不要选择 KMS 或其他选项。

  6. 其他设置(如 Block Public Access)可根据你的安全策略配置,但需注意不影响 ALB 写入权限。

  7. 点击 “Create bucket”

重要提示:桶和 ALB 可以属于不同的 AWS 账户,这在跨账户管理场景中非常有用。


三、关键一步:为 S3 桶配置正确的 Bucket Policy

这是配置过程中最容易出错的部分!AWS 根据你所在的 RegionZone 类型(标准可用区、Local Zone、Outpost),要求使用不同的 Principal(主体)

选择正确的策略模板

请根据你的 ALB 所在的区域,选择对应的策略:

情况 A:适用于大多数标准区域(如 us-east-1, eu-west-1, ap-southeast-1 等)

这些区域需要使用 Elastic Load Balancing 的特定账户 ID 作为 Principal。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::<ELB_ACCOUNT_ID>:root"
      },
      "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::<YOUR_BUCKET_NAME>/AWSLogs/<YOUR_AWS_ACCOUNT_ID>/*"
    }
  ]
}

你需要替换以下内容:

  • <ELB_ACCOUNT_ID>: 替换为对应区域的 ELB 账户 ID。例如:

    • us-east-1 (N. Virginia): 127311923021

    • us-west-2 (Oregon): 797873946194

    • eu-central-1 (Frankfurt): 054676820928

    • ap-southeast-1 (Singapore): 114774131450

    • (完整列表请参考官方文档或上文知识库)

  • <YOUR_BUCKET_NAME>: 你的 S3 桶名称。

  • <YOUR_AWS_ACCOUNT_ID>: 你自己的 AWS 账户 ID(12位数字)。

情况 B:适用于较新的区域(如 ap-south-2, eu-south-2, il-central-1, me-central-1 等)

这些较新的区域使用统一的服务主体 logdelivery.elasticloadbalancing.amazonaws.com

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "logdelivery.elasticloadbalancing.amazonaws.com"
      },
      "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::<YOUR_BUCKET_NAME>/AWSLogs/<YOUR_AWS_ACCOUNT_ID>/*"
    }
  ]
}

只需替换 <YOUR_BUCKET_NAME><YOUR_AWS_ACCOUNT_ID>

情况 C:适用于 AWS Outposts

如果你的 ALB 部署在 Outposts 上,则使用 logdelivery.elb.amazonaws.com 并附加一个特殊条件。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "logdelivery.elb.amazonaws.com"
      },
      "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::<YOUR_BUCKET_NAME>/AWSLogs/<YOUR_AWS_ACCOUNT_ID>/*",
      "Condition": {
        "StringEquals": {
          "s3:x-amz-acl": "bucket-owner-full-control"
        }
      }
    }
  ]
}

情况 D:适用于 AWS GovCloud (US) 区域

GovCloud 使用特殊的 ARN 格式 arn:aws-us-gov:iam::...

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws-us-gov:iam::<ELB_GOV_ACCOUNT_ID>:root"
      },
      "Action": "s3:PutObject",
      "Resource": "arn:aws-us-gov:s3:::<YOUR_BUCKET_NAME>/AWSLogs/<YOUR_AWS_ACCOUNT_ID>/*"
    }
  ]
}
  • <ELB_GOV_ACCOUNT_ID>:

    • us-gov-west-1: 048591011584

    • us-gov-east-1: 190560391635

关于 “Prefix” 的重要说明

如果你计划在启用日志时指定一个前缀(例如 prod/alb-logs/),那么在 Bucket Policy 的 Resource 字段中,必须包含这个前缀。

  • 无前缀arn:aws:s3:::my-bucket/AWSLogs/123456789012/*

  • 有前缀 (如 my-prefix)arn:aws:s3:::my-bucket/my-prefix/AWSLogs/123456789012/*

关于 “Deny” 策略的警告

如果你的 S3 桶策略中存在 Effect: "Deny" 且使用了 NotPrincipal必须logdelivery.elasticloadbalancing.amazonaws.com 添加到允许列表中,否则 ALB 将无法写入日志。

{
  "Effect": "Deny",
  "NotPrincipal": {
    "Service": [
      "logdelivery.elasticloadbalancing.amazonaws.com", // 必须包含此项
      "your-other-service.amazonaws.com"
    ]
  },
  "Action": "s3:*",
  "Resource": "..."
}

如何附加策略

  1. 在 S3 控制台,选中你的桶。

  2. 进入 “Permissions” 标签页。

  3. 找到 “Bucket policy”,点击 “Edit”

  4. 将你选择并修改好的 JSON 策略粘贴进去。

  5. 点击 “Save changes”

四、正式启用 ALB 访问日志

准备工作完成后,就可以为你的 ALB 启用日志功能了。

方法一:通过 AWS 控制台

  1. 登录 AWS EC2 控制台

  2. 在左侧导航栏,选择 “Load Balancers”

  3. 选中你要配置的 ALB,进入其详情页面。

  4. 切换到 “Attributes” 标签页。

  5. 点击 “Edit”

  6. “Monitoring” 部分,找到 “Access logs”,将其开关打开。

  7. “S3 URI” 输入框中,输入你的 S3 桶地址:

    • 无前缀: s3://your-bucket-name

    • 有前缀: s3://your-bucket-name/your-prefix

    重要:前缀不能包含 AWSLogs 字符串,这是系统保留路径。

  8. 点击 “Save changes”

方法二:通过 AWS CLI

aws elbv2 modify-load-balancer-attributes \
    --load-balancer-arn <your-alb-arn> \
    --attributes \
        Key=access_logs.s3.enabled,Value=true \
        Key=access_logs.s3.bucket,Value=<your-bucket-name> \
        Key=access_logs.s3.prefix,Value=<your-prefix> # 如果没有前缀,可以省略此行

五、验证配置是否成功

AWS 提供了一个非常贴心的验证机制。启用日志后,ALB 会自动尝试在你的 S3 桶中创建一个名为 ELBAccessLogTestFile 的测试文件。

如何验证:

  1. 回到 S3 控制台。

  2. 打开你为日志配置的桶。

  3. 根据你是否设置了前缀,导航到对应路径:

    • 无前缀: AWSLogs/<your-account-id>/ELBAccessLogTestFile

    • 有前缀: <your-prefix>/AWSLogs/<your-account-id>/ELBAccessLogTestFile

  4. 如果你看到了这个文件,恭喜你!配置成功✅。

  5. 如果没有看到,请检查:

    • Bucket Policy 是否完全正确(特别是 Region、Account ID、Resource ARN)。

    • S3 桶的加密方式是否为 SSE-S3。

    • ALB 和 S3 桶是否在同一区域。


六、重要注意事项与最佳实践

  1. 删除桶前务必先禁用日志:如果你要删除用于存储日志的 S3 桶,必须先在 ALB 属性中禁用访问日志。否则,如果有人创建了一个同名的桶并配置了正确的策略,你的 ALB 日志可能会被写入到别人的桶中,造成数据泄露!

  2. 配置 S3 生命周期规则:日志会不断累积,产生存储费用。建议配置生命周期规则,在一定时间后(如 30 天、90 天)自动删除或转为 Glacier 存档。

  3. 启用 S3 服务器访问日志(可选但推荐):为你的日志桶本身也启用 S3 访问日志,可以追踪是谁在访问或下载这些 ALB 日志文件,增强安全性。

  4. 使用 Athena 进行分析:日志存储在 S3 中,天然适合使用 Amazon Athena 进行 SQL 查询分析。你可以轻松统计请求数、错误率、热门 URL 等。

  5. 日志延迟:访问日志是按小时生成的,因此你看到的日志文件会有最多 1 小时的延迟。


结语

至此,你已经成功为你的 AWS ALB 配置了访问日志!虽然步骤看似繁琐,尤其是 Bucket Policy 部分需要根据 Region 仔细选择,但这份详细的指南应该能帮你避开所有常见的坑。

开启日志只是第一步,接下来你可以结合 CloudWatch、Athena、OpenSearch 或第三方工具(如 Datadog, Splunk)构建强大的监控和告警系统,让你的应用运行状态尽在掌握。

官方文档参考Enable Access Logs for Your Application Load Balancer

立即行动,为你的生产环境 ALB 启用访问日志吧!