首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >k8s快速部署kafka 3.3.1

k8s快速部署kafka 3.3.1

作者头像
从大数据到人工智能
发布2022-12-01 18:23:42
3K1
发布2022-12-01 18:23:42
举报
文章被收录于专栏:大数据-BigData大数据-BigData

在平常开发测试中,使用docker或者k8s快速部署某个组件会是一个不错的选择。kafka 3.3.1作为kraft第一个生产可用版本,本文介绍使用k8s快速部署基于kraft运行的kafka 3.3.1。

构建kafka镜像

首先我们要构建kafka 3.3.1镜像,简单地,我们只需要配置文件、启动脚本以及Dockerfile。

  • server.properties
  • start-kafka.sh
  • Dockerfile

为了在外网环境可以访问k8s中的kafka,需要对server.properties配置文件进行如下修改:

# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

#
# This configuration file is intended for use in KRaft mode, where
# Apache ZooKeeper is not present.  See config/kraft/README.md for details.
#

############################# Server Basics #############################

# The role of this server. Setting this puts us in KRaft mode
process.roles=broker,controller

# The node id associated with this instance's roles
node.id=1

# The connect string for the controller quorum
controller.quorum.voters=1@kafka:9093

############################# Socket Server Settings #############################

# The address the socket server listens on.
# Combined nodes (i.e. those with `process.roles=broker,controller`) must list the controller listener here at a minimum.
# If the broker listener is not defined, the default listener will use a host name that is equal to the value of java.net.InetAddress.getCanonicalHostName(),
# with PLAINTEXT listener name, and port 9092.
#   FORMAT:
#     listeners = listener_name://host_name:port
#   EXAMPLE:
#     listeners = PLAINTEXT://your.host.name:9092
listeners = INTERNAL://kafka:9092,EXTERNAL://kafka:30092,CONTROLLER://kafka:9093
# advertised.listeners = INTERNAL://kafka:9092,EXTERNAL://kafka:30092,CONTROLLER://kafka:9093

# Name of listener used for communication between brokers.
inter.broker.listener.name=INTERNAL

# Listener name, hostname and port the broker will advertise to clients.
# If not set, it uses the value for "listeners".
# advertised.listeners=PLAINTEXT://localhost:9092

# A comma-separated list of the names of the listeners used by the controller.
# If no explicit mapping set in `listener.security.protocol.map`, default will be using PLAINTEXT protocol
# This is required if running in KRaft mode.
controller.listener.names=CONTROLLER

# Maps listener names to security protocols, the default is for them to be the same. See the config documentation for more details
listener.security.protocol.map=INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT,CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT,SSL:SSL,SASL_PLAINTEXT:SASL_PLAINTEXT,SASL_SSL:SASL_SSL

# The number of threads that the server uses for receiving requests from the network and sending responses to the network
num.network.threads=3

# The number of threads that the server uses for processing requests, which may include disk I/O
num.io.threads=8

# The send buffer (SO_SNDBUF) used by the socket server
socket.send.buffer.bytes=102400

# The receive buffer (SO_RCVBUF) used by the socket server
socket.receive.buffer.bytes=102400

# The maximum size of a request that the socket server will accept (protection against OOM)
socket.request.max.bytes=104857600

############################# Log Basics #############################

# A comma separated list of directories under which to store log files
log.dirs=/data/kafka/kafka-logs

# The default number of log partitions per topic. More partitions allow greater
# parallelism for consumption, but this will also result in more files across
# the brokers.
num.partitions=1

# The number of threads per data directory to be used for log recovery at startup and flushing at shutdown.
# This value is recommended to be increased for installations with data dirs located in RAID array.
num.recovery.threads.per.data.dir=1

############################# Internal Topic Settings  #############################
# The replication factor for the group metadata internal topics "__consumer_offsets" and "__transaction_state"
# For anything other than development testing, a value greater than 1 is recommended to ensure availability such as 3.
offsets.topic.replication.factor=1
transaction.state.log.replication.factor=1
transaction.state.log.min.isr=1

############################# Log Flush Policy #############################

# Messages are immediately written to the filesystem but by default we only fsync() to sync
# the OS cache lazily. The following configurations control the flush of data to disk.
# There are a few important trade-offs here:
#    1. Durability: Unflushed data may be lost if you are not using replication.
#    2. Latency: Very large flush intervals may lead to latency spikes when the flush does occur as there will be a lot of data to flush.
#    3. Throughput: The flush is generally the most expensive operation, and a small flush interval may lead to excessive seeks.
# The settings below allow one to configure the flush policy to flush data after a period of time or
# every N messages (or both). This can be done globally and overridden on a per-topic basis.

# The number of messages to accept before forcing a flush of data to disk
#log.flush.interval.messages=10000

# The maximum amount of time a message can sit in a log before we force a flush
#log.flush.interval.ms=1000

############################# Log Retention Policy #############################

# The following configurations control the disposal of log segments. The policy can
# be set to delete segments after a period of time, or after a given size has accumulated.
# A segment will be deleted whenever *either* of these criteria are met. Deletion always happens
# from the end of the log.

# The minimum age of a log file to be eligible for deletion due to age
log.retention.hours=168

# A size-based retention policy for logs. Segments are pruned from the log unless the remaining
# segments drop below log.retention.bytes. Functions independently of log.retention.hours.
#log.retention.bytes=1073741824

# The maximum size of a log segment file. When this size is reached a new log segment will be created.
log.segment.bytes=1073741824

# The interval at which log segments are checked to see if they can be deleted according
# to the retention policies
log.retention.check.interval.ms=300000

启动脚本start-kafka.sh内容为:

#!/bin/sh

/data/kafka/bin/kafka-storage.sh format \
                    --config /data/kafka/config/kraft/server.properties \
                    --cluster-id $(/data/kafka/bin/kafka-storage.sh random-uuid)

/data/kafka/bin/kafka-server-start.sh /data/kafka/config/kraft/server.properties

Dockerfile内容为:

FROM centos:centos7.9.2009

WORKDIR /data

COPY start-kafka.sh /data
COPY server.properties /data

ARG ZK_VERSION=3.8.0
ARG KAFKA_SCALA_VERSION=2.12
ARG KAFKA_VERSION=3.3.1

EXPOSE 30092

RUN yum update -y
RUN yum install wget java-1.8.0-openjdk-devel java-1.8.0-openjdk -y

RUN wget https://mirrors.tuna.tsinghua.edu.cn/apache/kafka/${KAFKA_VERSION}/kafka_${KAFKA_SCALA_VERSION}-${KAFKA_VERSION}.tgz

RUN tar zxvf kafka_${KAFKA_SCALA_VERSION}-${KAFKA_VERSION}.tgz

RUN ln -s kafka_${KAFKA_SCALA_VERSION}-${KAFKA_VERSION} kafka

RUN rm -rf /data/kafka/config/kraft/server.properties

RUN cp /data/server.properties /data/kafka/config/kraft

RUN mkdir /data/kafka/kafka-logs

RUN chmod a+x /data/start-kafka.sh

CMD ["sh", "/data/start-kafka.sh"]

将上述文件保存到目录下之后执行构建

docker build . --build-arg KAFKA_VERSION=3.3.1 --build-arg ZK_VERSION=3.8.0 --tag xiaozhongcheng2022/kafka:3.3.1 --no-cache=true

即可得到镜像:

k8s快速部署kafka 3.3.1
k8s快速部署kafka 3.3.1

K8s部署kafka

基于此镜像我们就可以构建kafka deployment

---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: kafka
  name: kafka
spec:
  replicas: 1
  revisionHistoryLimit: 2
  selector:
    matchLabels:
      app: kafka
  template:
    metadata:
      labels:
        app: kafka
    spec:
      hostname: kafka
      containers:
        - env:
            - name: KUBERNETES_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
          image: xiaozhongcheng2022/kafka:3.3.1
          imagePullPolicy: IfNotPresent
          name: kafka
          ports:
            - containerPort: 30092
              name: kafka-port
              protocol: TCP
          securityContext:
            privileged: false

将上述配置文件保存为:kafka-deployment.yaml,启动kafka

kubectl apply -f kafka-deployment.yaml

得到:

k8s快速部署kafka 3.3.1
k8s快速部署kafka 3.3.1
k8s快速部署kafka 3.3.1
k8s快速部署kafka 3.3.1

查看kafka日志:

k8s快速部署kafka 3.3.1
k8s快速部署kafka 3.3.1

部署kafka service,将kafka服务通过NodePort暴露出来

---
apiVersion: v1
kind: Service
metadata:
  labels:
    expose: "true"
    app: kafka
  name: kafka
spec:
  type: NodePort
  ports:
    - name: kafka-port
      port: 30092
      protocol: TCP
      nodePort: 30092
  selector:
    app: kafka

将上述文件保存为kafka-service.yaml

kubectl apply -f kafka-service.yaml
k8s快速部署kafka 3.3.1
k8s快速部署kafka 3.3.1

Kafka Java Client连接kafka

由于我们在部署kafka deployment时将kafka的hostname设置为kafka,同时也在配置文件里面将hostname设置为kafka,所以我们在使用客户端进行连接是,需要配置本地hosts,将kafka配置为k8s节点IP

package com.zh.ch.bigdata.examples.kafka;

import com.zh.ch.bigdata.examples.utils.PropertiesUtil;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.Producer;
import org.apache.kafka.clients.producer.ProducerRecord;

import java.io.IOException;
import java.util.Properties;

public class KafkaClientExample<K, V> {

    private Producer<K, V> getProducer() throws IOException {
        Properties kafkaConfig = PropertiesUtil.load("kafka/src/main/resources/kafkaConfig.properties");
        return new KafkaProducer<>(kafkaConfig);
    }

    public static void main(String[] args) throws IOException {
        KafkaClientExample<String, String> kafkaClientExample = new KafkaClientExample<>();
        Producer<String, String> producer = kafkaClientExample.getProducer();
        for (int i = 0; i < 100; i++) {
            producer.send(new ProducerRecord<>("my-topic", Integer.toString(i), Integer.toString(i)));
        }
        producer.close();
    }

}

kafkaConfig.properties

bootstrap.servers        =192.168.1.15:30092
linger.ms                =1
key.serializer           =org.apache.kafka.common.serialization.StringSerializer
value.serializer         =org.apache.kafka.common.serialization.StringSerializer

相关日志:

[2022-11-24 14:33:14,002] INFO [Producer clientId=producer-1] Instantiated an idempotent producer. (org.apache.kafka.clients.producer.KafkaProducer)
[2022-11-24 14:33:14,771] INFO Kafka version: 3.3.1 (org.apache.kafka.common.utils.AppInfoParser)
[2022-11-24 14:33:14,771] INFO Kafka commitId: e23c59d00e687ff5 (org.apache.kafka.common.utils.AppInfoParser)
[2022-11-24 14:33:14,771] INFO Kafka startTimeMs: 1669271594768 (org.apache.kafka.common.utils.AppInfoParser)
[2022-11-24 14:33:15,069] WARN [Producer clientId=producer-1] Error while fetching metadata with correlation id 1 : {my-topic=UNKNOWN_TOPIC_OR_PARTITION} (org.apache.kafka.clients.NetworkClient)
[2022-11-24 14:33:15,070] INFO [Producer clientId=producer-1] Cluster ID: EBIPehHLSZOQyWQ8el4N3g (org.apache.kafka.clients.Metadata)
[2022-11-24 14:33:15,129] INFO [Producer clientId=producer-1] ProducerId set to 0 with epoch 0 (org.apache.kafka.clients.producer.internals.TransactionManager)
[2022-11-24 14:33:15,199] INFO [Producer clientId=producer-1] Resetting the last seen epoch of partition my-topic-0 to 0 since the associated topicId changed from null to UnwEqo7bRN-5vOb0rkA2Cw (org.apache.kafka.clients.Metadata)
[2022-11-24 14:33:15,217] INFO [Producer clientId=producer-1] Closing the Kafka producer with timeoutMillis = 9223372036854775807 ms. (org.apache.kafka.clients.producer.KafkaProducer)
[2022-11-24 14:33:15,320] INFO Metrics scheduler closed (org.apache.kafka.common.metrics.Metrics)
[2022-11-24 14:33:15,320] INFO Closing reporter org.apache.kafka.common.metrics.JmxReporter (org.apache.kafka.common.metrics.Metrics)
[2022-11-24 14:33:15,320] INFO Metrics reporters closed (org.apache.kafka.common.metrics.Metrics)
[2022-11-24 14:33:15,320] INFO App info kafka.producer for producer-1 unregistered (org.apache.kafka.common.utils.AppInfoParser)

再次查看kafka日志,可以发现my-topic创建成功

k8s快速部署kafka 3.3.1
k8s快速部署kafka 3.3.1

kafka数据持久化

如果需要持久化kafka数据,可使用nfs进行持久化。在已有nfs服务的情况下使用helm部署

helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/

helm install nfs-subdir-external-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \
    --set nfs.server=192.168.49.1 \
    --set nfs.path=/data1/nfs/rootfs

即可得到名称为nfs-client的StorageClass

k8s快速部署kafka 3.3.1
k8s快速部署kafka 3.3.1

使用nfs-client创建pvc

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: kafka-pvc
spec:
  storageClassName: nfs-client
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 50Gi

将上述配置文件保存为kafka-pvc.yaml

kubectl apply -f kafka-pvc.yaml

修改kafka-deployment.yaml

---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: kafka
  name: kafka
spec:
  replicas: 1
  revisionHistoryLimit: 2
  selector:
    matchLabels:
      app: kafka
  template:
    metadata:
      labels:
        app: kafka
    spec:
      hostname: kafka
      containers:
        - env:
            - name: KUBERNETES_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
          image: xiaozhongcheng2022/kafka:3.3.1
          imagePullPolicy: IfNotPresent
          name: kafka
          ports:
            - containerPort: 30092
              name: kafka-port
              protocol: TCP
          securityContext:
            privileged: false
          volumeMounts:
            - mountPath: /data/kafka/kafka-logs
              name: kafka-pvc
      volumes:
        - name: kafka-pvc
          persistentVolumeClaim:
            claimName: kafka-pvc

查看nfs路径可以看到持久化目录

k8s快速部署kafka 3.3.1
k8s快速部署kafka 3.3.1

总结

k8s快速部署应用进行测试是一个不错的选择,本文从头概述了如何构建kafka镜像以及在k8s上快速部署。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 构建kafka镜像
  • K8s部署kafka
  • Kafka Java Client连接kafka
  • kafka数据持久化
  • 总结
相关产品与服务
容器镜像服务
容器镜像服务(Tencent Container Registry,TCR)为您提供安全独享、高性能的容器镜像托管分发服务。您可同时在全球多个地域创建独享实例,以实现容器镜像的就近拉取,降低拉取时间,节约带宽成本。TCR 提供细颗粒度的权限管理及访问控制,保障您的数据安全。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档