当前位置: 首页 > news >正文

Kubernetes 构建高可用、高性能 Redis 集群实战指南

1. 部署方案规划

1.1 部署架构图

1.2 前提说明

  • 本实战环境使用 NFS 作为 k8s 集群的持久化存储
  • Redis 集群所有资源部署在命名空间 chengke 内。

2. 创建 ConfigMap 

2.1 创建 ConfigMap

2.1.1 创建 Redis 配置文件

[root@k8s-m1 1]# cat redis-cluster-cm.yaml 
apiVersion: v1
kind: ConfigMap
metadata:name: redis-cluster-config
data:redis-config: |appendonly yesprotected-mode nodir /dataport 6379cluster-enabled yescluster-config-file /data/nodes.confcluster-node-timeout 5000masterauth Chengke2025requirepass Chengke2025

2.1.2 创建资源

[root@k8s-m1 1]# kubectl apply -f redis-cluster-cm.yaml 

 2.1.3 验证资源

[root@k8s-m1 1]# kubectl get cm
NAME                   DATA   AGE
redis-cluster-config   1      68m

2.2 创建 Redis

本文使用 StatefulSet 部署 Redis 服务,需要创建 StatefulSet HeadLess 两种资源。

2.2.1 创建资源清单 

[root@k8s-m1 1]# cat redis-cluster-sts.yaml 
apiVersion: v1
kind: Service
metadata:name: redis-headlesslabels:app.kubernetes.io/name: redis-cluster
spec:ports:- name: redis-6379protocol: TCPport: 6379targetPort: 6379selector:app.kubernetes.io/name: redis-clusterclusterIP: Nonetype: ClusterIP
---
apiVersion: apps/v1
kind: StatefulSet
metadata:name: redis-clusterlabels:app.kubernetes.io/name: redis-cluster
spec:serviceName: redis-headlessreplicas: 6selector:matchLabels:app.kubernetes.io/name: redis-clustertemplate:metadata:labels:app.kubernetes.io/name: redis-clusterspec:affinity:podAntiAffinity:preferredDuringSchedulingIgnoredDuringExecution:- weight: 100podAffinityTerm:labelSelector:matchExpressions:- key: app.kubernetes.io/nameoperator: Invalues:- redis-clustertopologyKey: kubernetes.io/hostnamecontainers:- name: redisimage: redis:8.0.2imagePullPolicy: IfNotPresentcommand:- "redis-server"args:- "/etc/redis/redis.conf"- "--protected-mode"- "no"- "--cluster-announce-ip"- "$(POD_IP)"env:- name: POD_IPvalueFrom:fieldRef:fieldPath: status.podIPports:- name: redis-6379containerPort: 6379protocol: TCPvolumeMounts:- name: configmountPath: /etc/redis- name: redis-cluster-datamountPath: /dataresources:requests:cpu: 50mmemory: 500Milimits:cpu: "2"memory: 4Givolumes:- name: configconfigMap:name: redis-cluster-configitems:- key: redis-configpath: redis.confvolumeClaimTemplates:- metadata:name: redis-cluster-dataspec:accessModes:- ReadWriteOncestorageClassName: nfs-clientresources:requests:storage: 5Gi
注意: POD_IP 是重点,如果不配置会导致线上的 POD 重启换 IP 后,集群状态无法自动同步 

2.2.2 创建资源

[root@k8s-master01 1]# kubectl apply -f redis-cluster-sts.yaml
service/redis-headless created
statefulset.apps/redis-cluster created

2.2.3 验证资源

执行下面的命令,查看 StatefulSetPodService 创建结果
[root@k8s-m1 1]# kubectl get pod,svc,sts
NAME                                READY   STATUS    RESTARTS   AGE
pod/redis-cluster-0                 1/1     Running   0          69m
pod/redis-cluster-1                 1/1     Running   0          67m
pod/redis-cluster-2                 1/1     Running   0          48m
pod/redis-cluster-3                 1/1     Running   0          65m
pod/redis-cluster-4                 1/1     Running   0          65m
pod/redis-cluster-5                 1/1     Running   0          65m
pod/redisinsight-5cb887744f-79h5k   1/1     Running   0          42mNAME                             TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)          AGE
service/kubernetes               ClusterIP   10.0.0.1     <none>        443/TCP          8d
service/redis-cluster-external   NodePort    10.5.96.53   <none>        6379:31379/TCP   62m
service/redis-headless           ClusterIP   None         <none>        6379/TCP         69m
service/redisinsight-external    NodePort    10.9.143.0   <none>        5540:31380/TCP   42mNAME                             READY   AGE
statefulset.apps/redis-cluster   6/6     69m

2.3 创建 k8s 集群外部访问服务

2.3.1 编写资源

我们采用 NodePort 方式在 Kubernetes 集群外发布 Redis 服务,指定的端口为 31379
[root@k8s-m1 1]# cat redis-cluster-svc-external.yaml 
kind: Service
apiVersion: v1
metadata:name: redis-cluster-externallabels:app: redis-cluster-external
spec:ports:- protocol: TCPport: 6379targetPort: 6379nodePort: 31379selector:app.kubernetes.io/name: redis-clustertype: NodePort

 2.3.2 创建资源

[root@k8s-master01 1]# kubectl apply -f redis-cluster-svc-external.yaml
service/redis-cluster-external created

2.3.3 验证资源

执行下面的命令,查看 Service 创建结果
[root@k8s-m1 1]# kubectl get endpointslice
NAME                           ADDRESSTYPE   PORTS   ENDPOINTS                                                 AGE
kubernetes                     IPv4          6443    192.168.10.11                                             24d
my-service-noselector-1        IPv4          80      192.168.10.12,192.168.10.13                               18d
redis-cluster-external-qvl7h   IPv4          6379    10.244.215.78,10.244.215.111,10.244.111.244 + 3 more...   65m
redis-headless-j2x96           IPv4          6379    10.244.111.251,10.244.215.111,10.244.215.73 + 3 more...   73m
redisinsight-external-b2vks    IPv4          5540    10.244.111.252                                            45m
[root@k8s-m1 1]# kubectl get svc
NAME                     TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)          AGE
kubernetes               ClusterIP   10.0.0.1     <none>        443/TCP          8d
redis-cluster-external   NodePort    10.5.96.53   <none>        6379:31379/TCP   65m
redis-headless           ClusterIP   None         <none>        6379/TCP         73m
redisinsight-external    NodePort    10.9.143.0   <none>        5540:31380/TCP   46m

3. 创建 Redis 集群

Redis POD 创建完成后,不会自动创建 Redis 集群,需要手工执行集群初始化的命令,有自动创建和手工创建两种方式,二选一,建议选择自动

3.1 自动创建 Redis 集群 

 执行下面的命令,自动创建 3 master 3 slave 的集群,中间需要输入一次 yes

[root@k8s-m1 1]# kubectl exec -it redis-cluster-0 -- redis-cli -a Chengke2025 --cluster create --cluster-replicas 1 $(kubectl get pods -l app.kubernetes.io/name=redis-cluster -o jsonpath='{range.items[*]} {.status.podIP}:6379 {end}')
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
>>> 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.111.244:6379 to 10.244.111.251:6379
Adding replica 10.244.215.78:6379 to 10.244.215.111:6379
Adding replica 10.244.215.73:6379 to 10.244.111.253:6379
M: 80be000a17cc1b2d1d7180e722876d501c90c9a3 10.244.111.251:6379slots:[0-5460] (5461 slots) master
M: 01a21392ef5998e7da5d382a1ed6d0ec35bef845 10.244.215.111:6379slots:[5461-10922] (5462 slots) master
M: 8e009ec3ccc37b0810db6b1ffc5bd6c241c0cd31 10.244.111.253:6379slots:[10923-16383] (5461 slots) master
S: 48978e7c86fe9bf341880eb9cf1fac3aa8e48dc4 10.244.215.73:6379replicates 8e009ec3ccc37b0810db6b1ffc5bd6c241c0cd31
S: 0d8bab081a2125b7a83c67c588c2a9f93482d69a 10.244.111.244:6379replicates 80be000a17cc1b2d1d7180e722876d501c90c9a3
S: d7f1dc037259b2d2c155ac5a5c5c5b4b8f7818c4 10.244.215.78:6379replicates 01a21392ef5998e7da5d382a1ed6d0ec35bef845
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.111.251:6379)
M: 80be000a17cc1b2d1d7180e722876d501c90c9a3 10.244.111.251:6379slots:[0-5460] (5461 slots) master1 additional replica(s)
S: 48978e7c86fe9bf341880eb9cf1fac3aa8e48dc4 10.244.215.73:6379slots: (0 slots) slavereplicates 8e009ec3ccc37b0810db6b1ffc5bd6c241c0cd31
S: 0d8bab081a2125b7a83c67c588c2a9f93482d69a 10.244.111.244:6379slots: (0 slots) slavereplicates 80be000a17cc1b2d1d7180e722876d501c90c9a3
M: 8e009ec3ccc37b0810db6b1ffc5bd6c241c0cd31 10.244.111.253:6379slots:[10923-16383] (5461 slots) master1 additional replica(s)
M: 01a21392ef5998e7da5d382a1ed6d0ec35bef845 10.244.215.111:6379slots:[5461-10922] (5462 slots) master1 additional replica(s)
S: d7f1dc037259b2d2c155ac5a5c5c5b4b8f7818c4 10.244.215.78:6379slots: (0 slots) slavereplicates 01a21392ef5998e7da5d382a1ed6d0ec35bef845
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

3.2 验证集群状态

[root@k8s-m1 1]# kubectl exec -it redis-cluster-0 -- redis-cli -p 6379 -a Chengke2025 cluster info
E0802 16:18:19.072387   92106 websocket.go:297] Unknown stream id 1, discarding messageWarning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
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:6868
cluster_stats_messages_pong_sent:6767
cluster_stats_messages_sent:13635
cluster_stats_messages_ping_received:6762
cluster_stats_messages_pong_received:6867
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:13634
total_cluster_links_buffer_limit_exceeded:0

4. 集群功能测试

4.1 压力测试

使用 Redis 自带的压力测试工具,测试 Redis 集群是否可用,并简单测试性能。

使用 set 和get命令,发送100000次请求,每个请求包含一个键值对,其中键是随机生成的,值的大小是100字节,同时有20个客户端并发执行。

测试 set 场景:

kubectl exec -it redis-cluster-0 -- redis-benchmark -h 192.168.10.11 -p 31379 -a Chengke2025 -t set -n 100000 -c 20 -d 100 --cluster

测试 get 场景:

[root@k8s-master01 1]# kubectl exec -it redis-cluster-0 -- redis-benchmark -h
192.168.10.11 -p 31379 -a Chengke2025 -t get -n 100000 -c 20 -d 100 --cluster

4.2 故障切换测试

4.2.1. 测试场景1

测试:手动删除一个 Master Slave,观察 Slave Pod 是否会自动重建并加入原有 Master。

结果: 原有 Slave IP 删除后自动重建,IP 变更为 一个新的IP,并自动加入原有的Master

4.2.2. 测试场景2

测试:手动删除 Master ,观察 Master Pod 是否会自动重建并重新变成 Master

结果: 原有 Master IP 删除后自动重建 IP变更为一个新的IP,重新变成Master

以上测试内容,仅是简单的故障切换测试,生产环境请增加更多的测试场景!!!

http://www.dtcms.com/a/312060.html

相关文章:

  • #C语言——学习攻略:探索字符函数和字符串函数(一)--字符分类函数,字符转换函数,strlen,strcpy,strcat函数的使用和模拟实现
  • 数据库理论
  • 【MATLAB】(五)向量
  • 变量筛选—随机森林特征重要性
  • windows@Path环境变量中同名可执行文件优先级竞争问题@Scoop安装软件命令行启动存在同名竞争问题的解决
  • 解决 InputStream 只能读取一次问题
  • Java语言核心特性全解析:从面向对象到跨平台原理
  • Docker--将非root用户添加docker用户组,解决频繁sudo执行输入密码的问题
  • 【动态规划 | 子序列问题】子序列问题的最优解:动态规划方法详解
  • RK628F HDMI-IN调试:应用接口使用
  • Vulnhub ELECTRICAL靶机复现(附提权)
  • QPainter::CompositionMode解析
  • junit总@mockbaen与@mock的区别与联系
  • flutter分享到支付宝
  • Linux进程控制核心:创建·等待·终止·替换
  • Qt 信号和槽正常连接返回true,但发送信号后槽函数无响应问题【已解决】
  • 深入解析Java Stream Sink接口
  • Design Compiler:Milkyway库的创建与使用
  • 1-7〔 OSCP ◈ 研记 〕❘ 信息收集▸主动采集E:SMB基础
  • 硬件-可靠性学习DAY1——系统可靠性设计指南:从原理到实践
  • Markdown 中的图表 Mermaid 与 classDiagram
  • Thread 中的 run() 方法 和 start() 方法的
  • 笔记:C语言中指向指针的指针作用
  • MQTT协议测试环境部署
  • 错误: 找不到或无法加载主类 原因: java.lang.ClassNotFoundException
  • (nice!!!)(LeetCode 每日一题) 2561. 重排水果 (哈希表 + 贪心)
  • UNet改进(29):记忆增强注意力机制在UNet中的创新应用-原理、实现与性能提升
  • 【嵌入式汇编基础】-ARM架构基础(三)
  • 动态规划解最长回文子串:深入解析与优化问题
  • 【redis】基于工业界技术分享的内容总结