教你在 Kubernetes 上部署 Redis 高可用集群?

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
网络型负载均衡 NLB,每月750个小时 15LCU
简介: 教你在 Kubernetes 上部署 Redis 高可用集群?

Redis 介绍

Redis 代表REmote DIctionary Server是一种开源的内存中数据存储,通常用作数据库,缓存或消息代理。它可以存储和操作高级数据类型,例如列表,地图,集合和排序集合。由于Redis接受多种格式的密钥,因此可以在服务器上执行操作,从而减少了客户端的工作量。它仅将磁盘用于持久性,而将数据库完全保存在内存中。Redis是一种流行的数据存储解决方案,并被GitHubPinterestSnapchatTwitterStackOverflowFlickr等技术巨头所使用。

为什么使用 Redis

  • 它的速度非常快。它是用 ANSI C 编写的,并且可以在 POSIX 系统上运行,例如 Linux,Mac OS X 和 Solaris。
  • Redis 通常被排名为最流行的键/值数据库和最流行的与容器一起使用的 NoSQL 数据库。
  • 其缓存解决方案减少了对云数据库后端的调用次数。
  • 应用程序可以通过其客户端 API 库对其进行访问。
  • 所有流行的编程语言都支持 Redis。
  • 它是开源且稳定的。

什么是 Redis 集群

Redis Cluster 是一组 Redis 实例,旨在通过对数据库进行分区来扩展数据库,从而使其更具弹性。群集中的每个成员(无论是主副本还是辅助副本)都管理哈希槽的子集。如果主机无法访问,则其从机将升级为主机。在由三个主节点组成的最小 Redis 群集中,每个主节点都有一个从节点(以实现最小的故障转移),每个主节点都分配有一个介于 0 到 16,383 之间的哈希槽范围。节点 A 包含从 0 到 5000 的哈希槽,节点 B 从 5001 到 10000,节点 C 从 10001 到 16383。群集内部的通信是通过内部总线进行的,使用协议传播有关群集的信息或发现新节点。

在 Kubernetes 中部署 Redis 集群

Kubernetes中部署Redis集群面临挑战,因为每个 Redis 实例都依赖于一个配置文件,该文件可以跟踪其他集群实例及其角色。为此,我们需要结合使用Kubernetes StatefulSetsPersistentVolumes

克隆部署文件

git clone https://github.com/llmgo/redis-sts.git

创建 statefulset 类型资源

[root@node01 redis-sts]# cat redis-sts.yml 
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: redis-cluster
data:
  update-node.sh: |
    #!/bin/sh
    REDIS_NODES="/data/nodes.conf"
    sed -i -e "/myself/ s/[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}/${POD_IP}/" ${REDIS_NODES}
    exec "$@"
  redis.conf: |+
    cluster-enabled yes
    cluster-require-full-coverage no
    cluster-node-timeout 15000
    cluster-config-file /data/nodes.conf
    cluster-migration-barrier 1
    appendonly yes
    protected-mode no
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis-cluster
spec:
  serviceName: redis-cluster
  replicas: 6
  selector:
    matchLabels:
      app: redis-cluster
  template:
    metadata:
      labels:
        app: redis-cluster
    spec:
      containers:
      - name: redis
        image: redis:5.0.5-alpine
        ports:
        - containerPort: 6379
          name: client
        - containerPort: 16379
          name: gossip
        command: ["/conf/update-node.sh", "redis-server", "/conf/redis.conf"]
        env:
        - name: POD_IP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP
        volumeMounts:
        - name: conf
          mountPath: /conf
          readOnly: false
        - name: data
          mountPath: /data
          readOnly: false
      volumes:
      - name: conf
        configMap:
          name: redis-cluster
          defaultMode: 0755
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 5Gi
      storageClassName: standard
$ kubectl apply -f redis-sts.yml
configmap/redis-cluster created
statefulset.apps/redis-cluster created
$ kubectl get pods -l app=redis-cluster
NAME              READY   STATUS    RESTARTS   AGE
redis-cluster-0   1/1     Running   0          53s
redis-cluster-1   1/1     Running   0          49s
redis-cluster-2   1/1     Running   0          46s
redis-cluster-3   1/1     Running   0          42s
redis-cluster-4   1/1     Running   0          38s
redis-cluster-5   1/1     Running   0          34s

创建 service

[root@node01 redis-sts]# cat redis-svc.yml   
---  
apiVersion: v1  
kind: Service  
metadata:  
  name: redis-cluster  
spec:  
  type: ClusterIP  
  clusterIP: 10.96.0.100  
  ports:  
  - port: 6379  
    targetPort: 6379  
    name: client  
  - port: 16379  
    targetPort: 16379  
    name: gossip  
  selector:  
    app: redis-cluster  
$ kubectl apply -f redis-svc.yml  
service/redis-cluster created  
$ kubectl get svc redis-cluster  
NAME            TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)              AGE  
redis-cluster   ClusterIP   10.96.0.100   <none>        6379/TCP,16379/TCP   35s

初始化 redis cluster

下一步是形成Redis集群。为此,我们运行以下命令并键入yes以接受配置。前三个节点成为主节点,后三个节点成为从节点。

$ kubectl exec -it redis-cluster-0 -- redis-cli --cluster create --cluster-replicas 1 $(kubectl get pods -l app=redis-cluster -o jsonpath='{range.items[*]}{.status.podIP}:6379 ')  
>>> Performing hash slots allocation on 6 nodes...  
Master[0] -> Slots 0 - 5460  
Master[1] -> Slots 5461 - 10922  
Master[2] -> Slots 10923 - 16383  
Adding replica 10.244.2.11:6379 to 10.244.9.19:6379  
Adding replica 10.244.9.20:6379 to 10.244.6.10:6379  
Adding replica 10.244.8.15:6379 to 10.244.7.8:6379  
M: 00721c43db194c8f2cacbafd01fd2be6a2fede28 10.244.9.19:6379  
   slots:[0-5460] (5461 slots) master  
M: 9c36053912dec8cb20a599bda202a654f241484f 10.244.6.10:6379  
   slots:[5461-10922] (5462 slots) master  
M: 2850f24ea6367de58fb50e632fc56fe4ba5ef016 10.244.7.8:6379  
   slots:[10923-16383] (5461 slots) master  
S: 554a58762e3dce23ca5a75886d0ccebd2d582502 10.244.8.15:6379  
   replicates 2850f24ea6367de58fb50e632fc56fe4ba5ef016  
S: 20028fd0b79045489824eda71fac9898f17af896 10.244.2.11:6379  
   replicates 00721c43db194c8f2cacbafd01fd2be6a2fede28  
S: 87e8987e314e4e5d4736e5818651abc1ed6ddcd9 10.244.9.20:6379  
   replicates 9c36053912dec8cb20a599bda202a654f241484f  
Can I set the above configuration? (type 'yes' to accept): yes  
>>> Nodes configuration updated  
>>> Assign a different config epoch to each node  
>>> Sending CLUSTER MEET messages to join the cluster  
Waiting for the cluster to join  
...  
>>> Performing Cluster Check (using node 10.244.9.19:6379)  
M: 00721c43db194c8f2cacbafd01fd2be6a2fede28 10.244.9.19:6379  
   slots:[0-5460] (5461 slots) master  
   1 additional replica(s)  
M: 9c36053912dec8cb20a599bda202a654f241484f 10.244.6.10:6379  
   slots:[5461-10922] (5462 slots) master  
   1 additional replica(s)  
S: 87e8987e314e4e5d4736e5818651abc1ed6ddcd9 10.244.9.20:6379  
   slots: (0 slots) slave  
   replicates 9c36053912dec8cb20a599bda202a654f241484f  
S: 554a58762e3dce23ca5a75886d0ccebd2d582502 10.244.8.15:6379  
   slots: (0 slots) slave  
   replicates 2850f24ea6367de58fb50e632fc56fe4ba5ef016  
S: 20028fd0b79045489824eda71fac9898f17af896 10.244.2.11:6379  
   slots: (0 slots) slave  
   replicates 00721c43db194c8f2cacbafd01fd2be6a2fede28  
M: 2850f24ea6367de58fb50e632fc56fe4ba5ef016 10.244.7.8:6379  
   slots:[10923-16383] (5461 slots) master  
   1 additional replica(s)  
[OK] All nodes agree about slots configuration.  
>>> Check for open slots...  
>>> Check slots coverage...  
[OK] All 16384 slots covered.

验证集群

[root@node01 redis-sts]# kubectl exec -it redis-cluster-0 -- redis-cli cluster info  
cluster_state:ok  
cluster_slots_assigned:16384  
cluster_slots_ok:16384  
cluster_slots_pfail:0  
cluster_slots_fail:0  
cluster_known_nodes:6  
cluster_size:3  
cluster_current_epoch:6  
cluster_my_epoch:1  
cluster_stats_messages_ping_sent:16  
cluster_stats_messages_pong_sent:22  
cluster_stats_messages_sent:38  
cluster_stats_messages_ping_received:17  
cluster_stats_messages_pong_received:16  
cluster_stats_messages_meet_received:5  
cluster_stats_messages_received:38  
[root@node01 redis-sts]# for x in $(seq 0 5); do echo "redis-cluster-$x"; kubectl exec redis-cluster-$x -- redis-cli role; echo; done  
redis-cluster-0  
master  
14  
10.244.2.11  
6379  
14  
redis-cluster-1  
master  
28  
10.244.9.20  
6379  
28  
redis-cluster-2  
master  
28  
10.244.8.15  
6379  
28  
redis-cluster-3  
slave  
10.244.7.8  
6379  
connected  
28  
redis-cluster-4  
slave  
10.244.9.19  
6379  
connected  
14  
redis-cluster-5  
slave  
10.244.6.10  
6379  
connected  
28

测试集群

我们想使用集群,然后模拟节点的故障。对于前一项任务,我们将部署一个简单的 Python 应用程序,而对于后者,我们将删除一个节点并观察集群行为。

部署点击计数器应用

我们将一个简单的应用程序部署到集群中,并在其前面放置一个负载平衡器。此应用程序的目的是在将计数器值作为 HTTP 响应返回之前,增加计数器并将其存储在 Redis 集群中。

$ kubectl apply -f app-deployment-service.yml  
service/hit-counter-lb created  
deployment.apps/hit-counter-app created

在此过程中,如果我们继续加载页面,计数器将继续增加,并且在删除Pod之后,我们看到没有数据丢失。

$  curl `kubectl get svc hit-counter-lb -o json|jq -r .spec.clusterIP`  
I have been hit 20 times since deployment.  
$  curl `kubectl get svc hit-counter-lb -o json|jq -r .spec.clusterIP`  
I have been hit 21 times since deployment.  
$ curl `kubectl get svc hit-counter-lb -o json|jq -r .spec.clusterIP`  
I have been hit 22 times since deployment.  
$ kubectl delete pods redis-cluster-0  
pod "redis-cluster-0" deleted  
$ kubectl delete pods redis-cluster-1  
pod "redis-cluster-1" deleted  
$  curl `kubectl get svc hit-counter-lb -o json|jq -r .spec.clusterIP`  
I have been hit 23 times since deployment.

参考文档

  1. [redis-cluster集群配置1] http://llmgo.cn/post/redis-003/
  2. [redis-cluster集群配置2] http://www.yunweipai.com/36338.html

结语

如果这篇文章对您有所帮助,或者有所启发的话,求一键三连:点赞、评论、收藏➕关注,您的支持是我坚持写作最大的动力。


相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
目录
相关文章
|
4天前
|
缓存 容灾 网络协议
ACK One多集群网关:实现高效容灾方案
ACK One多集群网关可以帮助您快速构建同城跨AZ多活容灾系统、混合云同城跨AZ多活容灾系统,以及异地容灾系统。
|
8天前
|
存储 负载均衡 NoSQL
搭建高可用及负载均衡的Redis
通过本文介绍的高可用及负载均衡Redis架构,可以有效提升Redis服务的可靠性和性能。主从复制、哨兵模式、Redis集群以及负载均衡技术的结合,使得Redis系统在应对高并发和数据一致性方面表现出色。这些配置和技术不仅适用于小型应用,也能够支持大规模企业级应用的需求。希望本文能够为您的Redis部署提供实用指导和参考。
43 9
|
17天前
|
Prometheus Kubernetes 监控
OpenAI故障复盘 - 阿里云容器服务与可观测产品如何保障大规模K8s集群稳定性
聚焦近日OpenAI的大规模K8s集群故障,介绍阿里云容器服务与可观测团队在大规模K8s场景下我们的建设与沉淀。以及分享对类似故障问题的应对方案:包括在K8s和Prometheus的高可用架构设计方面、事前事后的稳定性保障体系方面。
|
14天前
|
Kubernetes Ubuntu 网络安全
ubuntu使用kubeadm搭建k8s集群
通过以上步骤,您可以在 Ubuntu 系统上使用 kubeadm 成功搭建一个 Kubernetes 集群。本文详细介绍了从环境准备、安装 Kubernetes 组件、初始化集群到管理和使用集群的完整过程,希望对您有所帮助。在实际应用中,您可以根据具体需求调整配置,进一步优化集群性能和安全性。
61 12
|
22天前
|
存储 Kubernetes 容器
K8S部署nexus
该配置文件定义了Nexus 3的Kubernetes部署,包括PersistentVolumeClaim、Deployment和服务。PVC请求20Gi存储,使用NFS存储类。Deployment配置了一个Nexus 3容器,内存限制为6G,CPU为1000m,并挂载数据卷。Service类型为NodePort,通过30520端口对外提供服务。所有资源位于`nexus`命名空间中。
|
19天前
|
Kubernetes 网络协议 应用服务中间件
Kubernetes Ingress:灵活的集群外部网络访问的利器
《Kubernetes Ingress:集群外部访问的利器-打造灵活的集群网络》介绍了如何通过Ingress实现Kubernetes集群的外部访问。前提条件是已拥有Kubernetes集群并安装了kubectl工具。文章详细讲解了Ingress的基本组成(Ingress Controller和资源对象),选择合适的版本,以及具体的安装步骤,如下载配置文件、部署Nginx Ingress Controller等。此外,还提供了常见问题的解决方案,例如镜像下载失败的应对措施。最后,通过部署示例应用展示了Ingress的实际使用方法。
37 2
|
1月前
|
Kubernetes 容灾 调度
阿里云 ACK 高可用稳定性最佳实践
本文整理自2024云栖大会刘佳旭的演讲,主题为《ACK高可用稳定性最佳实践》。文章探讨了云原生高可用架构的重要性,通过Kubernetes的高可用案例分析,介绍了ACK在单集群高可用架构设计、产品能力和最佳实践方面的方法,包括控制面和数据面的高可用策略、工作负载高可用配置、企业版容器镜像服务高可用配置等内容,旨在帮助企业构建更加可靠和高效的应用运行环境。
|
1月前
|
存储 Kubernetes 关系型数据库
阿里云ACK备份中心,K8s集群业务应用数据的一站式灾备方案
本文源自2024云栖大会苏雅诗的演讲,探讨了K8s集群业务为何需要灾备及其重要性。文中强调了集群与业务高可用配置对稳定性的重要性,并指出人为误操作等风险,建议实施周期性和特定情况下的灾备措施。针对容器化业务,提出了灾备的新特性与需求,包括工作负载为核心、云资源信息的备份,以及有状态应用的数据保护。介绍了ACK推出的备份中心解决方案,支持命名空间、标签、资源类型等维度的备份,并具备存储卷数据保护功能,能够满足GitOps流程企业的特定需求。此外,还详细描述了备份中心的使用流程、控制台展示、灾备难点及解决方案等内容,展示了备份中心如何有效应对K8s集群资源和存储卷数据的灾备挑战。
|
8月前
|
机器学习/深度学习 NoSQL Redis
Redis高可用之集群架构(第三部分)
Redis高可用之集群架构(第三部分)
|
存储 缓存 监控
Redis高可用之主从复制、哨兵、cluster集群
Redis高可用之主从复制、哨兵、cluster集群
262 0