亚马逊AWS官方博客

基于 Centralized Logging with OpenSearch 构建全球日志中心

背景介绍

在很多情况下,我们在定位线上服务问题时,需要借助应用日志来辅助我们做分析,而我们经常使用的 ELK 组件其中包含了日志收集、日志处理、日志存储和可视化,整个部署的过程是一个比较繁杂的过程,而如果使用亚马逊云科技提供的日志通的解决方案可以帮助我们快速地构建这套日志 pipeline。一般来讲我们的日志中心是(region 级服务,作用域在一个 region 内)部署在一个 region 中,但在全球化多区域部署的客户中,有些客户的需求是想将不同 region 的日志统一收集到一个 region 中进行统一分析,那么本文会结合日志通解决方案来 Step By Step 指导大家构建全球日志中心。

日志通:解决方案提供全面的日志管理和分析功能,帮助您简化日志分析管道的构建。该解决方案基于 Amazon OpenSearch Service 构建,可让您有效地完成日志摄取、日志处理和日志可视化。该解决方案可应用于多类场景,例如满足安全和合规性需求,实现精细化的业务运营,或者增强 IT 故障排除和维护。

部署架构图

当前的架构中,我们会使用 S3 作为我们的日志数据缓冲区,将不同区域的数据统一收集到统一的 S3 中,使用统一的日志通的 pipeline 来处理日志,最终写入到 OpenSearch。

前期工作准备

  1. 使用日志通部署整套解决方案
  2. 在目标区域创建 OpenSearch 后并通过日志通 UI 将 OpenSearch Domain 导入
  3. 在部署日志通的 region 创建 S3 桶作为未来日志中心的数据缓冲区,比如本例中,我们使用的 S3 Bucket 为:global-logs-center999
  4. 分别在两个 Region 部署好 Amazon EKS 集群,如果没有可以通过以下命令来进行创建:
eksctl create cluster —name eks1 —region {Region} —nodegroup-name wg1 —node-type t3.medium —nodes 2 —nodes-min 1 —nodes-max 4 —managed
  1. 部署示例应用 Nginx:
kubectl apply -f <(echo "
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: my-nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: my-nginx
  template:
    metadata:
      labels:
        app: my-nginx
    spec:
      containers:
      - name: nginx
        image: public.ecr.aws/nginx/nginx:1.21
        ports:
        - name: http
          containerPort: 80
        imagePullPolicy: IfNotPresent
")

同 region 中使用日志通 portal 配置日志 pipeline

本例中我们来收集 Nginx 的日志,我们遵循日志通的文档,首先导入 EKS。

导入 EKS,选择需要收集日志的 EKS 集群

选择存储日志的 Amazon OpenSearch Domain

创建日志 Pipeline



创建后,等待几分钟之后可以看到 pipeline 已经 ready。

创建 Ingestion

创建完毕后,等待 Ingestion 状态变为 Created

按照 Guide 来安装 DaemonSet

kubectl apply -f ~/fluent-bit-logging.yaml

判断 DaemonSet 是否已经创建成功

kubectl get ds -n logging

如果显示类似如下信息,则表示创建成功:

NAME         DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
fluent-bit   2         2         2       2            2           <none>          

查看相关 Fluent Bit POD 的日志可以看到“Successfully uploaded object”,则说明日志收集成功。

查看 S3 中是否有相应日志文件

然后我们确认一下 OpenSearch 中的数据

因为我们创建的 OpenSearch 在 VPC 内访问,可以通过以下方式来暴露出来:

ssh -i xxx.pem ec2-user@跳板机IP -N -L 9200:{opensearch domain}:443

至此我们同一个 region 下配置已经完成,下面我们来配置不同 region 下的日志收集。

不同 region 下 EKS 日志采集配置

因为我们已经完成了日志从 S3 到 OpenSearch 的日志流程,我们现在只需要将其他 region 的日志采集到我们指定的 S3 即可。

部署 Fluent Bit 至日志来源的 EKS

同样按照 Loghub 中 DaemonSet 的安装指导安装到当前 EKS 集群中,命令如下:

Yaml 文件修改

kubectl 地址,可以参考 Kubectl 地址使用不同版本的对应地址

- name: EKS_KUBECTL_DOWNLOAD_URL_ARM
  value: "https://s3.{region-code}.amazonaws.com/amazon-eks/1.27.1/2023-04-19/bin/linux/arm64/kubectl"
- name: EKS_KUBECTL_DOWNLOAD_URL_X86_64
  value: "https://s3.{region-code}.amazonaws.com/amazon-eks/1.27.1/2023-04-19/bin/linux/amd64/kubectl"

修改 Fluentbit 中环境变量 CLUSTER_NAME 值

containers:
- name: fluent-bit
  image: public.ecr.aws/aws-observability/aws-for-fluent-bit:2.28.4
  imagePullPolicy: Always
  env:
    - name: CLUSTER_NAME
      value: "eks-oregon" #修改为真实 Cluster Name

output 配置

[OUTPUT]
        Name                s3
        Match               loghub.7a2024f1-2dc8-44dd-9465-621c480a974f.e675fb15-7552-4185-9622-4709d370a0b6.*
        bucket              global-logs-center999
        region              {region-code} //目标 region 的 code
        total_file_size     50M
        upload_timeout      60s
        use_put_object      true
        s3_key_format       /AppLogs/my-nginx-log/year=%Y/month=%m/day=%d/%H-%M-%S-$UUID.gz
        compression    gzip
        storage_class       INTELLIGENT_TIERING
        json_date_key       time
        json_date_format    iso8601
        Retry_Limit         False
        tls.verify          false
        Role_arn            arn:aws:iam::715371302281:role/CL-AppPipe-e675fb15-BufferAccessRoleDF53FD85-Q3U557UWZP9E

kubectl apply -f ~/fluent-bit-logging.yaml

设置 IAM OIDC Provider

eksctl utils associate-iam-oidc-provider \
    --region {region-code} \
    --cluster {eks-cluster-name}\
    --approve

修改 Fluent Bit Service Account 的 Trust Relationships

添加新的 EKS 信息

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::xxxxxx:oidc-provider/oidc.eks.us-west-2.amazonaws.com/id/AF0699207421311C9DAFABEFC628EE4C"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "oidc.eks.us-west-2.amazonaws.com/id/AF0699207421311C9DAFABEFC628EE4C:sub": "system:serviceaccount:logging:fluent-bit",
                    "oidc.eks.us-west-2.amazonaws.com/id/AF0699207421311C9DAFABEFC628EE4C:aud": "sts.amazonaws.com"
                }
            }
        },
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::xxxxxxxx:oidc-provider/oidc.eks.us-west-1.amazonaws.com/id/07083DB1BF4EDE54F4C7D851DAB7A14C"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "oidc.eks.us-west-1.amazonaws.com/id/07083DB1BF4EDE54F4C7D851DAB7A14C:aud": "sts.amazonaws.com",
                    "oidc.eks.us-west-1.amazonaws.com/id/07083DB1BF4EDE54F4C7D851DAB7A14C:sub": "system:serviceaccount:logging:fluent-bit"
                }
            }
        }
    ]
}

查看日志收集

至此我们可以看到不同 region 的不同 EKS 集群的日志已经都被收集到 AOS 中了。

同时,有些客户对日志的实时性要求比较高,那么我可以使用 Kinesis 来作为日志的 buffer,将日志的收集延迟降到最低,下面我们就 step by step 教大家来配置基于 Kinesis 的全球日志中心。

基于 Kinesis 部署架构图

同 region 下日志 pipeline 配置

在日志通中创建 Application Log Pipeline



等待几分钟后,我们会发现 Pipeline 已经创建完毕,如下图所示,buffer layer 为 KDS

创建 EKS Ingestion



配置完毕后,等待状态变为 Created


点击 DaemonSet Guide,然后拷贝其中内容至文件:fluent-bit-logging-kinesis.yaml

执行命令 Apply 相关采集配置:

kubectl apply -f fluent-bit-logging-kinesis.yaml

待创建完毕后,判断 DaemonSet 是否已经创建成功

kubectl get ds -n logging

如果显示类似如下信息,则表示创建成功

NAME         DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
fluent-bit   2         2         2       2            2           <none>          2m54s

查看相关 Fluent Bit pod 的日志如果没有 error,则说明日志收集成功

然后试着访问 Nginx 应用,查看在 Opensearch 的日志记录,可以看到访问日志已经收集成功。

下面我们来看一下在其他 region 下的收集方式。

不同 region 下配置

因为我们已经完成了日志从 Kinesis 到 OpenSearch 的日志流程,我们现在只需要将其他 region 的日志采集到我们指定的 Kinesis 即可。

部署 Fluent Bit 至日志来源的 EKS

同样按照 Loghub 中 DaemonSet 的安装指导安装到当前 EKS 集群中,命令如下:

Kubectl 地址 可以参考 Kubectl 地址使用不同版本的对应地址

- name: EKS_KUBECTL_DOWNLOAD_URL_ARM
  value: "https://s3.{region-code}.amazonaws.com/amazon-eks/1.27.1/2023-04-19/bin/linux/arm64/kubectl"
- name: EKS_KUBECTL_DOWNLOAD_URL_X86_64
  value: "https://s3.{region-code}.amazonaws.com/amazon-eks/1.27.1/2023-04-19/bin/linux/amd64/kubectl"

修改 Fluentbit 中环境变量 CLUSTER_NAME 值

containers:
- name: fluent-bit
  image: public.ecr.aws/aws-observability/aws-for-fluent-bit:2.28.4
  imagePullPolicy: Always
  env:
    - name: CLUSTER_NAME
      value: "eks-oregon" #修改为真实 Cluster Name

修改 OUTPUT 相关的配置

[OUTPUT]
    Name                kinesis_streams
    Match               loghub.7a2024f1-2dc8-44dd-9465-621c480a974f.9408b405-ee86-4ff3-82b9-4547c6c53f1e.*
    Region              us-west-1 # 注意此处 Region 的值,通常来讲不需要改
    Stream              CL-AppPipe-9408b405-KDSBufferStream21B531A6-z43gi6b9mVn2
    Retry_Limit         False
    Role_arn            arn:aws:iam::715371302281:role/CL-AppPipe-9408b405-BufferAccessRoleDF53FD85-587TWRKO13GZ

执行命令 Apply 相关采集配置:

eks update-kubeconfig --region us-west-2 --name eks-oregon
kubectl apply -f fluent-bit-logging-kinesis.yaml

设置 IAM OIDC Provider

eksctl utils associate-iam-oidc-provider \
    --region {region-code} \
    --cluster {eks-cluster-name}\
    --approve

修改 Fluent Bit Service Account 的 Trust Relationships

添加新的 EKS 信息

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::xxxxxx:oidc-provider/oidc.eks.us-west-2.amazonaws.com/id/AF0699207421311C9DAFABEFC628EE4C"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "oidc.eks.us-west-2.amazonaws.com/id/AF0699207421311C9DAFABEFC628EE4C:sub": "system:serviceaccount:logging:fluent-bit",
                    "oidc.eks.us-west-2.amazonaws.com/id/AF0699207421311C9DAFABEFC628EE4C:aud": "sts.amazonaws.com"
                }
            }
        },
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::xxxxxxxx:oidc-provider/oidc.eks.us-west-1.amazonaws.com/id/07083DB1BF4EDE54F4C7D851DAB7A14C"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "oidc.eks.us-west-1.amazonaws.com/id/07083DB1BF4EDE54F4C7D851DAB7A14C:aud": "sts.amazonaws.com",
                    "oidc.eks.us-west-1.amazonaws.com/id/07083DB1BF4EDE54F4C7D851DAB7A14C:sub": "system:serviceaccount:logging:fluent-bit"
                }
            }
        }
    ]
}

部署完毕后,访问对应的 Nginx,产生日志后,查看 OpenSearch 内的日志记录,可以发现日志已经被收集上来。

总结

通过上面的步骤,我们可以根据自己的需求选择其中的方案来配置全球化的日志中心,下面是一些选择方案的参考维度。如果我们期望更低的成本,对延迟要求不高的话可以直接选择 S3 作为日志传输的数据缓冲区,同时配置合理的 OpenSearch 的生命周期管理,来达到节约成本的目的;如果我们期望日志收集更加实时,那么我们可以采用 Kinesis 作为我们日志传输的数据缓冲区,同时调高 Fluentbit Flush 的频率,以获取更低的延迟。总之通过上面的配置,我们可以非常方便地将日志记录接入到一个 Amazon OpenSearch Domain 作为统一的日志中心中,以协助我们更方便地做日志分析和审计。

FAQ

1. FluentBit 采集日志中报错“Auth error”,导致日志采集失败。

需要确认使用的 FluentBit 的版本的同时,也需要查看是否设置了 IAM OIDC Provider。

2. 处理日志的 Lambda 成本激增是什么原因?

需要确认日志量是否同步激增的同时,也需要查看一下 Amazon OpenSearch 的 workload 是否偏高,如果 AOS 的 workload 偏高,会导致 Lambda 在处理日志时耗时较久,从而会导致 Lambda 的 duration 增长,成本自然会比较高。

本篇作者

郭俊龙

亚马逊云科技解决方案架构师,主要负责游戏行业客户解决方案设计,比较擅长云原生微服务以及大数据方案设计和实践。

张雪斌

AWS 迁移技术客户经理,曾就职于 IBM、金蝶、腾讯专有云等高科技公司,拥有 15 年以上从业经验,在云计算,数据库,容器及微服务等技术方向有一定研究,擅长解决方案设计及技术选型和落地。

马涛

亚马逊云科技解决方案研发架构师,主要负责云上解决方案的设计与研发。