本文件將詳細闡述如何利用 Helm 這一強大的工具,快速而高效地在 K8s 叢集上安裝並配置一個 Kafka 叢集。
實戰伺服器配置(架構 1:1 復刻小規模生產環境,配置略有不同)
主機名 | IP | CPU | 記憶體 | 系統盤 | 資料盤 | 用途 |
---|---|---|---|---|---|---|
ksp-registry | 192.168.9.90 | 4 | 8 | 40 | 200 | Harbor 映象倉庫 |
ksp-control-1 | 192.168.9.91 | 4 | 8 | 40 | 100 | KubeSphere/k8s-control-plane |
ksp-control-2 | 192.168.9.92 | 4 | 8 | 40 | 100 | KubeSphere/k8s-control-plane |
ksp-control-3 | 192.168.9.93 | 4 | 8 | 40 | 100 | KubeSphere/k8s-control-plane |
ksp-worker-1 | 192.168.9.94 | 8 | 16 | 40 | 100 | k8s-worker/CI |
ksp-worker-2 | 192.168.9.95 | 8 | 16 | 40 | 100 | k8s-worker |
ksp-worker-3 | 192.168.9.96 | 8 | 16 | 40 | 100 | k8s-worker |
ksp-storage-1 | 192.168.9.97 | 4 | 8 | 40 | 400+ | ElasticSearch/Longhorn/Ceph/NFS |
ksp-storage-2 | 192.168.9.98 | 4 | 8 | 40 | 300+ | ElasticSearch/Longhorn/Ceph |
ksp-storage-3 | 192.168.9.99 | 4 | 8 | 40 | 300+ | ElasticSearch/Longhorn/Ceph |
ksp-gpu-worker-1 | 192.168.9.101 | 4 | 16 | 40 | 100 | k8s-worker(GPU NVIDIA Tesla M40 24G) |
ksp-gpu-worker-2 | 192.168.9.102 | 4 | 16 | 40 | 100 | k8s-worker(GPU NVIDIA Tesla P100 16G) |
ksp-gateway-1 | 192.168.9.103 | 2 | 4 | 40 | 自建應用服務代理閘道器/VIP:192.168.9.100 | |
ksp-gateway-2 | 192.168.9.104 | 2 | 4 | 40 | 自建應用服務代理閘道器/VIP:192.168.9.100 | |
ksp-mid | 192.168.9.105 | 4 | 8 | 40 | 100 | 部署在 k8s 叢集之外的服務節點(Gitlab 等) |
合計 | 15 | 68 | 152 | 600 | 2100+ |
實戰環境涉及軟體版本資訊
- 作業系統:openEuler 22.03 LTS SP3 x86_64
- KubeSphere:v3.4.1
- Kubernetes:v1.28.8
- KubeKey: v3.1.1
- Bitnami Kafka Helm Charts:29.3.13
- Kafka: 3.7.1
1. 前提條件
目前在 K8s 叢集部署 Kafka 的主流方案有以下幾種:
- 手寫資源配置清單(麻煩,涉及的元件、配置多)
- Kafka Helm chart (Bitnami 出品,簡單可定製,但是需要花時間成本學習可配置引數)
經過細緻的調研、思考,本文選擇採用 Bitnami 的 Kafka Helm chart 進行部署。Bitnami 提供的 Helm chart 以其穩定性和易用性著稱,是快速部署 Kafka 到 Kubernetes 叢集的理想選擇。
編寫本文的目的是為了驗證 Kafka Helm chart 的部署可行性,並評估其在實際應用中的表現。為了確保過程的順利和提高成功機率,以下部署配置進行了適度簡化,某些配置並不符合生產環境的標準。
- 外部訪問安全協議,使用了
PLAINTEXT
,關閉了訪問認證,預設值為SASL_PLAINTEXT
。生產環境務必開啟認證。 - 外部訪問使用了 NodePort 模式
- 預設 StorageClass 使用了 NFS
- 沒有考慮資料持久化的配置
對於計劃在生產環境部署的使用者,我建議詳細參考 Bitnami 官方文件,以獲取更全面的配置指導和最佳實踐。我認為生產環境應該考慮的幾項配置如下:
- 外部訪問安全協議,選擇
PLAINTEXT
,SASL_PLAINTEXT
,SASL_SSL
和SSL
中的哪種方式加密認證方式, - 資料、日誌持久化配置
- k8s 叢集外部訪問 Kafka 的方式,NodePort 是否合適?是否需要使用 LoadBalancer、Ingress
- 內否啟用內建的監控
Metrics
- 是否利用 Helm 生成 Kubectl 可用的資源配置清單,離線部署
2. 使用 Helm 安裝 Kafka 叢集
2.1 安裝 Kafka Helm Chart
- 新增 Kafka Helm repository
helm repo add bitnami https://charts.bitnami.com/bitnami
- 更新本地 charts
helm repo update bitnami
2.2 安裝 Kafka
- 官方預設安裝命令(僅供參考,本文未用)
helm install my-release oci://registry-1.docker.io/bitnamicharts/kafka
- 按規劃設定自定義配置項,執行下面的安裝命令:
helm install opsxlab bitnami/kafka \
--namespace opsxlab --create-namespace \
--set replicaCount=3 \
--set global.imageRegistry="registry.opsxlab.cn:8443" \
--set global.defaultStorageClass="nfs-sc" \
--set externalAccess.enabled=true \
--set externalAccess.controller.service.type=NodePort \
--set externalAccess.controller.service.nodePorts[0]='31211' \
--set externalAccess.controller.service.nodePorts[1]='31212' \
--set externalAccess.controller.service.nodePorts[2]='31213' \
--set externalAccess.controller.service.useHostIPs=true \
--set listeners.client.protocol=PLAINTEXT \
--set listeners.external.protocol=PLAINTEXT
自定義配置說明:
- 指定並自動建立名稱空間 opsxlab
- 設定元件的映象地址,本文為了演示修改方法,使用了內部的映象倉庫,實際使用中請修改為自己的映象倉庫地址
- 設定預設的持久化儲存類為
nfs-sc
,適用於 K8s 有多種儲存類,需要部署到指定儲存類的場景 - 開啟外部訪問,並設定相關引數
- 加密認證方式選擇了 PLAINTEXT
正確執行後,輸出結果如下 :
$ helm install opsxlab bitnami/kafka \
--set externalAccess.controller.service.nodePorts[1]='31212' \
> --namespace opsxlab --create-namespace \
> --set replicaCount=3 \
> --set global.imageRegistry="registry.opsxlab.cn:8443" \
> --set global.defaultStorageClass="nfs-sc" \
> --set externalAccess.enabled=true \
> --set externalAccess.controller.service.type=NodePort \
> --set externalAccess.controller.service.nodePorts[0]='31211' \
> --set externalAccess.controller.service.nodePorts[1]='31212' \
> --set externalAccess.controller.service.nodePorts[2]='31213' \
> --set externalAccess.controller.service.useHostIPs=true \
> --set listeners.client.protocol=PLAINTEXT \
> --set listeners.external.protocol=PLAINTEXT
NAME: opsxlab
LAST DEPLOYED: Wed Jul 30 22:08:38 2024
NAMESPACE: opsxlab
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: kafka
CHART VERSION: 29.3.13
APP VERSION: 3.7.1
---------------------------------------------------------------------------------------------
WARNING
By specifying "serviceType=LoadBalancer" and not configuring the authentication
you have most likely exposed the Kafka service externally without any
authentication mechanism.
For security reasons, we strongly suggest that you switch to "ClusterIP" or
"NodePort". As alternative, you can also configure the Kafka authentication.
---------------------------------------------------------------------------------------------
** Please be patient while the chart is being deployed **
Kafka can be accessed by consumers via port 9092 on the following DNS name from within your cluster:
opsxlab-kafka.opsxlab.svc.cluster.local
Each Kafka broker can be accessed by producers via port 9092 on the following DNS name(s) from within your cluster:
opsxlab-kafka-controller-0.opsxlab-kafka-controller-headless.opsxlab.svc.cluster.local:9092
opsxlab-kafka-controller-1.opsxlab-kafka-controller-headless.opsxlab.svc.cluster.local:9092
opsxlab-kafka-controller-2.opsxlab-kafka-controller-headless.opsxlab.svc.cluster.local:9092
To create a pod that you can use as a Kafka client run the following commands:
kubectl run opsxlab-kafka-client --restart='Never' --image registry.opsxlab.cn:8443/bitnami/kafka:3.7.1-debian-12-r4 --namespace opsxlab --command -- sleep infinity
kubectl exec --tty -i opsxlab-kafka-client --namespace opsxlab -- bash
PRODUCER:
kafka-console-producer.sh \
--broker-list opsxlab-kafka-controller-0.opsxlab-kafka-controller-headless.opsxlab.svc.cluster.local:9092,opsxlab-kafka-controller-1.opsxlab-kafka-controller-headless.opsxlab.svc.cluster.local:9092,opsxlab-kafka-controller-2.opsxlab-kafka-controller-headless.opsxlab.svc.cluster.local:9092 \
--topic test
CONSUMER:
kafka-console-consumer.sh \
--bootstrap-server opsxlab-kafka.opsxlab.svc.cluster.local:9092 \
--topic test \
--from-beginning
To connect to your Kafka controller+broker nodes from outside the cluster, follow these instructions:
Kafka brokers domain: You can get the external node IP from the Kafka configuration file with the following commands (Check the EXTERNAL listener)
1. Obtain the pod name:
kubectl get pods --namespace opsxlab -l "app.kubernetes.io/name=kafka,app.kubernetes.io/instance=opsxlab,app.kubernetes.io/component=kafka"
2. Obtain pod configuration:
kubectl exec -it KAFKA_POD -- cat /opt/bitnami/kafka/config/server.properties | grep advertised.listeners
Kafka brokers port: You will have a different node port for each Kafka broker. You can get the list of configured node ports using the command below:
echo "$(kubectl get svc --namespace opsxlab -l "app.kubernetes.io/name=kafka,app.kubernetes.io/instance=opsxlab,app.kubernetes.io/component=kafka,pod" -o jsonpath='{.items[*].spec.ports[0].nodePort}' | tr ' ' '\n')"
WARNING: There are "resources" sections in the chart not set. Using "resourcesPreset" is not recommended for production. For production installations, please set the following values according to your workload needs:
- controller.resources
+info https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
2.3 檢視安裝結果
Helm 安裝命令成功執行後,觀察 Pod 執行狀態。
kubectl get pods -n opsxlab
安裝成功後,輸出結果如下 :
$ kubectl get pods -n opsxlab
NAME READY STATUS RESTARTS AGE
opsxlab-kafka-controller-0 1/1 Running 0 1m17s
opsxlab-kafka-controller-1 1/1 Running 0 1m17s
opsxlab-kafka-controller-2 1/1 Running 0 1m17s
KubeSphere 管理控制檯檢視部署的元件資訊。
- StatefulSet(1個)
- Services(5個)
3. 驗證測試 Kafka 服務可用性
分別在 K8s 叢集內和叢集外驗證 Kafka 服務的可用性。
3.1 K8s 叢集內部驗證
在 K8s 叢集內的驗證過程,可以參考 Helm 部署 Kafka 時給出的提示資訊。
- 建立測試 Pod
kubectl run opsxlab-kafka-client --restart='Never' --image registry.opsxlab.cn:8443/bitnami/kafka:3.7.1-debian-12-r4 --namespace opsxlab --command -- sleep infinity
- 開啟測試 Pod 終端
kubectl exec --tty -i opsxlab-kafka-client --namespace opsxlab -- bash
- 執行命令,生產資料
kafka-console-producer.sh \
--broker-list opsxlab-kafka-controller-0.opsxlab-kafka-controller-headless.opsxlab.svc.cluster.local:9092,opsxlab-kafka-controller-1.opsxlab-kafka-controller-headless.opsxlab.svc.cluster.local:9092,opsxlab-kafka-controller-2.opsxlab-kafka-controller-headless.opsxlab.svc.cluster.local:9092 \
--topic test
- 再開啟一個測試 Pod 終端,消費資料
再開啟一個終端後,先執行 第 2 步開啟測試 Pod 終端
的命令,然後再執行下面的命令。
kafka-console-consumer.sh \
--bootstrap-server opsxlab-kafka.opsxlab.svc.cluster.local:9092 \
--topic test \
--from-beginning
- 生產並消費資料測試
在生產者一側隨便輸入測試資料,觀察消費者一側是否正確收到資訊。
生產者側:
I have no name!@opsxlab-kafka-client:/$ kafka-console-producer.sh --broker-list opsxlab-kafka-controller-0.opsxlab-kafka-controller-headless.opsxlab.svc.cluster.local:9092,opsxlab-kafka-controller-1.opsxlab-kafka-controller-headless.opsxlab.svc.cluster.local:9092,opsxlab-kafka-controller-2.opsxlab-kafka-controller-headless.opsxlab.svc.cluster.local:9092 --topic test
>cluster kafka test 1
>cluster kafka test 2
消費者側:
I have no name!@opsxlab-kafka-client:/$ kafka-console-consumer.sh \
--bootstrap-server opsxlab-kafka.opsxlab.svc.cluster.local:9092 \
--topic test \
--from-beginning
cluster kafka test 1
cluster kafka test 2
3.2 k8s 叢集外部驗證
為了更嚴謹的測試 Kafka 在 K8s 叢集外的可用性,我在 K8s 叢集外找了一臺機器,安裝 JDK 和 Kafka。安裝方式上 JDK 選擇了 Yum 安裝 openjdk
,Kafka 則選用了官方提供的二進位制包。
實際測試時還可以選擇 Docker 映象或是在 K8s 叢集上再建立一個 Pod,測試時連線 K8s 節點的宿主機 IP 和 NodePort。
- 準備外部測試環境
# 安裝 JDK
yum install java-1.8.0-openjdk
# 下載 Kafka
cd /srv
wget https://downloads.apache.org/kafka/3.7.1/kafka_2.13-3.7.1.tgz
# 解壓
tar xvf kafka_2.13-3.7.1.tgz
cd /srv/kafka_2.13-3.7.1/bin
- 獲取 Kafka 外部訪問配置資訊
一共 3個 Kafka Pod,每個 Pod 的 advertised.listeners
配置不同,在 K8s 控制節點,分別執行下面的命令:
kubectl exec -n opsxlab -it opsxlab-kafka-controller-0 -- cat /opt/bitnami/kafka/config/server.properties | grep advertised.listeners
kubectl exec -n opsxlab -it opsxlab-kafka-controller-1 -- cat /opt/bitnami/kafka/config/server.properties | grep advertised.listeners
kubectl exec -n opsxlab -it opsxlab-kafka-controller-2 -- cat /opt/bitnami/kafka/config/server.properties | grep advertised.listeners
正確執行後,輸出結果如下 :
$ kubectl exec -n opsxlab -it opsxlab-kafka-controller-0 -- cat /opt/bitnami/kafka/config/server.properties | grep advertised.listeners
Defaulted container "kafka" out of: kafka, kafka-init (init)
advertised.listeners=CLIENT://opsxlab-kafka-controller-0.opsxlab-kafka-controller-headless.opsxlab.svc.cluster.local:9092,INTERNAL://opsxlab-kafka-controller-0.opsxlab-kafka-controller-headless.opsxlab.svc.cluster.local:9094,EXTERNAL://192.168.9.125:31211
$ kubectl exec -n opsxlab -it opsxlab-kafka-controller-1 -- cat /opt/bitnami/kafka/config/server.properties | grep advertised.listeners
Defaulted container "kafka" out of: kafka, kafka-init (init)
advertised.listeners=CLIENT://opsxlab-kafka-controller-1.opsxlab-kafka-controller-headless.opsxlab.svc.cluster.local:9092,INTERNAL://opsxlab-kafka-controller-1.opsxlab-kafka-controller-headless.opsxlab.svc.cluster.local:9094,EXTERNAL://192.168.9.124:31212
$ kubectl exec -n opsxlab -it opsxlab-kafka-controller-2 -- cat /opt/bitnami/kafka/config/server.properties | grep advertised.listeners
Defaulted container "kafka" out of: kafka, kafka-init (init)
advertised.listeners=CLIENT://opsxlab-kafka-controller-2.opsxlab-kafka-controller-headless.opsxlab.svc.cluster.local:9092,INTERNAL://opsxlab-kafka-controller-2.opsxlab-kafka-controller-headless.opsxlab.svc.cluster.local:9094,EXTERNAL://192.168.9.126:31213
- 外部節點連線 Kafka 測試
跟 K8s 叢集內部驗證測試過程一樣,開啟兩個終端,執行生產者和消費者指令碼。執行下面的命令驗證測試(細節略過,直接上結果)。
外部生產者側:
$ ./kafka-console-producer.sh --broker-list 192.168.9.125:31211 --topic test
>external kafka test 3
>external kafka test 4
外部消費者側:
$ ./kafka-console-consumer.sh --bootstrap-server 192.168.9.125:31211 --topic test --from-beginning
cluster kafka test 1
cluster kafka test 2
external kafka test 3
external kafka test 4
注意: 外部消費者能消費到所有資料,包括叢集內部測試時生成的資料。
叢集內消費者側: 叢集內的消費者,同樣能獲取外部生產者產生的資料。
I have no name!@opsxlab-kafka-client:/$ kafka-console-consumer.sh \
--bootstrap-server opsxlab-kafka.opsxlab.svc.cluster.local:9092 \
--topic test \
--from-beginning
cluster kafka test 1
cluster kafka test 2
external kafka test 3
external kafka test 4
免責宣告:
- 筆者水平有限,儘管經過多次驗證和檢查,盡力確保內容的準確性,但仍可能存在疏漏之處。敬請業界專家大佬不吝指教。
- 本文所述內容僅透過實戰環境驗證測試,讀者可學習、借鑑,但嚴禁直接用於生產環境。由此引發的任何問題,作者概不負責!
本文由部落格一文多發平臺 OpenWrite 釋出!