亚马逊AWS官方博客

用 Kiro CLI 自动搭建 FluentBit 日志采集方案:两种 EKS 埋点数据落地 S3 Parquet 的实战对比

摘要:本文将展示如何使用 Kiro CLI(AWS 推出的 AI 驱动命令行助手)配合 Amazon EKS MCP Server,通过自然语言对话,自动完成两种 FluentBit 日志采集方案的规划、搭建和验证。你将看到: • 两种方案的架构差异和适用场景 • Kiro CLI 如何一步步驱动整个搭建过程 • 搭建复杂度和运行成本的量化对比 • AI 辅助运维带来的效率提升


一、引言:埋点数据采集的挑战

在互联网和移动应用开发中,埋点数据采集是产品分析、用户行为洞察和业务决策的基础。典型场景是:前端或后端服务产生 JSON 格式的事件日志(页面浏览、按钮点击、交易记录等),这些日志需要实时或准实时地汇聚到数据湖中,供下游的 Athena、Spark、Redshift Spectrum 等分析引擎查询。

Apache Parquet 已成为数据湖的事实标准存储格式——列式存储带来的压缩率和查询性能优势,使得同样的数据量在 S3 上的存储成本和 Athena 扫描成本都能降低 60-90%。

然而,从”EKS 上的应用日志”到”S3 上的 Parquet 文件”,中间的链路搭建并不简单:

  • Fluent Bit 原生 Parquet 支持需要自编译镜像,涉及 Apache Arrow C++ 库的交叉编译
  • Firehose 托管转换方案虽然免去了镜像构建,但需要配置 Glue Catalog、Firehose IAM Role、Delivery Stream 等多个 AWS 资源
  • 两种方案都涉及 IAM 权限、IRSA、K8s 部署、端到端验证等多个环节

对于一个 SA 或 DevOps 工程师来说,从零搭建任一方案,传统方式需要在 AWS 控制台、终端、文档之间反复切换,耗时数小时。

如果有一个 AI 助手,能理解你的需求,自动规划步骤,直接操作 EKS 集群和 AWS 资源,并在出错时帮你排查——整个过程会是什么样?

本文将展示如何使用 Kiro CLI(AWS 推出的 AI 驱动命令行助手)配合 Amazon EKS MCP Server,通过自然语言对话,自动完成两种 FluentBit 日志采集方案的规划、搭建和验证。你将看到:

  • 两种方案的架构差异和适用场景
  • Kiro CLI 如何一步步驱动整个搭建过程
  • 搭建复杂度和运行成本的量化对比
  • AI 辅助运维带来的效率提升

二、Kiro CLI:AI 驱动的云端运维助手

在深入方案搭建之前,先介绍本文的核心工具——Kiro CLI,以及它为什么能胜任这类复杂的云端运维任务。

2.1 什么是 Kiro CLI

Kiro 是 AWS 推出的 AI 驱动开发环境,提供 IDE 和 CLI 两种形态。Kiro CLI 是其命令行版本,运行在你的终端中,能够:

  • 通过自然语言对话理解你的需求
  • 读写本地文件、执行 Shell 命令
  • 连接外部工具和 AWS 服务
  • 自动规划多步骤任务并逐步执行

与传统的 ChatGPT 式对话不同,Kiro CLI 不只是”给建议”——它能直接动手:创建文件、执行 AWS CLI 命令、部署 K8s 资源、检查运行状态,形成一个完整的”对话 → 规划 → 执行 → 验证”闭环。

2.2 MCP:连接万物的协议层

Kiro CLI 的强大之处在于它的可扩展性。通过 Model Context Protocol (MCP)——一个由 Anthropic 提出的开放协议——Kiro 可以连接到各种外部工具服务器,获取实时数据和操作能力。

MCP 的核心思想是:让 AI 模型安全地访问外部工具和数据源,获得更好的上下文。

在本文的场景中,Kiro CLI 通过 MCP 连接了:

MCP Server 提供的能力
Amazon EKS MCP Server 管理 EKS 集群、部署 K8s 资源、查看 Pod 日志、排查故障
AWS Documentation MCP Server 搜索和阅读 AWS 官方文档,获取最新最佳实践

配置方式非常简单,在项目根目录的 .kiro/settings/mcp.json 中添加:

{
  "mcpServers": {
    "eks-mcp": {
      "command": "uvx",
      "args": [
        "mcp-proxy-for-aws@latest",
        "https://eks-mcp.us-west-2.api.aws/mcp",
        "--service", "eks-mcp",
        "--profile", "default",
        "--region", "us-west-2"
      ]
    },
    "aws-docs": {
      "command": "uvx",
      "args": ["awslabs.aws-documentation-mcp-server@latest"],
      "env": {
        "FASTMCP_LOG_LEVEL": "ERROR"
      }
    }
  }
}

配置完成后,Kiro CLI 就能在对话中自动调用这些工具——你不需要记住任何 kubectl 命令或 AWS CLI 语法。

2.3 Steering:让 AI 记住你的项目

在实际工作中,我们经常需要反复告诉 AI 助手项目的背景信息:”我们用的是 EKS 集群 eks-workshop,region 是 us-west-2,S3 bucket 是 eksfluentbit-logs-xxx……”

Kiro CLI 的 Steering 机制解决了这个问题。通过在 `.kiro/steering/` 目录下放置 Markdown 文件,你可以为 Kiro 提供持久化的项目知识:

.kiro/steering/
├── product.md          # 项目概述和目标
├── tech.md             # 技术栈和约定
└── eks-environment.md  # EKS 集群信息和 AWS 账户配置

例如,eks-environment.md 可以包含:

# EKS 环境信息
- 集群名称: eks-workshop
- Region: us-west-2
- S3 Bucket: eks-fluentbit-logs-<ACCOUNT_ID>
- Fluent Bit 自编译镜像: <ACCOUNT_ID>.dkr.ecr.us-west-2.amazonaws.com/fluent-bit-parquet:v6

有了 Steering,每次对话 Kiro 都会自动加载这些上下文,不需要你重复说明。Steering 支持三个层级:

  • Workspace 级别(.kiro/steering/):项目特定的知识
  • Global 级别(~/.kiro/steering/):跨项目通用的偏好
  • Team 级别:通过 MDM 或中央仓库分发给团队

2.4 Skills:可复用的工作流指令包

Skills 是 Kiro CLI 的另一个核心能力。每个 Skill 是一个包含 SKILL.md 文件的目录,定义了特定工作流的指令。当你的请求匹配 Skill 的描述时,Kiro 会自动激活对应的 Skill。

.kiro/skills/
└── eks-fluentbit-deploy/
    ├── SKILL.md           # 触发条件和工作流指令
    └── references/
        └── deploy-checklist.md

Skills 遵循开放的 Agent Skills 标准,可以在团队间共享。例如,你可以创建一个”EKS 日志采集部署”Skill,团队中的任何人都能通过自然语言触发相同的标准化部署流程。

2.5 Amazon EKS MCP Server:用自然语言管理 Kubernetes

Amazon EKS MCP Server 是 AWS 提供的托管 MCP 服务,让 AI 助手能够直接与 EKS 集群交互。它提供以下工具类别:

工具类别 能力 替代的传统命令
集群管理 创建、描述、升级 EKS 集群 aws eks describe-cluster
K8s 资源管理 列出、读取、创建、更新 K8s 资源 kubectl get/apply/describe
应用部署 生成 manifest、apply YAML kubectl apply -f
日志和事件 查看 Pod 日志、K8s 事件 kubectl logskubectl get events
故障排查 搜索 EKS 排障知识库 手动翻文档
CloudWatch 集成 查询指标和日志 aws cloudwatch get-metric-data

在本文的实战中,Kiro CLI 通过 EKS MCP Server 完成了:部署 K8s 资源、检查 Pod 状态、读取 Fluent Bit 日志、验证数据链路——全程无需手动输入任何 kubectl 命令。

三、环境准备:配置 EKS MCP Server

3.1 前提条件

在开始之前,请确保你已具备:

  • 一个 AWS 账户,已有 EKS 集群(本文使用 eks-workshop,region: us-west-2
  • 已安装 Kiro CLI
  • 已安装 Python 的 uv 包管理器(用于运行 MCP proxy)
  • AWS CLI 已配置,且 profile 有 EKS 相关 IAM 权限

3.2 配置 MCP Server

在项目根目录创建 MCP 配置文件:

mkdir -p .kiro/settings
// .kiro/settings/mcp.json
{
  "mcpServers": {
    "eks-mcp": {
      "command": "uvx",
      "args": [
        "mcp-proxy-for-aws@latest",
        "https://eks-mcp.us-west-2.api.aws/mcp",
        "--service", "eks-mcp",
        "--profile", "default",
        "--region", "us-west-2"
      ]
    }
  }
}

3.3 验证连接

启动 Kiro CLI 后,可以通过 /mcp 命令确认 EKS MCP Server 已加载:

> /mcp

MCP Servers:
  eks-mcp: connected (42 tools available)

看到 connected 状态,说明 Kiro CLI 已经可以通过自然语言操作你的 EKS 集群了。

四、两种方案架构概述

我们要解决的问题是:EKS 上的应用产生 JSON 埋点日志,需要以 Parquet 格式持续写入 S3。

实现这个目标有两条路径,核心区别在于 “谁来做 JSON → Parquet 的转换”。

4.1 方案 A 架构:Fluent Bit 原生 Parquet 直写 S3

┌─────────────────┐     ┌──────────────────────┐     ┌─────────────────┐
│   Demo App      │     │   Fluent Bit          │     │   Amazon S3     │
│  (log-generator)│────▶│   (自编译 Arrow 镜像)  │────▶│  (.parquet)     │
│                 │     │                       │     │                 │
│ JSON 埋点日志    │     │ tail → s3 (parquet)   │     │ /parquet-logs/  │
└─────────────────┘     └──────────────────────┘     └─────────────────┘
        │                       │
        └───────────────────────┘
          emptyDir / hostPath 共享卷

核心思路:Fluent Bit 在 v3.2+ 版本支持通过 S3 output plugin 的 `compression parquet` 参数直接输出 Parquet 格式,但需要在编译时启用 Apache Arrow 支持(`-DFLB_ARROW=On`)。官方镜像未包含此功能,因此需要自己编译镜像。

涉及的 AWS 资源

  • Amazon S3(存储 Parquet 文件)
  • Amazon ECR(托管自编译镜像)
  • IAM Policy + IRSA(授权 Fluent Bit 写入 S3)

4.2 方案 B 架构:Fluent Bit → Firehose → S3 Parquet

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│   Demo App      │     │   Fluent Bit     │     │   Firehose      │     │   Amazon S3     │
│  (log-generator)│────▶│   (官方镜像)      │────▶│  (Parquet 转换)  │────▶│  (.parquet)     │
│                 │     │                  │     │                  │     │                 │
│ JSON 埋点日志    │     │ tail → firehose  │     │ JSON → Parquet   │     │ /parquet-logs/  │
│                 │     │                  │     │   (SNAPPY 压缩)   │     │  year=/month=/  │
└─────────────────┘     └─────────────────┘     └─────────────────┘     └─────────────────┘
        │                       │                        │
        └───────────────────────┘                  ┌─────────────────┐
          emptyDir 共享卷                           │   AWS Glue      │
                                                   │  (Schema 定义)   │
                                                   └─────────────────┘

核心思路:Fluent Bit 使用 `aws-for-fluent-bit` 官方镜像,通过 `kinesis_firehose` output plugin 将 JSON 日志发送到 Amazon Data Firehose。Firehose 开启 Data Format Conversion,根据 AWS Glue Data Catalog 中定义的 Schema,将 JSON 自动转换为 Parquet 格式后写入 S3。

涉及的 AWS 资源

  • Amazon S3(存储 Parquet 文件)
  • Amazon Data Firehose(流式 ETL,JSON → Parquet 转换)
  • AWS Glue Data Catalog(定义 Parquet Schema)
  • IAM Role(Firehose 服务角色 + IRSA)

4.3 快速对比

维度 方案 A:直写 S3 Parquet 方案 B:Firehose + Glue
Fluent Bit 镜像 ❌ 需自编译(启用 Apache Arrow) ✅ 官方镜像即可
Parquet 转换位置 Pod 本地(Fluent Bit 进程内) 云端(Firehose 服务端)
额外 AWS 资源 ECR Firehose + Glue
Schema 管理 无(自动推断) Glue Table 声明式定义
字段过滤 需 Fluent Bit Filter 插件 Glue Schema 投影(改 schema 无需重启 Pod)
S3 分区 按时间路径(需手动配置) 内置动态分区(year=/month=/day=
镜像构建复杂度 ❌ 高(C++ 交叉编译,~15 分钟) ✅ 无需构建
AWS 资源配置量 ✅ 少(S3 + IAM) ❌ 多(S3 + Firehose + Glue + IAM)
运维复杂度 镜像版本管理 Firehose 监控 + Glue Schema 维护
适用场景 追求极简架构、对延迟敏感 需要 Schema 管理、字段过滤、托管 ETL
一句话总结:方案 A 的复杂度集中在镜像构建,方案 B 的复杂度集中在 AWS 资源编排。两者在 Kiro CLI 的辅助下,搭建体验都大幅简化。

五、方案 A:Fluent Bit 直写 S3 Parquet

5.1 第一步:向 Kiro 描述需求,生成搭建计划

打开终端,启动 Kiro CLI,用自然语言描述我们的需求:

用户:
我需要在 EKS 集群 eks-workshop (us-west-2) 上部署 Fluent Bit,
采集应用的 JSON 埋点日志,以 Parquet 格式直接写入 S3。
请帮我规划完整的搭建步骤。

Kiro 分析需求后,自动生成了搭建计划:

Kiro:
我来帮你规划 Fluent Bit 直写 S3 Parquet 的完整方案。

分析:Fluent Bit 的 S3 output plugin 支持 `compression parquet`,
但需要编译时启用 Apache Arrow。官方镜像不包含此功能,需要自编译。

搭建计划:

1. 基础设施准备
   - 创建 S3 Bucket
   - 创建 IAM Policy(S3 写入权限)
   - 创建 IRSA(为 K8s ServiceAccount 绑定 IAM Role)

2. 镜像构建
   - 生成 Dockerfile(多阶段构建,启用 -DFLB_ARROW=On)
   - 创建 ECR 仓库
   - 在 Linux x86_64 环境构建并推送镜像

3. K8s 部署
   - 创建 Fluent Bit ConfigMap(tail input → s3 output with parquet)
   - 部署 Demo App + Fluent Bit Sidecar

4. 端到端验证
   - 检查 Pod 状态
   - 验证 S3 中的 Parquet 文件
   - 用 pyarrow 读取验证内容

是否按此计划执行?

⚠️ 注意:

Kiro 通过 Steering 文件已经知道集群名称、region 等信息,所以能直接生成具体的命令,而不是泛化的模板。

5.2 第二步:基础设施准备(S3 + IAM + IRSA)

确认计划后,Kiro 开始逐步执行。以下是关键步骤的完整对话:

5.2.1 创建 S3 Bucket

Kiro:
首先创建 S3 Bucket 用于存储 Parquet 文件。

> 执行命令: aws s3 mb s3://eks-fluentbit-logs-<ACCOUNT_ID> --region us-west-2

✅ make_bucket: eks-fluentbit-logs-<ACCOUNT_ID>

S3 Bucket 创建成功。接下来创建 IAM Policy。

5.2.2 创建 IAM Policy

Kiro:
创建 IAM Policy,授权 Fluent Bit 写入 S3。

> 生成文件: fluentbit-s3-policy.json

{
    "Version": "2012-10-17",
    "Statement": [{
        "Effect": "Allow",
        "Action": ["s3:PutObject", "s3:GetObject", "s3:GetBucketLocation"],
        "Resource": [
            "arn:aws:s3:::eks-fluentbit-logs-<ACCOUNT_ID>",
            "arn:aws:s3:::eks-fluentbit-logs-<ACCOUNT_ID>/*"
        ]
    }]
}

> 执行命令: aws iam create-policy \
    --policy-name FluentBitS3Policy \
    --policy-document file://fluentbit-s3-policy.json

✅ Policy ARN: arn:aws:iam::<ACCOUNT_ID>:policy/FluentBitS3Policy

5.2.3 创建 IRSA

Kiro:
创建 IRSA,将 IAM Role 绑定到 K8s ServiceAccount,
这样 Fluent Bit Pod 就能通过 ServiceAccount 获取 S3 写入权限。

> 执行命令: eksctl create iamserviceaccount \
    --cluster eks-workshop \
    --namespace demo-app \
    --name demo-app-sa \
    --attach-policy-arn arn:aws:iam::<ACCOUNT_ID>:policy/FluentBitS3Policy \
    --approve \
    --region us-west-2

✅ ServiceAccount "demo-app-sa" 已创建,关联 IAM Role:
   arn:aws:iam::<ACCOUNT_ID>:role/eksctl-eks-workshop-addon-iamserviceac-Role1-xxxxx

5.3 第三步:构建支持 Parquet 的 Fluent Bit 镜像

这是方案 A 最复杂的环节。Kiro 生成了完整的 Dockerfile:

Kiro:
官方 Fluent Bit 镜像不支持 Parquet 输出,需要自编译。
我来生成 Dockerfile,使用多阶段构建:
- 构建阶段:安装 Apache Arrow 开发库,编译 Fluent Bit(启用 -DFLB_ARROW=On)
- 运行阶段:只包含运行时库和编译好的二进制文件

⚠️ 重要提示:需要在 Linux x86_64 机器上构建(推荐 Ubuntu EC2),
macOS ARM 跨平台编译 C++ 项目容易失败。

Kiro 生成的 Dockerfile 核心部分:

FROM ubuntu:22.04 AS builder
# 安装 Apache Arrow 开发库
RUN wget https://apache.jfrog.io/artifactory/arrow/ubuntu/apache-arrow-apt-source-latest-jammy.deb \
    && apt-get install -y ./apache-arrow-apt-source-latest-jammy.deb \
    && apt-get install -y libarrow-dev libparquet-dev

# 编译 Fluent Bit,关键参数:-DFLB_ARROW=On
RUN cmake -DFLB_ARROW=On -DFLB_OUT_S3=On .. \
    && cmake --build . --parallel $(nproc)

FROM ubuntu:22.04
# 安装 Arrow 运行时库 + 复制编译产物
COPY --from=builder /fluent-bit/build/bin/fluent-bit /usr/local/bin/

随后 Kiro 指导完成 ECR 仓库创建和镜像推送:

Kiro:
> 执行命令: aws ecr create-repository --repository-name fluent-bit-parquet --region us-west-2
> 执行命令: docker build --no-cache --platform linux/amd64 -t fluent-bit-parquet:v1 .
> 执行命令: docker tag fluent-bit-parquet:v1 <ACCOUNT_ID>.dkr.ecr.us-west-2.amazonaws.com/fluent-bit-parquet:v1
> 执行命令: docker push <ACCOUNT_ID>.dkr.ecr.us-west-2.amazonaws.com/fluent-bit-parquet:v1

✅ 镜像已推送到 ECR。验证 Arrow 支持:
> docker run --rm fluent-bit-parquet:v1 fluent-bit --help 2>&1 | grep ARROW
  FLB_HAVE_ARROW

5.4 第四步:部署到 EKS 并验证

Kiro 生成 Sidecar 部署 YAML,包含 Demo App(日志生成器)和 Fluent Bit(Parquet 采集器):

Kiro:
生成部署文件。Fluent Bit 配置的关键参数:
- [OUTPUT] Name: s3
- compression: parquet  ← 这是启用 Parquet 输出的关键
- s3_key_format: 按时间分层存储

我通过 EKS MCP Server 部署到集群。

Kiro 通过 EKS MCP Server 的 apply_yaml 工具部署资源,然后用 list_k8s_resources 检查状态:

Kiro:
> [EKS MCP] apply_yaml → ConfigMap + Deployment 已创建
> [EKS MCP] list_k8s_resources(kind=Pod, namespace=demo-app)

NAME                             READY   STATUS    RESTARTS
log-generator-7b8f9c6d4-x2k9p   2/2     Running   0

✅ Pod 运行正常,2 个容器(log-generator + fluent-bit)都已就绪。

等待约 2 分钟后,Kiro 验证 S3 中的 Parquet 文件:

Kiro:
> 执行命令: aws s3 ls s3://eks-fluentbit-logs-<ACCOUNT_ID>/parquet-logs/ --recursive

2026-04-07 01:23:45   12847  parquet-logs/demo-app/2026/04/07/01/23/45-abc123.parquet

✅ Parquet 文件已生成!下载并验证内容:

> python3 -c "
import pyarrow.parquet as pq
t = pq.read_table('test.parquet')
print('Schema:', t.schema)
print('Rows:', t.num_rows)
print(t.to_pandas().head(3))
"

Schema: timestamp: string, event: string, user_id: string, page: string
Rows: 12
     timestamp              event   user_id     page
0  2026-04-07T01:20:46Z  page_view    u680   /account
1  2026-04-07T01:20:51Z  page_view    u342   /products
2  2026-04-07T01:20:56Z  page_view    u891   /cart

方案 A 搭建完成!JSON 埋点日志已成功以 Parquet 格式写入 S3。

六、方案 B:Fluent Bit + Firehose + Glue 落地 S3 Parquet

6.1 第一步:向 Kiro 描述需求,生成搭建计划

用户:
方案 A 已经跑通了。现在我想试另一种方式:
用 Fluent Bit 官方镜像,通过 Firehose + Glue 实现 JSON 到 Parquet 的转换,
同样写入 S3。请帮我规划搭建步骤。
???? Kiro:
好的,方案 B 的核心区别是把 Parquet 转换从 Pod 本地移到 Firehose 服务端。
这样不需要自编译镜像,但需要配置更多 AWS 资源。

搭建计划:

1. 创建 Glue Database 和 Table
   - 定义 Parquet 的 Schema(6 个字段)
   - Firehose 根据此 Schema 做 JSON → Parquet 转换

2. 创建 Firehose IAM Role
   - 授权 Firehose 访问 S3(写入)和 Glue(读取 Schema)

3. 创建 Firehose Delivery Stream
   - 开启 Data Format Conversion(JSON → Parquet,SNAPPY 压缩)
   - 配置 S3 目标和分区路径

4. 创建 IRSA
   - 授权 Fluent Bit Pod 调用 firehose:PutRecord

5. K8s 部署
   - 使用 aws-for-fluent-bit 官方镜像
   - kinesis_firehose output plugin

6. 端到端验证

注意:方案 B 复用方案 A 已创建的 S3 Bucket。
是否按此计划执行?

6.2 第二步:创建 Glue Database 和 Table

Firehose 的 Data Format Conversion 需要 Glue Catalog 提供 Parquet 的 Schema 定义。

Kiro:
首先创建 Glue Database 和 Table。Table 定义了 6 个字段,
Firehose 会按此 Schema 将 JSON 转换为 Parquet。

> 执行命令: aws glue create-database \
    --database-input '{"Name":"fluentbit_logs"}' \
    --region us-west-2

✅ Glue Database "fluentbit_logs" 已创建。

> 执行命令: aws glue create-table \
    --database-name fluentbit_logs \
    --table-input '{
      "Name": "events",
      "StorageDescriptor": {
        "Columns": [
          {"Name": "timestamp", "Type": "string"},
          {"Name": "event", "Type": "string"},
          {"Name": "user_id", "Type": "string"},
          {"Name": "page", "Type": "string"},
          {"Name": "previous_page", "Type": "string"},
          {"Name": "next_page", "Type": "string"}
        ],
        "Location": "s3://eks-fluentbit-logs-<ACCOUNT_ID>/parquet-logs/",
        "InputFormat": "org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat",
        "OutputFormat": "org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat",
        "SerdeInfo": {
          "SerializationLibrary": "org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe"
        }
      },
      "TableType": "EXTERNAL_TABLE"
    }' \
    --region us-west-2

✅ Glue Table "events" 已创建,包含 6 个字段。

Glue Schema 投影的好处:JSON 中多出来的字段会被自动丢弃,
只有 Schema 中定义的字段会写入 Parquet。
修改 Schema 无需重启 Pod——这是方案 B 的一个独特优势。

6.3 第三步:创建 Firehose Delivery Stream

这是方案 B 最关键的环节——配置 Firehose 的 Data Format Conversion。

Kiro:
接下来创建 Firehose IAM Role 和 Delivery Stream。

> 执行命令: aws iam create-role \
    --role-name FirehoseParquetRole \
    --assume-role-policy-document '{
      "Version": "2012-10-17",
      "Statement": [{
        "Effect": "Allow",
        "Principal": {"Service": "firehose.amazonaws.com"},
        "Action": "sts:AssumeRole"
      }]
    }'

✅ Firehose IAM Role 已创建。

> 附加 Inline Policy(S3 写入 + Glue 读取权限)...
✅ Policy "FirehoseS3GlueAccess" 已附加。

> 执行命令: aws firehose create-delivery-stream \
    --delivery-stream-name fluentbit-parquet-stream \
    --delivery-stream-type DirectPut \
    --extended-s3-destination-configuration '{
      "RoleARN": "arn:aws:iam::<ACCOUNT_ID>:role/FirehoseParquetRole",
      "BucketARN": "arn:aws:s3:::eks-fluentbit-logs-<ACCOUNT_ID>",
      "Prefix": "parquet-logs/year=!{timestamp:yyyy}/month=!{timestamp:MM}/day=!{timestamp:dd}/",
      "ErrorOutputPrefix": "errors/",
      "BufferingHints": {"SizeInMBs": 64, "IntervalInSeconds": 60},
      "DataFormatConversionConfiguration": {
        "Enabled": true,
        "SchemaConfiguration": {
          "DatabaseName": "fluentbit_logs",
          "TableName": "events",
          "Region": "us-west-2",
          "RoleARN": "arn:aws:iam::<ACCOUNT_ID>:role/FirehoseParquetRole"
        },
        "InputFormatConfiguration": {
          "Deserializer": {"OpenXJsonSerDe": {}}
        },
        "OutputFormatConfiguration": {
          "Serializer": {"ParquetSerDe": {"Compression": "SNAPPY"}}
        }
      }
    }' \
    --region us-west-2

✅ Firehose Delivery Stream 已创建。验证状态:

> aws firehose describe-delivery-stream \
    --delivery-stream-name fluentbit-parquet-stream \
    --query '{Status: ..., ConversionEnabled: ..., Compression: ...}'

{
    "Status": "ACTIVE",
    "ConversionEnabled": true,
    "GlueDB": "fluentbit_logs",
    "GlueTable": "events",
    "Compression": "SNAPPY"
}

关键配置说明:
- BufferingHints: 60s 或 64MB 先到先 flush
- DataFormatConversionConfiguration: 开启 JSON → Parquet 转换
- SchemaConfiguration: 指向 Glue Table 获取 Schema
- Prefix: 按 year/month/day 自动分区

6.4 第四步:部署到 EKS 并验证

Kiro 创建 IRSA(授权 firehose:PutRecord),生成 Sidecar 部署 YAML,并通过 EKS MCP 部署:

Kiro:
IRSA 和部署文件已准备好。Fluent Bit 配置的关键区别:
- 使用官方镜像: public.ecr.aws/aws-observability/aws-for-fluent-bit:stable
- Output 插件: kinesis_firehose(而非 s3)
- delivery_stream: fluentbit-parquet-stream

> [EKS MCP] apply_yaml → ConfigMap + Deployment 已创建
> [EKS MCP] list_k8s_resources(kind=Pod, namespace=demo-app)

NAME                             READY   STATUS    RESTARTS
log-generator-5c4d8e7f2-m3n7q   2/2     Running   0

✅ Pod 运行正常。等待 ~2 分钟让 Firehose buffer flush...

> 执行命令: aws s3 ls s3://eks-fluentbit-logs-<ACCOUNT_ID>/parquet-logs/year= --recursive

parquet-logs/year=2026/month=04/day=07/fluentbit-parquet-stream-1-...-xxxx.parquet

✅ Parquet 文件已生成!验证内容:

Schema: timestamp: string, event: string, user_id: string,
        page: string, previous_page: string, next_page: string
Rows: 8
{'timestamp': '2026-04-07T01:20:46Z', 'event': 'page_view',
 'user_id': 'u680', 'page': '/account',
 'previous_page': '/checkout', 'next_page': '/account'}

方案 B 搭建完成!6 个字段全部正确写入 Parquet。

6.5 踩坑记录:timestamp 字段消失之谜

在方案 B 的搭建过程中,我们遇到了一个典型的坑——这也是 Kiro CLI 排查能力的一个很好的展示。

问题现象:第一次部署后,Parquet 文件中 timestamp 字段的值全部为 None

用户:
Parquet 文件里 timestamp 字段全是 None,其他字段正常。怎么回事?
Kiro:
让我检查 Fluent Bit 的配置和日志。

> [EKS MCP] get_pod_logs(pod=log-generator-xxx, container=fluent-bit)

日志显示 Fluent Bit 正常投递到 Firehose,没有错误。
问题可能出在 Parser 配置上。让我看一下 ConfigMap...

> [EKS MCP] read_k8s_resource(kind=ConfigMap, name=fluent-bit-firehose-config)

发现问题了!Parser 配置中设置了 Time_Key:

  [PARSER]
      Name        json
      Format      json
      Time_Key    timestamp        ← ???? 这是问题根因
      Time_Format %Y-%m-%dT%H:%M:%SZ

根因分析:
Fluent Bit 的 JSON Parser 会把 Time_Key 指定的字段"消费"为内部时间戳。
aws-for-fluent-bit 使用的 Firehose Go 插件不会将被消费的时间字段传递到 output。
因此 timestamp 字段在发送到 Firehose 之前就已经被移除了。

⚠️ 注意:Time_Keep On 在 aws-for-fluent-bit v2.34.3 的 Firehose Go 插件中不生效。

✅ 修复方案:去掉 Time_Key,让 timestamp 作为普通字段透传:

  [PARSER]
      Name        json
      Format      json
      # 不设置 Time_Key,timestamp 作为普通字段保留

我来更新 ConfigMap 并重建 Pod。

> [EKS MCP] 更新 ConfigMap...
> 执行命令: kubectl delete pod -n demo-app -l app=log-generator

✅ Pod 已重建。等待验证...

> 验证 Parquet 内容:
{'timestamp': '2026-04-07T02:15:30Z', 'event': 'page_view', ...}

timestamp 字段恢复正常!
这个踩坑案例展示了 Kiro CLI 的排查能力:它能通过 EKS MCP Server 读取 Pod 日志和 ConfigMap 配置,结合对 Fluent Bit 内部机制的理解,快速定位根因并给出修复方案。如果是手动排查,你可能需要在 Fluent Bit 文档、GitHub Issues、Stack Overflow 之间搜索很久才能找到这个 Time_Key 的隐含行为。

七、搭建复杂度与成本对比

7.1 搭建复杂度对比

维度 方案 A:直写 S3 Parquet 方案 B:Firehose + Glue
Kiro CLI 对话轮次 ~15 轮 ~20 轮
涉及 AWS 服务 3 个(S3、ECR、IAM) 5 个(S3、Firehose、Glue、IAM ×2)
需要创建的 AWS 资源 S3 Bucket、IAM Policy、IRSA、ECR Repo S3 Bucket、Glue DB、Glue Table、Firehose Role、Firehose Stream、IAM Policy、IRSA
镜像构建 ❌ 需要(~15 分钟编译,需 Linux x86_64 环境) ✅ 不需要(官方镜像)
最大难点 C++ 交叉编译 Arrow 库 Firehose Data Format Conversion 配置
踩坑风险 Arrow 库版本不匹配、macOS 编译失败 Time_Key 消费字段、IAM 权限遗漏
Kiro CLI 辅助价值 生成 Dockerfile、指导编译环境 自动编排多个 AWS 资源、排查 Time_Key 问题

7.2 月度成本估算

以每天 1 GB 日志量(约 30 GB/月)为基准,us-west-2 region:

费用项 方案 A 方案 B
S3 存储(Parquet 压缩后约 30% 原始大小) ~9 GB × $0.023/GB = $0.21 ~9 GB × $0.023/GB = $0.21
Firehose Ingestion 30 GB × $0.029/GB = $0.87
Firehose Format Conversion 30 GB × $0.018/GB = $0.54
Glue Data Catalog 免费(< 100 万对象/月)
ECR 镜像存储 ~1 GB × $0.10/GB = $0.10
月度总计 ~$0.31 ~$1.62
说明: – 以上为纯数据链路成本,不含 EKS 集群本身的费用(两种方案相同) – Firehose 按 5KB 增量计费,小记录场景下实际费用可能略高 – 方案 A 的隐性成本是镜像构建和维护的人力投入 – 日志量越大,方案 B 的 Firehose 费用线性增长;方案 A 的增量成本仅为 S3 存储

成本结论:方案 A 的运行成本更低(几乎只有 S3 存储费),但有镜像构建的一次性人力成本。方案 B 每月多出约 $1.3 的 Firehose 费用,但省去了镜像构建和维护的负担。对于大多数场景,两种方案的月度成本差异在 $1-5 之间,选择更多取决于运维偏好而非成本。

八、Kiro CLI 带来的效率提升

回顾整个搭建过程,我们可以量化 Kiro CLI 带来的效率提升:

维度 传统方式 Kiro CLI 辅助
方案 A 搭建时间 3-4 小时(含镜像编译调试) ~1.5 小时(Kiro 生成 Dockerfile + 指导编译)
方案 B 搭建时间 2-3 小时(多个 AWS 资源配置) ~45 分钟(Kiro 自动编排 AWS CLI 命令)
文档查阅 反复切换 Fluent Bit 文档、AWS 文档、K8s 文档 Kiro 内置知识 + MCP 实时查询
排查 Time_Key 问题 1-2 小时(搜索 GitHub Issues、Stack Overflow) ~5 分钟(Kiro 读取 ConfigMap + 分析根因)
K8s 操作 手动输入 kubectl 命令 自然语言 → EKS MCP 自动执行
IAM 权限配置 手动编写 Policy JSON Kiro 根据需求自动生成最小权限 Policy

核心效率提升来自四个方面

  1. 自然语言驱动:不需要记住 AWS CLI 语法、kubectl 命令、Fluent Bit 配置参数。描述你要做什么,Kiro 翻译成具体操作。
  2. MCP 实时集群感知:通过 EKS MCP Server,Kiro 能直接查看 Pod 状态、读取日志、检查配置——不需要你在终端和对话之间来回切换。
  3. Steering 知识积累:项目的集群信息、bucket 名称、account ID 等只需配置一次,后续所有对话自动加载。团队新成员也能立即上手。
  4. 错误排查辅助:Kiro 不只是执行命令,它能理解错误信息的含义,结合对 Fluent Bit、Firehose、K8s 的知识,给出根因分析和修复建议。

九、总结与方案选择建议

9.1 方案选择

如果你… 推荐方案
追求最简架构,团队有 C++ 编译经验 方案 A(直写 S3)
不想维护自定义镜像,接受少量额外成本 方案 B(Firehose + Glue)
需要声明式 Schema 管理和字段过滤 方案 B
对延迟敏感(需要秒级写入 S3) 方案 A
需要 S3 自动分区(year=/month=/day=) 方案 B
日志量大(>100 GB/天),关注成本 方案 A

9.2 Kiro CLI 的价值

无论选择哪种方案,Kiro CLI + EKS MCP Server 的组合都显著降低了搭建门槛

  • 方案 A 的难点(镜像编译)→ Kiro 生成 Dockerfile 并指导构建
  • 方案 B 的难点(多资源编排)→ Kiro 自动生成并执行 AWS CLI 命令
  • 两种方案的共同难点(K8s 部署和验证)→ EKS MCP Server 提供自然语言操作

对于 AWS 运维和开发人员来说,Kiro CLI 不是替代你的专业知识,而是放大你的生产力——让你把时间花在架构决策和业务逻辑上,而不是记忆命令语法和翻阅文档。

9.3 立即开始

1. 安装 Kiro CLI

2. 配置 EKS MCP Server

3. 用自然语言描述你的需求,让 Kiro 帮你搭建

十、资源链接

➡️ 下一步行动:

相关产品:

  • Amazon S3 — 适用于 AI、分析和存档的几乎无限的安全对象存储
  • Amazon EKS — 托管式 Kubernetes 服务
  • Amazon Glue — 简单、可扩展的无服务器数据集成
  • Amazon IAM — 身份管理和访问权限
  • Amazon Athena — 使用 SQL 在 S3 中查询数据

相关文章:

*前述特定亚马逊云科技生成式人工智能相关的服务目前在亚马逊云科技海外区域可用。亚马逊云科技中国区域相关云服务由西云数据和光环新网运营,具体信息以中国区域官网为准。

本篇作者

薛东

亚马逊云科技资深解决方案架构师,负责基于亚马逊云科技的解决方案设计和构建。加入亚马逊云科技之前曾就职于 EMC,阿里云等头部 IT 企业,积累了丰富的企业级应用开发,测试和架构经验。目前服务亚马逊云科技中国媒体和广告行业客户。专注于无服务,安全,生成式 AI 等技术方向。

杨冬冬

亚马逊云科技资深容器解决方案架构师,在云原生领域深耕多年,拥有丰富的行业经验。


AWS 架构师中心:云端创新的引领者

探索 AWS 架构师中心,获取经实战验证的最佳实践与架构指南,助您高效构建安全、可靠的云上应用