【Redis】记录一次K8S存储故障导致Redis集群拓扑异常的修复过程

背景

集群部署在K8S环境内,存储使用的localpv,有一台K8S主机节点磁盘故障,导致在该节点上的redis节点均出现故障,主要表现为持久化失败、集群拓扑异常,持久化失败可以临时关闭RDB和AOF持久化、等挂载好新的硬盘后,重新创建pvc进行恢复,经过观察,这些redis节点恢复后,operator并不能完成集群自愈,需要手动干预,主要表现为:集群拓扑异常:故障的节点没有被清理掉、新的节点没有以正常的角色加入到集群中。

集群是一个3主3从的规模,3个master,每个master一个slave,这个集群中故障的Pod,在创建pvc后,进行过重启操作,导致现在的拓扑,有4个正常的master,一个无效的节点,原因是恢复的节点没有以slave的角色加入到集群,且集群没有forget掉之前故障的节点

处理新节点

从新的节点上看,没有无效的节点

处理新节点比较简单,只需要对比下哪个master没有slave,将该节点设置为这个master的从节点即可:

执行完命令之后,其他的节点上能看到该节点的角色变了

监控中的拓扑也正常了,现在这种情况,集群是可以正常工作的,但是强迫症,必须要清除掉这个无效的节点。

遗忘旧节点

如果逐台执行cluster forget来遗忘这个无效的节点,由于集群之间会进行通信,同步拓扑信息,如果不是很快同事执行该操作,最后是无法保证成功的,所以写了个脚本,来模拟同时执行:

bath-forget-nodes.sh

#!/bin/bash

set -e

# 查出所有正常的节点(排除状态为fail的),需要在这些节点上执行forget操作 
nodes_addrs=$(redis-cli -a $3 -h $1 -p $2 cluster nodes|grep -v fail| awk '{print $2}')
echo " -------------normal cluster nodes -----------------"
echo " $nodes_addrs "  
echo " --------------------------------------------"  
for addr in ${nodes_addrs[@]}; do
    host=${addr%:*}
    port=${addr#*:}
    # 查出所有需要forget的节点
    del_nodeids=$(redis-cli -a $3 -h $host -p $port cluster nodes|grep -E 'handshake|fail'| awk '{print $1}')
    for nodeid in ${del_nodeids[@]}; do
        echo " -------------delete nodes info -----------------------"  
        echo "delete from host: $host $port, delete node id: $nodeid "
        echo " ------------------------------------------------------"   
        # 执行forget            
        redis-cli -a $3 -h $host -p $port cluster forget $nodeid
    done
done

一共是需要3个参数,IP、port、密码,最好先把执行forget的一行注释掉,看看输出是否符合预期。

执行完之后,每个节点的拓扑都恢复正常了:

大公告成,虽然是比较简单的操作,还是记录一下,好记性不如烂笔头。

### 使用Rancher部署Redis集群的方法 #### 创建必要的命名空间和服务账户 为了更好地管理和隔离资源,在Kubernetes中创建一个新的命名空间来容纳Redis集群的相关组件。这可以通过Rancher UI完成,也可以通过`kubectl`命令实现。 ```bash kubectl create namespace redis-cluster ``` #### 准备持久化存储卷声明(PVC)和配置映射(ConfigMap) 对于高可用性的考虑,需要为每个Redis实例准备独立的数据持久化方案以及共享的配置文件。根据需求定义PVC规格并设置合适的访问模式;同时编写ConfigMap用于保存自定义参数如端口号、密码保护等[^1]。 #### 编写StatefulSet描述符 利用StatefulSet控制器可以方便地管理有状态应用的工作负载。针对Redis集群场景,需指定副本数量、容器镜像版本号、挂载路径以及其他健康检查机制等内容。下面是一个简单的YAML模板: ```yaml apiVersion: apps/v1 kind: StatefulSet metadata: name: redis-statefulset spec: serviceName: "redis" replicas: 6 selector: matchLabels: app: redis template: metadata: labels: app: redis spec: containers: - name: redis image: redis:latest command: ["sh", "-c", "/conf/update-node.sh && exec redis-server /conf/redis.conf"] ports: - containerPort: 6379 protocol: TCP volumeMounts: - mountPath: /data name: data-volume - mountPath: /conf configMap: name: redis-configmap --- apiVersion: v1 kind: Service metadata: name: redis-headless-svc spec: clusterIP: None selector: app: redis ports: - port: 6379 targetPort: 6379 ``` 此部分代码展示了如何构建一个包含六个成员节点(即三个主服务器加其各自的一个备份)的基础架构,并确保它们之间能够相互通信[^4]。 #### 初始集群拓扑结构 当所有Pod都处于运行状态之后,则可借助官方提供的工具——`redis-cli`来进行初始化操作。具体来说就是执行如下所示的一串指令序列,其中涉及到了各个参与者的地址列表及其对应的监听端口信息[^2]: ```shell redis-cli --cluster create \ 192.168.238.142:20301 \ 192.168.238.142:20302 \ 192.168.238.142:20303 \ 192.168.238.142:20304 \ 192.168.238.142:20305 \ 192.168.238.142:20306 \ --cluster-replicas 1 ``` 上述命令会自动分配槽位给不同的master-slave pair组合形成完整的分布式键值数据库体系。 #### 设置网络策略(NetworkPolicy) 考虑到安全性因素,建议实施严格的流量控制措施以防止未经授权的外部连接尝试。为此可以在同一namespace内新增一条NetworkPolicy规则限定仅允许来自内部服务之间的互访请求到达目标端点[^5]。 ```yaml apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-internal-only-access-to-redis spec: podSelector: matchLabels: app: redis policyTypes: - Ingress ingress: - from: - podSelector: matchLabels: app: internal-service ``` 以上步骤构成了基于Rancher平台之上快速搭建稳定可靠的Redis Cluster解决方案的大致流程概述[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值