使用 Redis Enterprise 将 Redis 部署到 GKE


本指南介绍如何将 Redis Enterprise 部署到 Google Kubernetes Engine (GKE) 集群。

Redis 是一个开源内存中 NoSQL 数据库,主要用于缓存。它具有内置的复制功能、Lua 脚本、LRU 逐出、事务、磁盘持久性和高可用性。

Redis Enterprise 是一种企业级解决方案,扩展了 Redis 开源并简化了管理,包括地理位置复制的数据分布、运营吞吐量的线性扩缩、数据分层、高级安全功能等。

Redis Enterprise 为每种部署选项提供不同的价格,包括:软件混合云和多云

本指南适用于有意在 Google Kubernetes Engine (GKE) 上部署 Redis Enterprise 的平台管理员、云架构师和专业运营人员。

目标

  • 为 Redis 规划和部署 GKE 基础架构
  • 部署 Redis Enterprise Operator
  • 部署 Redis Enterprise 集群
  • 创建 Redis Enterprise 数据库
  • 演示数据库身份验证

优势

Redis Enterprise 具有以下优势:

  • 一种 Kubernetes 原生方法,用于管理 Redis Enterprise 集群 (REC) 生命周期和 Redis Enterprise 数据库 (REDB)
  • 在单个 Kubernetes Pod 中共置多个 Redis 数据库,提高资源利用率
  • 通过处理日常维护任务(如修补和升级)减少运营开销
  • 支持来自私有容器注册表(例如 Artifact Registry)的 Redis 软件映像,以增强容器的安全性和可用性
  • 支持 Google Cloud Managed Service for Prometheus,以实现数据库监控和可观测性
  • 增强的安全功能,例如加密、访问权限控制以及与 Kubernetes RBAC(基于角色的访问权限控制)的集成
  • 高级身份验证方法,包括 LDAP 和第三方凭据管理器(如 Vault)
  • 能够配置预定备份

部署架构

Redis Enterprise 管理以下 Kubernetes 资源:

  • Enterprise 集群及其在 StatefulSet 中的配置。该集群由安装了 Redis 软件包的 Redis 节点 (Pod) 组成。这些节点具有运行进程,以确保节点属于集群。每个节点都提供一个容器来运行多个数据库实例(分片)。虽然 Kubernetes 最佳实践声明 Pod 应代表一个具有一个容器的应用,但 Redis Enterprise 会将多个 Redis 数据库部署到单个容器中。此方法可以提高资源利用率、性能和网络吞吐量。每个容器还具有一个零延迟代理,用于将流量路由到容器内的特定 Redis 数据库进程并进行管理。
  • RedisEnterpriseDatabase (REDB) 自定义资源,表示在 REC 中创建的 Redis 数据库实例
  • 将 REDB 实例用作数据库端点的 Kubernetes Service
  • 名为 Service Rigger 的控制器 Pod,用于在创建或删除数据库时创建和删除数据库端点

在本教程中,您将 REC 部署到专用命名空间,并为应用部署使用单独的命名空间以创建一对多部署,从而实现更好的隔离。

下图介绍了 Redis Enterprise 组件及其互连方式:

图表展示了一个 Redis Enterprise 架构示例。
图 1:Redis Enterprise 架构示例。

在本教程中,您将对 Redis Enterprise 集群进行配置,使其具备高可用性。为此,REC 需要奇数个节点以及至少三个节点。您还将设置亲和性、反亲和性规则和节点污点,以确保每个 Redis 节点都放置在不同的 Kubernetes 节点中,并且 Redis 节点均匀分布在整个 Kubernetes 集群中。

使用多个节点和可用区对于实现高可用性 GKE 集群至关重要,原因如下:

  • 容错性:多个节点在整个集群中分配工作负载,确保某个节点发生故障时,其他节点可以接管任务,从而防止产生停机时间和发生服务中断。
  • 可伸缩性:拥有多个节点可以根据需要添加或移除节点,从而实现横向扩缩,确保最佳资源分配并适应增加的流量或工作负载需求。
  • 高可用性:在区域内使用多个可用区可确保冗余,并最大限度地降低单点故障风险。如果整个可用区发生服务中断,则集群可以继续在其他可用区中运行,从而保持服务可用性。
  • 地理位置冗余:通过让节点跨越各个区域,集群的数据和服务可分布在不同地理位置,从而防范自然灾害、电力中断或可能影响单个可用区的其他本地中断。
  • 滚动更新和维护:通过使用多个节点,您可以对单个节点执行滚动更新和维护,而不会影响集群的整体可用性。这样可确保服务不中断,同时您能够执行必要的更新并无缝应用补丁。
  • 服务等级协议 (SLA):Google Cloud 为多可用区部署提供服务等级协议,保证最低级别的正常运行时间和可用性。

费用

在本文档中,您将使用 Google Cloud 的以下收费组件:

您可使用价格计算器根据您的预计使用情况来估算费用。 Google Cloud 新用户可能有资格申请免费试用

完成本文档中描述的任务后,您可以通过删除所创建的资源来避免继续计费。如需了解详情,请参阅清理

准备工作

  1. 登录您的 Google Cloud 账号。如果您是 Google Cloud 新手,请创建一个账号来评估我们的产品在实际场景中的表现。新客户还可获享 $300 赠金,用于运行、测试和部署工作负载。
  2. 安装 Google Cloud CLI。
  3. 如需初始化 gcloud CLI,请运行以下命令:

    gcloud init
  4. 创建或选择 Google Cloud 项目

    • 创建 Google Cloud 项目:

      gcloud projects create PROJECT_ID

      PROJECT_ID 替换为您要创建的 Google Cloud 项目的名称。

    • 选择您创建的 Google Cloud 项目:

      gcloud config set project PROJECT_ID

      PROJECT_ID 替换为您的 Google Cloud 项目 名称。

  5. 确保您的 Google Cloud 项目已启用结算功能

  6. Enable the Compute Engine, IAM, GKE, and Resource Manager APIs:

    gcloud services enable compute.googleapis.com iam.googleapis.com container.googleapis.com cloudresourcemanager.googleapis.com
  7. 安装 Google Cloud CLI。
  8. 如需初始化 gcloud CLI,请运行以下命令:

    gcloud init
  9. 创建或选择 Google Cloud 项目

    • 创建 Google Cloud 项目:

      gcloud projects create PROJECT_ID

      PROJECT_ID 替换为您要创建的 Google Cloud 项目的名称。

    • 选择您创建的 Google Cloud 项目:

      gcloud config set project PROJECT_ID

      PROJECT_ID 替换为您的 Google Cloud 项目 名称。

  10. 确保您的 Google Cloud 项目已启用结算功能

  11. Enable the Compute Engine, IAM, GKE, and Resource Manager APIs:

    gcloud services enable compute.googleapis.com iam.googleapis.com container.googleapis.com cloudresourcemanager.googleapis.com
  12. 向您的 Google 账号授予角色。对以下每个 IAM 角色运行以下命令一次: roles/compute.securityAdmin, roles/compute.viewer, roles/container.clusterAdmin, roles/container.admin, roles/iam.serviceAccountAdmin, roles/iam.serviceAccountUser

    gcloud projects add-iam-policy-binding PROJECT_ID --member="user:EMAIL_ADDRESS" --role=ROLE
    • PROJECT_ID 替换为您的项目 ID。
    • EMAIL_ADDRESS 替换为您的电子邮件地址。
    • ROLE 替换为每个角色。

设置您的环境

在本教程中,您将使用 Cloud Shell 来管理 Google Cloud 上托管的资源。Cloud Shell 预安装有本教程所需的软件,包括 kubectlgcloud CLITerraform

如需使用 Cloud Shell 设置您的环境,请按照以下步骤操作:

  1. 点击 Google Cloud 控制台中的 Cloud Shell 激活图标 激活 Cloud Shell,从 Google Cloud 控制台启动 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-enterprise-operator
    

创建集群基础架构

在本部分中,您将运行 Terraform 脚本以创建可用性高的专用区域级 GKE 集群和 VPC。

下图显示了部署在三个不同可用区中的专用区域级 Standard GKE 集群:

若要部署此基础架构,请从 Cloud Shell 运行以下命令:

  cd terraform/gke-standard
  export GOOGLE_OAUTH_ACCESS_TOKEN=$(gcloud auth print-access-token)
  terraform init
  terraform apply -var project_id=${PROJECT_ID}   \
    -var region=${REGION}  \
    -var cluster_prefix=${KUBERNETES_CLUSTER_PREFIX}

出现提示时,请输入 yes。完成此命令并使集群显示就绪状态可能需要几分钟时间。

Terraform 会创建以下资源:

  • Kubernetes 节点的 VPC 网络和专用子网
  • 用于通过 NAT 访问互联网的路由器
  • 专用 GKE 集群(在 us-central1 区域中)
  • 一个启用了自动扩缩功能的节点池(每个可用区一个到两个节点,每个可用区最少一个节点)

输出类似于以下内容:

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

连接到集群

使用 Cloud Shell,配置 kubectl 以与集群通信:

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

将 Redis Enterprise Operator 部署到您的集群

在本部分中,您需要将 Redis Enterprise Operator 部署到 Kubernetes 集群。

  1. 为 REC 及其应用创建命名空间:

    kubectl create namespace rec-ns
    kubectl create namespace application
    
  2. 为命名空间添加标签:

    kubectl label namespace rec-ns connection=redis
    kubectl label namespace application connection=redis
    
  3. 获取最新版本的 Redis Enterprise Operator 软件包:

    VERSION=`curl --silent https://api.github.com/repos/RedisLabs/redis-enterprise-k8s-docs/releases/latest | grep tag_name | awk -F'"' '{print $4}'`
    
  4. 安装 Redis Enterprise Operator:

    kubectl apply -n rec-ns -f https://raw.githubusercontent.com/RedisLabs/redis-enterprise-k8s-docs/$VERSION/bundle.yaml
    

    输出类似于以下内容:

    role.rbac.authorization.k8s.io/redis-enterprise-operator created
    rolebinding.rbac.authorization.k8s.io/redis-enterprise-operator created
    serviceaccount/redis-enterprise-operator created
    service/admission created
    customresourcedefinition.apiextensions.k8s.io/redisenterpriseclusters.app.redislabs.com created
    customresourcedefinition.apiextensions.k8s.io/redisenterprisedatabases.app.redislabs.com created
    customresourcedefinition.apiextensions.k8s.io/redisenterpriseremoteclusters.app.redislabs.com created
    customresourcedefinition.apiextensions.k8s.io/redisenterpriseactiveactivedatabases.app.redislabs.com created
    deployment.apps/redis-enterprise-operator created
    

部署 Redis Enterprise 集群

  1. 将清单应用到您的集群:

    kubectl apply -n rec-ns -f manifests/01-basic-cluster/rec.yaml
    

    此命令可能需要几分钟才能完成。

  2. 检查 REC 部署的状态:

    kubectl get rec -n rec-ns
    

    输出类似于以下内容:

    NAME      NODES   VERSION    STATE     SPEC STATUS   LICENSE STATE   SHARDS LIMIT   LICENSE EXPIRATION DATE   AGE
    gke-rec   3       7.2.4-52   Running   Valid         Valid           4              2023-09-29T20:15:32Z      4m7s
    

    STATERUNNING 时,表示集群已准备就绪。

可选:配置准入控制器

您可以选择性地在部署时为数据库验证配置基础设施。

  1. 设置准入控制器并检查准入 tls Secret 是否存在:

    kubectl get secret admission-tls -n rec-ns
    
  2. 获取证书:

    export CERT=$(kubectl get secret admission-tls -n rec-ns -o jsonpath='{.data.cert}')
    
  3. 将证书复制到 webhook.yaml 文件中:

    sed -i -e 's/CRT/'$CERT'/g' manifests/01-basic-cluster/webhook.yaml
    
  4. 部署验证 webhook:

    sed -i -e 's/CRT/'$CERT'/g' manifests/01-basic-cluster/webhook.yaml
    

    准入控制器会在已加标签的命名空间上验证数据库语法。

  5. 通过创建非功能性数据库来验证准入控制器:

    kubectl apply -n rec-ns -f - << EOF
    apiVersion: app.redislabs.com/v1alpha1
    kind: RedisEnterpriseDatabase
    metadata:
      name: redis-enterprise-database
    spec:
      evictionPolicy: illegal
    EOF
    

    输出类似于以下内容:

    Error from server: error when creating "STDIN": admission webhook "redisenterprise.admission.redislabs" denied the request: 'illegal' is an invalid value for 'eviction_policy'. Possible values are ['volatile-lru', 'volatile-ttl', 'volatile-random', 'allkeys-lru', 'allkeys-random', 'noeviction', 'volatile-lfu', 'allkeys-lfu']
    

创建命名空间

默认情况下,Redis Enterprise Operator 无权在其自己的命名空间之外执行操作。如需允许 Redis Enterprise Operator 在其他命名空间中创建 REDB 和数据库端点,您必须配置 RBAC。

  1. 在应用命名空间中应用相应的角色和角色绑定:

    kubectl apply -f manifests/01-basic-cluster/role.yaml -n application
    kubectl apply -f manifests/01-basic-cluster/role-binding.yaml -n application
    
  2. rec-ns 命名空间中创建集群角色和集群角色绑定:

    kubectl apply -n rec-ns -f manifests/01-basic-cluster/cluster_role.yaml
    kubectl apply -n rec-ns -f manifests/01-basic-cluster/cluster_role_binding.yaml
    
  3. 修改 REC ConfigMap 以添加对应用命名空间的控制:

    kubectl patch ConfigMap/operator-environment-config --type merge -p '{"data": {"REDB_NAMESPACES_LABEL": "connection=redis"}}' -n rec-ns
    

    标记为 ConfigMap 的每个命名空间均会进行修补。

  4. 检查 rec-ns 命名空间的 Redis 基础设施中的资源的状态:

    kubectl get pod,deploy,svc,rec,statefulset,cm,secrets -n rec-ns
    

    输出类似于以下内容:

    NAME                                             READY   STATUS    RESTARTS        AGE
    pod/gke-rec-0                                    2/2     Running   0               172m
    pod/gke-rec-1                                    2/2     Running   0               171m
    pod/gke-rec-2                                    2/2     Running   0               168m
    pod/gke-rec-services-rigger-5f885f59dc-gc79g     1/1     Running   0               172m
    pod/redis-enterprise-operator-6668ccd8dc-kx29z   2/2     Running   2 (5m58s ago)   5h
    
    NAME                                        READY   UP-TO-DATE   AVAILABLE   AGE
    deployment.apps/gke-rec-services-rigger     1/1     1            1           172m
    deployment.apps/redis-enterprise-operator   1/1     1            1           5h
    
    NAME                   TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)             AGE
    service/admission      ClusterIP   10.52.11.13   <none>        443/TCP             5h
    service/gke-rec        ClusterIP   10.52.5.44    <none>        9443/TCP,8001/TCP   172m
    service/gke-rec-prom   ClusterIP   None          <none>        8070/TCP            172m
    service/gke-rec-ui     ClusterIP   10.52.3.29    <none>        8443/TCP            172m
    
    NAME                                               NODES   VERSION    STATE     SPEC STATUS   LICENSE STATE   SHARDS LIMIT   LICENSE EXPIRATION DATE   AGE
    redisenterprisecluster.app.redislabs.com/gke-rec   3       7.2.4-52   Running   Valid         Valid           4              2023-10-05T11:07:20Z      172m
    
    NAME                       READY   AGE
    statefulset.apps/gke-rec   3/3     172m
    
    NAME                                    DATA   AGE
    configmap/gke-rec-bulletin-board        1      172m
    configmap/gke-rec-health-check          5      172m
    configmap/kube-root-ca.crt              1      5h2m
    configmap/operator-environment-config   1      5h
    
    NAME                   TYPE     DATA   AGE
    secret/admission-tls   Opaque   2      5h
    secret/gke-rec         Opaque   2      172m
    

部署 Redis Enterprise 数据库

  1. 在应用命名空间中创建 Redis Enterprise 数据库:

    kubectl apply -f manifests/01-basic-cluster/a-rdb.yaml -n application
    
  2. 检查 REDB 状态:

    kubectl get redb --all-namespaces
    

    输出类似于以下内容:

    NAMESPACE       NAME       VERSION   PORT    CLUSTER   SHARDS   STATUS   SPEC STATUS   AGE
    application   app-db   7.2.0     12999   gke-rec   1        active   Valid         15s
    
  3. 验证每个 REDB 的 Service 是否正在运行:

    kubectl get svc --all-namespaces
    

    输出类似于以下内容:

    NAMESPACE      NAME      TYPE          CLUSTER-IP   EXTERNAL-IP                           PORT(S)    AGE
    application  app-db  ExternalName  <none>       redis-12999.rec-ns.svc.cluster.local  12999/TCP  72m
    
  4. 验证 Secret 是否已创建:

    kubectl get secrets -n application
    

    输出类似于以下内容:

    NAME            TYPE     DATA   AGE
    redb-app-db   Opaque   3      96m
    

使用密码进行身份验证

您可以在应用命名空间中使用具有 redis-cli 的 Pod 连接到 REDB。客户端 pod 使用应用命名空间 (REDB) 中可用的 Secret 来建立连接。

使用自定义资源 REDB 创建的数据库仅支持不使用 ACL 的密码身份验证

  1. 创建客户端 Pod:

    kubectl apply -n application -f manifests/03-auth/client_pod.yaml
    
  2. 连接到客户端 Pod:

    kubectl exec -n application -i -t redis-client -c redis-client -- /bin/sh
    
  3. 连接到数据库:

    redis-cli -h $SERVICE -p $PORT --pass $PASS
    
  4. 创建密钥:

    SET mykey "Hello World"
    

    输出类似于以下内容:

    OK
    
  5. 获取密钥:

    GET mykey
    

    输出类似于以下内容:

    "Hello World"
    
  6. 退出 Pod shell

    exit
    

了解 Prometheus 如何收集 Redis 集群的指标

下图展示了 Prometheus 指标收集的工作原理:

在该图中,GKE 专用集群包含:

  • Redis Pod,用于收集路径 / 和端口 8070 的指标
  • 基于 Prometheus 的收集器,用于处理 Redis Pod 中的指标
  • 将指标发送到 Cloud Monitoring 的 PodMonitoring 资源

Redis Enterprise Operator 以 Prometheus 格式公开集群指标。

  1. 创建 metrics-proxy Deployment:

    kubectl apply -n rec-ns -f manifests/02-prometheus-metrics/metrics-proxy.yaml
    

    由于该 Operator 仅提供具有自签名证书的 HTTPS 端点,并且 PodMonitoring 资源不支持停用 TLS 证书验证,因此您可以将 metrics-proxy Pod 用作此端点的反向代理,以在 HTTP 端口上公开指标。

  2. 创建 PodMonitoring 资源,以按 labelSelector 爬取指标:

    kubectl apply -n rec-ns -f manifests/02-prometheus-metrics/pod-monitoring.yaml
    
  3. 在 Google Cloud 控制台中,转到 GKE 集群信息中心页面。

    转到 GKE 集群信息中心

    信息中心显示非零指标提取率。

创建信息中心

您可以通过创建信息中心来查看指标。

  1. 创建信息中心:

    gcloud --project "${PROJECT_ID}" monitoring dashboards create --config-from-file monitoring/dashboard.json
    

    输出类似于以下内容:

    Created [f4efbe4e-2605-46b4-9910-54b13d29b3be].
    
  2. 在 Google Cloud 控制台中,转到信息中心页面。

    转到“信息中心”

  3. 打开 Redis Enterprise 集群信息中心。信息中心可能需要几分钟时间才能完成自动预配。

验证导出的指标

如需验证指标,请创建新数据库并检查指标。

  1. 打开 Redis Enterprise 集群信息中心

  2. 创建一个额外的 Redis 数据库:

    kubectl apply -n rec-ns -f manifests/02-prometheus-metrics/c-rdb.yaml
    

    信息中心上的数据库计数应更新。

  3. 创建客户端 pod 以连接到新数据库:

    kubectl apply -n rec-ns -f manifests/02-prometheus-metrics/client_pod.yaml
    
  4. 连接到客户端 Pod 并准备变量:

    kubectl exec -it redis-client-c -n rec-ns -- /bin/bash
    
  5. 使用 redis-cli 工具创建新密钥:

    for i in {1..50}; do \
      redis-cli -h $SERVICE -p $PORT -a $PASS \
      --no-auth-warning SET mykey-$i "myvalue-$i"; \
    done
    
  6. 刷新页面,您会观察到图表已更新为显示实际数据库状态。

  7. 退出 Pod shell

    exit
    

清理

删除项目

    删除 Google Cloud 项目:

    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)
    cd terraform/gke-standard
    terraform destroy -var project_id=${PROJECT_ID}   \
      -var region=${REGION}  \
      -var cluster_prefix=${KUBERNETES_CLUSTER_PREFIX}
    

    出现提示时,请输入 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
    
  5. 删除 GitHub 代码库:

    rm -r ~/kubernetes-engine-samples/
    

后续步骤