【问题标题】:How is it possible that data in Kafka survives container recycling?Kafka 中的数据如何在容器回收中幸存下来?
【发布时间】:2022-04-01 04:32:43
【问题描述】:

首先,我不知道这个问题是出在 Kafka 上还是 Docker 上……我对这两个主题都是新手。但我认为这更像是一个 Docker 而不是 Kafka 的问题(事实上,我的问题是我没有真正理解其中一个……)。

我在 Raspberry 4 上安装了 Docker,并为 Kafka 和 Zookeeper 创建了 Docker 镜像;我不得不自己创建它们,因为任何现有图像都不支持 64 位 Raspi(至少我找不到任何人)。但我让他们工作了。

接下来我实现了 Kafka 文档中的 Kafka Streams 示例(Wordcount);它运行良好,计算您输入的所有文本中的单词,保留所有先前运行的数字。这在某种程度上是意料之中的;至少在那个文档中是这样描述的。

所以在一些测试运行之后,我想重置整个东西。

我认为最简单的方法是关闭 docker 容器,删除主机上已安装的文件夹并重新开始。

但这不起作用:单词计数器仍然存在!意味着字数不是从 0 开始的……

好的,下一步:不仅要删除容器,还要重建映像!当然是 Zookeeper 和 Kafka!

没有区别!保留所有先前运行的字数。

使用docker system prune --volumes 也没有区别……

根据我对 Docker 的有限了解,我假设任何运行时数据都存储在容器中,或安装的文件夹(卷)中。因此,当我删除容器和容器挂载的 Docker 主机上的文件夹时,我希望任何状态都会消失。

显然不是……所以我在这里错过了一些重要的东西,很可能是 Docker。

我使用的 docker-compose 文件:

version: '3'

services:
  zookeeper:
    image: tquadrat/zookeeper:latest
    ports:
      - "2181:2181"
      - "2888:2888"
      - "3888:3888"
      - "8080:8080"
    volumes:
      - /data/zookeeper/config:/config
      - /data/zookeeper/data:/data
      - /data/zookeeper/datalog:/datalog
      - /data/zookeeper/logs:/logs
    environment:
      ZOO_SERVERS: "server.1=zookeeper:2888:3888;2181"
    restart: always

  kafka:
    image: tquadrat/kafka:latest
    depends_on:
      - zookeeper
    ports:
      - "9091:9091"
    volumes:
      - /data/kafka/config:/config
      - /data/kafka/logs:/logs
    environment:
      KAFKA_LISTENERS: "INTERNAL://kafka:29091,EXTERNAL://:9091"
      KAFKA_ADVERTISED_LISTENERS: "INTERNAL://kafka:29091,EXTERNAL://TCON-PI4003:9091"
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: "INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT"
      KAFKA_INTER_BROKER_LISTENER_NAME: "INTERNAL"
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_DELETE_TOPIC_ENABLE: "true"
    restart: always

我用来清除挂载文件夹的脚本文件:

#!/bin/sh

set -eux

DATA="/data"
KAFKA_DATA="$DATA/kafka"
ZOOKEEPER_DATA="$DATA/zookeeper"

sudo rm -R "$KAFKA_DATA"
sudo rm -R "$ZOOKEEPER_DATA"

mkdir -p "$KAFKA_DATA/config" "$KAFKA_DATA/logs"
mkdir -p "$ZOOKEEPER_DATA/config" "$ZOOKEEPER_DATA/data" "$ZOOKEEPER_DATA/datalog" "$ZOOKEEPER_DATA/logs"

有什么想法吗?

【问题讨论】:

  • 您的 kafka 和 zookeeper 映像是否配置为使用您作为卷安装的路径?你如何销毁和重启你的容器?
  • 是的,它们被配置为使用路径,当我查看这些位置时,Kafka 和 Zookeeper 都在那里写了一些东西。为了销毁容器,我通常只使用docker-compose down,而docker ps -a 不再显示它们了……我也尝试了docker system prune --volumes……当然我也必须运行我的cleanup.sh 脚​​本。
  • 你真的不应该挂载配置。让环境变量设置配置
  • 如前所述,我是 Docker 新手,我的 Dockerfile 和 docker-compose.yaml 是基于我在 DockerHub 和 github 上找到的(以避免“复制自”)。但是我发现挂载的配置目录对于验证配置非常有用,因为我开始使用的基本映像没有外壳(同时我更改了一些东西)。但这可能与我的问题有关吗?
  • 不一定,但如果您决定在主机上编辑文件,则每次容器重启时文件都会被覆盖。如果您不能 docker-compose exec kafka cat /config/server.properties 或使用 grep`... 容器需要 shell 来运行 Kafka 脚本,我会感到惊讶。

标签: docker apache-kafka docker-compose apache-kafka-streams


【解决方案1】:

Kafka Streams 将自己的状态存储在运行它的主机上的 "state.dir" 配置下。在 Apache Kafka 库中,它位于 /tmp 下。首先检查您是否在代码中覆盖了该属性。

就 Docker 而言,先尝试不使用卷。

使用 docker system prune --volumes 也没有区别……

这将清除在 Compose 中使用 docker volume createvolumes: 创建的未附加卷,而不是主机安装目录。

【讨论】:

  • 您明确提到了 Kafka Streams,它将自己的状态存储在运行的主机上。就我而言,Kafka Streams 处理器运行在 Docker 之外的另一台机器上(以及该 Docker 内的 Kafka 服务器),但在那台机器上,我在 /tmp 中找不到任何来自 Kafka 的痕迹。
  • 在 Confluent 库中,它的 /var/lib/kafka-streams... docs.confluent.io/current/streams/developer-guide/…
  • 是的,在你用state.dir 提示之后,我也找到了那个页面。但是在我的工作站(我运行 Streams 处理器的地方)上,该文件夹对我来说是不可写的,我也不知道 Docker 将它放在哪里。但是在明确设置配置(并在运行后删除其内容)之后,我现在可以重置 Streams 处理器。
  • 如果客户端代码没有在容器中运行,那么 Docker 没有控制该目录
【解决方案2】:

正如我从一开始就认为的那样,问题主要是我缺乏知识。

我观察到的行为与 Docker 的神奇数据存储有关,它在所有试图杀死它的情况下都幸存下来;它与 Docker 完全无关。

我使用这些 Docker 映像在其上运行 Zookeeper 和 Kafka 服务器。然后我切换回我的工作站机器,编写了实现 Kafka 流处理器的代码(“Wordcount”示例)。当我在我的 IDE 中启动它时,它在我的本地机器上执行,通过网络访问 Kafka。

我的假设是 任何 状态都存储在 Kafka 服务器上,因此转储应该重置整个事情;因为这不起作用,我也抛弃了 Zookeeper,因为这也无济于事,我几乎删除了所有东西......

经过这里的一些提示后,我发现 Kafka Streams 处理器在通过 state.dir (StreamsConfig.STATE_DIR_CONFIG) 配置的文件系统文件夹中维护自己的本地状态 - 请参阅 Configuring a Streams Application。这意味着 Kafka Streams 处理器保持其 自己的本地 状态 独立 与任何 Kafka 服务器,并且 - 就像我在本地机器上运行时一样 - 也在外部/不相关到任何 Docker 容器……

根据文档,默认位置应该是/var/lib/kafka-streams,但这在我的环境中是不可写的——不知道流处理器将其状态放在哪里。

在将 Streams 处理器的配置值 state.dir 显式设置为我的主目录中的一个文件夹后,我可以在我的磁盘上看到该状态,删除该状态后,字数从 1 开始。

深入研究 Kafka Streams 的文档后发现,在启动或关闭流处理器之前或之后调用 KafkaStream.cleanup() (无需删除文件系统上的文件),我可能会得到相同的结果。

【讨论】:

  • 注意:该链接仅在您从 Confluent repo 而非 Maven Central 中提取 kafka-streams 依赖项时有效
  • @cricket_007:抱歉,您指的是哪个链接?
  • 答案中的一个链接
  • @cricket_007:那么您的意思是,通过该链接提供的信息仅在从 Confluent 存储库中提取 kafka-streams 依赖项时才有效,而不是链接本身已损坏......不过,我使用了 Maven Central 的东西,我基于链接文档创建的配置对我有用。看来我还没有达到临界点。
  • 我的意思是链接在表格中提供的属性,是的,与kafka.apache.org/documentation/streams/developer-guide/…相比
猜你喜欢
  • 2016-09-08
  • 2023-04-04
  • 1970-01-01
  • 2022-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-07
相关资源
最近更新 更多