全网最详细K8S部署redis cluster

K8S部署redis cluster

Redis Cluster介绍

Redis 是一个开源的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。Redis 通过 哨兵(Sentinel) 和自动分区(Cluster)提供高可用性(high availability)。在Redis集群中,节点负责保存数据并获取集群状态,包括将键映射到正确的节点。集群节点还能够自动发现其他节点、检测不工作的节点并在需要时将副本节点提升为主节点,以便在发生故障时继续运行。所有集群节点都使用 TCP 总线和二进制协议(称为Redis 集群总线)连接起来。每个节点都使用集群总线连接到集群中的每个其他节点。节点使用 gossip 协议传播有关集群的信息,以便发现新节点,发送 ping 数据包以确保所有其他节点正常工作,并发送集群消息以表示特定情况。由于集群节点无法代理请求,因此客户端可能会使用重定向错误-MOVED和重定向到其他节点-ASK。理论上,客户端可以自由地将请求发送到集群中的所有节点,并在需要时进行重定向,因此客户端无需保存集群的状态。但是,能够缓存键和节点之间的映射的客户端可以以合理的方式提高性能。
————————————————————————————————————

集群部署架构

集群拓补图

在这里插入图片描述

文档环境说明

节点角色软件版本K8S版本备注
Master1Redis 6.2.121.23.6角色非固定
Master2Redis 6.2.121.23.6角色非固定
Master3Redis 6.2.121.23.6角色非固定
Slave1Redis 6.2.121.23.6角色非固定
Slave2Redis 6.2.121.23.6角色非固定
Slave3Redis 6.2.121.23.6角色非固定

参考文档:redis cluster官方文档

redis集群部署

创建namespace

kubectl create ns redis-clu-9

redis-pv.yaml (基于nfs)

容量根据业务需要修改,如果集群已经存在可用pv资源,可不用创建这个yaml

apiVersion: v1  
kind: PersistentVolume  
metadata:  
  name: nfs-redis-cluster-pv1  
spec:  
  capacity:  
    storage: 1000M  
  accessModes:  
    - ReadWriteMany  
  nfs:  
    server: 192.XXX.XXX.240  
path: "/home/nfsdata/redis-cluster/pv1"
---
apiVersion: v1  
kind: PersistentVolume  
metadata:  
  name: nfs-redis-cluster-pv2  
spec:  
  capacity:  
    storage: 1000M  
  accessModes:  
    - ReadWriteMany  
  nfs:  
    server: 192.XXX.XXX.240  
    path: "/home/nfsdata/redis-cluster/pv2"
---
apiVersion: v1  
kind: PersistentVolume  
metadata:  
  name: nfs-redis-cluster-pv3  
spec:  
  capacity:  
    storage: 1000M  
  accessModes:  
    - ReadWriteMany  
  nfs:  
    server: 192.XXX.XXX.240  
    path: "/home/nfsdata/redis-cluster/pv3"

---
apiVersion: v1  
kind: PersistentVolume  
metadata:  
  name: nfs-redis-cluster-pv4  
  namespace: redis-clu-9  
spec:  
  capacity:  
    storage: 1000M  
  accessModes:  
    - ReadWriteMany  
  nfs:  
    server: 192.XXX.XXX.240  
    path: "/home/nfsdata/redis-cluster/pv4“

---
apiVersion: v1  
kind: PersistentVolume  
metadata:  
  name: nfs-redis-cluster-pv5  
spec:  
  capacity:  
    storage: 1000M  
  accessModes:  
    - ReadWriteMany  
  nfs:  
    server: 192.XXX.XXX.240  
path: "/home/nfsdata/redis-cluster/pv5“
---
apiVersion: v1  
kind: PersistentVolume  
metadata:  
  name: nfs-redis-cluster-pv6  
spec:  
  capacity:  
    storage: 1000M  
  accessModes:  
    - ReadWriteMany  
  nfs:  
    server: 192.XXX.XXX.240  
    path: "/home/nfsdata/redis-cluster/pv6“

redis集群configmap

kubectl apply -f redis-configmap.yaml -n redis-clu-9

cat redis-configmap.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: redis-conf
  namespace: redis-clu-9
data:
  fix-pod-ip.sh: |
    #!/bin/sh
    CLUSTER_CONFIG="/var/lib/redis/nodes.conf"
    if [ -f ${CLUSTER_CONFIG} ]; then
      if [ -z "${POD_IP}" ]; then
        echo "Unable to determine Pod IP address!"
        exit 1
      fi
      echo "Updating pod IP to ${POD_IP} in ${CLUSTER_CONFIG}"
    sed -i -e '/myself/ s/[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}/'${POD_IP}'/' ${CLUSTER_CONFIG}
      count=`grep -c ${POD_IP} ${CLUSTER_CONFIG}`
      if [[ $count > 0 ]];then
        echo "Successful updated pod Ip to ${POD_IP} in ${CLUSTER_CONFIG}"
      fi
    fi
    exec "$@"
  redis.conf: |
    # 在这里粘贴你的 redis.conf 文件的内容  
    # 或者你可以使用 kubectl create configmap --dry-run -o yaml ... 来生成
    #开启集群模式
    cluster-enabled yes
    # 监听ip
    bind 0.0.0.0
    port 6379
    #保护模式
    protected-mode no
    #redis后台运行
    #daemonize yes
    #设置客户端连接的超时时间,避免长时间占用连接资源
    timeout 300
    #设置集群节点之间通信的超时时间
    cluster-node-timeout 5000
    #指定集群配置文件名称
    cluster-config-file /var/lib/redis/nodes.conf
    #数据存储目录
    dir /var/lib/redis
    #设置同时连接客户端的最大数量
    maxclients 10000
    #指定服务器冗余级别
    loglevel notice
    # 设置Redis能够使用的最大内存量。这有助于防止Redis因内存耗尽而崩溃
    maxmemory 1000mb
    #内存淘汰策略
    maxmemory-policy volatile-lru
    # 数据持久化
    appendonly yes
    #设置AOF的同步策略,如everysec(每秒同步一次)以平衡性能和数据安全性。
    appendfsync everysec
    #AOF文件名
    appendfilename "appendonly.aof"
    #自动重写附加文件条件配置
    auto-aof-rewrite-percentage 100
    auto-aof-rewrite-min-size 64mb
    # 允许在AOF重写期间进行增量fsync操作它可以帮助减少延迟并减轻fsync对应用程序性能的影响
    aof-rewrite-incremental-fsync yes
    # 优化内存使用
    hash-max-ziplist-entries 512
    hash-max-ziplist-value 64kb 
    # 频率
    hz 10

redis集群svc

kubectl apply  -f  headless-service.yaml 

cat headless-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: redis-service
  namespace: redis-clu-9
  labels:
    app: redis
spec:
  ports:
  - name: redis-port
port: 6379
  - name: redis-cluster-port
    port: 16379
  clusterIP: None
  selector:
    app: redis
    appCluster: redis-cluster

暴漏访问集群入口:

kubectl apply  -f  redis-cluster-access-service.yaml

cat redis-cluster-access-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: redis-cluster-access-service
  namespace: redis-clu-9
  labels:
    app: redis
spec:
  ports:
    - name: redis-cluster-port
      protocol: TCP
      port: 6379
      targetPort: 6379
      nodePort: 34476
  selector:
    app: redis
    appCluster: redis-cluster
  type: NodePort

redis集群statefulSet

kubectl apply  -f  redis.yaml

cat redis.yaml

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis-app
  namespace: redis-clu-9
spec:
  serviceName: "redis-service"
  selector:
    matchLabels:
      app: redis
  replicas: 6
  template:
    metadata:
      labels:
        app: redis
        appCluster: redis-cluster
    spec:
      terminationGracePeriodSeconds: 20
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - redis
              topologyKey: kubernetes.io/hostname
      containers:
      - name: redis
        image: redis:6.2.12
        command: ["/etc/redis/fix-pod-ip.sh", "redis-server", "/etc/redis/redis.conf"]
        resources:
          requests:
            cpu: "100m"    #此处根据业务需求修改
            memory: "100Mi" #此处根据业务需求修改
        env:
          - name: POD_IP
            valueFrom:
              fieldRef:
                fieldPath: status.podIP
        ports:
            - name: redis
              containerPort: 6379
              protocol: "TCP"
            - name: cluster
              containerPort: 16379
              protocol: "TCP"
        volumeMounts:
          - name: "redis-conf"
            mountPath: "/etc/redis"
            readOnly: false
          - name: "redis-data"
            mountPath: "/var/lib/redis"
            readOnly: false
      volumes:
      - name: "redis-conf"
        configMap:
          name: "redis-conf"
          defaultMode: 0755
  volumeClaimTemplates:
  - metadata:
      name: redis-data
      namespace: redis-clu-9
    spec:
      accessModes: [ "ReadWriteMany" ]
      resources:
        requests:
          storage: 1000M
      storageClassName: nfs

redis集群初始化

容器内创建
#### 手动获取集群node ip
kubectl get pod -n redis-clu-9 -o wide 
#### 命令获取集群node ip
kubectl get pods -n redis-clu-9 -l app=redis -o jsonpath='{range.items[*]}{.status.podIP}:6379 ' | sed 's/ :6379//g'
#### 输出下面类似格式的IP:PORT列表, 复制这个输出下面命令会用到###
192.168.53.251:6379 192.168.232.57:6379 192.168.161.250:6379 192.168.104.168:6379 192.168.201.26:6379  192.168.77.202:6379
########
kuectl exec -it -n redis-clu-9 pod-name bash
### 以下为进入容器操作,node_IP 列表为上面命令输出
redis-cli --cluster create node1_IP:6379 node2_IP:6379 node3_IP:6379 node4_IP:6379 node5_IP:6379 node6_IP:6379 --cluster-replicas 1
容器外创建
### 也可以在容器外一键创建
kubectl -n redis-clu-9 exec -it pod-name -- redis-cli --cluster create $(kubectl get pods -n redis-clu-9 -l app=redis -o jsonpath='{range.items[*]}{.status.podIP}:6379 ' | sed 's/ :6379//g') --cluster-replicas 1
集群创建过程结果

在这里插入图片描述
在这里插入图片描述

redis集群参数优化

配置文件参数

Redis-configmap.yaml 的 redis.conf部分

apiVersion: v1
kind: ConfigMap
metadata:
  name: redis-conf
  namespace: redis-clu-9
data:
  redis.conf: |
    # 在这里粘贴你的 redis.conf 文件的内容
    # 或者你可以使用 kubectl create configmap --dry-run -o yaml ... 来生成
    #开启集群模式
    cluster-enabled yes
    port 6379
#保护模式
protected-mode no
    #redis后台运行
    #daemonize yes
    # 设置客户端连接的超时时间,避免长时间占用连接资源
    timeout 300
    #设置集群节点之间通信的超时时间
    cluster-node-timeout 5000
    #指定集群配置文件名称
    cluster-config-file /var/lib/redis/nodes.conf
#集群数据目录
    dir /var/lib/redis  
    #设置同时连接客户端的最大数量
    maxclients 10000
    #指定服务器冗余级别
    loglevel notice
    ##############

    # 设置Redis能够使用的最大内存量。这有助于防止Redis因内存耗尽而崩溃
    maxmemory 1000mb
    #内存淘汰策略,针对设置 expried key 
    maxmemory-policy volatile-lru

    # 数据持久化
    appendonly yes
    #设置AOF的同步策略,如everysec(每秒同步一次)以平衡性能和数据安全性。
    appendfsync everysec
    appendfilename "appendonly.aof"
    #自动重写附加文件
    auto-aof-rewrite-percentage 100
    auto-aof-rewrite-min-size 64mb
    # 优化内存使用
    hash-max-ziplist-entries 512
    hash-max-ziplist-value 64kb

    # 任务频率 
    # 值越大redis 响应时间越短性能较好但同时资源消(cpu)耗也会增大
# 最好结合监控数据如: cpu memery network 来测试验证设定
# 也可以结合业务性能要求来设置
# 需要重启生效
    hz 10
    # 允许在AOF重写期间进行增量fsync操作可以帮助减少延迟并减轻fsync对应用程序性能的影响
    aof-rewrite-incremental-fsync yes

其他重要参数:

cluster-replica-validity-factor:10
cluster-slave-validity-factor  老版本
它会影响副本如何决定在发生故障时是否有资格对主节点进行故障转移。
如果设置为零,副本将始终认为自己可以进行故障转移,这意味着无论与主服务器断开连接多长时间,它都会尝试接管主服务器。
如果设置为正值,则通过将节点超时值乘以此因子来计算最大断开连接时间。如果副本与其主服务器断开连接的时间超过此计算时间,则副本不会尝试对主服务器进行故障转移。
例如,如果节点超时时间为 5 秒,有效性因子为 10,则如果副本断开连接超过 50 秒,则副本不会尝试故障转移其主节点。将因子设置为零是确保在网络分区解决后集群继续运行的唯一方法。

cluster-node-timeout : 15000 ms
一个至关重要的配置参数,用于指定 Redis Cluster 节点在被视为发生故障之前可以处于不可用状态的最长时间。如果主节点在此超时期限内无法与大多数其他主节点通信,它将进入错误状态并停止接受写入。此设置可确保集群能够可靠地确定节点何时不再按预期运行并采取必要的措施,例如故障转移到副本

cluster-migration-barrier: 1
用于指定主服务器必须具有的最小副本数,在此数量下,其他副本才被允许迁移到缺少副本的另一个主服务器。这有助于确保主服务器保持足够的副本数,然后才允许其副本之一在其他地方提供帮助。
如果主服务器最终没有任何副本,则具有超过规定的最低所需副本数的主服务器的副本将迁移到需要副本的主服务器。此机制通过确保所有主服务器都由副本备份来帮助维护 Redis 集群的弹性和稳定性,从而促进服务的连续性。

cluster-require-full-coverage: yes
默认情况下,它设置为“是”,这意味着如果由于故障或问题导致任何节点无法覆盖一定比例的键空间,则集群将停止接受写入。这可确保集群仅在能够覆盖整个键空间时才处理事务,从而保持数据完整性和一致性。
如果设置为“否”,即使只能处理部分键,集群也将继续处理读取和写入查询,从而允许操作在键空间的可用部分上进行。如果您想确保应用程序在出现某些节点故障或使用只有一两个分片的集群时仍能部分可用,这将非常有用。
cluster-allow-reads-when-dow: no
决定了当集群被标记为失败时,节点是否将继续处理读取请求。默认情况下,此设置为“否”,这意味着当集群关闭时,节点将停止处理所有流量,以确保不会读取任何可能不一致的数据。但是,将此选项设置为“是”可让节点在失败状态下继续处理读取请求。如果您的应用程序优先考虑读取可用性,这可能很有用,但需要注意的是,这可能会导致读取可能过时或不一致的数据。

读写key测试

Create-key.py

from rediscluster import RedisCluster

# Redis集群的启动节点列表,这里需要根据你的实际环境进行修改
startup_nodes = [
    {"host": "192.168.123.240", "port": "34476"},
    # 如果有多个节点,继续添加...
    # {"host": "another_host", "port": "another_port"},
]
# 连接到Redis集群
rc = RedisCluster(startup_nodes=startup_nodes, decode_responses=True)
# 批量创建1万个键值对
for i in range(1, 10001):
    key = f"key_{i}"
    value = f"value_{i}"
    rc.set(key, value)
print("键值对创建完成!")

创建的key分布测试

root@k8s-master1:[/root/zl_test/redis_cluster]redis-cli -h 192.168.123.240 -p 34476
192.168.123.240:34476> get key_1
(error) MOVED 11998 192.168.53.192:6379
192.168.123.240:34476> get key_100
(error) MOVED 12624 192.168.53.192:6379
192.168.123.240:34476> get key_800
(error) MOVED 12225 192.168.53.192:6379
192.168.123.240:34476> get key_1000
(error) MOVED 33 192.168.161.230:6379
192.168.123.240:34476> get key_5000
(error) MOVED 2768 192.168.161.230:6379
192.168.123.240:34476> get key_8000
(error) MOVED 13142 192.168.53.192:6379
192.168.123.240:34476> get key_9001
(error) MOVED 5571 192.168.104.186:6379
192.168.123.240:34476> get key_9006
(error) MOVED 9508 192.168.104.186:6379
192.168.123.240:34476> get key_10000
(error) MOVED 8087 192.168.104.186:6379
### 可以使用redis-cli -c 集群模式测试

redis集群验证

集群当前状态

在这里插入图片描述

高可用测试

从集群状态中可看出

192.168.53.192主和192.168.232.52从互为主备
在这里插入图片描述

删除节点模拟故障

通过修改主节点镜像的方式故障
在这里插入图片描述

从节点日志

可以看到主节点故障后从节点已成为主节点
在这里插入图片描述

查看集群信息及使用

可以看到原slave已切换成master且集群仍可正常使用
在这里插入图片描述
在这里插入图片描述

恢复集群

恢复pod
在这里插入图片描述
新成为master上日志,显示主从同步成功
在这里插入图片描述
查看集群状态新上线后已成为slave节点
在这里插入图片描述
集群状态正常

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值