DuckDB 中的 AWS 凭证链

💡 原文英文,约1000词,阅读约需4分钟。
📝

内容提要

DuckDB 读写 S3 上的 Parquet 文件需要 AWS 凭证。除硬编码密钥外,可用 `PROVIDER credential_chain` 让 DuckDB 按 AWS SDK 顺序自动查找凭证:环境变量、IRSA Web Identity、SSO 配置文件、ECS 任务角色、EC2 实例元数据,取首个可用者。该逻辑位于 aws 扩展,也适用于 GCS 和 R2。IRSA 通过注解 ServiceAccount 注入角色与令牌,由 kubelet 和 SDK 自动轮换。DuckLake 本地开发用静态密钥,生产用凭证链。

🔎

延伸解读

凭证链的自动发现机制

DuckDB 的凭证链按固定顺序查找 AWS 凭证:环境变量、IRSA Web Identity、SSO 配置文件、ECS 任务角色、EC2 实例元数据,取首个可用者。这意味着你无需在代码中指定凭证来源,只需使用 PROVIDER credential_chain,运行时环境会自动决定使用哪一步。例如,在本地笔记本上会使用 SSO 配置文件,在带 IRSA 的 Kubernetes Pod 中会使用 Web Identity 令牌。这种设计简化了跨环境部署,但要求环境正确配置了相应的凭证源。

IRSA 的两层自动轮换

IRSA 通过注解 ServiceAccount 注入角色 ARN 和令牌文件路径。Kubelet 负责轮换 JWT 令牌文件(默认 24 小时过期,约 80% TTL 时刷新),而 AWS SDK 或 DuckDB 负责在 STS 会话过期时(通常 1 小时)刷新临时凭证。这两层轮换都是自动的,应用代码无需处理。这降低了长期凭证泄露的风险,但需要确保 Pod 能访问 STS 服务,并且 ServiceAccount 注解正确。

凭证链的扩展性与适用场景

凭证链逻辑位于 DuckDB 的 aws 扩展中,不仅适用于 S3,也适用于 GCS 和 Cloudflare R2 等 S3 兼容存储。当创建 secret 时指定 PROVIDER credential_chain,DuckDB 会自动加载 aws 扩展来处理 STS 调用和凭证刷新。因此,如果你使用多种云存储,可以统一使用凭证链来管理访问,但需注意不同存储的端点配置可能影响凭证链的触发条件。

本地开发与生产环境的配置差异

在 DuckLake 结合 S3 存储的服务中,本地开发通常使用静态密钥指向本地 S3 兼容存储(如 MinIO),而生产环境使用凭证链让运行时环境提供凭证。决策逻辑是:如果配置了 S3 端点(指向本地存储),则使用静态密钥;如果没有端点和静态密钥,则使用凭证链。这种区分避免了在生产中硬编码密钥,同时保留了本地开发的便利性。

❓

Q&A

DuckDB 如何在不硬编码密钥的情况下访问 S3 上的 Parquet 文件?

可以使用 `PROVIDER credential_chain` 创建 S3 密钥,让 DuckDB 按 AWS SDK 的顺序自动查找凭证,依次检查环境变量、IRSA Web Identity、SSO 配置文件、ECS 任务角色、EC2 实例元数据,取第一个可用的凭证。

AWS 凭证链的查找顺序具体是怎样的?

顺序为:1. 环境变量(AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY,可选 AWS_SESSION_TOKEN);2. Web Identity Token(IRSA,使用 AWS_ROLE_ARN 和 AWS_WEB_IDENTITY_TOKEN_FILE 调用 STS AssumeRoleWithWebIdentity);3. SSO/配置文件(~/.aws/config 和 ~/.aws/credentials);4. ECS 任务角色(通过 AWS_CONTAINER_CREDENTIALS_RELATIVE_URI 调用 ECS 元数据端点);5. EC2 实例元数据(IMDS,访问 http://169.254.169.254/latest/meta-data/iam/security-credentials/)。

IRSA 是如何让 Kubernetes Pod 获得 AWS 凭证的?

当 ServiceAccount 被注解了 IAM 角色 ARN 后,AWS 在 Pod 准入时修改 Pod 规格,注入两个环境变量:AWS_ROLE_ARN 和 AWS_WEB_IDENTITY_TOKEN_FILE。令牌文件包含 JWT,由 kubelet 定期轮换(默认 24 小时过期,约 80% TTL 时刷新)。凭证链在第二步读取该令牌,调用 STS AssumeRoleWithWebIdentity 获取临时凭证(AccessKeyId、SecretAccessKey、SessionToken),通常有效期为 1 小时。

凭证链中的凭证轮换是如何自动进行的?

有两层自动轮换:kubelet 大约每 24 小时轮换磁盘上的 JWT 令牌文件;AWS SDK/DuckDB 在 STS 会话过期时(约每 1 小时)刷新会话。应用程序无需编写任何代码,SDK 会透明地处理令牌交换和凭证刷新。

DuckDB 的凭证链逻辑位于哪里?是否支持其他云存储?

凭证链逻辑位于 DuckDB 的 aws 扩展(duckdb/duckdb-aws 仓库),而非核心 DuckDB。核心 DuckDB 通过查找表将 `PROVIDER credential_chain` 映射到 aws 扩展。因此,凭证链也适用于 GCS 和 Cloudflare R2 等任何 DuckDB 支持的 S3 兼容存储。

在 DuckLake 中,本地开发和生产的凭证配置有何不同?

本地开发使用静态密钥指向本地 S3 兼容存储(如 MinIO),例如设置 KEY_ID、SECRET、ENDPOINT 等。生产环境使用凭证链(`PROVIDER credential_chain`)并配合 IRSA 或平台提供的凭证。决策逻辑:如果配置了 S3 端点(指向本地存储),则使用静态密钥;如果没有端点和静态密钥,则使用凭证链,由运行时环境提供凭证。

🏷️

标签

➡️

继续阅读