ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

OpenReplay 自托管指南:在 Kubernetes 上部署无 ZooKeeper 的 KRaft Kafka 集群(含 TLS 方案)

OpenReplay 自托管指南:在 Kubernetes 上部署无 ZooKeeper 的 KRaft Kafka 集群(含 TLS 方案) 可观测性开发工具前端后端【免费下载链接】openreplaySession replay, cobrowsing and product analytics you can self-host. Best for reproducing issues and iterating on your product.项目地址https://gitcode.com/gh_mirrors/op/openreplay点击查看免费下载本篇技术指南讲解如何在 Kubernetes 上以 KRaft 模式不再依赖 ZooKeeper部署 OpenReplay 自托管所需的 2 节点 Kafka 集群覆盖 PLAINTEXT 与 TLS 两套完整清单、证书生成、连接测试、故障排查与生产化配置。读完本文你将能够用 3~4 条 kubectl 命令拉起一套与既有 Helm Chart 完全兼容同名 Service 与 PVC的 Kafka 集群并掌握消息大小、保留策略、副本因子、存储与资源配额等关键参数的调整方法。部署方案概览OpenReplay 的数据库层运行在db命名空间内Kafka 是其消息总线。本方案用 KRaft 模式替代传统的 ZooKeeper 依赖核心规格如下模式KRaft不需要 ZooKeeper副本数2 个节点命名空间dbService 名称kafka、kafka-headless与既有 Helm Chart 保持一致PVC 名称data-kafka-{0,1}与既有 Helm Chart 保持一致与旧 Helm ZooKeeper 方案相比KRaft 方案将组件从 Kafka ZooKeeper 两个 StatefulSet 缩减为仅 Kafka 一个 StatefulSetPod 数从 3 个2 kafka 1 zookeeper降为 2 个且 Service、PVC、端口名kafka-client、kafka-internal、标签app.kubernetes.io/namekafka与配置方式Bitnami 风格环境变量全部保持一致可以视为既有部署的即插即用替换。前提条件Kubernetes 集群1.19已配置好的kubectl可用的 StorageClass用于 PVC 动态供给构建并推送 Kafka 镜像# 构建镜像默认使用 podman可用 builder 指定构建器 make build # 打标签推送到你的私有仓库 docker tag local/kafka:3 your-registry/kafka:3 # 推送 docker push your-registry/kafka:3 # 将清单中的镜像地址全局替换 sed -i s|local/kafka:3|your-registry/kafka:3|g k8s-kafka-kraft*.yaml镜像的构建定义在 scripts/dockerfiles/kafka/Dockerfile基于cgr.dev/chainguard/wolfi-base通过apk安装kafka~3、openssl、bash、tini以 UID 1001 的非 root 用户运行入口为start-kafka.sh。对应构建目标定义在 scripts/dockerfiles/kafka/Makefilemake build/make kube。若你希望跳过手动sed也可直接使用清单中已有的公共镜像地址PLAINTEXT 清单默认引用rjshrjndrn/kafka:3。两种部署选项选项 1纯 PLAINTEXT无 TLS适用场景开发、测试或纯内网集群清单k8s-kafka-kraft.yaml端口9092CLIENTPLAINTEXT9093INTERNAL CONTROLLERPLAINTEXT选项 2PLAINTEXT TLS适用场景生产环境渐进式迁移 TLS清单k8s-kafka-kraft-tls.yaml端口9092CLIENTPLAINTEXT9093INTERNAL CONTROLLERPLAINTEXT9094SSL加密快速部署部署 PLAINTEXT 集群# 1. 创建命名空间 kubectl create namespace db # 2. 应用清单 kubectl apply -f k8s-kafka-kraft.yaml # 3. 等待 Pod 就绪 kubectl wait --forconditionready pod -l app.kubernetes.io/namekafka -n db --timeout300s # 4. 检查状态 kubectl get pods -n db -l app.kubernetes.io/namekafka kubectl get svc -n db部署启用 TLS 的集群# 1. 创建命名空间 kubectl create namespace db # 2. 生成证书并创建 Secret ./k8s-generate-certs.sh # 或者手动创建 Secret # kubectl create secret generic kafka-tls-certs \ # --from-fileca-cert.pem./k8s-certs/ca-cert.pem \ # --from-filekafka-0-cert.pem./k8s-certs/kafka-0-cert.pem \ # --from-filekafka-0-key.pem./k8s-certs/kafka-0-key.pem \ # --from-filekafka-1-cert.pem./k8s-certs/kafka-1-cert.pem \ # --from-filekafka-1-key.pem./k8s-certs/kafka-1-key.pem \ # -n db # 3. 应用 TLS 清单 kubectl apply -f k8s-kafka-kraft-tls.yaml # 4. 等待 Pod 就绪 kubectl wait --forconditionready pod -l app.kubernetes.io/namekafka -n db --timeout300s # 5. 检查状态 kubectl get pods -n db -l app.kubernetes.io/namekafka kubectl get svc -n dbTLS 清单还内置了一个setup-certsinitContainer见 k8s-kafka-kraft-tls.yaml它根据 Pod 名推导出序号kafka-0→ 0把 Secret 中的kafka-{i}-cert.pem、kafka-{i}-key.pem复制为统一的/tls/server-cert.pem、/tls/server-key.pem并设置 600 权限保护私钥再挂载给 Kafka 主容器。服务端点PLAINTEXT 部署集群内访问引导地址kafka.db.svc.cluster.local:9092单节点地址kafka-0.kafka-headless.db.svc.cluster.local:9092kafka-1.kafka-headless.db.svc.cluster.local:9092TLS 部署PLAINTEXT用于迁移期引导地址kafka.db.svc.cluster.local:9092SSL加密引导地址kafka-ssl.db.svc.cluster.local:9094单节点地址kafka-0.kafka-headless.db.svc.cluster.local:9094kafka-1.kafka-headless.db.svc.cluster.local:9094说明引导地址指向ClusterIP类型的kafka/kafka-sslService负责把请求负载均衡到任一 Broker单节点地址依赖kafka-headlessclusterIP: NonepublishNotReadyAddresses: true无头 Service供客户端直连指定 Broker这也是 KRaft 集群中advertised.listeners使用的地址形态。测试部署测试 PLAINTEXT 连接# 创建测试 Pod kubectl run kafka-test -n db --rm -it --restartNever \ --imageyour-registry/kafka:3 \ -- /bin/bash # 进入 Pod 后 # 列出主题 /usr/lib/kafka/bin/kafka-topics.sh \ --list \ --bootstrap-server kafka.db.svc.cluster.local:9092 # 创建主题 /usr/lib/kafka/bin/kafka-topics.sh \ --create \ --topic test-topic \ --bootstrap-server kafka.db.svc.cluster.local:9092 \ --replication-factor 1 \ --partitions 3 # 生产消息 echo Hello Kafka | /usr/lib/kafka/bin/kafka-console-producer.sh \ --topic test-topic \ --bootstrap-server kafka.db.svc.cluster.local:9092 # 消费消息 /usr/lib/kafka/bin/kafka-console-consumer.sh \ --topic test-topic \ --from-beginning \ --bootstrap-server kafka.db.svc.cluster.local:9092 \ --max-messages 1测试 TLS 连接# 创建挂载 TLS 证书的测试 Pod kubectl run kafka-test-tls -n db --rm -it --restartNever \ --imageyour-registry/kafka:3 \ --overrides { spec: { containers: [{ name: kafka-test-tls, image: your-registry/kafka:3, command: [/bin/bash], stdin: true, tty: true, volumeMounts: [{ name: tls, mountPath: /tls }] }], volumes: [{ name: tls, secret: { secretName: kafka-tls-certs } }] } } \ -- /bin/bash # 进入 Pod 后创建 SSL 客户端配置 cat /tmp/ssl-client.properties EOF security.protocolSSL ssl.truststore.location/tls/ca-cert.pem ssl.truststore.typePEM ssl.endpoint.identification.algorithm EOF # 通过 SSL 列出主题 /usr/lib/kafka/bin/kafka-topics.sh \ --list \ --bootstrap-server kafka-ssl.db.svc.cluster.local:9094 \ --command-config /tmp/ssl-client.properties # 通过 SSL 创建主题 /usr/lib/kafka/bin/kafka-topics.sh \ --create \ --topic secure-topic \ --bootstrap-server kafka-ssl.db.svc.cluster.local:9094 \ --command-config /tmp/ssl-client.properties \ --replication-factor 1 \ --partitions 3 # 通过 SSL 生产 echo Hello Secure Kafka | /usr/lib/kafka/bin/kafka-console-producer.sh \ --topic secure-topic \ --bootstrap-server kafka-ssl.db.svc.cluster.local:9094 \ --producer.config /tmp/ssl-client.properties # 通过 SSL 消费 /usr/lib/kafka/bin/kafka-console-consumer.sh \ --topic secure-topic \ --from-beginning \ --bootstrap-server kafka-ssl.db.svc.cluster.local:9094 \ --consumer.config /tmp/ssl-client.properties \ --max-messages 1部署验证检查 Pod 状态# 查看 Pod kubectl get pods -n db -l app.kubernetes.io/namekafka # 查看日志 kubectl logs -n db kafka-0 --tail50 kubectl logs -n db kafka-1 --tail50 # 确认 node.id 正确 kubectl logs -n db kafka-0 | grep node.id kubectl logs -n db kafka-1 | grep node.id检查 Service# 列出 Service kubectl get svc -n db # 查看详情 kubectl describe svc kafka -n db kubectl describe svc kafka-headless -n db kubectl describe svc kafka-ssl -n db # 仅 TLS 部署检查 PVC# 列出 PVC kubectl get pvc -n db # 应显示 #># 进入 Pod kubectl exec -it kafka-0 -n db -- /bin/bash # 查看 Broker 列表 /usr/lib/kafka/bin/kafka-broker-api-versions.sh \ --bootstrap-server localhost:9092 # 查看集群 ID cat /bitnami/kafka/data/meta.properties | grep cluster.id配置定制两份清单中的 Kafka 配置全部以环境变量的形式暴露在 StatefulSet 的env段中。启动时由 start-kafka.sh 统一转换为server.properties写入/tmp/server.properties因此改配置只需编辑 YAML 中的环境变量再kubectl apply即可。修改消息大小编辑清单中的环境变量- name: KAFKA_MESSAGE_MAX_BYTES value: 10485760 # 10MB - name: KAFKA_REPLICA_FETCH_MAX_BYTES value: 10485760对应生成的配置项为message.max.bytes与replica.fetch.max.bytes。清单默认值为31457283MB与 OpenReplay 现有部署配置保持一致用于适配其会话回放数据的单条消息体积。修改保留策略- name: KAFKA_LOG_RETENTION_HOURS value: 720 # 30 天 - name: KAFKA_LOG_RETENTION_BYTES value: 10737418240 # 10GB对应log.retention.hours与log.retention.bytes两者同时满足其一即触发删除。清单默认值为168小时7 天与10737418241GB并附带KAFKA_LOG_SEGMENT_BYTES10737418241GB 日志分段。此外start-kafka.sh还会透传KAFKA_CFG_LOG_FLUSH_INTERVAL_MESSAGES、KAFKA_CFG_LOG_FLUSH_INTERVAL_MS、KAFKA_CFG_LOG_RETENTION_CHECK_INTERVAL_MS等刷盘参数。修改副本因子2 节点生产环境建议开启复制- name: KAFKA_CFG_DEFAULT_REPLICATION_FACTOR value: 2 - name: KAFKA_CFG_OFFSETS_TOPIC_REPLICATION_FACTOR value: 2 - name: KAFKA_CFG_TRANSACTION_STATE_LOG_REPLICATION_FACTOR value: 2 - name: KAFKA_CFG_MIN_INSYNC_REPLICAS value: 2清单默认值为1单副本适合当前 2 节点开发部署生产环境建议按上表提升并将KAFKA_CFG_TRANSACTION_STATE_LOG_MIN_ISR同步调整。修改存储大小编辑volumeClaimTemplatesvolumeClaimTemplates: - metadata: name: data spec: accessModes: - ReadWriteOnce resources: requests: storage: 200Gi # 修改大小清单默认申请100Gi与旧 Helm Chart 一致生产建议 200Gi 起。修改资源限制resources: requests: cpu: 1000m memory: 2Gi limits: cpu: 4000m memory: 8Gi清单默认值为requests: cpu 500m / memory 1Gi、limits: cpu 2000m / memory 2Gi对应 K8S_SUMMARY 文档中匹配 Helm Chart的档位上表为文档推荐的生产档位。其他常用参数start-kafka.sh对KAFKA_CFG_前缀变量做了通用转换例如KAFKA_CFG_NUM_NETWORK_THREADS8会被自动写成num.network.threads8大写转小写、下划线转点号这意味着任何 Kafka 原生配置项都可以用该前缀注入。清单中已使用的典型项包括性能KAFKA_CFG_NUM_IO_THREADS8、KAFKA_CFG_NUM_NETWORK_THREADS3、KAFKA_CFG_NUM_PARTITIONS1、KAFKA_CFG_NUM_RECOVERY_THREADS_PER_DATA_DIR1网络缓冲KAFKA_CFG_SOCKET_RECEIVE_BUFFER_BYTES102400、KAFKA_CFG_SOCKET_SEND_BUFFER_BYTES102400、KAFKA_CFG_SOCKET_REQUEST_MAX_BYTES104857600安全KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLEtrue、KAFKA_CFG_DELETE_TOPIC_ENABLEfalse、KAFKA_CFG_ALLOW_EVERYONE_IF_NO_ACL_FOUNDtrue、KAFKA_CFG_SUPER_USERSUser:admin节点 ID 与 KRaft 关键机制KRaft 依赖固定节点 ID 组成控制器投票集quorum。本方案的实现方式值得说明KAFKA_NODE_ID直接取 Pod 名fieldRef: metadata.name即kafka-0、kafka-1start-kafka.sh 启动时用正则-([0-9])$从 Pod 名提取序号并加 1 得到数字节点 IDkafka-0→ 1kafka-1→ 2再写入node.idKAFKA_CONTROLLER_QUORUM_VOTERS硬编码为1kafka-0.kafka-headless.db.svc.cluster.local:9093,2kafka-1.kafka-headless.db.svc.cluster.local:9093与上述推导规则一一对应KAFKA_CLUSTER_ID使用固定的共享集群 IDSjg_Rr1iQbO9xpahgDbYpQ配合KAFKA_PROCESS_ROLESbroker,controller让两个节点都同时承担 Broker 与 Controller 角色advertised.listeners中的${MY_POD_NAME}占位符会在启动脚本中被替换为实际 Pod 名同时兼容${MY_POD_NAME}与$MY_POD_NAME两种写法确保客户端能从集群内任何位置解析到正确的 Broker 地址。若改动副本数或调整节点务必同步修改KAFKA_CONTROLLER_QUORUM_VOTERS。证书生成脚本解析TLS 方案依赖 k8s-generate-certs.sh 一键生成整套证书并输出 Secret 清单生成有效期 365 天的自签 CAca-cert.pem/ca-key.pem为kafka-0、kafka-1分别生成 2048 位 RSA 私钥与 CSR证书CN和 SAN 覆盖完整 Pod DNS 链kafka-{i}、kafka-{i}.kafka-headless、kafka-{i}.kafka-headless.db、kafka-{i}.kafka-headless.db.svc、kafka-{i}.kafka-headless.db.svc.cluster.local、kafka-headless.db.svc.cluster.local、localhost以及回环地址127.0.0.1用 CA 签署各 Broker 证书输出kafka-{i}-cert.pem/kafka-{i}-key.pem以--dry-runclient -o yaml生成k8s-certs/kafka-tls-secret.yaml可直接kubectl apply也可按脚本末尾提示用kubectl create secret generic直接创建。对应的服务端 TLS 配置在 TLS 清单中通过环境变量启用- name: KAFKA_SSL_CERT_FILE value: /tls/server-cert.pem - name: KAFKA_SSL_KEY_FILE value: /tls/server-key.pem - name: KAFKA_SSL_CA_FILE value: /tls/ca-cert.pem - name: KAFKA_SSL_CLIENT_AUTH value: required - name: KAFKA_SSL_ENDPOINT_IDENTIFICATION_ALGORITHM value: 其中KAFKA_SSL_CLIENT_AUTHrequired表示强制双向 TLSmTLS客户端也必须携带 CA 签发的证书KAFKA_SSL_ENDPOINT_IDENTIFICATION_ALGORITHM置空则关闭主机名校验配合自签证书场景。start-kafka.sh会在容器内把 PEM 证书转换为 JKS keystore/truststore密码默认kafka-ssl-pass可用KAFKA_SSL_KEYSTORE_PASSWORD覆盖再注入ssl.keystore.location、ssl.truststore.location等配置。扩容与缩容扩容StatefulSet 场景不推荐KRaft 的扩容需要谨慎处理。如需增加 Broker# 修改副本数 kubectl scale statefulset kafka -n db --replicas3 # 将新节点加入 KAFKA_CONTROLLER_QUORUM_VOTERS # 这需要修改清单并重启所有 Pod注意扩容 KRaft 集群必须同步更新所有节点上的KAFKA_CONTROLLER_QUORUM_VOTERS。建议部署时直接按目标规模设置副本数而非后期扩容。缩容警告缩容可能导致数据丢失# 首先将待移除 Broker 上的分区 reassign 到其他节点 # 然后缩容 kubectl scale statefulset kafka -n db --replicas1故障排查Pod 无法启动# 查看 Pod 事件 kubectl describe pod kafka-0 -n db # 查看日志 kubectl logs kafka-0 -n db # 常见原因 # - PVC 未绑定检查 StorageClass # - 镜像拉取失败检查镜像名与仓库访问权限 # - 配置错误检查环境变量节点 ID 问题节点 ID 由 Pod 序号推导而来验证方式kubectl exec kafka-0 -n db -- env | grep KAFKA_NODE_ID kubectl exec kafka-1 -n db -- env | grep KAFKA_NODE_ID # 应显示 # kafka-0: KAFKA_NODE_IDkafka-0 (由 start-kafka.sh 转换为 1) # kafka-1: KAFKA_NODE_IDkafka-1 (由 start-kafka.sh 转换为 2)若节点 ID 错误需要调整 start-kafka.sh 中的推导逻辑。也可开启DEBUG1环境变量让启动脚本输出完整的server.properties脚本内自带DEBUG: Generated server.properties 输出段便于核对node.id、controller.quorum.voters、advertised.listeners等关键值。TLS 证书问题# 检查 Secret 是否存在 kubectl get secret kafka-tls-certs -n db # 检查 Secret 内容 kubectl describe secret kafka-tls-certs -n db # 检查 Pod 内证书文件 kubectl exec kafka-0 -n db -- ls -la /tls/ # 验证证书 kubectl exec kafka-0 -n db -- openssl x509 -in /tls/server-cert.pem -text -noout连接问题# 集群内连通性测试 kubectl run test -n db --rm -it --restartNever \ --imagebusybox -- nc -zv kafka.db.svc.cluster.local 9092 # 检查 Service 端点 kubectl get endpoints kafka -n db kubectl get endpoints kafka-headless -n db # 检查端口是否监听 kubectl exec kafka-0 -n db -- netstat -tlnp仲裁Quorum问题# 查看控制器仲裁元数据 kubectl exec kafka-0 -n db -- cat /bitnami/kafka/data/meta.properties # 查看集群元数据日志快照 kubectl exec kafka-0 -n db -- /usr/lib/kafka/bin/kafka-metadata.sh \ --snapshot /bitnami/kafka/data/__cluster_metadata-0/00000000000000000000.log \ --print注意KRaft 的格式化只在meta.properties不存在时执行由start-kafka.sh判断且所有节点必须使用同一个KAFKA_CLUSTER_ID否则节点无法加入同一集群。升级镜像升级# 修改清单中的镜像 sed -i s|local/kafka:3|local/kafka:4|g k8s-kafka-kraft.yaml # 应用变更滚动重启 kubectl apply -f k8s-kafka-kraft.yaml # 监控滚动进度 kubectl rollout status statefulset/kafka -n db配置变更# 编辑清单中的新配置 vim k8s-kafka-kraft.yaml # 应用变更 kubectl apply -f k8s-kafka-kraft.yaml # 重启 Pod 使配置生效 kubectl rollout restart statefulset/kafka -n db提示StatefulSet 的环境变量变更会在滚动更新中自动重建 Podrollout restart适用于强制重载场景如 Secret 内容更新但 Pod 未重建的情况。清理删除集群保留数据kubectl delete statefulset kafka -n db kubectl delete svc kafka kafka-headless kafka-ssl -n db kubectl delete sa kafka -n db kubectl delete secret kafka-tls-certs -n db # PVC 会被保留删除集群删除数据kubectl delete statefulset kafka -n db kubectl delete svc kafka kafka-headless kafka-ssl -n db kubectl delete pvc>kubectl delete namespace db从 ZooKeeper 迁移到 KRaft如需从现有 ZooKeeper 部署迁移备份数据导出主题与消费者 offset部署新 KRaft 集群使用本目录下的清单MirrorMaker配置 MirrorMaker 2 复制数据切换更新客户端配置指向新集群下线移除旧 ZooKeeper 集群注意Kafka 3.x 不支持在同一集群上从 ZooKeeper 直接原地迁移到 KRaft必须走新集群 数据复制的路径。K8S_SUMMARY 文档还给出了三种可选的迁移形态干净部署推荐、并排部署Side-by-Side、蓝绿部署Blue/Green。生产环境检查清单使用正规签发的 TLS 证书而非自签生产环境启用主机名校验设置合理的资源限制配置合理的保留策略部署监控Prometheus/Grafana配置日志聚合EFK/Loki设置副本因子 ≥ 2使用带备份的持久化存储配置 PodDisruptionBudget设置网络策略为 Kafka 使用专用节点池配置亲和 / 反亲和规则延伸阅读本文是对 scripts/dockerfiles/kafka/kube/K8S_DEPLOYMENT.md 的完整展开仓库内还有配套资料可继续深入K8S_QUICK_START.md5 分钟快速上手K8S_SUMMARY.md新旧方案对比与迁移路径汇总start-kafka.sh环境变量到server.properties的转换实现k8s-kafka-kraft.yamlPLAINTEXT 清单k8s-kafka-kraft-tls.yamlTLS 清单k8s-generate-certs.sh证书生成脚本TLS_SETUP.mdTLS 手工配置参考CONFIG_REFERENCE.txt配置项参考docker-compose-tls.yml非 K8s 环境的 TLS 编排参考以上文件均位于 scripts/dockerfiles/kafka 目录是 OpenReplay 自托管部署中 Kafka 组件的完整素材包。赞分享可观测性开发工具前端后端【免费下载链接】openreplaySession replay, cobrowsing and product analytics you can self-host. Best for reproducing issues and iterating on your product.项目地址https://gitcode.com/gh_mirrors/op/openreplay点击查看免费下载相关推荐OpenReplay 自托管 Kafka Helm Chart 部署实战KRaft 模式、TLS 加密与生产化配置全指南OpenReplay 自托管 Kafka Helm Chart 部署实战KRaft 模式、TLS 加密与生产化配置全指南 本文以 OpenReplay 仓库中可观测性开发工具前端后端Strimzi KRaft 部署实战基于 KafkaNodePool 构建去 ZooKeeper 化的 Apache Kafka 集群Strimzi KRaft 部署实战基于 KafkaNodePool 构建去 ZooKeeper 化的 Apache Kafka 集群 ! KRaft 双角色云原生后端消息队列用 Meshery 设计文件在 Kubernetes 上部署 Apache Kafka 4.0KRaft 模式用 Meshery 设计文件在 Kubernetes 上部署 Apache Kafka 4.0KRaft 模式 导读 本文以 Meshery 仓库 Cata云原生微服务运维DevOps创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表