本指南說明如何使用 Strimzi 運算子部署 Apache Kafka 叢集。
Kafka 是開放原始碼的分散式訊息傳遞系統,專為處理大量、高輸送量和即時串流資料而設計。您可以使用這項服務建構串流資料管道,在不同系統和應用程式之間可靠地傳輸資料,以支援處理和分析工作。
運算子是軟體擴充功能,可運用自訂資源管理應用程式及其元件。如要進一步瞭解使用運算子的動機,請參閱開放原始碼 Kubernetes 說明文件中的運算子模式。Strimzi 運算子提供彈性的部署選項,並可讓您使用 Kubernetes 汙點和容許度,在專用節點上執行 Kafka。
本指南適用於有興趣在 GKE 上部署 Kafka 叢集的平台管理員、雲端架構師和營運專員。
如果您想瞭解如何使用第三方運算子部署 Kafka 叢集,以自動化管理作業並減少錯誤,這項解決方案是個不錯的起點。如要更精細地控管作業,請參閱「在 GKE 上部署高可用性 Kafka 叢集」。
準備環境
在本教學課程中,您將使用 Cloud Shell 管理託管在 Google Cloud上的資源。Cloud Shell 已預先安裝本教學課程所需的軟體,包括 kubectl
、gcloud CLI、Helm 和 Terraform。
如要使用 Cloud Shell 設定環境,請按照下列步驟操作:
在 Google Cloud 控制台中,按一下
Google Cloud 控制台中的「啟用 Cloud Shell」,即可啟動 Cloud Shell 工作階段。系統會在 Google Cloud 控制台的底部窗格啟動工作階段。
設定環境變數:
export PROJECT_ID=PROJECT_ID export KUBERNETES_CLUSTER_PREFIX=kafka export REGION=us-central1
將
PROJECT_ID
: your Google Cloud 替換為您的專案 ID。複製 GitHub 存放區:
git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
變更為工作目錄:
cd kubernetes-engine-samples/streaming/
建立叢集基礎架構
在本節中,您將執行 Terraform 指令碼,建立高可用性的地區 GKE 私人叢集。請按照下列步驟公開存取控制層。如要限制存取權,請建立私人叢集。
您可以使用標準或 Autopilot叢集安裝運算子。
標準
下圖顯示部署在三個不同可用區的私有區域標準 GKE 叢集:
如要部署這項基礎架構,請在 Cloud Shell 中執行下列指令:
export GOOGLE_OAUTH_ACCESS_TOKEN=$(gcloud auth print-access-token)
terraform -chdir=kafka/terraform/gke-standard init
terraform -chdir=kafka/terraform/gke-standard apply -var project_id=${PROJECT_ID} \
-var region=${REGION} \
-var cluster_prefix=${KUBERNETES_CLUSTER_PREFIX}
系統顯示提示訊息時,請輸入 yes
。這個指令可能需要幾分鐘才能完成,且叢集會顯示就緒狀態。
Terraform 會建立下列資源:
- Kubernetes 節點的虛擬私有雲網路和私有子網路。
- 透過 NAT 存取網際網路的路由器。
us-central1
地區的私人 GKE 叢集。- 2 個啟用自動調度資源功能的節點集區 (每個可用區 1 到 2 個節點,每個可用區至少 1 個節點)
- 具備記錄與監控權限的
ServiceAccount
。 - Backup for GKE,用於災難復原。
- Google Cloud Managed Service for Prometheus,用於監控叢集。
輸出結果會與下列內容相似:
...
Apply complete! Resources: 14 added, 0 changed, 0 destroyed.
Outputs:
kubectl_connection_command = "gcloud container clusters get-credentials strimzi-cluster --region us-central1"
Autopilot
下圖顯示私人區域 Autopilot GKE 叢集:
如要部署基礎架構,請透過 Cloud Shell 執行下列指令:
export GOOGLE_OAUTH_ACCESS_TOKEN=$(gcloud auth print-access-token)
terraform -chdir=kafka/terraform/gke-autopilot init
terraform -chdir=kafka/terraform/gke-autopilot apply -var project_id=${PROJECT_ID} \
-var region=${REGION} \
-var cluster_prefix=${KUBERNETES_CLUSTER_PREFIX}
系統顯示提示訊息時,請輸入 yes
。這個指令可能需要幾分鐘才能完成,且叢集會顯示就緒狀態。
Terraform 會建立下列資源:
- Kubernetes 節點的虛擬私有雲網路和私人子網路。
- 透過 NAT 存取網際網路的路由器。
us-central1
地區的私人 GKE 叢集。- 具備記錄與監控權限的
ServiceAccount
- Google Cloud Managed Service for Prometheus,用於監控叢集。
輸出結果會與下列內容相似:
...
Apply complete! Resources: 12 added, 0 changed, 0 destroyed.
Outputs:
kubectl_connection_command = "gcloud container clusters get-credentials strimzi-cluster --region us-central1"
連線至叢集
設定 kubectl
與叢集通訊:
gcloud container clusters get-credentials ${KUBERNETES_CLUSTER_PREFIX}-cluster --region ${REGION}
將 Strimzi 運算子部署至叢集
在本節中,您將使用 Helm chart 部署 Strimzi 運算子。此外,您也可以透過其他幾種方式部署 Strimzi。
新增 Strimzi Helm 資訊套件存放區:
helm repo add strimzi https://strimzi.io/charts/
為 Strimzi Operator 和 Kafka 叢集新增命名空間:
kubectl create ns kafka
使用 Helm 部署 Strimzi 叢集運算子:
helm install strimzi-operator strimzi/strimzi-kafka-operator -n kafka
如要將 Strimzi Cluster Operator 和 Kafka 叢集部署至不同的命名空間,請在 helm 指令中新增
--set watchNamespaces="{kafka-namespace,kafka-namespace-2,...}"
參數。確認 Strimzi Cluster Operator 是否已使用 Helm 成功部署:
helm ls -n kafka
輸出結果會與下列內容相似:
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION strimzi-operator kafka 1 2023-06-27 11:22:15.850545 +0200 CEST deployed strimzi-kafka-operator-0.35.0 0.35.0
部署 Kafka
將運算子部署至叢集後,即可部署 Kafka 叢集執行個體。
在本節中,您將以基本設定部署 Kafka,然後嘗試各種進階設定情境,以滿足可用性、安全性及可觀測性需求。
基本設定
Kafka 執行個體的基本設定包含下列元件:
- Kafka 代理程式的三項備用資源,至少須有兩項備用資源,才能確保叢集一致性。
- 三個 ZooKeeper 節點副本,組成一個叢集。
- 兩個 Kafka 監聽器:一個不需驗證,另一個使用 TLS 驗證,並搭配 Strimzi 產生的憑證。
- Java MaxHeapSize 和 MinHeapSize 設為 Kafka 4 GB,ZooKeeper 2 GB。
- Kafka 和 ZooKeeper 的 CPU 資源分配均為 1 個 CPU 要求和 2 個 CPU 限制,Kafka 的記憶體要求和限制為 5 GB (主要服務為 4 GB,指標匯出工具為 0.5 GB),ZooKeeper 的記憶體要求和限制為 2.5 GB (主要服務為 2 GB,指標匯出工具為 0.5 GB)。
- 實體運算子,具有下列要求和限制:
tlsSidecar
:100 m/500 m CPU 和 128 Mi 記憶體。topicOperator
:100 m/500 m CPU 和 512 Mi 記憶體。userOperator
:500 m CPU 和 2 Gi 記憶體。
- 使用
premium-rwo
storageClass
為每個 Pod 分配 100 GB 的儲存空間。 - 為每個工作負載設定容許條件、nodeAffinity 和 podAntiAffinity,確保工作負載在節點之間適當分配,並利用各自的節點集區和不同區域。
- 透過自行簽署的憑證保護叢集內的通訊:叢集和用戶端 (mTLS) 各自有不同的憑證授權單位 (CA)。您也可以設定使用其他憑證授權單位。
這項設定代表建立可供正式環境使用的 Kafka 叢集所需的基本設定。下列各節將示範自訂設定,以解決叢集安全、存取控制清單 (ACL)、主題管理、憑證管理等問題。
建立基本 Kafka 叢集
使用基本設定建立新的 Kafka 叢集:
kubectl apply -n kafka -f kafka-strimzi/manifests/01-basic-cluster/my-cluster.yaml
這項指令會建立 Strimzi 運算子的 Kafka 自訂資源,其中包含 CPU 和記憶體要求與限制、區塊儲存空間要求,以及汙點和親和性的組合,可將佈建的 Pod 分散到 Kubernetes 節點。
請稍候片刻,等待 Kubernetes 啟動必要的工作負載:
kubectl wait kafka/my-cluster --for=condition=Ready --timeout=600s -n kafka
確認 Kafka 工作負載已建立:
kubectl get pod,service,deploy,pdb -l=strimzi.io/cluster=my-cluster -n kafka
輸出結果會與下列內容相似:
NAME READY STATUS RESTARTS AGE pod/my-cluster-entity-operator-848698874f-j5m7f 3/3 Running 0 44m pod/my-cluster-kafka-0 1/1 Running 0 5m pod/my-cluster-kafka-1 1/1 Running 0 5m pod/my-cluster-kafka-2 1/1 Running 0 5m pod/my-cluster-zookeeper-0 1/1 Running 0 6m pod/my-cluster-zookeeper-1 1/1 Running 0 6m pod/my-cluster-zookeeper-2 1/1 Running 0 6m NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/my-cluster-kafka-bootstrap ClusterIP 10.52.8.80 <none> 9091/TCP,9092/TCP,9093/TCP 5m service/my-cluster-kafka-brokers ClusterIP None <none> 9090/TCP,9091/TCP,9092/TCP,9093/TCP 5m service/my-cluster-zookeeper-client ClusterIP 10.52.11.144 <none> 2181/TCP 6m service/my-cluster-zookeeper-nodes ClusterIP None <none> 2181/TCP,2888/TCP,3888/TCP 6m NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/my-cluster-entity-operator 1/1 1 1 44m NAME MIN AVAILABLE MAX UNAVAILABLE ALLOWED DISRUPTIONS AGE poddisruptionbudget.policy/my-cluster-kafka 2 N/A 1 5m poddisruptionbudget.policy/my-cluster-zookeeper 2 N/A 1 6m
運算子會建立下列資源:
- 兩個
StrimziPodSets
,分別適用於 Kafka 和 ZooKeeper。 - Kafka 代理程式副本的三個 Pod。
- 三個 ZooKeeper 副本的 Pod。
- 兩個
PodDisruptionBudgets
,確保叢集一致性至少有兩個副本可用。 - 名為
my-cluster-kafka-bootstrap
的 Service,可做為從 Kubernetes 叢集內連線的 Kafka 用戶端啟動伺服器。這項服務提供所有內部 Kafka 監聽器。 - 名為
my-cluster-kafka-brokers
的無介面 Service,可直接解析 Kafka 代理程式 Pod 的 IP 位址。這項服務用於代理程式間的通訊。 - 名為
my-cluster-zookeeper-client
的服務,可讓 Kafka 代理程式以用戶端身分連線至 ZooKeeper 節點。 - 名為
my-cluster-zookeeper-nodes
的無介面 Service,可直接解析 ZooKeeper Pod IP 位址的 DNS。這項服務用於連線至 ZooKeeper 副本。 - 名為
my-cluster-entity-operator
的 Deployment,內含 topic-operator 和 user-operator,可協助管理自訂資源KafkaTopics
和KafkaUsers
。
您也可以設定兩個 NetworkPolicies
,方便從任何 Pod 和 Namespace 連線至 Kafka 監聽器。這些政策也會將連線限制為代理程式,並啟用叢集 Pod 與叢集專屬內部服務連接埠之間的通訊。
驗證和使用者管理
本節說明如何啟用驗證和授權,確保 Kafka 監聽器安全無虞,並與用戶端共用憑證。
Strimzi 提供 Kubernetes 原生方法,可使用獨立的User Operator
和對應的 Kubernetes 自訂資源 KafkaUser
定義使用者設定,藉此管理使用者。使用者設定包括驗證和授權設定,並在 Kafka 中佈建對應的使用者。
Strimzi 可以建立支援多種驗證機制的 Kafka 監聽器和使用者,例如以使用者名稱和密碼為基礎的驗證 (SCRAM-SHA-512) 或 TLS。您也可以使用 OAuth 2.0 驗證,相較於使用密碼或憑證進行驗證,這通常是較好的做法,因為 OAuth 2.0 驗證具有安全性,且可管理外部憑證。
部署 Kafka 叢集
本節說明如何部署 Strimzi 運算子,示範使用者管理功能,包括:
- Kafka 叢集,其中一個接聽程式已啟用密碼驗證 (SCRAM-SHA-512)。
- 包含 3 個副本的
KafkaTopic
。 - 具有 ACL 的
KafkaUser
,指定使用者對主題擁有讀取和寫入權限。
將 Kafka 叢集設定為在通訊埠 9094 上使用具備密碼型 SCRAM-SHA-512 驗證的接聽程式,以及簡單授權:
kubectl apply -n kafka -f kafka-strimzi/manifests/03-auth/my-cluster.yaml
建立
Topic
、User
和用戶端 Pod,對 Kafka 叢集執行指令:kubectl apply -n kafka -f kafka-strimzi/manifests/03-auth/topic.yaml kubectl apply -n kafka -f kafka-strimzi/manifests/03-auth/my-user.yaml
Secret
my-user
會以磁碟區的形式,掛接到用戶端 Pod。這些憑證會確認使用者有權透過啟用密碼驗證 (SCRAM-SHA-512) 的接聽程式,將訊息發布至主題。
建立用戶端 Pod:
kubectl apply -n kafka -f kafka-strimzi/manifests/03-auth/kafkacat.yaml
請稍待幾分鐘,等待用戶端 Pod 變成
Ready
,然後連線至該 Pod:kubectl wait --for=condition=Ready pod --all -n kafka --timeout=600s kubectl exec -it kafkacat -n kafka -- /bin/sh
使用
my-user
憑證產生新訊息,然後嘗試取用:echo "Message from my-user" |kcat \ -b my-cluster-kafka-bootstrap.kafka.svc.cluster.local:9094 \ -X security.protocol=SASL_SSL \ -X sasl.mechanisms=SCRAM-SHA-512 \ -X sasl.username=my-user \ -X sasl.password=$(cat /my-user/password) \ -t my-topic -P kcat -b my-cluster-kafka-bootstrap.kafka.svc.cluster.local:9094 \ -X security.protocol=SASL_SSL \ -X sasl.mechanisms=SCRAM-SHA-512 \ -X sasl.username=my-user \ -X sasl.password=$(cat /my-user/password) \ -t my-topic -C
輸出結果會與下列內容相似:
Message from my-user % Reached end of topic my-topic [0] at offset 0 % Reached end of topic my-topic [2] at offset 1 % Reached end of topic my-topic [1] at offset 0
輸入
CTRL+C
即可停止消費者程序。退出 Pod 殼層
exit
備份與災難復原
雖然 Strimzi 運算子未提供內建備份功能,但您可以按照特定模式實作有效的備份策略。
您可以使用 GKE 備份服務備份下列項目:
- Kubernetes 資源資訊清單。
- 從備份叢集的 Kubernetes API 伺服器擷取的 Strimzi API 自訂資源及其定義。
- 與資訊清單中找到的 PersistentVolumeClaim 資源對應的磁碟區。
如要進一步瞭解如何使用 GKE 備份功能備份及還原 Kafka 叢集,請參閱「準備進行災難復原」。
您也可以備份使用 Strimzi 運算子部署的 Kafka 叢集。建議備份的項目:
- Kafka 設定,包括 Strimzi API 的所有自訂資源,例如
KafkaTopics
和KafkaUsers
。 - 資料儲存在 Kafka 代理程式的 PersistentVolume 中。
在 Git 存放區中儲存 Kubernetes 資源資訊清單 (包括 Strimzi 設定),可免除 Kafka 設定的個別備份需求,因為必要時,資源可以重新套用至新的 Kubernetes 叢集。
為確保在 Kafka 伺服器執行個體或部署 Kafka 的 Kubernetes 叢集遺失時,Kafka 資料能夠復原,建議您將用於為 Kafka 代理人佈建磁碟區的 Kubernetes 儲存空間類別,設定為 reclaimPolicy
選項設為 Retain
。我們也建議您為 Kafka 代理程式磁碟區建立快照。
下列資訊清單說明使用 reclaimPolicy
選項 Retain
的 StorageClass:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: premium-rwo-retain
...
reclaimPolicy: Retain
volumeBindingMode: WaitForFirstConsumer
以下範例顯示新增至 Kafka 叢集自訂資源 spec
的 StorageClass:
# ...
spec:
kafka:
# ...
storage:
type: persistent-claim
size: 100Gi
class: premium-rwo-retain
完成這項設定後,即使刪除對應的 PersistentVolumeClaim,系統也不會刪除使用儲存空間類別佈建的 PersistentVolume。
如要使用現有設定和代理程式執行個體資料,在新 Kubernetes 叢集上復原 Kafka 執行個體,請按照下列步驟操作:
- 將現有的 Strimzi Kafka 自訂資源 (
Kakfa
、KafkaTopic
、KafkaUser
等) 套用至新的 Kubernetes 叢集 - 使用 PersistentVolumeClaim 的
spec.volumeName
屬性,以舊的 PersistentVolumes 更新 PersistentVolumeClaims,並使用新的 Kafka 代理程式執行個體名稱。