使用 Spotahome 將 Redis 部署至 GKE


Redis 是開放原始碼的記憶體內建 NoSQL 資料庫,主要用於快取。內建複寫、Lua 指令碼、LRU 逐出、交易、磁碟上持續性及高可用性。

本指南適用於有興趣在 Google Kubernetes Engine (GKE) 上部署 Redis 叢集的平台管理員、雲端架構師和營運專員。

本指南說明如何使用 Spotahome Redis 運算子部署 Redis 叢集。

運算子已取得 Apache 授權 2.0 版授權

Spotahome 提供以下優點:

  • Kubernetes 原生 Redis 叢集管理
  • Redis Sentinel 提供高可用性
  • 完美整合 Prometheus,方便您監控資料庫
  • 支援設定自訂 Redis 設定

目標

  • 規劃及部署 Redis 適用的 GKE 基礎架構
  • 部署及設定 Spotahome Redis 運算子
  • 使用運算子設定 Redis,確保可用性、安全性、可觀測性和效能

部署架構

在本教學課程中,您將使用 Spotahome Redis 運算子,在 GKE 中部署及設定高可用性 Redis 叢集,其中包含一個領導者節點和兩個讀取副本,以及由三個副本組成的 Redis Sentinel 叢集。

Redis Sentinel 是開放原始碼 Redis 的高可用性和監控系統。持續監控 Redis 執行個體,包括領導者和相關聯的副本。如果領導者節點發生故障,Sentinel 可以自動將其中一個副本升級為新的領導者,確保始終有可用的領導者節點,供資料讀取和寫入。當 Redis 叢集發生重大事件 (例如領導者故障或容錯移轉事件) 時,Sentinel 可以透過電子郵件或其他通知機制,通知管理員或其他系統。

您也會為 Redis 部署高可用性地區 GKE 叢集,並在多個可用區中分散多個 Kubernetes 節點。這項設定有助於確保容錯能力、擴充性和地理位置備援。這項功能可讓您進行輪流更新和維護作業,同時提供運作時間和可用性的服務水準協議。詳情請參閱區域叢集

下圖顯示 Redis 叢集如何在 GKE 叢集的多個節點和區域中執行:

在圖表中,Redis StatefulSet 部署在三個不同區域的三個節點上。您可以在 RedisFailover 自訂資源規格中設定 Pod affinity拓撲散布規則,控管 GKE 將 StatefulSet 部署至節點和區域的方式。

如果一個區域失效,使用建議的設定時,GKE 會在新節點上重新排定 Pod。

下圖顯示在三個不同區域的三個節點中排定的 Sentinel 部署作業:

費用

在本文件中,您會使用 Google Cloud的下列計費元件:

如要根據預測用量估算費用,請使用 Pricing Calculator

初次使用 Google Cloud 的使用者可能符合免費試用資格。

完成本文所述工作後,您可以刪除已建立的資源,避免繼續計費。詳情請參閱清除所用資源一節。

事前準備

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. Install the Google Cloud CLI.

  3. If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.

  4. To initialize the gcloud CLI, run the following command:

    gcloud init
  5. Create or select a Google Cloud project.

    • Create a Google Cloud project:

      gcloud projects create PROJECT_ID

      Replace PROJECT_ID with a name for the Google Cloud project you are creating.

    • Select the Google Cloud project that you created:

      gcloud config set project PROJECT_ID

      Replace PROJECT_ID with your Google Cloud project name.

  6. Make sure that billing is enabled for your Google Cloud project.

  7. Enable the Compute Engine, IAM, GKE, Backup for GKE, and Resource Manager APIs:

    gcloud services enable compute.googleapis.com iam.googleapis.com container.googleapis.com gkebackup.googleapis.com cloudresourcemanager.googleapis.com
  8. Install the Google Cloud CLI.

  9. If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.

  10. To initialize the gcloud CLI, run the following command:

    gcloud init
  11. Create or select a Google Cloud project.

    • Create a Google Cloud project:

      gcloud projects create PROJECT_ID

      Replace PROJECT_ID with a name for the Google Cloud project you are creating.

    • Select the Google Cloud project that you created:

      gcloud config set project PROJECT_ID

      Replace PROJECT_ID with your Google Cloud project name.

  12. Make sure that billing is enabled for your Google Cloud project.

  13. Enable the Compute Engine, IAM, GKE, Backup for GKE, and Resource Manager APIs:

    gcloud services enable compute.googleapis.com iam.googleapis.com container.googleapis.com gkebackup.googleapis.com cloudresourcemanager.googleapis.com
  14. Grant roles to your user account. Run the following command once for each of the following IAM roles: roles/storage.objectViewer, roles/container.admin, roles/iam.serviceAccountAdmin, roles/compute.admin, roles/gkebackup.admin, roles/monitoring.viewer

    gcloud projects add-iam-policy-binding PROJECT_ID --member="user:USER_IDENTIFIER" --role=ROLE
    • Replace PROJECT_ID with your project ID.
    • Replace USER_IDENTIFIER with the identifier for your user account. For example, user:myemail@example.com.

    • Replace ROLE with each individual role.

設定環境

在本教學課程中,您將使用 Cloud Shell 管理託管於Google Cloud的資源。Cloud Shell 已預先安裝本教學課程所需的軟體,包括 kubectlgcloud CLIHelmTerraform

如要使用 Cloud Shell 設定環境,請按照下列步驟操作:

  1. 在 Google Cloud 控制台中,按一下Cloud Shell 啟用圖示Google Cloud 控制台中的「啟用 Cloud Shell」,即可啟動 Cloud Shell 工作階段。系統會在 Google Cloud 控制台的底部窗格啟動工作階段。

  2. 設定環境變數:

    export PROJECT_ID=PROJECT_ID
    export KUBERNETES_CLUSTER_PREFIX=redis
    export REGION=us-central1
    

    PROJECT_ID 替換為 Google Cloud專案 ID

  3. 複製 GitHub 存放區:

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
    
  4. 變更為工作目錄:

    cd kubernetes-engine-samples/databases/redis-spotahome
    

建立叢集基礎架構

在本節中,您將執行 Terraform 指令碼,建立高可用性的地區 GKE 私人叢集。按照下列步驟操作,即可公開存取控制層。

您可以使用標準或 Autopilot叢集安裝運算子。

標準

下圖顯示部署在三個不同可用區的私有區域標準 GKE 叢集:

如要部署這項基礎架構,請在 Cloud Shell 中執行下列指令:

export GOOGLE_OAUTH_ACCESS_TOKEN=$(gcloud auth print-access-token)
terraform -chdir=terraform/gke-standard init
terraform -chdir=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 叢集
  • 兩個啟用自動調度資源功能的節點集區 (每個可用區一到兩個節點,每個可用區至少一個節點)
  • 具備記錄與監控權限的 ServiceAccount
  • 使用 Backup for GKE 進行災難復原
  • 使用 Google Cloud Managed Service for Prometheus 監控叢集

輸出結果會與下列內容相似:

...
Apply complete! Resources: 14 added, 0 changed, 0 destroyed.
...

Autopilot

下圖顯示私人區域 Autopilot GKE 叢集:

如要部署基礎架構,請透過 Cloud Shell 執行下列指令:

export GOOGLE_OAUTH_ACCESS_TOKEN=$(gcloud auth print-access-token)
terraform -chdir=terraform/gke-autopilot init
terraform -chdir=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.
...

連線至叢集

使用 Cloud Shell 設定 kubectl 與叢集通訊:

gcloud container clusters get-credentials ${KUBERNETES_CLUSTER_PREFIX}-cluster --region ${REGION}

將 Spotahome 運算子部署至叢集

在本節中,您將使用 Helm 資訊套件將 Spotahome 運算子部署至 Kubernetes 叢集,然後部署 Redis 叢集。

  1. 新增 Spotahome Redis 運算子 Helm 資訊套件存放區:

    helm repo add redis-operator https://spotahome.github.io/redis-operator
    
  2. 為 Spotahome 運算子和 Redis 叢集新增命名空間:

    kubectl create ns redis
    
  3. 使用 Helm 指令列工具部署 Spotahome 運算子:

    helm install redis-operator redis-operator/redis-operator --version 3.2.9 -n redis
    
  4. 使用 Helm 檢查 Spotahome 運算子的部署狀態:

    helm ls -n redis
    

    輸出結果會與下列內容相似:

    NAME             NAMESPACE    REVISION    UPDATED                                STATUS      CHART                   APP VERSION
    redis-operator    redis      1           2023-09-12 13:21:48.179503 +0200 CEST    deployed    redis-operator-3.2.9    1.2.4
    

部署 Redis

Redis 叢集執行個體的基本設定包含下列元件:

  • 三個 Redis 節點備用資源:一個領導者和兩個唯讀備用資源。
  • 三個 Sentinel 節點副本,形成仲裁。
  • 一個 CPU 要求和兩個 CPU 限制的 CPU 資源分配量,Redis 的記憶體要求和限制為 4 GB,Sentinel 的 CPU 要求和限制為 100 m/500 m,記憶體要求和限制為 500 MB。
  • 為每個工作負載設定容許條件、nodeAffinitiestopologySpreadConstraints,確保工作負載在 Kubernetes 節點之間適當分配,並利用各自的節點集區和不同可用區。

這項設定代表建立可供正式環境使用的 Redis 叢集所需的基本設定。

建立基本 Redis 叢集

  1. 使用使用者憑證建立密鑰:

    export PASSWORD=$(openssl rand -base64 12)
    kubectl create secret generic my-user -n redis \
        --from-literal=password="$PASSWORD"
    

    運算子沒有產生憑證的功能,資料庫密碼應預先產生。

  2. 使用基本設定建立新的 Redis 叢集:

    kubectl apply -n redis -f manifests/01-basic-cluster/my-cluster.yaml
    

    這項指令會建立 Spotahome 運算子的 RedisFailover 自訂資源,指定 CPU、記憶體要求和限制,以及汙染和親和性,將佈建的 Pod 副本分散到 Kubernetes 節點。

  3. 請稍候片刻,等待 Kubernetes 啟動必要的工作負載:

    kubectl wait pods -l redisfailovers.databases.spotahome.com/name=my-cluster --for condition=Ready --timeout=300s -n redis
    
  4. 確認 Redis 工作負載已建立:

    kubectl get pod,svc,statefulset,deploy,pdb -n redis
    

    輸出結果會與下列內容相似:

    NAME                                READY   STATUS  RESTARTS   AGE
    pod/redis-operator-5dc65cb7cc-krlcs   1/1   Running   0         49m
    pod/rfr-my-cluster-0                2/2     Running   0         60s
    pod/rfr-my-cluster-1                2/2     Running   0         60s
    pod/rfr-my-cluster-2                2/2     Running   0         60s
    pod/rfs-my-cluster-8475dfd96c-h5zvw   1/1   Running   0         60s
    pod/rfs-my-cluster-8475dfd96c-rmh6f   1/1   Running   0         60s
    pod/rfs-my-cluster-8475dfd96c-shzxh   1/1   Running   0         60s
    
    NAME                    TYPE        CLUSTER-IP  EXTERNAL-IP   PORT(S)   AGE
    service/redis-my-cluster ClusterIP   10.52.14.87   <none>       6389/TCP    55s
    service/redis-operator   ClusterIP   10.52.13.217   <none>      9710/TCP    49m
    service/rfr-my-cluster   ClusterIP   None           <none>      9121/TCP    61s
    service/rfs-my-cluster   ClusterIP   10.52.15.197   <none>      26379/TCP   61s
    
    NAME                            READY   AGE
    statefulset.apps/rfr-my-cluster   3/3   61s
    
    NAME                            READY   UP-TO-DATE   AVAILABLE   AGE
    deployment.apps/redis-operator   1/1    1           1           50m
    deployment.apps/rfs-my-cluster   3/3    3           3           62s
    
    NAME                                        MIN AVAILABLE   MAX UNAVAILABLE   ALLOWED DISRUPTIONS   AGE
    poddisruptionbudget.policy/rfr-my-cluster   2               N/A             1                   64s
    poddisruptionbudget.policy/rfs-my-cluster   2               N/A             1                   63s
    

運算子會建立下列資源:

  • Redis StatefulSet 和 Sentinel 部署作業
  • Redis 的三個 Pod 副本
  • Sentinel 的三個 Pod 副本
  • 兩個 PodDisruptionBudgets,確保叢集一致性至少有兩個可用的副本
  • rfr-my-cluster 服務,可公開 Redis 指標
  • redis-my-cluster Service,以 Redis 叢集領導節點為目標
  • rfs-my-cluster 服務,可讓用戶端透過 Sentinel 連線至叢集。用戶端程式庫必須支援 Sentinel。

共用 Redis 憑證

您可以使用 Spotahome 運算子舊版驗證方法,與用戶端共用 Redis 憑證

您必須使用 requirepass 設定資料庫密碼。所有用戶端都會使用這個密碼。如要管理其他使用者,請使用 Redis CLI 指令

apiVersion: databases.spotahome.com/v1
kind: RedisFailover
metadata:
  name: my-cluster
spec:
  ...
  auth:
    secretPath: my-user

使用這種方法與用戶端共用 Redis 憑證有以下限制:

  • Spotahome 不提供使用者管理用的自訂資源。您可以將憑證儲存在 Secrets 中,並在 auth 規格中參照這些憑證。
  • 使用自訂資源時,無法透過 TLS 加密保護連線安全。
  • 系統不支援即時更新憑證。

連線至 Redis

您可以部署 Redis 用戶端,並使用儲存在 Kubernetes Secret 中的密碼進行驗證。

  1. 執行用戶端 Pod,與 Redis 叢集互動:

    kubectl apply -n redis -f manifests/02-auth/client-pod.yaml
    

    PASS 環境變數會從保管箱取得 my-user 密鑰。

  2. 等待 Pod 準備就緒,然後連線:

    kubectl wait pod redis-client --for=condition=Ready --timeout=300s -n redis
    kubectl exec -it redis-client -n redis -- /bin/bash
    
  3. 確認連線是否正常運作:

    redis-cli -h redis-my-cluster -a $PASS --no-auth-warning SET my-key "testvalue"
    

    輸出結果會與下列內容相似:

    OK
    
  4. 取得 my-key 值:

    redis-cli -h redis-my-cluster -a $PASS --no-auth-warning GET my-key
    

    輸出結果會與下列內容相似:

    "testvalue"
    
  5. 退出 Pod 殼層

    exit
    

瞭解 Prometheus 如何收集 Redis 叢集的指標

下圖顯示 Prometheus 指標的收集方式:

在圖表中,GKE 私人叢集包含:

  • 在路徑 / 和通訊埠 9121 上收集指標的 Redis Pod
  • 以 Prometheus 為基礎的收集器,可處理 Redis Pod 的指標
  • 將指標傳送至 Cloud Monitoring 的 PodMonitoring 資源

Google Cloud Managed Service for Prometheus 支援以 Prometheus 格式收集指標。Cloud Monitoring 會使用 整合式資訊主頁來顯示 Redis 指標。

Spotahome 運算子會使用 redis_exporter 做為補充資訊,以 Prometheus 格式公開叢集指標。

  1. 建立 PodMonitoring 資源,透過 labelSelector 擷取指標:

    kubectl apply -n redis -f manifests/03-prometheus-metrics/pod-monitoring.yaml
    
  2. 在 Google Cloud 控制台中,前往「GKE Clusters Dashboard」(GKE 叢集資訊主頁) 頁面。

    前往 GKE 叢集資訊主頁

    資訊主頁會顯示非零指標的擷取率。

  3. 前往 Google Cloud 控制台的「資訊主頁」頁面。

    前往資訊主頁

  4. 開啟 Redis Prometheus 總覽資訊主頁。資訊主頁會顯示連線和金鑰數量。自動佈建資訊主頁可能需要幾分鐘的時間。

  5. 連線至用戶端 Pod 並準備變數:

    kubectl exec -it redis-client -n redis -- /bin/bash
    
  6. 使用 redis-cli 工具建立新金鑰:

    for i in {1..50}; do \
      redis-cli -h redis-my-cluster -a $PASS \
      --no-auth-warning SET mykey-$i "myvalue-$i"; \
    done
    
  7. 重新整理頁面,您會發現「每秒指令數」和「鍵」圖表已更新,顯示實際的資料庫狀態。

  8. 退出 Pod 殼層

    exit
    

清除所用資源

刪除專案

    Delete a Google Cloud project:

    gcloud projects delete PROJECT_ID

刪除個別資源

  1. 設定環境變數。

    export PROJECT_ID=${PROJECT_ID}
    export KUBERNETES_CLUSTER_PREFIX=redis
    export REGION=us-central1
    
  2. 執行 terraform destroy 指令:

    export GOOGLE_OAUTH_ACCESS_TOKEN=$(gcloud auth print-access-token)
    terraform -chdir=terraform/FOLDER destroy -var project_id=${PROJECT_ID} \
      -var region=${REGION} \
      -var cluster_prefix=${KUBERNETES_CLUSTER_PREFIX}
    

    FOLDER 替換為 gke-autopilotgke-standard

    系統顯示提示訊息時,請輸入 yes

  3. 找出所有未連接的磁碟:

    export disk_list=$(gcloud compute disks list --filter="-users:* AND labels.name=${KUBERNETES_CLUSTER_PREFIX}-cluster" --format "value[separator=|](name,zone)")
    
  4. 刪除磁碟:

    for i in $disk_list; do
      disk_name=$(echo $i| cut -d'|' -f1)
      disk_zone=$(echo $i| cut -d'|' -f2|sed 's|.*/||')
      echo "Deleting $disk_name"
      gcloud compute disks delete $disk_name --zone $disk_zone --quiet
    done
    

後續步驟

  • 探索 Google Cloud 的參考架構、圖表和最佳做法。 歡迎瀏覽我們的雲端架構中心