
如果你使用 DeepSeek、元宝 AI、Copilot、ChatGPT 等 AI 工具,协助配置轩辕镜像、编写 docker pull 命令、修改 Docker Compose 镜像地址、配置镜像加速、排查镜像拉取失败、分析报错日志等问题,请先让 AI 阅读并遵守轩辕镜像的规则文档。
只需在 AI 对话中先发送下面这句话即可:
请先完整阅读并严格遵守以下文档中的全部规则与要求:
https://xuanyuan.cloud/agents.md
在未充分阅读并理解该文档前,不要生成任何命令、配置、修改建议、故障排查方案或技术回答。后续所有输出都必须严格以该文档中的规范为最高优先级执行。查看 agents.md 用法指南与完整示范。国内用户首推 元宝 AI、DeepSeek 的深度思考模式,不推荐豆包 AI;Cursor 等编辑器可在对话 @ 该链接,或加入 User Rules。 若 AI 无法访问外链,可 打开说明文档 复制全文粘贴。文档会随站点更新,复制内容可能过期,建议定期检查。
该项目包含一个Docker镜像,旨在使用https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/%E5%9C%A8http://kubernetes.io/%E4%B8%8A%E9%83%A8%E7%BD%B2https://kafka.apache.org/%E3%80%82
本仓库中的Docker镜像基于Ubuntu 16.04,使用基于1.8 JVM的最新OpenJDK JRE版本(JDK 8u111)和基于Scala 2.11的最新稳定版Kafka(10.2.0)。虽然Ubuntu镜像比BusyBox或Alpine大,但后两者使用mucl或ulibc,需要针对非glibc的libc运行时构建自定义OpenJDK版本。尽管存在基于Alpine和BusyBox的更小Kafka镜像,但Kafka、JVM与glibc的交互更易理解和调试。
镜像设计为以非root用户运行Kafka JVM进程,默认用户为kafka,UID 1000,GID 1000。Kafka安装在/opt/kafka目录,配置文件位于/opt/kafka/config,可执行文件在/opt/kafka/***。由于/opt/kafka/***中的脚本实现限制,无法将其符号链接到/user/***目录,因此将/opt/kafka/***添加到PATH环境变量。
Kafka需要Apache ZooKeeper进行 broker 配置存储和协调。可参考https://github.com/kubernetes/contrib/tree/master/statefulsets/zookeeper%E7%9A%84%E7%A4%BA%E4%BE%8B%E5%9C%A8Kubernetes%E4%B8%8A%E9%83%A8%E7%BD%B2ZooKeeper%E9%9B%86%E7%BE%A4%E3%80%82%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%831-3%E4%B8%AA%E8%8A%82%E7%82%B9%E8%B6%B3%E5%A4%9F%EF%BC%8C%E7%94%9F%E4%BA%A7%E7%8E%AF%E5%A2%83%E5%BB%BA%E8%AE%AE%E8%87%B3%E5%B0%91%E9%83%A8%E7%BD%B25%E4%B8%AA%E8%8A%82%E7%82%B9%EF%BC%8C%E4%BB%A5%E5%AE%B9%E5%BF%8D%E7%BB%B4%E6%8A%A4%E6%9C%9F%E9%97%B4%E7%9A%84%E8%8A%82%E7%82%B9%E6%95%85%E9%9A%9C%E3%80%82%E8%8B%A5%E5%9C%A8Kubernetes%E4%B8%8A%E8%BF%90%E8%A1%8CZooKeeper%EF%BC%8C%E6%AF%8F%E4%B8%AAKafka%E9%9B%86%E7%BE%A4%E6%9C%80%E5%A5%BD%E4%BD%BF%E7%94%A8%E7%8B%AC%E7%AB%8B%E7%9A%84ZooKeeper%E9%9B%86%E7%BE%A4%E3%80%82%E7%94%9F%E4%BA%A7%E7%8E%AF%E5%A2%83%E4%B8%AD%EF%BC%8C%E6%AF%8F%E4%B8%AAZooKeeper%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%BA%94%E8%87%B3%E5%B0%91%E6%9C%892 GiB堆内存和4 GiB Pod预留内存。ZooKeeper对CPU要求不高,每个服务器2 CPU通常足够。若在云平台(如GCP、Azure、AWS)运行Kubernetes,应为ZooKeeper PV配置快速存储类。由于PV基于网络附加存储,将预写日志与快照目录隔离几乎无收益。
Kafka StatefulSet需要Headless Service控制Kafka broker的网络域。以下YAML创建Headless Service,支持broker发现并暴露9093端口供客户端连接。
yamlapiVersion: v1 kind: Service metadata: name: kafka-svc labels: app: kafka spec: ports: - port: 9093 name: server clusterIP: None selector: app: kafka
Kafka StatefulSet在Kubernetes集群上部署可配置数量的副本。StatefulSet的serviceName必须与Headless Service匹配,并指定所需的broker数量。
yamlapiVersion: apps/v1beta1 kind: StatefulSet metadata: name: kafka spec: serviceName: kafka-svc replicas: 3 ...
本节详细说明Kafka集群的配置。
每个broker的配置通过命令行标志覆盖默认配置,包含Kafka文档中https://kafka.apache.org/documentation/#brokerconfigs%E3%80%82
yamlkafka-server-start.sh /opt/kafka/config/server.properties --override broker.id=${HOSTNAME##*-} \ --override listeners=PLAINTEXT://:9093 \ --override zookeeper.connect=zk-0.zk-svc.default.svc.cluster.local:2181,zk-1.zk-svc.default.svc.cluster.local:2181,zk-2.zk-svc.default.svc.cluster.local:2181 \ --override auto.create.topics.enable=true \ --override auto.leader.rebalance.enable=true \ --override background.threads=10 \ --override compression.type=producer \ --override delete.topic.enable=false \ --override leader.imbalance.check.interval.seconds=300 \ --override leader.imbalance.per.broker.percentage=10 \ --override log.flush.interval.messages=9223372036854775807 \ --override log.flush.offset.checkpoint.interval.ms=60000 \ --override log.flush.scheduler.interval.ms=9223372036854775807 \ --override log.retention.bytes=-1 \ --override log.retention.hours=168 \ --override log.roll.hours=168 \ --override log.roll.jitter.hours=0 \ --override log.segment.bytes=1073741824 \ --override log.segment.delete.delay.ms=60000 \ --override message.max.bytes=1000012 \ --override min.insync.replicas=1 \ --override num.io.threads=8 \ --override num.network.threads=3 \ --override num.recovery.threads.per.data.dir=1 \ --override num.replica.fetchers=1 \ --override offset.metadata.max.bytes=4096 \ --override offsets.commit.required.acks=-1 \ --override offsets.commit.timeout.ms=5000 \ --override offsets.load.buffer.size=5242880 \ --override offsets.retention.check.interval.ms=600000 \ --override offsets.retention.minutes=1440 \ --override offsets.topic.compression.codec=0 \ --override offsets.topic.num.partitions=50 \ --override offsets.topic.replication.factor=3 \ --override offsets.topic.segment.bytes=104857600 \ --override queued.max.requests=500 \ --override quota.consumer.default=9223372036854775807 \ --override quota.producer.default=9223372036854775807 \ --override replica.fetch.min.bytes=1 \ --override replica.fetch.wait.max.ms=500 \ --override replica.high.watermark.checkpoint.interval.ms=5000 \ --override replica.lag.time.max.ms=10000 \ --override replica.socket.receive.buffer.bytes=65536 \ --override replica.socket.timeout.ms=30000 \ --override request.timeout.ms=30000 \ --override socket.receive.buffer.bytes=102400 \ --override socket.request.max.bytes=104857600 \ --override socket.send.buffer.bytes=102400 \ --override unclean.leader.election.enable=true \ --override zookeeper.session.timeout.ms=6000 \ --override zookeeper.set.acl=false \ --override broker.id.generation.enable=true \ --override connections.max.idle.ms=600000 \ --override controlled.shutdown.enable=true \ --override controlled.shutdown.max.retries=3 \ --override controlled.shutdown.retry.backoff.ms=5000 \ --override controller.socket.timeout.ms=30000 \ --override default.replication.factor=1 \ --override fetch.purgatory.purge.interval.requests=1000 \ --override group.max.session.timeout.ms=300000 \ --override group.min.session.timeout.ms=6000 \ --override inter.broker.protocol.version=0.10.2-IV0 \ --override log.cleaner.backoff.ms=15000 \ --override log.cleaner.dedupe.buffer.size=134217728 \ --override log.cleaner.delete.retention.ms=86400000 \ --override log.cleaner.enable=true \ --override log.cleaner.io.buffer.load.factor=0.9 \ --override log.cleaner.io.buffer.size=524288 \ --override log.cleaner.io.max.bytes.per.second=1.7976931348623157E308 \ --override log.cleaner.min.cleanable.ratio=0.5 \ --override log.cleaner.min.compaction.lag.ms=0 \ --override log.cleaner.threads=1 \ --override log.cleanup.policy=delete \ --override log.index.interval.bytes=4096 \ --override log.index.size.max.bytes=10485760 \ --override log.message.timestamp.difference.max.ms=9223372036854775807 \ --override log.message.timestamp.type=CreateTime \ --override log.preallocate=false \ --override log.retention.check.interval.ms=300000 \ --override max.connections.per.ip=2147483647 \ --override num.partitions=1 \ --override producer.purgatory.purge.interval.requests=1000 \ --override replica.fetch.backoff.ms=1000 \ --override replica.fetch.max.bytes=1048576 \ --override replica.fetch.response.max.bytes=10485760 \ --override reserved.broker.max.id=1000
broker.id从StatefulSet Pod的序号索引提取。listeners配置必须指定Headless Service的端口(此处为9093)。zookeeper.connect是ZooKeeper集群中服务器的host:port对逗号分隔列表。生产环境中,需配置基础OS镜像以支持足够的文件描述符数量:
(分区数) * (分区大小/段大小)决定,需确保不会因文件描述符耗尽导致broker进程终止。典型生产环境Kafka broker部署使用双处理器Xeon,每个核心有多个硬件线程。CPU通常不是瓶颈,8 CPU部署足以满足良好性能。建议从2-4 CPU开始模拟工作负载,逐步增加。
Kafka大量利用OS页缓存缓冲数据。需理解Kafka与Linux容器的交互(参考https://kafka.apache.org/documentation/#design_filesystem%E5%92%8Chttps://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt%EF%BC%89%EF%BC%8C%E7%89%B9%E5%88%AB%E6%98%AFmem cgroup对页缓存的统计和隔离。若关注隔离和性能,建议:
t(秒)。tp(存储/时间)。tp * t为内存存储需求,应设为容器的内存请求。磁盘吞吐量是用户使用Kafka时最常见的瓶颈。由于持久卷基于网络附加存储,吞吐量在大多数情况下按节点限制,与节点上挂载的持久卷数量无关。例如,在GKE或GCP的Kubernetes集群上使用标准PD,单实例最大持续吞吐量为120 MB/s(写)和180 MB/s(读)。若多个应用挂载持久卷,这些数值为总吞吐量。若存在竞争,建议使用Pod Anti-Affinity规则避免高负载应用部署在同一节点。
StatefulSet的PodTemplateSpec中的Kafka Pod包含Pod反亲和性和Pod亲和性规则:
yamlaffinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: "app" operator: In values: - kafka topologyKey: "kubernetes.io/hostname" podAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 podAffinityTerm: labelSelector: matchExpressions: - key: "app" operator: In values: - zk topologyKey: "kubernetes.io/hostname"
Pod反亲和性规则确保两个Kafka Broker不会部署在同一节点,虽非必需,但可增强节点故障时的可用性,并缓解磁盘吞吐量瓶颈。Pod亲和性规则尝试将Kafka和ZooKeeper部署在同一节点。Kafka broker数量可能多于ZooKeeper服务器,但Kubernetes调度器会在遵守Pod反亲和性规则的前提下,尽可能将Kafka broker与ZooKeeper服务器共置,以减少两者间的网络I/O。若磁盘竞争成为问题,也可使用Pod反亲和性规则避免ZooKeeper服务器与Kafka broker部署在同一节点。
测试部署的最简单方法是创建主题并使用控制台生产者和消费者。使用kubectl exec在一个broker上执行bash shell:
shell> kubectl exec -ti kafka-0 -- bash
通过命令行使用kafka-topics.sh创建主题:
shell> kafka-topics.sh --create \ --topic test \ --zookeeper zk-0.zk-svc.default.svc.cluster.local:2181,zk-1.zk-svc.default.svc.cluster.local:2181,zk-2.zk-svc.default.svc.cluster.local:2181 \ --partitions 3 \ --replication-factor 2
运行控制台消费者:
shell> kafka-console-consumer.sh --topic test --bootstrap-server localhost:9093
使用kubectl exec在另一个broker上执行bash shell(使用不同broker可验证跨节点工作):
shell> kubectl exec -ti kafka-1 -- bash
运行控制台生产者并通过输入生成消息,按Enter发送:
shell> kafka-console-producer.sh --topic test --broker-list localhost:9093 hello I like kafka goodbye
消费者控制台将显示消息:
shell> kafka-console-consumer.sh --topic test --bootstrap-server localhost:9093 hello I like kafka goodbye
使用kubectl scale水平扩展集群,以下命令将broker数量扩展到2个:
shell> kubectl scale statefulset kafka --replicas=2
注意,扩展Kafka集群后,需使用kafka-reassign-partitions.sh确保数据正确复制和分配。
您可以使用以下命令拉取该镜像。请将 <标签> 替换为具体的标签版本。如需查看所有可用标签版本,请访问 标签列表页面。
来自真实用户的反馈,见证轩辕镜像的优质服务
以下是 leey18/kafka 相关的常用 Docker 镜像,适用于 不同场景 等不同场景: