本指南說明如何使用 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-rwostorageClass為每個 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.yamlSecretmy-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 代理程式執行個體名稱。