背景

随着业务规模的倒退,须要的kafka集群越来越来,这给部署与治理带来了很大的挑战。咱们冀望可能利用K8S优良的扩容能力与疾速部署能力,为日常的工作减负。所以就kafka上K8S的可行性计划进行了调研。

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

kafka组件交互图

计划

  1. 应用阿里云K8S集群部署Strimzi
  2. 因为组内应用的kafka是由开源版本二次开发而来,所以须要保护一个自定义的Strimzi-kafka镜像
  3. Strimzi治理kafka集群,其中蕴含kafka、zk、kafka-exporter、
  4. 应用zoo-entrance 代理集群中的zk GitHub地址
  5. 部署prometheus,采集kafka和zk的metrics
  6. 开启服务端口,裸露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/v1beta2kind: Kafkametadata:  name: my-clusterspec:  kafka:    version: 2.8.1    replicas: 3    resources:      requests:        memory: 16Gi        cpu: 4000m      limits:        memory: 16Gi        cpu: 4000m    image: repository.poizon.com/kafka-operator/poizon/kafka:2.8.4    jvmOptions:      -Xms: 3072m      -Xmx: 3072m    listeners:      - name: external        port: 9092        type: nodeport        tls: false      - name: plain        port: 9093        type: internal        tls: false    config:      offsets.topic.replication.factor: 2      transaction.state.log.replication.factor: 2      transaction.state.log.min.isr: 1      default.replication.factor: 2      ***    template:      pod:        affinity:          podAntiAffinity:            requiredDuringSchedulingIgnoredDuringExecution:              - labelSelector:                  matchExpressions:                    - key: strimzi.io/name                      operator: In                      values:                        - my-cluster-kafka                topologyKey: "kubernetes.io/hostname"    storage:      type: persistent-claim      size: 100Gi      class: rocketmq-storage      deleteClaim: false    metricsConfig:      type: jmxPrometheusExporter      valueFrom:        configMapKeyRef:          name: kafka-metrics          key: kafka-metrics-config.yml  zookeeper:    replicas: 3    resources:      requests:        memory: 3Gi        cpu: 1000m      limits:        memory: 3Gi        cpu: 1000m    jvmOptions:      -Xms: 2048m      -Xmx: 2048m    jmxOptions: {}    template:      pod:        affinity:          podAntiAffinity:          ***    storage:      type: persistent-claim      size: 50Gi      class: rocketmq-storage      deleteClaim: false    metricsConfig:      type: jmxPrometheusExporter      valueFrom:        configMapKeyRef:          name: kafka-metrics          key: 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/zo...
    • 部署完zk的代理,咱们须要在k8s管制台上 创立一个loadbalance服务将这个代理裸露给集群外的利用进行连贯。具体操作:k8s控制台-->网络-->服务-->创立(抉择loadbalance创立,而后找到zoo-entrance这个利用即可)
  • 部署 zk-exporter
    • 官网operator中没有zk-exporter, 咱们采纳 https://github.com/dabealu/zo...
    • 在文件夹中的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: v1kind: Servicemetadata:  labels:    strimzi.io/cluster: my-cluster    strimzi.io/name: my-cluster-kafka-jmx  name: my-cluster-kafka-jmx-0spec:  ports:    - name: kafka-jmx-nodeport      port: 9999      protocol: TCP      targetPort: 9999  selector:    statefulset.kubernetes.io/pod-name: my-cluster-kafka-0    strimzi.io/cluster: my-cluster    strimzi.io/kind: Kafka    strimzi.io/name: my-cluster-kafka  type: NodePort
  • 部署 kafka-exporter-service
    • 后面部署完kafka之后,咱们的配置中是开启了exporter的。然而官网开启完exporter之后,并没有主动生成一个相干的service,为了让Prometheus连贯更加不便,咱们部署了一个service
    • 在文件夹中kafka-exporter-service.yaml 文件中
apiVersion: v1kind: Servicemetadata:  labels:    app: kafka-export-service  name: my-cluster-kafka-exporter-servicespec:  ports:    - port: 9404      protocol: TCP      targetPort: 9404  selector:    strimzi.io/cluster: my-cluster    strimzi.io/kind: Kafka    strimzi.io/name: my-cluster-kafka-exporter  type: ClusterIP
    • 执行kubectl apply -f kafka-exporter-service.yaml即可部署实现
  • 部署 kafka-prometheus
    • 如果将Prometheus部署在k8s集群外,数据采集会比拟麻烦,所以咱们间接将Prometheus部署到集群内
    • 在文件夹中kafka-prometheus.yaml文件中,能够选择性的批改其中prometheus的配置,比方须要的内存CPU的大小,比方监控数据保留工夫,外挂的云盘大小,以及须要监听的kafka与zk地址
apiVersion: apps/v1kind: StatefulSetmetadata:  name: kafka-prometheus  labels:    app: kafka-prometheusspec:  replicas: 1  revisionHistoryLimit: 10  selector:    matchLabels:      app: kafka-prometheus  serviceName: kafka-prometheus  updateStrategy:    type: RollingUpdate  template:    metadata:      labels:        app: kafka-prometheus    spec:      containers:        - args:            - '--query.max-concurrency=800'            - '--query.max-samples=800000000'            ***          command:            - /bin/prometheus          image: 'repository.poizon.com/prometheus/prometheus:v2.28.1'          imagePullPolicy: IfNotPresent          livenessProbe:            failureThreshold: 10            httpGet:              path: /status              port: web              scheme: HTTP            initialDelaySeconds: 300            periodSeconds: 5            successThreshold: 1            timeoutSeconds: 3          name: kafka-prometheus          resources:            limits:              cpu: 500m              memory: 512Mi            requests:              cpu: 200m              memory: 128Mi          volumeMounts:            - mountPath: /etc/localtime              name: volume-localtime            - mountPath: /data/prometheus/              name: kafka-prometheus-config            - mountPath: /data/database/prometheus              name: kafka-prometheus-db          terminationMessagePath: /dev/termination-log          terminationMessagePolicy: File      terminationGracePeriodSeconds: 30      restartPolicy: Always      schedulerName: default-scheduler      securityContext:        fsGroup: 0      volumes:        - hostPath:            path: /etc/localtime            type: ''          name: volume-localtime        - configMap:            defaultMode: 420            name: kafka-prometheus-config          name: kafka-prometheus-config  volumeClaimTemplates:    - apiVersion: v1      kind: PersistentVolumeClaim      metadata:        name: kafka-prometheus-db      spec:        accessModes:          - ReadWriteOnce        resources:          requests:            storage: 20Gi        storageClassName: rocketmq-storage        volumeMode: Filesystem      status:        phase: Pending
    • 执行kubectl apply -f kafka-prometheus.yaml即可部署实现
    • 部署实现后将prometheus裸露给监控组的grafana,能够直连pod IP做验证,而后在k8s管控台的 网络-->路由-->创立, 创立一个ingress,抉择刚刚部署的这个Prometheus的service,而后找运维申请域名,即可。

总结

  • 长处
    • 疾速部署集群(分钟级),疾速集群扩容(秒级),疾速劫难复原(秒级)
    • 反对滚动更新,反对备份以及还原
  • 毛病
    • 引入较多组件,复杂度升高
    • 对K8S集群外的拜访不太敌对

文/ZUOQI

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