背景

随着业务规模的发展,需要的kafka集群越来越来,这给部署与管理带来了很大的挑战。我们期望能够利用K8S优秀的扩容能力与快速部署能力,为日常的工作减负。所以就kafka上K8S的可行性方案进行了调研。

像kafka集群这种,涉及到的组件比较多,且都是有状态的集群,业界采用自定义operator的解决方案。目前GitHub上有多个相关的仓库,根据社区活跃度及使用数等综合考虑,此次采用Strimzi Github地址。

kafka组件交互图

方案

  1. 使用阿里云K8S集群部署Strimzi
  2. 由于组内使用的kafka是由开源版本二次开发而来,所以需要维护一个自定义的Strimzi-kafka镜像
  1. Strimzi管理kafka集群,其中包含kafka、zk、kafka-exporter、
  2. 使用zoo-entrance 代理集群中的zk GitHub地址
  1. 部署prometheus,采集kafka和zk的metrics
  2. 开启服务端口,暴露kafka及zk给K8S集群外部使用

实战过程

构建自定义kafka镜像

  • 从公司Git上拉取最新代码 strimzi-kafka-operator (与开源版本有些微的改动,做实验可直接用开源版)
  • 在docker-images 文件夹下,有个Makefile文件,执行其中的docker_build, 它会去执行其中的build.sh脚本;此步会从官网拉取kafka的安装包,我们需要将这一步的包修改为我司内部的安装包。
  • 构建完镜像,镜像在本地,我们需要将镜像上传到公司内部的harbor服务器上

部署operator

每个K8S集群仅需部署一个operator

  • 充分必要条件:一个健康的k8s集群
  • 创建namespace, 如已有则跳过,默认使用kafka,kubectl create namespace kafka
  • 从公司Git上拉取最新代码(地址在前边)
  • 目前文件中默认监听的是名称为 kafka 的namespace,如果需要修改则执行 sed -i 's/namespace: .*/namespace: kafka/' install/cluster-operator/*RoleBinding*.yaml (将命令中的kafka/ 替换掉)
  • 然后将所有文件都应用一下 kubectl apply -f install/cluster-operator/ -n kafka
  • 此时稍等片刻,就能查看到创建的自定义资源以及operator了 kubectl get pods -nkafka,
  • 从阿里云的k8s管控台查看这些资源的创建情况,以及operator的运行情况

部署kafka集群

确保你的operator已经部署成功,且kafka部署的namespace需在上边operator的监控中

  • 还是来到最新的代码目录中,其中examples/kafka目录下边就是本次部署所需要的文件了
  • 部署 kafka及zk
    • 查看kafka-persistent.yaml, 该文件就是核心文件了,这个文件部署了kafka与zk及kafka-exporter, 部分内容如下:
apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
metadata:name: my-cluster
spec:kafka:version: 2.8.1replicas: 3resources:requests:memory: 16Gicpu: 4000mlimits:memory: 16Gicpu: 4000mimage: repository.poizon.com/kafka-operator/poizon/kafka:2.8.4jvmOptions:-Xms: 3072m-Xmx: 3072mlisteners:- name: externalport: 9092type: nodeporttls: false- name: plainport: 9093type: internaltls: falseconfig:offsets.topic.replication.factor: 2transaction.state.log.replication.factor: 2transaction.state.log.min.isr: 1default.replication.factor: 2***template:pod:affinity:podAntiAffinity:requiredDuringSchedulingIgnoredDuringExecution:- labelSelector:matchExpressions:- key: strimzi.io/nameoperator: Invalues:- my-cluster-kafkatopologyKey: "kubernetes.io/hostname"storage:type: persistent-claimsize: 100Giclass: rocketmq-storagedeleteClaim: falsemetricsConfig:type: jmxPrometheusExportervalueFrom:configMapKeyRef:name: kafka-metricskey: kafka-metrics-config.ymlzookeeper:replicas: 3resources:requests:memory: 3Gicpu: 1000mlimits:memory: 3Gicpu: 1000mjvmOptions:-Xms: 2048m-Xmx: 2048mjmxOptions: {}template:pod:affinity:podAntiAffinity:***storage:type: persistent-claimsize: 50Giclass: rocketmq-storagedeleteClaim: falsemetricsConfig:type: jmxPrometheusExportervalueFrom:configMapKeyRef:name: kafka-metricskey: zookeeper-metrics-config.yml******
  • 可修改kafka集群的名称,在第四行的name属性,目前默认为 my-cluster
  • 可修改kafka的Pod个数,即节点数,默认为3
    • 可修改Pod配置 内存CPU
    • 可修改kafka JVM 启动的堆内存大小
    • 可修改kafka的配置,在36行 config配置
    • 可修改磁盘类型及大小,类型为第50行,可修改为其它的存储类,目前可选为高效云盘、SSD、ESSD
    • zk修改同kafka,可修改的东西类似, 且在同一个文件中
    • 文件下边是kafka与zk需要暴露的metrics,可按需求增删改
    • 修改完配置之后,直接执行 kubect apply -f kafka-persistent.yaml -nkafka 即可创建
  • 部署 zk代理
    • 由于官方不支持外部组件直接访问zk,所以采用代理的方式访问
    • 出于安全性 的考虑,官方是故意不支持外部程序访问zk的: https://github.com/strimzi/strimzi-kafka-operator/issues/1337
    • 解决方案:https://github.com/scholzj/zoo-entrance/blob/main/deploy.yaml
    • 部署完zk的代理,我们需要在k8s控制台上 创建一个loadbalance服务将这个代理暴露给集群外的应用进行连接。具体操作:k8s控制台-->网络-->服务-->创建(选择loadbalance创建,然后找到zoo-entrance这个应用即可)
  • 部署 zk-exporter
    • 官方operator中没有zk-exporter, 我们采用 https://github.com/dabealu/zookeeper-exporter
    • 在文件夹中的zk-exporter.yaml 文件中,我们仅需要修改被监听的zk的地址(spec.container.args)
    • 执行kubectl apply -f zk-exporter.yaml即可部署完成
  • 部署 kafka-jmx
    • 由于ingress不支持tcp连接,而loadbalance的成本又过高,所以kafka 的 jmx 使用nodeport对外暴露
    • 可以在阿里云控制台上创建相应的nodeport,也可以使用kafka-jmx.yaml 文件的方式创建
apiVersion: v1
kind: Service
metadata:labels:strimzi.io/cluster: my-clusterstrimzi.io/name: my-cluster-kafka-jmxname: my-cluster-kafka-jmx-0
spec:ports:- name: kafka-jmx-nodeportport: 9999protocol: TCPtargetPort: 9999selector:statefulset.kubernetes.io/pod-name: my-cluster-kafka-0strimzi.io/cluster: my-clusterstrimzi.io/kind: Kafkastrimzi.io/name: my-cluster-kafkatype: NodePort
  • 部署 kafka-exporter-service
    • 前面部署完kafka之后,我们的配置中是开启了exporter的。但是官方开启完exporter之后,并没有自动生成一个相关的service,为了让Prometheus连接更加方便,我们部署了一个service
    • 在文件夹中kafka-exporter-service.yaml 文件中
apiVersion: v1
kind: Service
metadata:labels:app: kafka-export-servicename: my-cluster-kafka-exporter-service
spec:ports:- port: 9404protocol: TCPtargetPort: 9404selector:strimzi.io/cluster: my-clusterstrimzi.io/kind: Kafkastrimzi.io/name: my-cluster-kafka-exportertype: ClusterIP
    • 执行kubectl apply -f kafka-exporter-service.yaml即可部署完成
  • 部署 kafka-prometheus
    • 如果将Prometheus部署在k8s集群外,数据采集会比较麻烦,所以我们直接将Prometheus部署到集群内
    • 在文件夹中kafka-prometheus.yaml文件中,可以选择性的修改其中prometheus的配置,比如需要的内存CPU的大小,比如监控数据保存时间,外挂的云盘大小,以及需要监听的kafka与zk地址
apiVersion: apps/v1
kind: StatefulSet
metadata:name: kafka-prometheuslabels:app: kafka-prometheus
spec:replicas: 1revisionHistoryLimit: 10selector:matchLabels:app: kafka-prometheusserviceName: kafka-prometheusupdateStrategy:type: RollingUpdatetemplate:metadata:labels:app: kafka-prometheusspec:containers:- args:- '--query.max-concurrency=800'- '--query.max-samples=800000000'***command:- /bin/prometheusimage: 'repository.poizon.com/prometheus/prometheus:v2.28.1'imagePullPolicy: IfNotPresentlivenessProbe:failureThreshold: 10httpGet:path: /statusport: webscheme: HTTPinitialDelaySeconds: 300periodSeconds: 5successThreshold: 1timeoutSeconds: 3name: kafka-prometheusresources:limits:cpu: 500mmemory: 512Mirequests:cpu: 200mmemory: 128MivolumeMounts:- mountPath: /etc/localtimename: volume-localtime- mountPath: /data/prometheus/name: kafka-prometheus-config- mountPath: /data/database/prometheusname: kafka-prometheus-dbterminationMessagePath: /dev/termination-logterminationMessagePolicy: FileterminationGracePeriodSeconds: 30restartPolicy: AlwaysschedulerName: default-schedulersecurityContext:fsGroup: 0volumes:- hostPath:path: /etc/localtimetype: ''name: volume-localtime- configMap:defaultMode: 420name: kafka-prometheus-configname: kafka-prometheus-configvolumeClaimTemplates:- apiVersion: v1kind: PersistentVolumeClaimmetadata:name: kafka-prometheus-dbspec:accessModes:- ReadWriteOnceresources:requests:storage: 20GistorageClassName: rocketmq-storagevolumeMode: Filesystemstatus:phase: Pending
    • 执行kubectl apply -f kafka-prometheus.yaml即可部署完成
    • 部署完成后将prometheus暴露给监控组的grafana,可以直连pod IP做验证,然后在k8s管控台的 网络-->路由-->创建, 创建一个ingress,选择刚刚部署的这个Prometheus的service,然后找运维申请域名,即可。

总结

  • 优点
    • 快速部署集群(分钟级),快速集群扩容(秒级),快速灾难恢复(秒级)
    • 支持滚动更新,支持备份以及还原
  • 缺点
    • 引入较多组件,复杂度升高
    • 对K8S集群外的访问不太友好
  • 文/ZUOQI

  • 关注得物技术,做最潮技术人

Kafka上K8S实战相关推荐

  1. 炫‘库’行动-人大金仓有奖征文-挑战国产数据库金仓上k8s(二)

    本文正在参与炫"库"行动-人大金仓有奖征文: 快来点击活动链接参与投稿吧 https://marketing.csdn.net/p/98bd30353e7cb998b6070a89 ...

  2. K8S实战:Centos7上集群部署

    K8S实战:Centos7上集群部署 更多技术类博文,请关注微信公众号:运维之美. 集群架构 k8s集群的架构 master节点:etcd,api-server,scheduler,controlle ...

  3. .net core上 K8S(七).netcore程序的服务发现

    正文 上一章我们分享了k8s的网络代理模式,今天我们来分享一下k8s中的服务发现. 1.环境变量模式的服务发现 k8s默认为我们提供了通过环境变量来实现服务发现的功能,前提是 1.需要service在 ...

  4. .net core i上 K8S(六).netcore程序的service网络代理模式

    正文 上一章我们讲了pod的hostip模式,但在生产环境中,我们都是通过service来访问k8s集群的,service有两种模式来暴漏端口,今天我们来分享一下 1.clusterIP模式 我们在创 ...

  5. .net core i上 K8S(五).netcore程序的hostip模式

    正文 上一章讲了pod的管理,今天再分享一个pod的访问方式 1.Pod的HostIP模式 Pod的HostIP模式,可以通过宿主机访问pod内的服务,创建yaml文件如下 apiVersion: v ...

  6. k8s实战之从私有仓库拉取镜像 - kubernetes

    1.实战目的 从私有docker仓库拉取镜像,部署pod.上一篇中,我们搭建了私有的镜像仓库,这一篇我们将与k8s结合实战使用私有仓库. 2.登录docker 为了完成本次实战,需要登录docker, ...

  7. K8S实战之环境部署1.18(一)

    安装要求,准备环境 #系统centos7.6 #硬件:2个CPU,2G内存 #可以访问外网,禁用swap #提前安装docker环境 准备三台服务器 初始化系统环境,以下命令三台服务器全部执行 1.1 ...

  8. K8S实战之部署java应用

    kubernetes基本概念 Pod: 1.最小的部署单元, 2.一组容器的集合 3.一个pod中的容器共享网络命名空间 4.生命周期是短暂的 Controllers: 1.Deployment:部署 ...

  9. 【K8S实战】-超详细教程(二)

    [K8S实战]-超详细教程(二) 环境这块的这里我就不过多描述了,需要了解的可以看这篇文章[k8s搭建(超详细,保姆级教程)]. 1.Deployment Deployment其他功能我上一篇文章已写 ...

  10. 【K8S实战】-超详细教程(三)

    [K8S实战]-超详细教程(三) 1.存储 1.1.nfs默认存储 我这里只演示nfs作为K8S的默认存储,其他的可以看这里[存储类]. 1.1.1.安装nfs服务 所有机器都安装nfs工具 所有机器 ...

最新文章

  1. java datahandler_Java Web Services:使用DataHandler类发送文件
  2. 【Android开发】自定义ListView,使用通用适配器,并实现ListView上的每一项和每一项上的按钮等控件同时监听
  3. python获取命令行参数的方法
  4. WinForm界面设计优化过程
  5. 从零开始学Xamarin.Forms(四) Android 准备步骤(添加第三方Xamarin.Forms.Labs库)
  6. SAP CRM Genil Text-for-Key-Codes vs SAP C4C只读字段
  7. 异步加载js文件并执行js方法:实现异步处理网页的复杂效果
  8. [构造训练]CF1227G Not Same,CF1375H Set Merging,CF1364E X-OR
  9. 基础强化:深入理解JVM中的方法调用
  10. 基于html5的在线教育,基于HTML5的在线学习系统的设计与实现
  11. Android Studio 将github作为远程maven仓库
  12. 17届互联网校招薪酬报告:白菜价22W,青菜价30W,神价150W
  13. cadence设计PCB流程
  14. java让字体闪动_java 字体闪烁
  15. 把一个人的特点写具体作文_五年级把一个人的特点写具体作文500字5篇
  16. Dell OptiPlex 7090插入耳机有声音没有麦克风的解决方案
  17. traceroute的一些用法
  18. C# RichTextBox 修改内容
  19. 精心整理了100+Python字符串常用操作,备用
  20. Android备考01 黑马76期-day03 操作数据库

热门文章

  1. python 卡方检验批量筛选_用python进行列联表卡方检验
  2. Java实现的中间库
  3. 以太网口差分电平_以太网差分信号线在两层PCB板上的布线方法
  4. 立志欲坚不欲锐 - 2019 年小结
  5. Liskov Substitution Principle
  6. 工具类-BasePopupWindow
  7. (拯救者Y7000)重装win10后,耳机插入电脑声音还是外放
  8. PhotoShop软件笔记
  9. Roundcube开启用户自助更改密码功能
  10. 从一个简单的main方法执行谈谈JVM工作机制