共计 6099 个字符,预计需要花费 16 分钟才能阅读完成。
背景
随着业务规模的倒退,须要的 kafka 集群越来越来,这给部署与治理带来了很大的挑战。咱们冀望可能利用 K8S 优良的扩容能力与疾速部署能力,为日常的工作减负。所以就 kafka 上 K8S 的可行性计划进行了调研。
像 kafka 集群这种,波及到的组件比拟多,且都是有状态的集群,业界采纳自定义 operator 的解决方案。目前 GitHub 上有多个相干的仓库,依据社区活跃度及应用数等综合思考,此次采纳 Strimzi Github 地址。
kafka 组件交互图
计划
- 应用阿里云 K8S 集群部署 Strimzi
- 因为组内应用的 kafka 是由开源版本二次开发而来,所以须要保护一个自定义的 Strimzi-kafka 镜像
- Strimzi 治理 kafka 集群,其中蕴含 kafka、zk、kafka-exporter、
- 应用 zoo-entrance 代理集群中的 zk GitHub 地址
- 部署 prometheus,采集 kafka 和 zk 的 metrics
- 开启服务端口,裸露 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.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: v1
kind: Service
metadata:
labels:
strimzi.io/cluster: my-cluster
strimzi.io/name: my-cluster-kafka-jmx
name: my-cluster-kafka-jmx-0
spec:
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: v1
kind: Service
metadata:
labels:
app: kafka-export-service
name: my-cluster-kafka-exporter-service
spec:
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/v1
kind: StatefulSet
metadata:
name: kafka-prometheus
labels:
app: kafka-prometheus
spec:
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
关注得物技术,做最潮技术人!
正文完