Redis 是一个开源内存中 NoSQL 数据库,主要用于缓存。它具有内置的复制功能、Lua 脚本、LRU 逐出、事务、磁盘持久性和高可用性。
本指南适用于有意在 Google Kubernetes Engine (GKE) 上部署 Redis 集群的平台管理员、云架构师和专业运营人员。
本指南介绍如何使用 Spotahome Redis 运算符部署 Redis 集群。
运算符根据 Apache License 2.0 获得授权。
Spotahome 具有以下优势:
- Kubernetes 原生 Redis 集群管理
- Redis Sentinel 提供的高可用性
- 无缝 Prometheus 集成,实现数据库可观测性
- 支持设置自定义 Redis 配置
目标
- 为 Redis 规划和部署 GKE 基础架构
- 部署和配置 Spotahome Redis 运算符
- 使用运算符配置 Redis,以确保可用性、安全性、可观测性和性能
部署架构
在本教程中,您将使用 Spotahome Redis Operator 将高可用性 Redis 集群部署和配置到一个具有主节点和两个读取副本的 GKE,以及由三个副本组成的 Redis Sentinel 集群。
Redis Sentinel 是开源 Redis 的高可用性和监控系统。它会持续监控 Redis 实例,包括主要副本及其关联的副本。如果主节点发生故障,Sentinel 可以自动将一个副本提升为新的主节点,确保始终有可用的主节点用于数据读写。当 Redis 集群中发生重大事件(例如领导者故障或故障切换事件)时,Sentinel 可以通过电子邮件或其他通知机制通知管理员或其他系统。
您还将部署 Redis 的高可用性区域级 GKE 集群,其中多个 Kubernetes 节点分布在多个可用区中。此设置有助于确保容错、可伸缩性和地理冗余。这样可支持滚动更新和维护,同时提供 SLA 以保证正常运行时间和可用性。如需了解详情,请参阅区域级集群。
下图显示了 Redis 集群如何在 GKE 集群中的多个节点和可用区上运行:
在该图中,Redis StatefulSet 部署在三个不同可用区的三个节点上。您可以通过以下方式控制 GKE 如何将 StatefulSet 部署到节点和可用区:在 RedisFailover
自定义资源规范中设置 Pod 亲和性和拓扑扩展规则。
如果一个可用区发生故障,则使用推荐的配置,GKE 会在新节点上重新调度 Pod。
下图显示了安排在三个不同可用区的三个节点上的 Sentinel Deployment:
费用
在本文档中,您将使用 Google Cloud 的以下收费组件:
您可使用价格计算器根据您的预计使用情况来估算费用。
完成本文档中描述的任务后,您可以通过删除所创建的资源来避免继续计费。如需了解详情,请参阅清理。
准备工作
- 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.
- Install the Google Cloud CLI.
-
To initialize the gcloud CLI, run the following command:
gcloud init
-
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.
-
-
Make sure that billing is enabled for your Google Cloud project.
-
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 - Install the Google Cloud CLI.
-
To initialize the gcloud CLI, run the following command:
gcloud init
-
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.
-
-
Make sure that billing is enabled for your Google Cloud project.
-
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 -
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_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.
- Replace
设置您的环境
在本教程中,您将使用 Cloud Shell 来管理 Google Cloud 上托管的资源。Cloud Shell 预安装有本教程所需的软件,包括 kubectl
、gcloud CLI、Helm 和 Terraform。
如需使用 Cloud Shell 设置您的环境,请按照以下步骤操作:
点击 Google Cloud 控制台中的 激活 Cloud Shell,从 Google Cloud 控制台启动 Cloud Shell 会话。此操作会在 Google Cloud 控制台的底部窗格中启动会话。
设置环境变量:
export PROJECT_ID=PROJECT_ID export KUBERNETES_CLUSTER_PREFIX=redis export REGION=us-central1
替换
PROJECT_ID
:您的 Google Cloud 项目 ID。克隆 GitHub 代码库:
git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
切换到工作目录:
cd kubernetes-engine-samples/databases/redis-spotahome
创建集群基础架构
在本部分中,您将运行 Terraform 脚本以创建可用性高的专用区域级 GKE 集群。通过执行以下步骤,可以公开访问控制平面。
您可以使用 Standard 或 Autopilot 集群安装操作器。
标准
下图显示了部署在三个不同可用区中的专用区域级 Standard 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 节点的 VPC 网络和专用子网
- 用于通过 NAT 访问互联网的路由器
- 专用 GKE 集群(在
us-central1
区域中) - 两个启用了自动扩缩功能的节点池(每个可用区一个到两个节点,每个可用区最少一个节点)
- 具有日志记录和监控权限的
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 节点的 VPC 网络和专用子网
- 用于通过 NAT 访问互联网的路由器
- 专用 GKE 集群(在
us-central1
区域中) - 具有日志记录和监控权限的
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 Chart 将 Spotahome 运算符部署到 Kubernetes 集群,然后部署 Redis 集群。
添加 Spotahome Redis 运算符 Helm 图表代码库:
helm repo add redis-operator https://spotahome.github.io/redis-operator
为 Spotahome 运算符和 Redis 集群添加命名空间:
kubectl create ns redis
使用 Helm 命令行工具部署 Spotahome 运算符:
helm install redis-operator redis-operator/redis-operator --version 3.2.9 -n redis
使用 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 为 100 m/500 m CPU 和 500 MB。
- 为每个工作负载配置容忍设置、
nodeAffinities
和topologySpreadConstraints
,利用它们各自的节点池和不同的可用区来确保跨 Kubernetes 节点进行适当分布。
此配置表示创建可直接用于生产环境的 Redis 集群所需的最少设置。
创建基本 Redis 集群
创建包含用户凭据的 Secret:
export PASSWORD=$(openssl rand -base64 12) kubectl create secret generic my-user -n redis \ --from-literal=password="$PASSWORD"
Operator 没有生成凭据的功能,并且应预先生成数据库密码。
使用基本配置创建新的 Redis 集群:
kubectl apply -n redis -f manifests/01-basic-cluster/my-cluster.yaml
此命令会创建一个 Spotahome 运算符的
RedisFailover
自定义资源,用于指定 CPU、内存请求和限制;以及在 Kubernetes 节点之间分发预配的 Pod 副本的污点及亲和性。请等待几分钟,让 Kubernetes 启动所需的工作负载:
kubectl wait pods -l redisfailovers.databases.spotahome.com/name=my-cluster --for condition=Ready --timeout=300s -n redis
验证是否已创建 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 Deployment
- 三个适用于 Redis 的 Pod 副本
- Sentinel 的三个 Pod 副本
- 两个
PodDisruptionBudgets
,确保至少有两个可用的副本以实现集群一致性 rfr-my-cluster
Service,用于公开 Redis 指标redis-my-cluster
Service,用于定位 Redis 集群主节点rfs-my-cluster
Service,允许客户端通过 Sentinels 连接到集群。客户端库需要 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 不为用户管理提供自定义资源。您可以将凭据存储在 Secret 中,并在
auth
规范中引用它们。 - 无法使用自定义资源通过 TLS 加密保护连接。
- 不支持实时更新凭据。
连接到 Redis
您可以部署 Redis 客户端,并使用存储在 Kubernetes Secret 中的密码进行身份验证。
运行客户端 pod 以与您的 Redis 集群进行交互:
kubectl apply -n redis -f manifests/02-auth/client-pod.yaml
PASS
环境变量从保险柜中获取my-user
Secret。等待 Pod 准备就绪,然后连接到 Pod:
kubectl wait pod redis-client --for=condition=Ready --timeout=300s -n redis kubectl exec -it redis-client -n redis -- /bin/bash
验证连接是否有效:
redis-cli -h redis-my-cluster -a $PASS --no-auth-warning SET my-key "testvalue"
输出类似于以下内容:
OK
获取
my-key
值:redis-cli -h redis-my-cluster -a $PASS --no-auth-warning GET my-key
输出类似于以下内容:
"testvalue"
退出 Pod shell
exit
了解 Prometheus 如何收集 Redis 集群的指标
下图展示了 Prometheus 指标收集的工作原理:
在该图中,GKE 专用集群包含:
- Redis Pod,用于收集路径
/
和端口9121
的指标 - 基于 Prometheus 的收集器,用于处理 Redis Pod 中的指标
- 将指标发送到 Cloud Monitoring 的 PodMonitoring 资源
Google Cloud Managed Service for Prometheus 支持 Prometheus 格式的指标收集。Cloud Monitoring 使用集成式信息中心来处理 Redis 指标。
Spotahome 运算符使用 redis_exporter 作为 Sidecar 公开采用 Prometheus 格式的集群指标。
创建 PodMonitoring 资源,以按 labelSelector 抓取指标:
kubectl apply -n redis -f manifests/03-prometheus-metrics/pod-monitoring.yaml
在 Google Cloud 控制台中,转到 GKE 集群信息中心页面。
信息中心显示非零指标提取率。
在 Google Cloud 控制台中,转到信息中心页面。
打开 Redis Prometheus 概览信息中心。信息中心会显示连接数和密钥数。信息中心可能需要几分钟时间才能完成自动预配。
连接到客户端 Pod 并准备变量:
kubectl exec -it redis-client -n redis -- /bin/bash
使用
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
刷新页面,您会观察到每秒命令数和键图已更新为显示实际数据库状态。
退出 Pod shell
exit
清理
删除项目
Delete a Google Cloud project:
gcloud projects delete PROJECT_ID
删除各个资源
设置环境变量。
export PROJECT_ID=${PROJECT_ID} export KUBERNETES_CLUSTER_PREFIX=redis export REGION=us-central1
运行
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-autopilot
或gke-standard
。出现提示时,请输入
yes
。查找所有未挂接的磁盘:
export disk_list=$(gcloud compute disks list --filter="-users:* AND labels.name=${KUBERNETES_CLUSTER_PREFIX}-cluster" --format "value[separator=|](name,zone)")
删除磁盘:
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 的参考架构、图表和最佳做法。查看我们的 Cloud 架构中心。