您的位置:

打造高可用的Kubernetes Kafka集群

随着近年来大数据的快速发展和人工智能技术的不断普及,消息队列已经成为了大量企业和机构中不可或缺的关键组件。其中,Kafka 由于其高性能、高可用以及可扩展性等特点而备受青睐,成为了流行的分布式消息系统之一。而在云环境中部署 Kubernetes Kafka 集群,可以大幅度简化 Kafka 部署和管理,从而提高生产力、便捷可靠地进行Kafka 开发。本篇文章将从多个方面讲解如何打造高可用的Kubernetes Kafka 集群,包括集群架构、存储、网络等,以满足实际业务需求。

一、集群架构

Kafka 可以在 Kubernetes 上部署成为一个分布式的结构,这里的部署方式有不同的选择。下面,我们介绍一种主要的架构方式:

spec:
  replicas: 3 # 设置3个副本形成一个 Kafka 集群
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1
  template:
    metadata:
      labels:
        app: kafka
    spec:
      containers:
      - name: kafka
        image: wurstmeister/kafka:2.13-2.8.1
        ports:
        - containerPort: 9092 # 配置 Kafka 端口,服务监听端口
        env:
        - name: KAFKA_ADVERTISED_HOST_NAME # 配置 hostname
          value: kafka-lb.example.com
        - name: KAFKA_ADVERTISED_PORT
          value: "9092"
        - name: KAFKA_ZOOKEEPER_CONNECT # 配置 ZooKeeper
          value: "zookeeper-1:2181,zookeeper-2:2181,zookeeper-3:2181"

通过上述代码部署了一个 Kubernetes Kafka 集群,其中 Kafka 节点数量为 3 台,支持节点的水平扩展。同时,使用 Rolling Update 策略能够保证 Kafka 集群的正常运转,并且在节点平滑升级时不会影响生产环境服务的持续提供。使用 KAFKA_ZOOKEEPER_CONNECT 指向 Zookeeper 节点,这里采用 3 台机器作为 Zookeeper 集群,保证了数据的高可用。

二、存储

Kafka 数据存储使用本地磁盘进行存储,这种方式会面临磁盘容量不足,或者节点宕机的风险。为了解决这些问题,我们可以使用 Kubernetes 的 PV 和 PVC 技术,来对 Kafka 数据进行持久化存储。

通过下方代码示例创建 Kafka 集群所需的这个 PersistentVolumeClaim:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: kafka-pvc
spec:
  resources:
    requests:
      storage: 10Gi # 申请10GB的存储容量
  accessModes:
    - ReadWriteOnce
  storageClassName: standard

此代码部分定义了一个名为 kafka-pvc 的 PersistenceVolumeClaim 对象,用于在系统中申请10 GB 的存储空间。同时,定义 storageClassName 手动连接 Kubernetes 集群中的 StorageClass,从而完成集群存储的自动化配置。

三、网络

与大部分微服务中的网络解决方案不同,Kafka 的协议是默认使用明文 socket 方式传输的,考虑到网络传输中的数据安全问题,建议采用 HTTPS 进行数据保护。此时,需要使用 Kubernetes 的 ingress 和 HTTPS 协议。其配置方式如下:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: kafka-ingress
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt"


spec:
  tls:
  - hosts:
      - kafka-lb.example.com
    secretName: kafka-tls-secret
  rules:
    - host: kafka-lb.example.com
      http:
        paths:
        - backend:
            serviceName: kafka-svc
            servicePort: 443

通过以上代码部署,我们定义了一个基于 TLS 的安全数据传输方案,以解决网络传输中的安全性问题。可以看到,这里采用的是 Nginx Ingress Controller ,当环境中租户对访问服务的域名进行 HTTPS 请求时,用户请求会首先被 Nginx 实例负载 IP 转发至内部 Kafka 服务,并且将协议转变为对应的 HTTP。

四、监控

Kafka 集群的监控是保障其高可用的前提。在 Kubernetes 环境中,我们通常使用 Prometheus 和 Grafana 来实现 Kafka 集群的监控

以下为采用标准的 Prometheus Operator 方式实现监控的代码:

apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
  name: kafka-prometheus
  labels:
    app: prometheus
spec:
  replicas: 1
  storage:
    volumeClaimTemplate:
      metadata:
        name: prometheus-data
      spec:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 10Gi
        volumeMode: Filesystem
  serviceAccountName: prometheus
  serviceMonitorSelector:
    matchLabels:
      app: kafka
    namespaceSelector:
      matchNames:
        - kafka
  ruleSelector:
    matchLabels:
      app: kafka
    matchExpressions:
      - key: job
        operator: In
        values:
        - kafka-exporter
  alerting:
    alertmanagers:
    - namespace: monitoring
      name: alertmanager-main
      port: web

使用 Prometheus Operator 可以自动化进行 Kafka 集群的监控数据收集,而且在 Prometheus collect 的时候,还可以使用 Kafka Exporter 从 Kafka node 获取应用指标数据。除此之外,我们可以通过 Grafana 显示出收集到的 Kafka 相关数据,如下所示:

五、实现各节点的高可用

为了实现 Kafka 集群的高可用,我们需要在集群中设置 leader 和 follower 节点,从而实现 Kafka 副本之间数据的复制,以实现高可用。

对于服务器故障等单点问题,我们可以使用热备节点的方式来解决,具体代码如下所示:

apiVersion: v1
kind: Pod
metadata:
  name: kafka-0
  labels:
    broker.id: "0"
spec:
  containers:
  - name: kafka
    image: wurstmeister/kafka:2.13-2.8.1
    env:
    - name: KAFKA_BROKER_ID
      value: "0"
    - name: KAFKA_ADVERTISED_HOST_NAME
      value: kafka.example.com
    - name: KAFKA_META_BROKER_LIST
      value: "kafka-0:9092,kafka-1:9092,kafka-2:9092"
    - name: KAFKA_ZOOKEEPER_CONNECT
      value: "zk-0:2181,zk-1:2181,zk-2:2181/kafka"
    ports:
    - containerPort: 9092
    volumeMounts:
    - name: kafka-data
      mountPath: /var/lib/kafka
    - name: config-volume
      mountPath: /opt/kafka/config/kafka-0.properties
      subPath: kafka-0.properties
  volumes:
  - name: kafka-data
    persistentVolumeClaim:
      claimName: pvc-kafka-0
  - name: config-volume
    configMap:
      name: kafka-config-map
      items:
         - key: kafka-0.properties
           path: kafka-0.properties
      defaultMode: 420

上述代码中定义了一个名为 kafka-0 的副本,用于备份 Kafka 集群中的数据。如此一来,当 Kafka 集群中某一台主节点宕机时,副本节点会接替主节点的职责,实现高可用。

六、总结

本文介绍了如何在 Kubernetes 环境下打造高可用的 Kafka 集群,分别从高可用架构、存储、网络、监控以及实现各节点的高可用等方面进行了详细讲解,是初学者学习 Kubernetes Kafka 集群的一篇不可多得的好文章。