AWS OpenSearch(AOS) 服务
AWS OpenSearch 是一个完全开源的搜索和分析引擎,用于日志分析、实时应用程序监控和点击流分析等用例。
AWS OpenSearch(AOS) 和 Elasticsearch 对比
| OpenSearch | Elasticsearch | |
|---|---|---|
| 背景 | AWS 主导的开源分支 | Elastic 公司主导 |
| 授权 | Apache 2.0 | SSPL + Elastic License |
| 商业控制 | 社区驱动 | 公司控制 |
| K8s 生态 | 非常友好 | 也支持 |
| 云原生趋势 | 越来越主流 | 商业版更强 |
| 日志检索 | 很强 | 很强 |
| 向量搜索 | 有 | 更成熟 |
| ML 功能 | 有 | 更强 |
| APM | 基础 | 商业版更强 |
| 插件生态 | 少一些 | 更丰富 |
原本是同一个项目
2021 年因授权问题分叉
👉 7.10 是最后一个纯开源 Elasticsearch 版本
之后 AWS fork 出:
🔹 OpenSearch
而原厂继续发展:
🔹 Elasticsearch
在 AWS 上,Amazon 托管服务默认是 OpenSearch。
创建 OpenSearch 域 (AOS)
- AWS OpenSearch Service Version: v 3.3.0
OpenSearch 服务域是 OpenSearch 集群的同义词.域是包含您指定的设置、实例类型、实例计数和存储资源的集群。
登录控制台:前往 Amazon OpenSearch Service。 Domains -> Create domain 。
- 填写 域(Domain)名称
- 选择 标准创建
- 选择实例类型和数量
- 网络选项包含 2 种,创建集群后不能再变更:
- VPC 访问,此中方式创建的 Domain 只支持 VPC 内部访问,不支持互联网公开访问,如果要互联网访问,可以通过在 VPC 内部使用 Nginx 代理。
- 公开访问权限,允许互联网访问
使用 公开访问权限 部署的 AOS,可以直接使用 OpenSearch 控制面板 URL 在互联网访问。如果要控制访问,可以使用以下方法:
修改 集群访问策略 (Access Policy)
- 进入 Amazon OpenSearch Service 控制台,点击进入你的 Domain (网域) 。
- 点击 Security configuration (安全配置) 选项卡。
- 滚动到 Access policy (访问策略) 部分。
- 在 JSON 编辑框中,添加基于
IpAddress的Condition。{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "es:*",
"Resource": "arn:aws:es:ap-southeast-1:你的账号ID:domain/你的域/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": [
"1.2.3.4/32", // 你办公室的公网出口 IP
"5.6.7.8/32" // EKS 节点的公网出口 IP (NAT Gateway EIP)
]
}
}
}
]
}
EKS 1.34 部署 AWS Fluent Bit 写入日志到 AOS
- aws-for-fluent-bit: 2.32.2
aws-for-fluent-bit 配置修改和自定义不够灵活,如果要自定义配置推荐使用官方 Helm Chart fluent/fluent-bit
在 EKS 1.34(自动模式/Auto Mode)中部署 Fluent Bit 并写入托管的 OpenSearch (AOS) 是一个非常高效的组合。EKS Auto 会自动处理节点配置,但日志采集逻辑依然遵循 IRSA (IAM Roles for Service Accounts) 机制。
以下是完整的部署指南
准备 AOS 访问策略 (Access Policy)
确保你的 AOS 集群允许来自 EKS 的访问。如果 AOS 和 EKS 内网能互通,建议使用 AOS 内网通信,可以节省流量费用。
在 AOS 控制台的 Access Policy 中添加:
{
"Effect": "Allow",
"Principal": { "AWS": "*" },
"Action": "es:*",
"Resource": "arn:aws:es:ap-southeast-1:账号ID:domain/域名/*",
"Condition": {
"IpAddress": { "aws:SourceIp": ["NAT_GATEWAY_EIP/32", "你的办公室IP/32"] }
}
}EKS 中创建 IAM 角色 (IRSA) 。Fluent Bit 需要权限向 AOS 写入数据。使用
eksctl是最简单的方法:替换变量
CLUSTER_NAME="your-eks-auto-cluster"
REGION="ap-southeast-1"
POLICY_ARN="arn:aws:iam::aws:policy/AmazonOpenSearchServiceFullAccess" # 建议生产环境用精简权限
eksctl create iamserviceaccount \
--name fluent-bit-sa \
--namespace logging \
--cluster $CLUSTER_NAME \
--region $REGION \
--attach-policy-arn $POLICY_ARN \
--approve \
--override-existing-serviceaccounts部署 Fluent Bit (Helm)
helm repo add eks https://aws.github.io/eks-charts
helm repo update创建 FluentBit 部署配置文件 values.yaml
serviceAccount:
create: false
name: fluent-bit-sa
image:
repository: public.ecr.aws/aws-observability/aws-for-fluent-bit
tag: 2.32.2
# 显式关闭默认的输出
cloudWatchLogs:
enabled: false
firehose:
enabled: false
kinesis:
enabled: false
# 关键修正:在该 Chart 中,自定义输出需要写在 additionalOutputs 下
additionalOutputs: |
[OUTPUT]
Name opensearch
Match kube.*
Host search-aos-dashboard-singapore-logs-5piwcj3oxpdojos7cxfeelgbku.ap-southeast-1.es.amazonaws.com
Port 443
TLS On
AWS_Auth On
AWS_Region ap-southeast-1
Logstash_Format On
Logstash_Prefix eks-logs
Replace_Dots On
Suppress_Type_Name On
# 如果你需要修改默认的 Filter(比如 Buffer_Size),该 Chart 通常不支持直接覆盖
# 你可能需要通过全量自定义配置文件的方式,或者接受默认的 Kubernetes Filter 设置部署
helm install fluent-bit eks/aws-for-fluent-bit -f values.yaml -n logging
使用此配置部署的 FluentBit 默认配置(
fluent-bit.conf)如下:kubectl describe configmap -n logging fluent-bit-aws-for-fluent-bit
Name: fluent-bit-aws-for-fluent-bit
Namespace: logging
Labels: app.kubernetes.io/instance=fluent-bit-aws-for-fluent-bit
app.kubernetes.io/managed-by=Helm
app.kubernetes.io/name=aws-for-fluent-bit
app.kubernetes.io/version=3.2.1
helm.sh/chart=aws-for-fluent-bit-0.2.0
Annotations: meta.helm.sh/release-name: fluent-bit
meta.helm.sh/release-namespace: logging
Data
====
fluent-bit.conf:
----
[SERVICE]
HTTP_Server On
HTTP_Listen 0.0.0.0
HTTP_PORT 2020
Health_Check On # Health_Check: 开启健康检查。
HC_Errors_Count 5
HC_Retry_Failure_Count 5
HC_Period 5
Parsers_File /fluent-bit/parsers/parsers.conf
[INPUT]
Name tail # 使用 tail 插件,像执行 tail -f 一样监听文件。
Tag kube.*
Path /var/log/containers/*.log
DB /var/log/flb_kube.db
multiline.parser docker, cri
Mem_Buf_Limit 5MB
Skip_Long_Lines On
Refresh_Interval 10
[FILTER]
Name kubernetes # 调用 K8s 过滤器插件为日志添加 K8S 元数据,如 Namespace、Pod、Container 等信息
Match kube.*
Kube_URL https://kubernetes.default.svc.cluster.local:443
Merge_Log On # 如果容器输出的是 JSON 格式,Fluent Bit 会尝试把 JSON 里的字段展开,并放入 data 这个 Key 下。
Merge_Log_Key data
Keep_Log On
K8S-Logging.Parser On # 允许通过 Pod 的 Annotation(注解)来决定如何解析该 Pod 的日志(实现按需自定义解析)。
K8S-Logging.Exclude On # 允许通过注解 fluentbit.io/exclude: true 来过滤掉不需要采集的 Pod 日志。
Buffer_Size 32k # 设置与 K8s API 交互时的缓冲区大小。
[OUTPUT]
Name opensearch
Match kube.*
Host opensearch-dashboard--logs-5piwcj3oxpdojos7cxfeelgbku.ap-southeast-1.es.amazonaws.com
Port 443
TLS On
AWS_Auth On
AWS_Region ap-southeast-1
Logstash_Format On
Logstash_Prefix eks-logs
Replace_Dots On
Suppress_Type_Name On
BinaryData
====在 Fluent Bit 的默认配置下,所有日志都汇聚到了
eks-logs-*索引中,但 Kubernetes Filter 已经自动为每条日志注入了丰富的元数据(Metadata)。可以在 Dashboard 的 Discover 页面进行筛选。如果想要在 FluentBit 的
[OUTPUT]部分动态修改索引名,Fluent Bit 支持使用 Record Access 语法动态设置索引[OUTPUT]
Name opensearch
Match kube.*
...
# 禁用固定的 Logstash_Prefix,改用动态标签
Logstash_Format On
# 使用 $kubernetes['namespace_name'] 动态提取命名空间作为索引前缀,这种做法会导致产生的索引数量变多(每个 Namespace 一个),请确保 OpenSearch 集群的分片(Shards)充足。
Logstash_Prefix_Key $kubernetes['namespace_name']本示例中 AWS Opensearch 使用了 细粒度访问控制 (Fine-Grained Access Control) ,因此 IAM 角色还必须在 OpenSearch 内部进行“身份映射” 。
在 OpenSearch Dashboard 映射 Backend Role (最核心)
- 登录你的 OpenSearch Dashboard。
- 点击左侧侧边栏:Security (安全) -> Roles (角色) 。
- 在列表中搜索并点击
all_access(为了测试建议先用这个,生产环境建议用logstash角色)。 - 点击顶部的 Mapped users (映射的用户) 标签页。
- 点击 Manage mapping (管理映射)
- 在 Backend roles (后端角色) 输入框中,粘贴你的 IAM Role ARN:
arn:aws:iam::<ACCOUNT_ID>:role/addon-iamserviceaccount-logging--Role1-hXqpDva2jMoyIAM Role ARN 可以使用以下命令查询:
# kubectl get sa fluent-bit-sa -n logging -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::<ACCOUNT_ID>:role/eksctl-addon-iamserviceaccount-logging--Role1-hXqpDva2jMoy
creationTimestamp: "2026-02-15T08:27:50Z"
labels:
app.kubernetes.io/managed-by: eksctl
name: fluent-bit-sa
namespace: logging
resourceVersion: "27178999"
uid: 3031f611-f501-4fa3-be44-3d73cb81fb1c
在 EKS 环境中,Fluent Bit 默认通过 tail 插件从节点的 /var/log/containers/*.log 路径收集日志。由于 K8s 会将所有容器的 stdout 和 stderr 重定向到这个物理路径,因此收集业务日志的核心在于确保你的业务程序将日志输出到标准输出(Console)。只要业务日志出现在 kubectl logs 中,Fluent Bit 就会自动读取文件,并通过 kubernetes 过滤器自动关联 namespace、pod_name 和 container_name 等元数据。
如果业务必须将日志写入容器内部的文件(例如 /app/logs/access.log ),你需要通过 Sidecar 模式 或 共享卷 来解决。
日志读取:
方式 A:使用一个轻量级的 Sidecar(如
stream-logger)执行tail -f /app/logs/access.log,将内容转到stdout。方式 B:修改 Fluent Bit 的 INPUT 配置,增加一个新的
tail路径,但这需要 Fluent Bit 容器有权限访问该卷。较为复杂些。
Fluent Bit 日志未写入 AOS 排查流程
首先检查 FluentBit 日志信息,看其中是否有报错信息
kubectl logs -n logging -l app.kubernetes.io/name=aws-for-fluent-bit | grep -iE "opensearch|error|exception"
如果没有报错信息,可以修改 Fluentbit 日志级别,输出更详细日志,编辑 Configmap
fluent-bit-aws-for-fluent-bit,[SERVICE]部分添加或修改Log_Level debug。重启 Pod 后再次检查日志。定位完问题后记得改回原来的日志级别kubectl get configmap -n logging
NAME DATA AGE
fluent-bit-aws-for-fluent-bit 1 86m
kube-root-ca.crt 1 97m
kubectl edit configmap -n logging fluent-bit-aws-for-fluent-bit
configmap/fluent-bit-aws-for-fluent-bit edited
kubectl delete pod -n logging fluent-bit-aws-for-fluent-bit-jjbfx重新检查日志信息,可以搜索关键字,如输出到 AWS Opensearch
kubectl logs -n logging -l app.kubernetes.io/name=aws-for-fluent-bit | grep -i opense
[2026/02/15 10:12:27] [ warn] [engine] failed to flush chunk '1-1771150346.332440544.flb', retry in 11 seconds: task_id=6, input=tail.0 > output=opensearch.0 (out_id=0)
[2026/02/15 10:12:27] [debug] [output:opensearch:opensearch.0] HTTP Status=403 URI=/_bulk
[2026/02/15 10:12:27] [error] [output:opensearch:opensearch.0] HTTP status=403 URI=/_bulk, response:
[2026/02/15 10:12:27] [ warn] [engine] failed to flush chunk '1-1771150346.251003257.flb', retry in 7 seconds: task_id=1, input=tail.0 > output=opensearch.0 (out_id=0)
[2026/02/15 10:12:27] [debug] [output:opensearch:opensearch.0] HTTP Status=403 URI=/_bulk
[2026/02/15 10:12:27] [error] [output:opensearch:opensearch.0] HTTP status=403 URI=/_bulk, response:从错误信息可见是因为请求 Opensearch 返回了 403。说明 网络是通的,但 OpenSearch 拒绝了 Fluent Bit 的写入请求。
本示例中 AWS Opensearch 使用了 细粒度访问控制 (Fine-Grained Access Control) ,因此 IAM 角色还必须在 OpenSearch 内部进行“身份映射” 。
- 在 OpenSearch Dashboard 映射 Backend Role (最核心)
- 登录你的 OpenSearch Dashboard。
- 点击左侧侧边栏:Security (安全) -> Roles (角色) 。
- 在列表中搜索并点击
all_access(为了测试建议先用这个,生产环境建议用logstash角色)。 - 点击顶部的 Mapped users (映射的用户) 标签页。
- 点击 Manage mapping (管理映射)
- 在 Backend roles (后端角色) 输入框中,粘贴你的 IAM Role ARN:
arn:aws:iam::<ACCOUNT_ID>:role/addon-iamserviceaccount-logging--Role1-hXqpDva2jMoy
- 在 OpenSearch Dashboard 映射 Backend Role (最核心)
EKS 1.34 部署官方 FluentBit
- cr.fluentbit.io/fluent/fluent-bit:4.2.2
参考 EKS 1.34 部署 AWS Fluent Bit 写入日志到 AOS 准备 AOS 访问策略 (Access Policy) 和 EKS 中创建 IAM 角色 (IRSA)
安装官方 Helm Chart
helm repo add fluent https://fluent.github.io/helm-charts |
创建自定义配置文件 fluentbit-values.yaml
serviceAccount: |
部署并检查状态
helm upgrade --install fluent-bit fluent/fluent-bit -n logging -f fluentbit-values.yaml |
Fluent Bit 配置说明
Fluent Bit 是一个轻量级、高性能的日志收集与转发工具,常用于 Kubernetes / EKS / Docker / Linux 服务器 场景。
核心理念就是:Input → Filter → Output
日志文件 / 容器 stdout |
Fluent Bit 的核心配置分为 4 大块 :
[SERVICE] |
SERVICE 配置详解
定义了整个 Fluent Bit 运行时的全局行为。
[SERVICE] |
| 参数 | 作用 |
|---|---|
| Flush | Fluent Bit 引擎每隔 1 秒会将收集到的日志从缓冲区(Buffer)发送到指定的输出端(如 OpenSearch) |
| Daemon | 是否以守护进程(后台)模式运行, 容器相关场景中设为 Off |
| Log_Level | Fluent Bit 服务的日志级别( debug/info/warn/error ) |
| Parsers_File | 指定解析规则文件,这些规则用于将原始的字符串日志解析为结构化的 JSON 字段。 |
| HTTP_Server | 监控接口,启动一个内建的轻量级 HTTP 服务。 http://<FLUENT_BIT_POD_IP>:2020/api/v1/metrics 获取运行指标 |
| storage.path | 开启磁盘缓存。文件系统缓冲(Filesystem Buffering) 机制 ,主要作用是防止日志丢失。如果 OpenSearch 暂时无法连接(比如网络波动或正在更新),Fluent Bit 会将日志从内存转存到磁盘,等恢复后再补发。 |
| storage.sync | 将数据刷新到磁盘的同步模式 - normal ,使用系统的写缓存,在保证性能的同时提供基本的数据保护。 - full ,则强制每次写入都同步到物理磁盘,安全性最高但 IO 性能损耗极大。生产环境通常推荐 normal。 |
| storage.checksum | 是否对存储的数据块进行校验和(Checksum)检查. 开启后(on)可以检测磁盘数据损坏,但会增加 CPU 开销。如果底层存储介质(如 AWS EBS 或节点本地盘)本身非常可靠,通常设置为 off 以提升性能。 |
| storage.backlog.mem_limit | 处理积压数据时的内存限制。 |
生产建议:
storage.path /var/log/flb-storage/ |
INPUT 配置详解
[INPUT] |
| 参数 | 作用 |
|---|---|
| Path | 监听文件 |
| Tag | 打标签(后面匹配用) |
| Mem_Buf_Limit | 如果日志产生速度远快于发送速度,内存中最多只存 50MB,超过后将暂停采集,防止撑爆 Pod 内存。 |
| DB | 这是一个 SQLite 数据库,记录了每个文件读取到了哪一行。如果 Fluent Bit 重启,它能从这里恢复,防止日志重复或丢失。 如果此文件没有持久化,Pod 重启或漂移后会丢失,所有容器日志会重新采集一遍。OpenSearch 端每条日志都有单独的 id,因此会重复保存(存储),导致数据重复 |
| Skip_Long_Lines | 如何处理超过缓冲区大小(默认通常为 32KB)的超长单行日志, 防止 Fluent Bit Pod 因为内存不足(OOM)而崩溃。On : 丢弃该行 它受 Buffer_Chunk_Size 和 Buffer_Max_Size 的约束 |
| multiline.parser | 自动识别 docker 或 cri 格式的多行日志(例如 Java 堆栈报错),防止一条日志被拆分成多行。 |
FILTER 配置详解
Kubernetes 元数据增强配置示例
[FILTER] |
| 参数 | 作用 |
|---|---|
| Merge_Log | 如果日志内容本身是 JSON {"level":"info","msg":"hello"} 对其进行一定(合并)格式化而不是展示为 "log": "{\"level\":\"info\"}" |
| Merge_Log_Key | 把原始 log ( "log": "{\"level\":\"info\"}" ) 放到指定的 Key 如 data |
| Keep_Log | 保留原始 log( "log": "{\"level\":\"info\"}" ) 字段。 如果设为 Off ,会删除 log 字段。 |
OUTPUT 配置详解
输出到 Elasticsearch 使用 es ,如果输出到 AWS OpenSearch Service,使用 opensearch
[OUTPUT] |
AWS OpenSearch Dashboard 操作
- AWS OpenSearch Service Version: v 3.3.0
创建索引和查看索引日志
要在 OpenSearch Dashboard 中查看具体的日志内容,请按照以下步骤操作:
创建 Index Pattern(索引模式)
OpenSearch 需要你先定义一个模式,告诉它你想查看哪些索引的数据。
点击 Dashboard 左侧菜单,进入 Dashboard Management (通常在最下方)。
点击左侧栏的 Index Patterns 。
点击右上角的 Create index pattern 。
在 Index pattern name 中输入:
eks-logs-*。这时下方应该会显示该模式匹配到了对应的索引。
点击 Next step 。
在 Time field 下拉框中选择
@timestamp。点击 Create index pattern 。
在 Discover 页面查询日志 。创建好 Pattern 后,就可以实时看日志了。
点击左侧菜单顶部的 Discover 。
在左上角的下拉菜单中,确保选中了刚才创建的
eks-logs-*。调整时间范围:点击右上角的时间选择器(默认通常是 Last 15 minutes),确保覆盖了你日志产生的时间。
此时你应该能看到直方图和下方的日志明细表。
在 OpenSearch Dashboards 中,Discover 下拉列表显示的不是数据库里的原始索引,而是用户在 Dashboard Management 上创建的 Index Pattern 对象。
如果这些 Index Pattern (模式)是在 Global Tenant(全局租户) 下创建的,所有能访问 Global 的人都能看到这个名字。
即使用户被限制了查看索引数据,也可能会在 Discover 中看到索引名,没有数据权限,用户点开后也只是报错,但名字会留在列表里。
要隐藏无关索引,配置 租户隔离 (Tenancy) 是最有效的方法。
用户权限管理
用户管理和权限分配主要通过 Security 插件完成。要实现 不同用户分配不同权限和查看不同索引,核心逻辑是:用户 (User) -> 角色 (Role) -> 权限策略 (Permission Policy)
- Role(角色) : 定义了 能对哪些索引做什么
在 Security 页面,点击左侧的 Roles 。
点击 Create role 。
Role name : 例如
dev-team-role。Index permissions (索引权限) :
Index patterns : 输入该用户允许查看的索引模式,例如
eks-logs-dev-*。Index permissions : 选择内置组
read或者手动添加indices:data/read/* , indices:data/write/*等权限。
Tenant permissions (租户权限) (可选):如果你希望用户拥有独立的 Dashboard 配置空间,可以指定 Tenant 权限。
创建好需要的 Role 后,需要将 User 映射(Map) 到 Role
- 在 Security - > Roles 页面,选择创建好的或者已有的 Role,切换到 Mapped Users 页面,进行用户和角色绑定

只给索引权限是不够的 。将 User 和 Role 绑定后,还需要配置 Dashboard 访问权限,用户才能使用 Dashboard 查看图形或者日志。
- 在 Security - > Roles 页面,找到 opensearch_dashboards_user Role,在 Mapped Users 页面,将该用户也映射到这个角色中。
常用术语
- DQL(Dashboards Query Language) : Dashboard 中使用的默认查询语法,只支持通配符
*。要切换只需在 OpenSearch Dashboards 中将其设置为Off,即可切换为 Lucene

- PPL(Piped Processing Language) : 专为查询、探索和发现存储在 OpenSearch 中的数据而设计的查询语言。它的语法结构通过管道符号 (|) 将一系列命令连接起来,使得数据流转逻辑非常直观,类似于 Unix 命令行或 Splunk 的搜索处理语言 (SPL)。