1、基于Kraft 在宿主机实现Kafka集群3.5.x
2、基于Zookeeper在kubernetes环境结合storageclass部署kafka 2.8.x集群
3、总结kafka的主要配置
############################# Server Basics #############################
process.roles=broker,controller
#角色配置,broker为只是node角色(不参与controller选举),controller为只是controller角色(不参数数据读写),broker和controller两种角色都是,如果process.roles 没有设置,那么集群就假定是运行在ZooKeeper模式下。
node.id=101
#在kraft模式下的节点id,同一个集群中的不同节点不能重复,在使用zk的时候设置broker.id=X
controller.quorum.voters=101@172.31.4.101:9093,102@172.31.4.102:9093,103@172.31.4.103:9093
#controller节点的配置,会通过以上地址进行集群投票和通告,格式为node.idX@IP:PORT,node.idY@IP:PORT,node.idZ@IP:PORT
############################# Socket Server Settings #############################
listeners=PLAINTEXT://:9092,CONTROLLER://:9093
#内网的监听地址,用于通过当前主机IP的直接访问,也就是没有通过其他外网访问入口(如公有云的外网LB)访问kafka,9092为客户端端口,9093为集群端口
inter.broker.listener.name=PLAINTEXT
#设置broker监听器名称,被listeners引用
advertised.listeners=PLAINTEXT://172.31.4.101:9092
#通告kafka节点的连接信息
#kafka只有一个内网网卡IP为172.31.0.101,外网通过代理访问kafka的
#listener.security.protocol.map=INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT
#listeners=INTERNAL://172.31.0.101:9092,EXTERNAL://172.31.0.101:19092
#advertised.listeners=INTERNAL://172.31.0.101:9092,EXTERNAL://101.0.0.1:19092
#inter.broker.listener.name=INTERNAL
#kafka有双网卡,内网IP172.31.0.101,外网IP101.0.0.1
#listener.security.protocol.map=INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT
#listeners=INTERNAL://172.31.0.101:9092,EXTERNAL://101.0.0.1:19092
#advertised.listeners=INTERNAL://172.31.0.101:9092,EXTERNAL://101.0.0.1:19092
#inter.broker.listener.name=INTERNAL
controller.listener.names=CONTROLLER
#设置controller监听器名称,被listeners引用
listener.security.protocol.map=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT,SSL:SSL,SASL_PLAINTEXT:SASL_PLAINTEXT,SASL_SSL:SASL_SSL
#将侦听器名称映射到的安全协议
num.network.threads=3
#用于接收来自网络的请求并向网络发送响应的线程数
num.io.threads=8
#服务器用于处理请求的线程数,可能会包括磁盘IO的线程数,数值应该大于主机的硬盘数
socket.send.buffer.bytes=102400
#socket的发送缓冲区大小,数据不是一下子就发送的,先会存储到缓冲区、到达一定的大小后再发送,能提网络高性能
socket.receive.buffer.bytes=102400
#socket的接受缓冲区,当数据到达一定大小后在序列化到磁盘
socket.request.max.bytes=104857600
#socket server接收的最大请求大小bytes,用于控制向kafka请求消息或者向kafka发送消息的请请求的最大数,这个值不能超过java的堆栈大小
############################# Log Basics #############################
log.dirs=/tmp/kraft-combined-logs
#日志目录
num.partitions=1
#默认分区数,更多分区允许更多并行读写,但是会跨越多主机
num.recovery.threads.per.data.dir=1
#用于在启动时,用于日志恢复的线程个数,默认是1
############################# Internal Topic Settings #############################
offsets.topic.replication.factor=1
#kafka的内部topic consumer_offsets副本数,默认1副本,如果全部丢失,则使用该分区存储消费分组offset位置的消费者均会收到影响,会导致生产者可以发送消息但消费者不可用
transaction.state.log.replication.factor=1
#事务主题的副本数
transaction.state.log.min.isr=1
#事务状态主题的每个分区,处于ISR最⼩节点数量,(lsr=ln-sync,表示可以参加选举成为leader)
############################# Log Flush Policy #############################
#log.flush.interval.messages=10000
#每当producer写入10000条消息时,刷数据到磁盘
#log.flush.interval.ms=1000
#每间隔1秒钟时间,刷数据到磁盘
############################# Log Retention Policy #############################
log.retention.hours=168
#消息保存时间,会滚动删除过期的数据
log.segment.bytes=1073741824
#将日志切分为每段1073741824字节(1G)保存,方便kafa对数据进行回收和管理
log.retention.check.interval.ms=300000
#日志清理检查周期,300000ms=300s=5分钟
4、总结kafka topic的分区及副本的作用、基于python脚本验证消息的写入Kafka并从Kafka集群消费
分区作用:
实现存储空间的横向扩容,即将多个kafka服务器的空间结合利用
提升性能,多服务器读写
分区的最大数量不建议高于Broker 的总数。
副本 作用:
实现高可用,分区leader和Replica被自动分布在不同的kafka服务器,比如topic myserver(假如有2分区1副本)分区0的leader为服务器Broker 101,则Broker 102和Broker 103为topic myserver分区0的follower,而topic myserver分区1的leader为Broker 102,则Broker 101和Broker 103为topic myserver分区1的follower。
副本数量不能高于Broker 的总数。
follower状态为lsr(ln-sync(In-Sync Replicas),表示当前副本可以参加选举成为leader)
5、基于Strimzi Operator部署面向生产环境的Kafka集群
官方文档地址: https://strimzi.io/docs/operators/latest/overview
创建命名空间并部署 strimzi-cluster-operator
kubectl create namespace myserver
kubectl apply -f https://strimzi.io/install/latest?namespace=myserver
等 strimzi-cluster-operator pod 为 running 状态
[root@DELL_PC 7.strimzi-kafka-operator]# kubectl get pod -n myserver
NAME READY STATUS RESTARTS AGE
strimzi-cluster-operator-7b6bcddf-jjxz9 1/1 Running 0 62m
提前部署好存储类nfs-csi,部署kafka集群
wget https://strimzi.io/examples/latest/kafka/kafka-persistent-single.yaml
vim kafka-persistent-single.yaml
version: 3.5.1
replicas: 1 #副本数,默认为1
listeners:
- name: plain
port: 9092
type: internal
tls: false
- name: tls
port: 9093
type: internal
tls: true
- name: external # 增加外部客户端访问用的linstener
port: 9094 #监听端口
type: nodeport #指定nodeport类型
tls: false
configuration:
bootstrap:
nodePort: 39092 # 指定宿主机nodeport端口
config:
offsets.topic.replication.factor: 1
transaction.state.log.replication.factor: 1
transaction.state.log.min.isr: 1
default.replication.factor: 1
min.insync.replicas: 1
inter.broker.protocol.version: "3.5"
storage:
type: jbod
volumes:
- id: 0
type: persistent-claim
class: nfs-csi
size: 40Gi
deleteClaim: false
zookeeper:
replicas: 1
storage:
type: persistent-claim
class: nfs-csi
size: 10Gi
deleteClaim: false
entityOperator:
topicOperator: {}
userOperator: {}
这几个 kafka配置参数不能大于节点数offsets.topic.replication.factor: transaction.state.log.replication.factor: transaction.state.log.min.isr:
kubectl apply -f kafka-persistent-single.yaml
确保 pod 全部处于 running 状态
[root@DELL_PC 7.strimzi-kafka-operator]# kubectl get pod -n myserver
NAME READY STATUS RESTARTS AGE
myserver-kafka-cluster-entity-operator-5fd9fdfd95-tlhhd 2/2 Running 0 40m
myserver-kafka-cluster-kafka-0 1/1 Running 0 40m
myserver-kafka-cluster-zookeeper-0 1/1 Running 0 41m
strimzi-cluster-operator-7b6bcddf-jjxz9 1/1 Running 0 62m
K8s集群内部测试 kafka 数据数据读写
测试写入数据:
kubectl -n myserver run kafka-producer -ti --image=quay.io/strimzi/kafka:0.30.0-kafka-3.2.0 --rm=true --restart=Never -- bin/kafka-console-producer.sh --bootstrap-server myserver-kafka-cluster-kafka-bootstrap:9092 --topic my-topic
>1111 >222 >333
测试消费数据:
kubectl -n myserver run kafka-consumer -ti \
--image=quay.io/strimzi/kafka:0.30.0-kafka-3.2.0 \
--rm=true --restart=Never -- bin/kafka-console-consumer.sh \
--bootstrap-server myserver-kafka-cluster-kafka-bootstrap:9092 \
--topic my-topic --from-beginning
If you don't see a command prompt, try pressing enter. 1111 222 333
使用python脚本在K8s外部访问测试
yum install -y python3-pip
pip3 install --index-url https://mirrors.aliyun.com/pypi/simple/ kafka-python
vim kafka-server.py
#/usr/bin/env python3
#coding=utf-8
#pip3 install --index-url https://mirrors.aliyun.com/pypi/simple/ kafka-python
from kafka import KafkaProducer
conn = KafkaProducer(bootstrap_servers=['192.168.220.101:39092','192.168.220.201:39092','192.168.220.111:39092'],compression_type='gzip')
conn.send('foobar', key=b'foo', value=b'bar')
for i in range(3):
msg = "msg%d" % i
#conn.send('myserver', msg)
conn.send('myserver10',key=b'myserver-key', value=b'msg%d' % i)
print('topic-->myserver: msg%d发送成功!' % i)
conn.close()
[root@DELL_PC 7.strimzi-kafka-operator]# python3 kafka-server.py
topic-->myserver: msg0发送成功!
topic-->myserver: msg1发送成功!
topic-->myserver: msg2发送成功!
进入K8s集群测试获取消息
kubectl -n myserver run kafka-consumer-myserver -ti --image=quay.io/strimzi/kafka:0.30.0-kafka-3.2.0 --rm=true --restart=Never -- bin/kafka-console-consumer.sh --bootstrap-server myserver-kafka-cluster-kafka-bootstrap:9092 --topic myserver10 --from-beginning
If you don't see a command prompt, try pressing enter. msg0 msg1 msg2
部署kafka管理UI
docker run --name kafka-ui -d -p 8080:8080 -e DYNAMIC_CONFIG_ENABLED=true -e KAFKA_CLUSTERS_0_NAME="kafka-cluster1" -e KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS="192.168.220.101:39092,192.168.220.201:39092,192.168.220.111:39092" --restart always provectuslabs/kafka-ui:master
创建自定义 topic
vim 2.create-topic.yaml
apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaTopic
metadata:
name: myserver-topic25 #主题名称
namespace: myserver #kafka所在的NS
labels:
strimzi.io/cluster: "myserver-kafka-cluster" #匹配kafka集群名称
spec:
partitions: 3 #3分区,相当于一个完整的数据拆分为3部分
replicas: 1 #每部分数据分别存3份(每份单独一个主机)
kubectl apply -f 2.create-topic.yaml
验证 topic
[root@DELL_PC 7.strimzi-kafka-operator]# kubectl get crd | grep kafka
kafkabridges.kafka.strimzi.io 2023-12-03T10:27:18Z
kafkaconnectors.kafka.strimzi.io 2023-12-03T10:27:19Z
kafkaconnects.kafka.strimzi.io 2023-12-03T10:27:17Z
kafkamirrormaker2s.kafka.strimzi.io 2023-12-03T10:27:18Z
kafkamirrormakers.kafka.strimzi.io 2023-12-03T10:27:19Z
kafkanodepools.kafka.strimzi.io 2023-12-03T10:27:20Z
kafkarebalances.kafka.strimzi.io 2023-12-03T10:27:19Z
kafkas.kafka.strimzi.io 2023-12-03T10:27:19Z
kafkatopics.kafka.strimzi.io 2023-12-03T10:27:18Z
kafkausers.kafka.strimzi.io 2023-12-03T10:27:19Z
[root@DELL_PC 7.strimzi-kafka-operator]# kubectl get kafkatopic.kafka.strimzi.io -n myserver
NAME CLUSTER PARTITIONS REPLICATION FACTOR READY
myserver-topic25 myserver-kafka-cluster 3 1 True
6、总结分布式链路追踪的基础功能
分布式链路跟踪系统的主要作用是在分布式系统中跟踪一个用户请求的完整过程,确定客户端的一次请求到结束的背后究竟调用了哪些应用以及哪些模块并经过了哪些节点,且每个模块的调用先后顺序是怎样的、每个模块的处理相应性能如何,基础功能 包括数据采集、数据传输、数据存储、数据分析和数据可视化,获取并存储和分享此类跟踪可以让运维清晰了解用户请求与业务系统交互背后的整个调用链的调用关系,因此链路追踪系统是针对业务调试和监控微服务不可或缺的重要统。
7、总结SkyWalking的特性、组件及与其它链路追踪系统对比
SkyWalking的特性
实现从请求跟踪、指标收集和日志记录的完整信息记录。
多语言自动探针,支持Java、GO、Python、PHP、NodeJS、LUA、Rust等客户端。
内置服务网格可观察性,支持从Istio+Envoy Service Mesh收集和分析数据。
模块化架构,存储、集群管理、使用插件集合都可以进行自由选择。
支持告警。
优秀的可视化效果
组件介绍:
OAP平台(Observability Analysis Platform,可观测性分析平台)或OAP Server,它是一个高度组件化的轻量级分析程序,由兼容各种探针 Receiver、流式分析内核和查询内核三部分构成。
探针:基于无侵入式的收集,并通过HTTP或者gRPC方式发送数据到OAP Server。
存储实现(Storage Implementors),SkyWalking OAP Server支持多种存储实现并且提供了标准接口,可支持不同的存储后端。
UI模块(SkyWalking),通过标准的GraphQL(Facebook在2012年开源)协议进行统计数据查询和展示 。
扩展:
1、部署kafka ui管理工具kafdrop、kafka-ui
2、Prometheus基于kafka-exporter采集kafka指标数据在grafana绘图
在K8s中使用Strimzi Operator部署kafka之后部署kafka-exporter,配置kafka-exporter连接zookeeper和kafka集群,kafka-exporter对外暴露NodePort端口
vim 4.kafka-exporter.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: kafka-exporter
namespace: myserver
spec:
replicas: 1
selector:
matchLabels:
app: kafka-exporter
template:
metadata:
annotations:
prometheus.io/scrape: "true"
prometheus.io/path: /metrics
prometheus.io/port: "9308"
labels:
app: kafka-exporter
spec:
containers:
- name: kafka-exporter
imagePullPolicy: IfNotPresent
image: registry.cn-hangzhou.aliyuncs.com/zhangshijie/kafka-exporter:v1.7.0
command: ["/bin/kafka_exporter"]
#配置kafka-exporter连接zookeeper和kafka集群
args: ["--zookeeper.server=myserver-kafka-cluster-zookeeper-client:2181", "--kafka.server=myserver-kafka-cluster-kafka-bootstrap:9092"]
ports:
- name: http-metrics
containerPort: 9308
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: kafka-exporter
namespace: myserver
spec:
type: NodePort
ports:
- name: http-metrics
port: 9308
protocol: TCP
targetPort: 9308
selector:
app: kafka-exporter
验证kafka-exporter
部署prometheus的ConfigMap,配置kafka-exporter的NodePort地址
vim 5.1.prometheus-cfg-test1.yaml
---
kind: ConfigMap
apiVersion: v1
metadata:
labels:
app: prometheus
name: prometheus-config
namespace: monitoring
data:
prometheus.yml: |
global:
evaluation_interval: 1m
scrape_interval: 10s
scrape_timeout: 10s
remote_write:
#########VictoriaMetrics Cluster
- url: http://vminsert1.myserver:8480/insert/0/prometheus
- url: http://vminsert2.myserver:8480/insert/0/prometheus
- url: http://vminsert3.myserver:8480/insert/0/prometheus
rule_files:
- /etc/config/recording_rules.yml
- /etc/config/alerting_rules.yml
- /etc/config/rules
- /etc/config/alerts
scrape_configs:
- job_name: 'kafka-monitor'
static_configs:
- targets: ['192.168.220.111:39826']
重启prometheus
kubectl delete pod -n monitoring prometheus-server-65484dd797-82556
验证grafana 模板11285,添加自定义指标:
sum(kafka_brokers) by (instance) #自定义指标集群节点数