master:192.168.91.166
node2:192.168.91.167
node3:192.168.91.168

一、所有节点创建目录

二、创建命名空间

kubectl create namespace redis-cluster
##kubectl get ns
三、创建PV
###创建PV
kubectl apply -f redis-pv.yaml
####查看
kubectl get pv


redis-pv.yaml内容:
apiVersion: v1
kind: PersistentVolume
metadata:
name: redis-pv-0
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: local-path
local:
path: /data/redis/redis0
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- k8s-master
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: redis-pv-1
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: local-path
local:
path: /data/redis/redis1
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- k8s-node2
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: redis-pv-2
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: local-path
local:
path: /data/redis/redis2
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- k8s-node3
四、创建配置文件ConfigMap
(ConfigMap:redis 主配置 + sentinel 哨兵配置)
#####创建配置文件ConfigMap
kubectl apply -f redis-config.yml
#####基础查看:确认资源存在kubectl get configmap -n redis-cluster

redis-config.yaml内容:
apiVersion: v1
kind: ConfigMap
metadata:
name: redis-conf
namespace: redis-cluster
data:
redis.conf: |
port 6379
requirepass Redis@123456
masterauth Redis@123456
daemonize no
logfile /data/redis.log
dir /data
appendonly yes
protected-mode no
tcp-keepalive 60
# 允许从节点同步密码
replrequirepass Redis@123456
sentinel.conf: |
port 26379
sentinel monitor redis-master redis-0.redis-service.redis-cluster.svc.cluster.local 6379 2
sentinel auth-pass redis-master Redis@123456
sentinel down-after-milliseconds redis-master 30000
sentinel parallel-syncs redis-master 1
sentinel failover-timeout redis-master 180000
port 26379
# 监控主节点集群名、主节点域名、端口、法定投票数2
sentinel monitor redis-master redis-0.redis-service.redis-cluster.svc.cluster.local 6379 2
sentinel auth-pass redis-master Redis@123456
# 30秒无响应判定主观下线
sentinel down-after-milliseconds redis-master 30000
# 故障转移时同时同步从节点数量
sentinel parallel-syncs redis-master 1
# 故障转移总超时
sentinel failover-timeout redis-master 180000
# 禁止哨兵自动重写配置文件(容器只读环境推荐加上)
sentinel config-epoch redis-master 0
已把哨兵监控域名统一为 redis-service(和你的无头服务名称匹配,之前名称不一致 bug 已修复)
五、创建服务(Headless 无头服务,内部集群通信)
##创建内部无头服务
kubectl apply -f redis-service.yaml
##查看
kubectl get svc -n redis-cluster


redis-service.yaml内容:
apiVersion: v1
kind: Service
metadata:
name: redis-service
namespace: redis-cluster
spec:
selector:
app: redis
ports:
- port: 6379
targetPort: 6379
clusterIP: None
六、创建StatefulSet 一主两从主体,已挂载自定义配置
#部署Redis有状态集群
kubectl apply -f redis-sts.yaml
###查看 StatefulSet 整体状态
kubectl get sts -n redis-cluster
###查看生成的 3 个 Redis Pod(最核心)
kubectl get pods -n redis-cluster
###查看 PVC 绑定情况(核对 PV 是否匹配上)
kubectl get pv,pvc -n redis-cluster



进入容器内部校验配置 & 挂载是否生效

redis-sts.yaml内容:
# Redis StatefulSet 主体
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
namespace: redis-cluster
spec:
replicas: 3
serviceName: redis-service
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
# 容忍master控制平面污点,仅本Redis Pod可调度master
tolerations:
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule
# 容忍磁盘压力污点
- key: node.kubernetes.io/disk-pressure
operator: Exists
effect: NoSchedule
containers:
- name: redis
image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/redis:7-alpine
ports:
- containerPort: 6379
name: redis-port
# 数据持久化挂载
volumeMounts:
- name: redis-data
mountPath: /data
# 挂载自定义redis配置文件
- name: redis-config
mountPath: /etc/redis
# 启动加载自定义redis.conf
command: ["redis-server", "/etc/redis/redis.conf"]
# 引入configmap配置卷
volumes:
- name: redis-config
configMap:
name: redis-conf
# 自动创建PVC模板
volumeClaimTemplates:
- metadata:
name: redis-data
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: local-path
resources:
requests:
storage: 1Gi
七、创建服务(外网服务)
redis-service-out.yaml(NodePort 外网访问入口)
####开启外网访问端口
kubectl apply -f redis-service-out.yaml
####查看所有 service 列表
kubectl get svc -n redis-cluster


redis-service-out.yaml内容:
apiVersion: v1
kind: Service
metadata:
name: redis-nodeport
namespace: redis-cluster
spec:
selector:
app: redis
type: NodePort
ports:
- port: 6379
targetPort: 6379
nodePort: 30084
八、集群外部访问(任选集群k8节点 IP)


九、创建哨兵sentinel集群:Deployment
####创建哨兵群
kubectl apply -f redis-sentinel.yaml
####观察状态


两步验证哨兵集群有效性
任意哨兵客户端查看集群状态
kubectl exec -it redis-sentinel-5d5cd9fdf-22m2j -n redis-cluster -- redis-cli -p 26379
哨兵内部执行查询命令
# 查看主节点完整信息
SENTINEL master redis-master

# 查看另外2个哨兵节点
SENTINEL sentinels redis-master

# 查看从节点列表
SENTINEL slaves redis-master

核心异常问题
SENTINEL slaves redis-master 返回 empty array(空数组)
1. 给两台从库配置主从复制
分别进入 redis-1、redis-2 执行:
# 进入redis-1
kubectl exec -it redis-1 -n redis-cluster -- redis-cli
AUTH Redis@123456
# 设置为从节点,填写主节点IP和端口
SLAVEOF 10.244.1.173 6379
# 进入redis-2
kubectl exec -it redis-2 -n redis-cluster -- redis-cli
AUTH Redis@123456
SLAVEOF 10.244.1.173 6379

出现问题
哨兵 pod 执行日志查看:
kubectl logs redis-sentinel-86ddbf8ffc-d2pj2 -n redis-cluster
kubectl describe pod redis-sentinel-86ddbf8ffc-d2pj2 -n redis-cluster


解决问题

方案 2:直接使用 redis-0 Pod 固定 IP(彻底规避 DNS 解析问题)

####先获取 redis-0 的集群 IP
kubectl get pod redis-0 -n redis-cluster -o jsonpath='{.status.podIP}'

redis-config.yaml把 sentinel 配置改成 IP 形式
sentinel monitor redis-master 这里粘贴查到的IP 6379 2


####更新配置文件
kubectl apply -f redis-config.yaml
####删除异常哨兵
kubectl delete -f redis-sentinel.yaml
####重新拉起哨兵
kubectl apply -f redis-sentinel.yaml
redis-redis-sentinel.yaml内容:
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-sentinel
namespace: redis-cluster
spec:
replicas: 3
selector:
matchLabels:
app: redis-sentinel
template:
metadata:
labels:
app: redis-sentinel
spec:
containers:
- name: redis-sentinel
image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/redis:7-alpine
ports:
- containerPort: 26379
volumeMounts:
# 只读初始配置
- name: config-init
mountPath: /etc/redis-init
# 可读写运行配置目录
- name: conf-write
mountPath: /etc/redis
# 数据目录
- name: sentinel-data
mountPath: /data
# 启动脚本:复制配置 + 启动哨兵
command:
- sh
- -c
- |
cp /etc/redis-init/sentinel.conf /etc/redis/
exec redis-sentinel /etc/redis/sentinel.conf
volumes:
# 原始配置来自configmap(只读)
- name: config-init
configMap:
name: redis-conf
defaultMode: 0644
# 可读写临时目录
- name: conf-write
emptyDir: {}
- name: sentinel-data
emptyDir: {}
十、哨兵sentinel故障切换测试(等主从识别正常后)
手动关闭主节点 redis-0,等待 30s(down-after-milliseconds=30000),
哨兵会自动投票选出新主库,从节点自动切换角色
完整故障切换演练步骤(可一步步照着执行)
1. 前置确认状态
任意哨兵节点执行
redis
SENTINEL master redis-master
确认:
主节点:10.244.1.173(redis-0)
从节点数量:1 个
主节点状态正常
2. 关停原主节点 redis-0
bash
# 删除主节点Pod,模拟宕机
kubectl delete pod redis-0 -n redis-cluster

3. 等待超时时间(30 秒)
配置 down-after-milliseconds 30000 = 30s,哨兵等待 30s 判定原主节点下线,随后开始哨兵集群投票选举新主。
4. 观测切换全过程
方式 1:哨兵端持续查看
SENTINEL master redis-master

方式 2:进入原从节点查看角色变化
切换成功后:
role:master,不再绑定 SLAVEOF


浙公网安备 33010602011771号