亚马逊AWS官方博客

基于 Amazon Athena Amazon S3 和 Fluentbit 实现 Amazon EKS kubernetes event 的 Log 方案

1. 背景介绍

在 Kubernetes 环境中,事件 Events 是系统状态变化的重要指示器,它们记录了与集群中资源(如 Pods、Deployments、Services 等)相关的各种活动,如创建、更新、删除等。对于 Amazon EKS(Elastic Kubernetes Service)用户而言,有效地采集、存储和分析这些事件日志对于理解集群运行状态、问题排查和性能优化至关重要。然而,Amazon EKS 本身并没有提供专门的 Kubernetes 事件日志采集方案,目前亚马逊云的集中式日志方案 Centralized logging 还没有覆盖 Kubernetes Events,这导致用户需要自行设计并实现 Kubernetes 事件 Events 日志采集、存储和分析的解决方案。

2. 主要技术难点

  • 事件日志的实时采集:Kubernetes 事件日志的生成频率高,需要确保采集过程的高效性和实时性,避免事件日志丢失。
  • 日志的存储与查询:采集到的事件日志需要高效存储,并支持灵活的查询方式,以便进行快速的问题定位和性能分析。
  • 成本的优化成本优化在此方案中的重要性在于确保日志采集、存储和分析过程在经济高效的前提下运行,避免不必要的资源浪费,使整体解决方案更加可持续和可扩展。
  • 易于部署与配置:为了实现 CI/CD(持续集成/持续部署)的自动化,需要设计易于部署和配置的日志解决方案。

3. 解决方案

1. 选用 Fluentbit 作为日志采集器

Fluentbit 是一个轻量级的开源多平台日志采集器,特别适用于 Kubernetes 环境。它能够高效地采集容器日志、应用日志以及 Kubernetes 事件日志。在 Amazon EKS 中,Fluentbit 可以通过 DaemonSet 方式部署在每个节点上,以实现对节点上所有 Pod 的事件日志采集。从 Fluentbit v2.1 版本开始,Fluentbit 开始支持 Kubernetes Events 的日志采集。

2. 将事件日志发送到 Amazon S3 存储

为了存储采集到的事件日志,我们选择 Amazon S3 作为存储服务。Amazon S3 是一个面向互联网的存储服务,提供了高可靠性和可扩展性。Fluentbit 支持将日志直接发送到 Amazon S3,支持 multipart upload API 或 PutObject API,确保日志在上传过程中的完整性和高效性。

3. 使用 Amazon Athena 进行日志查询

Amazon Athena 是一个交互式查询服务,允许用户直接使用标准 SQL 查询存储在 Amazon S3 中的数据。通过将事件日志存储在 Amazon S3 中,并使用 Amazon Athena 进行查询,可以极大地简化日志分析过程,其关键点是如何裁剪和自定义 Amazon S3 中日志格式并在 Amazon Athena 中建立 kubernets Events 对应的 Table 以方便运维人员查询有效信息。Amazon Athena 支持无服务器架构,用户无需管理任何基础设施,只需为查询时扫描的数据量付费。

4. 自动化部署与配置

为了实现自动化部署和配置,可以通过 Kubernetes 的 ConfigMap 来管理 Fluentbit 的配置,确保配置的灵活性和安全性。当然,运维人员也可以使用 CI/CD 工具(如 Jenkins、GitLab CI/CD 等)来自动化整个部署和配置过程。

4. 具体方案实现

1. 方案架构

2. 前提条件

3. 创建或者使用已经存在的 Amazon S3 bucket 作为 fluentbit 输出日志的目标

可以选择控制台创建,或者使用下面亚马逊云科技 CLI 命令行来创建

aws s3 mb s3://my-new-s3-test --region us-east-2
PowerShell

4. 创建 fluentbit 读写 Amazon S3 的 iam policy

cat <<EOF > s3-putobject-iam-policy.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject"
            ],
            "Resource": "arn:aws-cn:s3::: my-new-s3-test /*"
        }
     ]
}
EOF

aws iam create-policy --policy-name S3PutObjectPolicy --policy-document file://./s3-putobject-iam-policy.json --region us-east-2
PowerShell

5. 为 Amazon EKS 集群创建 oidc provider,该步骤为创建 iamserviceaccount 的先决条件

eksctl utils associate-iam-oidc-provider --region=us-east-2 --cluster=myEKS --approve
PowerShell

6. 创建 fluentbit 读写需要的 iam serviceaccount

POLICY_NAME=$(aws iam list-policies --query 'Policies[?PolicyName==` S3PutObjectPolicy`].Arn' --output text --region us-east-2)

eksctl create iamserviceaccount \
       --cluster=myEKS \
       --region us-east-2 \
       --namespace=default \
       --name=s3-putobject \
       --attach-policy-arn=${POLICY_NAME} \
       --override-existing-serviceaccounts \
       --approve
PowerShell

7. 为 fluentbit 的部署和 Amazon S3 输出准备配置文件并在 configmap 里面 kubernetes events 插件配置项

cat <<EOF > fluentbit-config-s3.yml	
apiVersion: v1
kind: ConfigMap
metadata:
  name: fluentbit-config
  labels:
    k8s-app: fluentbit
data:
# Configuration files: server, input, filters and output
# ======================================================
  fluentbit.conf: |
    [SERVICE]
        flush           1
        log_level       info

    [INPUT]
        name            kubernetes_events
        tag             k8s_events
        kube_url        https://kubernetes.default.svc

    [OUTPUT]
        Name                          s3
        Match                         k8s_events
        bucket                        my-new-s3-test
        region                        us-east-2
        store_dir                     /home
        total_file_size               10M
        upload_timeout                1m
        s3_key_format                 /fluentbit-logs/k8s_events/year=%Y/month=%m/day=%d/%H-%M-%S
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: fluentbit-read
rules:
  - nonResourceURLs:
      - /metrics
    verbs:
      - get
  - apiGroups: [""]
    resources:
      - namespaces
      - pods
      - pods/logs
      - nodes
      - nodes/proxy
      - events
    verbs: ["get", "list", "watch"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: fluentbit-read
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: fluentbit-read
subjects:
- kind: ServiceAccount
  name: s3-putobject
  namespace: default

---
apiVersion: apps/v1
kind: DaemonSet
metadata:
    name: fluentbit
    labels:
        k8s-app: fluentbit
        version: v8
        kubernetes.io/cluster-service: "true"
spec:
    selector:
        matchLabels:
          k8s-app: fluentbit
          version: v1
    updateStrategy:
        type: RollingUpdate
    template:
        metadata:
            labels:
                k8s-app: fluentbit
                version: v1
                kubernetes.io/cluster-service: "true"
        spec:
            containers:
              - name: fluentbit
                image: cr.fluentbit.io/fluent/fluent-bit
                imagePullPolicy: Always
                command: ["/fluent-bit/bin/fluent-bit","-c", "/fluent-bit/etc/fluentbit.conf"]
                env:
                - name: NODE_NAME
                  valueFrom:
                    fieldRef:
                        fieldPath: spec.nodeName
                - name: MY_POD_NAME
                  valueFrom:
                    fieldRef:
                        fieldPath: metadata.name
                - name: MY_POD_NAMESPACE
                  valueFrom:
                    fieldRef:
                        fieldPath: metadata.namespace
                - name: MY_POD_IP
                  valueFrom:
                    fieldRef:
                        fieldPath: status.podIP
                resources:
                    requests:
                        cpu: 5m
                        memory: 20Mi
                    limits:
                        cpu: 60m
                        memory: 60Mi
                volumeMounts:
                - name: varlog
                  mountPath: /var/log
                - name: logs
                  mountPath: /data/logs
                  readOnly: true
                - name: fluentbit-config
                  mountPath: /fluent-bit/etc/
            serviceAccountName: s3-putobject
            terminationGracePeriodSeconds: 10
            volumes:
                - name: varlog
                  hostPath:
                    path: /var/log
                - name: logs
                  hostPath:
                    path: /data/logs
                - name: fluentbit-config
                  configMap:
                    name: fluentbit-config
EOF    
PowerShell

8. 应用该 fluentbit 配置文件

kubectl apply -f fluentbit-config-s3.yml
PowerShell

验证部署成功

9. 检查对应的 Amazon s3 存储桶 my-new-s3-test 的/fluentbit-logs/k8s_events/的目录

确认 kubernets events 日志成功生成

下载生成的日志并检查内容

10. 使用 Amazon Athena 查询日志

登陆亚马逊云科技 Console,进入 Amazon Athena 服务,链接为 https://us-east-2.console.aws.amazon.com/athena/home?region=us-east-2#/query-editor

在 Query editor 中创建一个新的 query 并执行下面的语句创建 k8s_events 表

CREATE EXTERNAL TABLE `default`.`k8s_events`(
   `date` string, 
   `kind` string, 
   `namespace` string,
   `name` string,
   `reason` string,
   `message` string,
   `reportingComponent` string,
   `reportingInstance` string)
   PARTITIONED BY (year int,month int,day int)
   ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe' 
   WITH SERDEPROPERTIES ( 
     'input.regex'='\\{\"date\":\"([^ ]*)\",\"metadata\":[^ ]*\"involvedObject\":[^ ]*\"kind\":\"([^ ]*)\",\"namespace\":\"([^ ]*)\",\"name\":\"([^ ]*)\",\"uid\"[^ ]*\"reason\":\"([^ ]*)\",\"message\":\"(.*)\",\"source\".*\"reportingComponent\":\"([^ ]*)\",\"reportingInstance\":\"([^ ]*)\"\\}'
) 
   STORED AS INPUTFORMAT 'org.apache.hadoop.mapred.TextInputFormat' 
   OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
   LOCATION 's3://my-new-s3-test/fluentbit-logs/k8s_events/'
   TBLPROPERTIES ('has_encrypted_data'='false')
PowerShell

然后新创建一个 query 2 并执行下面语句,更新 table 的 partition 信息

MSCK REPAIR TABLE default. k8s_events;
PowerShell

然后新创建一个 query 3 并执行下面语句,查询日志

select * from default. k8s_events limit 10;
PowerShell

总结

本文主要介绍 Amazon EKS 环境下如何通过 Amazon Athena, Amazon S3, Fluentbit 实现 kubernets events 的日志方案。方便用户在 Amazon EKS 环境下,快速实现针对 kubernets events 的日志查询,本方案可以作为亚马逊云科技 Centralized logging 集中式日志方案 的补充,支持用户实现对 Amazon EKS 的更加完整全面的日志监控。

参考文档

  1. https://aws.amazon.com/cn/blogs/china/scheme-of-using-fluent-bit-in-eks-to-collect-application-logs-and-save-them-in-s3/
  2. https://docs.fluentbit.io/manual/pipeline/inputs/kubernetes-events

本篇作者

董杰

西云数据解决方案架构师,曾就职于多家外企、知名民企,主要负责支持企业客户上云,专注于亚马逊云解决方案设计和技术咨询,15+年软件开发、项目交付、售前咨询等丰富的行业实践建议。

郑毅

西云数据解决方案架构师,曾就职于外企、互联网企业和央企,擅长系统交付、运维和解决方案设计,对于传统 IT 技术以及云计算技术有深入了解和丰富的实战经验。

刘兵

亚马逊云科技高性能计算专业解决方案架构师,专注于协助客户在亚马逊云科技上构建经济、可持续的高性能计算解决方案。拥有 Linux 系统及内核优化、定制和构建各种 HPC 方案的丰富经验,擅长为客户量身定制高度优化的HPC解决方案。同时,在系统编程、故障排除和调试以及可观察性领域拥有深厚的专业知识,确保客户能够高效、顺利地在云端构建和迁移应用程序,覆盖多种架构。目标是充分发挥云计算的优势,助力客户的业务实现可持续发展。