Kafka on Kubernetes 有状态应用部署文档(KRaft 模式)

Kafka on Kubernetes 有状态应用部署文档(KRaft 模式)

适用版本:Kafka 3.9.0(KRaft 模式,无需 Zookeeper)

部署方式:StatefulSet + Headless Service(贴合有状态应用特性)

适用环境:测试/开发环境(单副本),生产环境可基于此优化为3副本高可用

命名空间:test-kafka

一、部署说明

  • Kafka 作为典型有状态应用,需通过 StatefulSet 保证 Pod 名称、网络标识、存储的稳定性,避免随机变化导致服务异常。

  • 采用 KRaft 模式,无需依赖 Zookeeper,简化部署架构,降低维护成本。

  • 当前为单副本部署,生产环境建议调整为3副本,提升服务可用性。

  • 核心依赖 Headless Service(无头服务),为 Kafka Pod 提供固定域名解析,确保集群内通信稳定。

二、环境前置条件

  1. Kubernetes 集群版本 ≥ 1.21,确保 StatefulSet、KRaft 相关特性支持。

  2. 已配置 kubectl 命令行工具,且能正常访问 K8s 集群(具备集群操作权限)。

  3. 提前创建命名空间 test-kafka(若未创建,可执行部署命令中的命名空间创建指令)。

三、核心部署文件(kafka-sts.yaml)

该文件包含 Kafka 有状态部署的全部核心资源(Headless Service + StatefulSet),无需拆分其他文件,直接部署即可。

yaml 复制代码
---
# Kafka 无头服务(StatefulSet 必需,提供固定域名解析,不分配集群IP)
apiVersion: v1
kind: Service
metadata:
  name: kafka-headless
  namespace: test-kafka
  labels:
    app: kafka
spec:
  selector:
    app: kafka
  ports:
    - name: client
      port: 9092
    - name: internal
      port: 19092
    - name: controller
      port: 29093
    - name: external
      port: 9094
  clusterIP: None
---
# Kafka StatefulSet(有状态应用核心,保证 Pod 稳定运行)
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: kafka
  namespace: test-kafka
spec:
  serviceName: kafka-headless  # 关联无头服务,必需配置,保证域名生成规则固定
  replicas: 1  # 单副本部署,生产环境建议改为3
  selector:
    matchLabels:
      app: kafka
  template:
    metadata:
      labels:
        app: kafka
    spec:
      securityContext:
        runAsUser: 1000
        fsGroup: 1000
      containers:
        - name: kafka
          image: apache/kafka:3.9.0  # Kafka 镜像版本,可按需升级
          ports:
            - containerPort: 9092
              name: client
            - containerPort: 19092
              name: internal
            - containerPort: 29093
              name: controller
            - containerPort: 9094
              name: external
          securityContext:
            privileged: true
            runAsUser: 1000
            runAsGroup: 1000
          env:
            - name: TZ
              value: "Asia/Shanghai"  # 时区配置,避免时间异常
            - name: HOSTNAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: PODIP
              valueFrom:
                fieldRef:
                  fieldPath: status.podIP
            - name: KAFKA_NODE_ID
              value: "0"  # 节点ID,单副本为0,多副本依次为0、1、2
            - name: KAFKA_PROCESS_ROLES
              value: "broker,controller"  # 单节点同时作为 broker 和 controller
            - name: KAFKA_LISTENER_SECURITY_PROTOCOL_MAP
              value: "CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT,INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT"
            - name: KAFKA_LISTENERS
              value: "CONTROLLER://:29093,PLAINTEXT://:9092,INTERNAL://:19092,EXTERNAL://:9094"
            - name: KAFKA_ADVERTISED_LISTENERS
              value: "PLAINTEXT://$(PODIP):9092,INTERNAL://$(HOSTNAME).kafka-headless.test-kafka.svc.cluster.local:19092,EXTERNAL://192.168.133.200:30094"
            - name: KAFKA_CONTROLLER_QUORUM_VOTERS
              value: "0@kafka-0.kafka-headless.test-kafka.svc.cluster.local:29093"  # 单副本投票节点
            - name: KAFKA_INTER_BROKER_LISTENER_NAME
              value: "INTERNAL"  # 集群内 broker 通信监听器
            - name: KAFKA_CONTROLLER_LISTENER_NAMES
              value: "CONTROLLER"
            - name: CLUSTER_ID
              value: "test-kafka"  # 集群ID,自定义即可
            - name: KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR
              value: "1"  # 偏移量主题副本因子,单副本为1,多副本为3
            - name: KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR
              value: "1"
            - name: KAFKA_TRANSACTION_STATE_LOG_MIN_ISR
              value: "1"
            - name: KAFKA_DEFAULT_REPLICATION_FACTOR
              value: "1"  # 新创建主题默认副本因子
            - name: KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS
              value: "3000"  # 初始重平衡延迟,避免频繁触发
            - name: KAFKA_SHARE_COORDINATOR_STATE_TOPIC_REPLICATION_FACTOR
              value: "1"
            - name: KAFKA_SHARE_COORDINATOR_STATE_TOPIC_MIN_ISR
              value: "1"
            - name: KAFKA_NUM_PARTITIONS
              value: "2"  # 新主题默认分区数,提升并行处理能力
            - name: KAFKA_LOG_RETENTION_HOURS
              value: "168"  # 日志保留7天,按需调整
            - name: KAFKA_LOG_SEGMENT_BYTES
              value: "1073741824"  # 单个日志段1GB,避免段文件过多
            - name: KAFKA_LOG_RETENTION_CHECK_INTERVAL_MS
              value: "3600000"  # 每1小时检查日志清理
            - name: KAFKA_LOG_SEGMENT_DELETE_DELAY_MS
              value: "60000"  # 日志段标记删除后延迟1分钟物理删除
            - name: KAFKA_AUTO_CREATE_TOPICS_ENABLE
              value: "true"  # 允许自动创建主题
            - name: KAFKA_HEAP_OPTS
              value: "-Xms1024m -Xmx1024m"  # JVM堆内存,按需调整
            - name: KAFKA_LOG_DIRS
              value: "/var/lib/kafka/data/kafka-logs"  # 日志存储路径
          volumeMounts:
            - name: kafka-data
              mountPath: /var/lib/kafka/data  # 挂载存储卷
          livenessProbe:  # 存活探针,检测服务是否正常运行
            tcpSocket:
              port: 9092
            initialDelaySeconds: 15
            periodSeconds: 10
            failureThreshold: 3
            timeoutSeconds: 3
          readinessProbe:  # 就绪探针,检测服务是否可提供服务
            tcpSocket:
              port: 9092
            initialDelaySeconds: 15
            periodSeconds: 10
            failureThreshold: 3
            timeoutSeconds: 3
          resources:  # 资源限制,按需调整
            limits:
              cpu: 4000m
              memory: 4Gi
            requests:
              cpu: 500m
              memory: 1Gi
      # 存储配置:测试用emptyDir(Pod删除后数据丢失),生产需替换为PVC
      volumes:
      - name: kafka-data
        emptyDir: {}
---
# 可选:NodePort服务(外部访问用,不影响有状态核心部署)
apiVersion: v1
kind: Service
metadata:
  labels:
    app: kafka
  name: kafka-nodeport
  namespace: test-kafka
spec:
  ports:
  - name: client
    nodePort: 30094
    port: 9094
    protocol: TCP
    targetPort: 9094
  selector:
    app: kafka
  sessionAffinity: None
  type: NodePort

四、一键部署与验证命令

复制以下命令,在终端执行,即可完成部署并验证状态,无需手动分步操作。

bash 复制代码
# 1. 创建命名空间(若未创建)
kubectl create namespace test-kafka

# 2. 部署 Kafka 有状态应用(核心命令)
kubectl apply -f kafka-sts.yaml

# 3. 验证部署状态(查看StatefulSet、Pod、Service)
kubectl get sts kafka -n test-kafka
kubectl get pods -n test-kafka -l app=kafka
kubectl get svc -n test-kafka | grep kafka

验证标准:StatefulSet 状态 READY 为 1/1,Pod 状态为 Running,两个 Service(kafka-headless、kafka-nodeport)正常存在。

五、访问方式

5.1 集群内访问(推荐,适用于集群内其他服务调用)

  • 服务访问:kafka-headless.test-kafka.svc.cluster.local:9092

  • 固定Pod域名访问(有状态特性):kafka-0.kafka-headless.test-kafka.svc.cluster.local:19092

5.2 外部访问(可选,适用于本地客户端测试)

通过 NodePort 服务访问:192.168.133.200:30094(确保节点3009端口可被外部访问)

六、功能测试(验证 Kafka 可用性)

bash 复制代码
# 1. 进入 Kafka Pod 内部
kubectl exec -it kafka-0 -n test-kafka -- /bin/bash

# 2. 创建测试主题(名称:test-topic,分区数2,副本数1)
kafka-topics.sh --create --topic test-topic --bootstrap-server localhost:9092 --partitions 2 --replication-factor 1

# 3. 发送测试消息
kafka-console-producer.sh --topic test-topic --bootstrap-server localhost:9092
# 输入消息后按回车发送,例如:hello kafka on k8s

# 4. 新开终端,消费测试消息(从开头消费)
kubectl exec -it kafka-0 -n test-kafka -- /bin/bash
kafka-console-consumer.sh --topic test-topic --bootstrap-server localhost:9092 --from-beginning

七、生产环境优化建议

  1. 数据持久化:将 emptyDir 替换为 volumeClaimTemplates(PVC模板),确保Pod删除/重启后数据不丢失,示例:
bash 复制代码
volumeClaimTemplates:
- metadata:
    name: kafka-data
  spec:
    accessModes: [ "ReadWriteOnce" ]
    resources:
      requests:
        storage: 10Gi  # 按需调整存储大小
    storageClassName: "your-storage-class"  # 替换为集群可用的存
  1. 高可用部署

    • 将 replicas 改为3,确保多节点冗余。

    • 调整 KAFKA_NODE_ID 为0、1、2(每个节点唯一)。

    • 更新 KAFKA_CONTROLLER_QUORUM_VOTERS:0@kafka-0.kafka-headless.test-kafka.svc.cluster.local:29093,1@kafka-1.kafka-headless.test-kafka.svc.cluster.local:29093,2@kafka-2.kafka-headless.test-kafka.svc.cluster.local:29093

    • 将所有副本因子相关配置(如 KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR)改为3。

  2. 资源调整:根据业务压力,调整 resources.limits 和 resources.requests,避免资源不足或浪费。

  3. 安全优化:生产环境建议关闭 KAFKA_AUTO_CREATE_TOPICS_ENABLE,手动创建主题;替换 PLAINTEXT 协议为加密协议(如 SSL)。

八、常见问题排查

  • Pod启动失败:执行 kubectl describe pod kafka-0 -n test-kafka,查看事件日志,排查镜像拉取失败、资源不足、配置错误等问题。

  • 域名解析失败:确认 StatefulSet 的 serviceName 与无头服务名称一致;检查集群 CoreDNS 组件是否正常运行(kubectl get pods -n kube-system | grep coredns)。

  • 数据丢失:确认是否使用了 emptyDir 存储,生产环境需立即替换为 PVC。

  • 外部访问失败:检查 NodePort 端口是否被防火墙拦截;确认节点IP(192.168.133.200)是否正确,且集群节点可被外部访问。

九、文档说明

  1. 部署文件 kafka-sts.yaml 可直接复制保存,无需修改即可用于测试环境部署,生产环境需按优化建议调整配置。

  2. 若无需外部访问,可删除文件中 NodePort 服务相关配置,不影响 Kafka 核心功能。

十、kafka可视化管理(kafka-ui)

bash 复制代码
version: '3.3'

services:
  kafka-ui:
    image: provectuslabs/kafka-ui:latest
    container_name: kafka-ui
    restart: always
    ports:
      - "8080:8080"  # 宿主机端口:容器端口,可自定义宿主机端口
    environment:
      # 配置Kafka集群(支持多个集群,用逗号分隔)
      - KAFKA_CLUSTERS_0_NAME=kafka-cluster  # 集群名称(自定义)
#      #- KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS=kafka-broker1:9092,kafka-broker2:9092  # Kafka Broker地址列表
      - KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS=10.0.12.10:9092  # 替换成kafka实际的连接地址
      # 可选:若Kafka启用了SASL认证(如PLAIN/SCRAM),添加以下配置
      # - KAFKA_CLUSTERS_0_PROPERTIES_SECURITY_PROTOCOL=SASL_PLAINTEXT
      # - KAFKA_CLUSTERS_0_PROPERTIES_SASL_MECHANISM=PLAIN
      # - KAFKA_CLUSTERS_0_PROPERTIES_SASL_JAAS_CONFIG=org.apache.kafka.common.security.plain.PlainLoginModule required username="admin" password="admin-secret";
      # 可选:配置ZooKeeper地址(用于查看Broker元数据,非必须)
      # - KAFKA_CLUSTERS_0_ZOOKEEPER=zookeeper-host1:2181,zookeeper-host2:2181
      # 可选:设置默认主题创建策略(分区数、副本数)
      # - KAFKA_CLUSTERS_0_TOPIC_CREATION_DEFAULTREPLICATIONFACTOR=3
      # - KAFKA_CLUSTERS_0_TOPIC_CREATION_DEFAULTPARTITIONS=12


十一、docker-compose 快速部署kafka

bash 复制代码
version: '3.3'
services:
  broker:
    image: apache/kafka:3.9.0
    hostname: broker
    container_name: broker
    ports:
      - '9092:9092'
    # 新增:允许容器访问公网,且绑定所有网卡
    network_mode: host
    environment:
      KAFKA_NODE_ID: 1
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: 'CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT'
      KAFKA_ADVERTISED_LISTENERS: 'PLAINTEXT_HOST://10.0.12.10:9092,PLAINTEXT://localhost:19092'
      KAFKA_PROCESS_ROLES: 'broker,controller'
      KAFKA_CONTROLLER_QUORUM_VOTERS: '1@localhost:29093'
      KAFKA_LISTENERS: 'CONTROLLER://localhost:29093,PLAINTEXT_HOST://0.0.0.0:9092,PLAINTEXT://localhost:19092'
      KAFKA_INTER_BROKER_LISTENER_NAME: 'PLAINTEXT'
      KAFKA_CONTROLLER_LISTENER_NAMES: 'CONTROLLER'
      CLUSTER_ID: 'prod-kafka'
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
      KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0
      KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
      KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
      KAFKA_SHARE_COORDINATOR_STATE_TOPIC_REPLICATION_FACTOR: 1
      KAFKA_SHARE_COORDINATOR_STATE_TOPIC_MIN_ISR: 1
      KAFKA_LOG_DIRS: '/var/lib/kafka/data'
      KAFKA_AUTO_CREATE_TOPICS_ENABLE: "true"
相关推荐
肥猪猪爸2 小时前
数据库 2PC 极简流程图
java·数据库·分布式·mysql·分布式事务·2pc
码luffyliu2 小时前
K8s 核心知识点详解:Pod、NAT 与 Osim 隔离环境的实际应用
云原生·容器·kubernetes
斯普信专业组3 小时前
Kafka集群数据迁移方案:基于多Listener配置的集群迁移实践指南
分布式·kafka
Meta393 小时前
SpringBoot通过kt-connect+kubectl进行本地调试k8s服务
spring boot·后端·kubernetes
认真的柯南3 小时前
关于在 Kubernetes 环境中停止使用 CPU 限制的分析与建议
容器·kubernetes·cpu
only-qi3 小时前
RabbitMQ 深度解析:从架构原理到消息全链路可靠性保障
分布式·架构·rabbitmq
柒.梧.5 小时前
从0到1理解K8s:为什么用、怎么设计、如何搭建
云原生·容器·kubernetes
隔壁小邓5 小时前
TIDB分布式数据库
数据库·分布式·tidb
蜜獾云5 小时前
Kafka(2)-kafka架构-基本原理
分布式·架构·kafka