阿里云ACK+Kafka采集

更新时间:
复制为 MD 格式

本文提供一套生产级的日志采集方案,用于将部署在容器服务 Kubernetes 版 ACK中的应用日志,通过OpenTelemetry Collector进行采集,经由云消息队列 Kafka版进行缓冲,最终持久化到阿里云Elasticsearch(ES)实例中。此方案以声明式YAML配置为核心,旨在实现高效、可靠且可自动化的日志管理。

业务场景说明

在微服务架构下,应用的日志数据量通常非常庞大。如果日志采集组件直接将数据写入ES,当日志流量洪峰或后端ES集群出现性能抖动、不可用时,极易导致日志采集链路中断,甚至引发数据丢失。

本方案通过在采集端与存储端之间引入Kafka作为消息队列,实现两者的解耦。Kafka作为高性能缓冲层,能够平滑处理突发日志流量,增强整个日志系统的稳定性和数据可靠性。即使下游ES暂时不可用,日志数据也会暂存在Kafka中,待恢复后继续消费,从而避免数据丢失。

方案架构

本方案采用两级OpenTelemetry Collector的部署模式:Sidecar采集器和中心化采集器。

image

工作流程与核心逻辑:

  1. Sidecar OTel Collector:作为Sidecar容器与业务应用Pod一同部署。它通过共享卷(emptyDir)读取应用容器写入的日志文件。采集到的日志数据被发送到指定的Kafka Topic。

  2. 云消息队列 Kafka 版:作为日志数据的缓冲队列。它接收来自所有Sidecar采集器的日志,为后端消费提供一个统一、稳定的数据源。引入Kafka可以提升架构的稳定性,有效应对日志洪峰。

  3. 中心化 OTel Collector:作为一个独立的Deployment部署在ACK集群中。它作为Kafka的消费组,从Topic中拉取日志数据,经过处理后,批量写入目标ES集群。

  4. 阿里云ES:作为日志数据的最终存储和检索系统。

架构决策:为何引入Kafka?

  • 应对日志流量的突发性增长:避免后端ES因瞬时写入压力过大而性能下降或拒绝请求。

  • 系统解耦:将日志采集端(应用Pod)与存储端(ES)解耦。任何一方的故障或维护都不会直接影响另一方,提升了系统的整体可用性。

  • 数据缓冲与可靠性:当ES不可用时,日志数据被暂存在Kafka中,避免了数据丢失。待ES恢复后,中心化Collector会自动追赶消费,确保数据的最终一致性。

实施步骤

1. 环境准备

请确保以下环境和配置已准备就绪:

  1. 准备 ACK、 ES以及Kafka实例

    • 一个可用的容器服务 ACK 集群。

    • 一个阿里云 ES 实例。建议开启自动创建索引功能,以便服务能自动根据上报数据创建索引。

      进入ES实例的基本信息页面,单击 配置与管理 > ES集群配置,单击修改配置,选择允许自动创建索引

    • Kaffka实例中创建TopicGroup资源

  2. 确保网络连通性

    • 确认 ACK 集群与 ES 实例之间的网络是连通的。如果两者不在同一个专有网络 VPC (Virtual Private Cloud) 内,必须先打通网络。推荐使用 VPC对等连接实现网络互通

  3. 准备容器镜像

    本方案使用 Elastic Agent 的官方镜像。为确保部署的稳定性和可访问性,建议将所需镜像预先拉取并推送到您自己的阿里云容器镜像服务 ACR (Alibaba Cloud Container Registry) 仓库中。

    # 拉取官方镜像
    docker pull elastic/elastic-agent:9.1.5

    方案经过测试,elastic/elastic-agent:9.x 版本与 8.17 版本的 ES 兼容。

2. 在ACK中配置OTel Collector

ACK中创建两个ConfigMap作为OTel配置文件的引用,分别用于将日志数据输出到Kafka(名为otel2kafka-config)以及用来消费Kafka数据并输出到ES(名为otel-kafka2es-config)。

  1. 登录ACK控制台,单击配置管理 > 配置项

  2. 创建配置项:

    • 创建名称otel2kafka-config的配置项,具体名称为otel.yml,值为您的otel配置文件内容,用于将日志数据输出到Kafka。

      otel.yml示例值,请根据实际配置进行修改,详细otel配置请参见openTelemetryReceivers

      receivers:
        # 配置文件日志接收器
        filelog:
          include: [/path/to/logs/*.log] # 日志文件路径
          exclude: []                    # 排除文件列表
          start_at: end                  # 从文件结尾开始读取
          multiline:
            line_start_pattern: ^xxxx    # 改为您日志的实际行开头pattern正则
      
      exporters:
        kafka/logs:
          brokers:
            - broker1:9092
            - broker2:9092
            - broker3:9092
          logs:
            topic: otel-kafka            # 您在kafka中创建的用来收集日志的topic
          producer:
            compression: zstd            # 开启zstd压缩
            compression_params:
              level: 3                   # 压缩等级3
      
      service:
        pipelines:
          logs:
            receivers: [filelog]
            exporters: [kafka/logs]
    • 创建名称为otel-kafka2es-config的配置项,具体名称为otel.yml,值为您的otel配置文件内容,用来消费Kafka数据并输出到ES。

      otel.yml示例值,请根据实际配置进行修改:

      receivers:
        kafka:
          brokers:
            - broker1:9092
            - broker2:9092
            - broker3:9092
          logs:
            topic: otel-kafka          # 您在kafka中创建的用来收集日志的topic
          group_id: gid_otel_collector # 您在kafka中创建的用来收集日志的group_id
      
      exporters:
        elasticsearch/logs:
          endpoints: ["http://es-cn-xxxxxxpxi00xxxxxx.elasticsearch.aliyuncs.com:9200"]  # ES 集群地址
          user: "elastic"                          
          password: "your_password"
          tls:
            insecure_skip_verify: false     # 生产环境应设为 true
          retry:
            enabled: true
            initial_interval: 5s
            max_interval: 30s
      
      service:
        pipelines:
          logs:
            receivers: [kafka]
            exporters: [elasticsearch/logs]
  3. 创建完成后,返回配置项列表。

3. 部署OTel Collector服务

部署OTel Collector服务,用来消费Kafka数据并输出到ES实例。

  1. 登录容器服务管理控制台,在左侧导航栏选择集群列表集群列表页面,单击目标集群名称,然后在左侧导航栏,选择工作负载 > 无状态无状态页面,单击使用镜像创建

  2. 应用基本信息配置向导页面,设置应用的基本信息。然后单击下一步,进入容器配置向导页面。

  3. 配置容器

    容器配置区域,完成容器的镜像名端口环境变量以及数据卷配置。其余设置均为可选设置,保持默认即可。

    • 镜像名称:选择在环境准备环节提前准备好的elastic/elastic-agent:9.1.5镜像。

    • 环境变量:添加 ELASTIC_AGENT_OTEL,值为 true启用 OpenTelemetry 采集模式。

    • 数据卷

      • 类型:选择 配置项

      • 名称:kafka2es-config

      • 挂载源:otel-kafka2es-config ConfigMap

      • 挂载路径:/usr/share/elastic-agent/otel.yml(必须严格匹配官方镜像路径)

      • 子路径:otel.yml(必须指定,否则会覆盖整个 /usr/share/elastic-agent 目录)

  4. 然后单击下一步,进入高级配置向导页面,保持默认配置,单击创建

4. 部署应用与 Sidecar 容器

在现有Deployment 或 StatefulSet 的 Pod 模板中添加日志采集 Sidecar 容器的定义,可使需要日志采集的业务 Pod 在创建时自动包含该 Sidecar 容器。以下以 Deployment 为例说明,StatefulSet 的配置方式相同。

  1. Deployment列表中,单击目标 Deployment 名称,进入详情页。

  2. 单击编辑

  3. 编辑页面,找到数据卷区域,单击增加本地存储为业务容器添加共享日志卷。

    重要

    此处的数据卷作为业务容器与 Sidecar 的共享存储,确保日志文件可被 Sidecar 读取,容器路径必须与业务容器实际日志路径严格一致,否则 Sidecar 无法采集数据。

  4. 编辑页面,单击添加容器添加日志采集 Sidecar 容器。

    • 镜像名称:选择在环境准备环节提前准备好的elastic/elastic-agent:9.1.5镜像。

    • 环境变量:添加 ELASTIC_AGENT_OTEL,值为 true启用 OpenTelemetry 采集模式。

  5. 配置 Sidecar 容器的卷挂载,添加两个挂载项:

    • 挂载 1:共享日志卷

      • 卷名称:选择 app-log(与业务容器共享的卷)。

      • 容器路径:/path/to/logs(与业务容器挂载路径完全一致)。

    • 挂载 2:OTel 配置文件

      • 卷类型:选择 ConfigMap

      • 卷名称:otel-config(需提前创建的 ConfigMap 名称)。

      • 挂载路径:/usr/share/elastic-agent/otel.yml(必须严格匹配官方镜像路径)。

      • 子路径:otel.yml(关键:仅挂载单个文件,避免覆盖目录)。

  6. 确认所有配置无误后,单击更新提交变更。

    Kubernetes将自动滚动重启 Pod,新 Pod 会包含业务容器和 Sidecar 容器。

5. 验证方案

  1. 检查Pod状态:确认中心化OTel Collector和注入了Sidecar的应用Pod都正常运行。

  2. 查看采集器日志,确认没有错误信息。

  3. 检查Kafka Topic:确认Topic中有新的日志数据流入。

  4. 查询Elasticsearch:在Kibana中查询对应的索引,验证新的应用日志是否已成功写入。