Kubernetes Redis 7.2 集群部署:NFS存储+StatefulSet 6节点配置详解
Redis作为高性能的内存数据库,在分布式系统中扮演着关键角色。本文将深入探讨如何在Kubernetes环境中,利用StatefulSet和NFS存储部署一个高可用的Redis 7.2集群(3主3从架构)。不同于传统手动配置方式,我们将采用Kubernetes原生资源实现自动化部署和管理,显著提升运维效率。
1. 架构设计与核心组件
在Kubernetes中部署Redis集群需要考虑以下几个关键因素:
- 数据持久化:Redis作为有状态服务,需要确保数据在Pod重启或迁移时不丢失
- 服务发现:集群节点需要能够相互发现并建立连接
- 高可用性:主从节点应分布在不同的物理节点上
- 自动化运维:包括集群初始化、故障恢复等操作
我们选择的解决方案组合如下:
| 组件 | 用途 | 优势 |
|---|---|---|
| StatefulSet | 管理Redis Pod | 提供稳定的网络标识和有序部署 |
| NFS StorageClass | 动态提供持久化存储 | 支持多节点读写,简化PV管理 |
| Headless Service | 内部DNS发现 | 为每个Pod提供唯一域名 |
| ClusterIP Service | 外部访问入口 | 统一访问入口,负载均衡 |
| Init Job | 自动初始化集群 | 替代手动执行redis-cli命令 |
关键配置要点:
- 每个Redis Pod独占一个PV,确保数据隔离
- 通过Pod反亲和性(Anti-Affinity)分散主节点
- 使用ConfigMap统一管理Redis配置文件
- 通过Job自动完成集群节点握手和槽位分配
2. 环境准备与NFS配置
2.1 NFS服务器设置
首先在任意节点(可以是K8s集群外)部署NFS服务:
# 安装NFS服务端 sudo apt-get install nfs-kernel-server -y # 创建共享目录 sudo mkdir -p /nfs/redis sudo chmod -R 777 /nfs/redis # 配置导出目录 echo "/nfs/redis *(rw,sync,no_subtree_check,no_root_squash)" | sudo tee -a /etc/exports # 应用配置 sudo exportfs -ra sudo systemctl restart nfs-kernel-server2.2 Kubernetes端NFS配置
在Kubernetes集群中创建StorageClass,实现动态PV供给:
# nfs-storageclass.yaml apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: redis-nfs-sc provisioner: example.com/nfs parameters: archiveOnDelete: "false" mountOptions: - hard - nfsvers=4.1提示:如果使用云服务商的托管Kubernetes,建议使用对应的CSI驱动(如AWS EFS CSI)替代原生NFS
3. Redis集群核心配置
3.1 ConfigMap配置
创建包含Redis配置和初始化脚本的ConfigMap:
# redis-configmap.yaml apiVersion: v1 kind: ConfigMap metadata: name: redis-cluster-config data: 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 port 6379 dir /data update-node.sh: | #!/bin/sh REDIS_NODES="/data/nodes.conf" if [ -f "${REDIS_NODES}" ]; then 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} fi exec "$@"3.2 StatefulSet配置
这是最核心的部署文件,实现了6节点Redis集群:
# redis-statefulset.yaml 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: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - redis-cluster topologyKey: kubernetes.io/hostname containers: - name: redis image: redis:7.2-alpine command: ["/conf/update-node.sh", "redis-server", "/conf/redis.conf"] ports: - containerPort: 6379 name: client - containerPort: 16379 name: gossip 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-config defaultMode: 0755 volumeClaimTemplates: - metadata: name: data spec: accessModes: [ "ReadWriteOnce" ] storageClassName: redis-nfs-sc resources: requests: storage: 5Gi关键参数解析:
podAntiAffinity:确保Redis Pod分散在不同节点update-node.sh:动态更新节点配置文件中的IP地址volumeClaimTemplates:为每个Pod自动创建PVC
3.3 服务配置
创建两种Service分别用于集群内部通信和外部访问:
# redis-services.yaml apiVersion: v1 kind: Service metadata: name: redis-cluster spec: clusterIP: None ports: - port: 6379 targetPort: 6379 name: client - port: 16379 targetPort: 16379 name: gossip selector: app: redis-cluster --- apiVersion: v1 kind: Service metadata: name: redis-access spec: type: ClusterIP ports: - port: 6379 targetPort: 6379 selector: app: redis-cluster4. 集群初始化与验证
4.1 自动初始化Job
传统方式需要手动执行redis-cli命令初始化集群,我们通过Job实现自动化:
# redis-init-job.yaml apiVersion: batch/v1 kind: Job metadata: name: redis-cluster-init spec: template: spec: containers: - name: cluster-init image: redis:7.2-alpine command: - sh - -c - | sleep 10 redis-cli --cluster create \ redis-cluster-0.redis-cluster:6379 \ redis-cluster-1.redis-cluster:6379 \ redis-cluster-2.redis-cluster:6379 \ redis-cluster-3.redis-cluster:6379 \ redis-cluster-4.redis-cluster:6379 \ redis-cluster-5.redis-cluster:6379 \ --cluster-replicas 1 --cluster-yes restartPolicy: OnFailure4.2 部署流程
按顺序应用所有配置文件:
kubectl apply -f nfs-storageclass.yaml kubectl apply -f redis-configmap.yaml kubectl apply -f redis-services.yaml kubectl apply -f redis-statefulset.yaml # 等待所有Pod就绪 kubectl wait --for=condition=Ready pod -l app=redis-cluster --timeout=300s # 初始化集群 kubectl apply -f redis-init-job.yaml4.3 集群验证
检查集群状态:
# 查看Pod运行状态 kubectl get pods -l app=redis-cluster -o wide # 检查集群节点关系 kubectl exec redis-cluster-0 -- redis-cli cluster nodes # 测试数据读写 kubectl exec -it redis-cluster-0 -- redis-cli set test-key "hello" kubectl exec -it redis-cluster-1 -- redis-cli get test-key5. 高级配置与优化
5.1 资源限制与探针
在生产环境中,应为Redis容器配置资源限制和健康检查:
resources: limits: cpu: "2" memory: "4Gi" requests: cpu: "1" memory: "2Gi" livenessProbe: exec: command: - redis-cli - ping initialDelaySeconds: 30 periodSeconds: 10 readinessProbe: exec: command: - redis-cli - ping initialDelaySeconds: 5 periodSeconds: 105.2 密码认证
增强安全性可启用Redis密码认证:
# 在ConfigMap的redis.conf中添加 requirepass your-strong-password masterauth your-strong-password # 初始化Job需要相应修改 redis-cli --cluster create ... -a your-strong-password5.3 监控与告警
建议配置Prometheus监控Redis集群:
# 添加Annotations暴露指标 annotations: prometheus.io/scrape: "true" prometheus.io/port: "9121"6. 故障排查与维护
6.1 常见问题处理
节点无法加入集群:
- 检查Pod间网络连通性
- 验证DNS解析是否正常
- 查看Redis日志:
kubectl logs <pod-name>
数据持久化问题:
- 检查PVC/PV状态:
kubectl get pvc,pv - 验证NFS服务器连接和权限
- 检查存储空间使用情况
6.2 集群扩容
横向扩展Redis集群(从6节点扩展到9节点):
# 扩展StatefulSet kubectl scale statefulset redis-cluster --replicas=9 # 添加新节点到集群 kubectl exec redis-cluster-0 -- redis-cli --cluster add-node \ redis-cluster-6.redis-cluster:6379 \ redis-cluster-0.redis-cluster:63796.3 备份与恢复
建议的备份策略:
- 定期对NFS存储进行快照
- 使用Redis的BGSAVE命令创建RDB备份
- 通过
redis-cli --cluster backup命令导出集群数据
# 示例备份命令 kubectl exec redis-cluster-0 -- redis-cli bgsave