一、部署前准备
(一)KubeSphere部署redis集群思路
参考上一篇文章的部署思路:KubeSphere安装mysql-CSDN博客
(二)部署方法参考
1、参考Docker Hub的中docker部署redis的方法
部署方法按照Docker Hub官网部署redis的步骤进行,官网地址:https://hub.docker.com/
docker部署redis命令如下:
docker run -d --name my-persistent-redis -p 6379:6379 -v /data/redis:/data redis:latest redis-server --appendonly yes
(三)将redis镜像上传到阿里云私有仓库
#登录
docker login --username=xxx registry.cn-hangzhou.aliyuncs.com
#打标签
docker tag redis:6.2.6 registry.cn-hangzhou.aliyuncs.com/yangbin-docker/redis:6.2.6
#上传
docker push registry.cn-hangzhou.aliyuncs.com/yangbin-docker/redis:6.2.6
二、KubeSphere部署redis集群步骤
1、创建项目(NameSpace)
2、创建保密字典(Secret)
用于连接阿里云redis私有镜像
3、创建redis配置字典
配置文件内容如下:
daemonize no
supervised no
protected-mode no
bind 0.0.0.0
port 6379
cluster-announce-bus-port 16379
cluster-enabled yes
appendonly yes
cluster-node-timeout 5000
dir /data
cluster-config-file /data/nodes.conf
requirepass redis_123
masterauth redis_123
pidfile /data/redis.pid
loglevel notice
logfile /data/redis_log
4、点击工作负载,选择StatefulSet(有状态副本集)
因为redis是开源服务所以最好是选择有状态副本集
4.1、填写创建的名称---> 选择项目(选择指定的项目方便管理)
4.2、添加容器
步骤一:选择上述创建的阿里云保密字典,填写容器仓库名称和版本号
步骤二:确认私有镜像链接是否正确(能搜索出镜像的详细信息说明配置正确)
步骤三:定义容器的名称(可根据自己的习惯自定义)
步骤四:填写容器资源限制(生产环境需要评估)
步骤五:配置端口用于访问容器内部
步骤六:填写启动命令选项(redis不需要配置环境变量)
步骤七:同步主机时区
步骤八:添加持久卷声明模板存放redis数据(可以多个路径进行挂载)
步骤九:挂载配置字典(挂载配置时需要选择特定键指向对应的文件)
因为在创建配置时指定的键值是redis.conf但是进行启动时指定的配置文件是redis-cluster.conf
5、创建容器查看redis集群状态
6、创建服务(Service)让外部可以访问到redis
步骤一:基本信息栏:填写服务名称 --> 选择项目
步骤二:服务设置栏:选择指定工作负载 --> 选择有状态副本集
步骤三:服务设置栏:设置端口(设置容器端口和服务端口)
步骤四:高级设置栏:选择外部访问 --> 选择访问模式为NodePort;完成创建
7、外部环境连接数据库测试
在RDM工具上填写redis的连接信息
8、检查集群数据存储是否正确
9、操作生成的yaml文件
kind: StatefulSet
apiVersion: apps/v1
metadata:
name: redis-cluster
namespace: redis-cluster
labels:
app: redis-cluster
annotations:
kubesphere.io/creator: admin
kubesphere.io/description: redis集群
spec:
replicas: 6
selector:
matchLabels:
app: redis-cluster
template:
metadata:
creationTimestamp: null
labels:
app: redis-cluster
annotations:
kubesphere.io/creator: admin
kubesphere.io/imagepullsecrets: '{"redis-cluster":"aliyun-secretredis"}'
logging.kubesphere.io/logsidecar-config: '{}'
spec:
volumes:
- name: host-time
hostPath:
path: /etc/localtime
type: ''
- name: volume-c8t44w
configMap:
name: redis-cluster-conf
items:
- key: redis-cluster.conf
path: redis-cluster.conf
defaultMode: 420
containers:
- name: redis-cluster
image: 'registry.cn-hangzhou.aliyuncs.com/yangbin-docker/redis:6.2.6'
command:
- redis-server
args:
- /etc/redis/redis-cluster.conf
- '--cluster-announce-ip'
- $(POD_IP)
ports:
- name: http-6379
containerPort: 6379
protocol: TCP
env:
- name: HOST_IP
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: status.hostIP
- name: POD_IP
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: status.podIP
- name: POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
- name: TZ
value: Asia/Shanghai
resources:
limits:
cpu: '1'
memory: 1000Mi
volumeMounts:
- name: host-time
mountPath: /etc/localtime
- name: redis-data-pvc
mountPath: /data
- name: volume-c8t44w
readOnly: true
mountPath: /etc/redis
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
imagePullPolicy: IfNotPresent
restartPolicy: Always
terminationGracePeriodSeconds: 30
dnsPolicy: ClusterFirst
serviceAccountName: default
serviceAccount: default
securityContext: {}
imagePullSecrets:
- name: aliyun-secretredis
schedulerName: default-scheduler
volumeClaimTemplates:
- kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: redis-data-pvc
namespace: redis-cluster
creationTimestamp: null
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: nfs-client
volumeMode: Filesystem
status:
phase: Pending
serviceName: redis-cluster-3d8c
podManagementPolicy: OrderedReady
updateStrategy:
type: RollingUpdate
rollingUpdate:
partition: 0
revisionHistoryLimit: 10
三、初始化redis集群
1、初始化集群
#在master节点上执行集群初始化命令
kubectl exec -it redis-cluster-0 -n redis-cluster -- redis-cli -a redis_123 --cluster create --cluster-replicas 1 $(kubectl get pods -n redis-cluster -l app=redis-cluster -o jsonpath='{range.items[*]}{.status.podIP}:6379 {end}')
2、查看集群节点状态
主从对应关系如下
#查看集群节点状态
KubeSphere(192.168.72.130:32728)>cluster nodes
"b0bbab8b5f2df749838a2ce91909a14165be1b16 192.169.166.150:6379@16379 master - 0 1740476861325 2 connected 5461-10922
3383c9422337b76a4e4595bdd0d7f50845ddba11 192.169.104.25:6379@16379 slave 080af61b560842ac04025e6820a68aaa6cb10b8b 0 1740476861000 3 connected
f5e7cdd9d7f4c895a1a84cfcb3f5d74196569e8e 192.169.104.26:6379@16379 slave b0bbab8b5f2df749838a2ce91909a14165be1b16 0 1740476862000 2 connected
ccbb5e70f4434b5468df3c3d9a884a428a2e79fc 192.169.104.24:6379@16379 myself,master - 0 1740476861000 1 connected 0-5460
080af61b560842ac04025e6820a68aaa6cb10b8b 192.169.166.151:6379@16379 master - 0 1740476861000 3 connected 10923-16383
da032400ebd5c0a7e4efec444b00ebece6bf8ec1 192.169.166.152:6379@16379 slave ccbb5e70f4434b5468df3c3d9a884a428a2e79fc 0 1740476862333 1 connected
3、数据写入验证
3.1、批量插入数据
#批量插入20条数据
for i in {1..20};do kubectl exec -it redis-cluster-0 -n redis-cluster -- redis-cli -c -p 6379 -a redis_123 -c set k_${i} v_${i}; done
插入20条数据可以看到有7条数据在该节点上存储
3.2、批量查看数据
#使用命令查看数据插入的情况
for i in {1..20};do kubectl exec -it redis-cluster-0 -n redis-cluster -- redis-cli -c -p 6379 -a redis_123 -c get k_${i}; done
#查看数据插入的情况
[root@master k8s]# kubectl exec -it redis-cluster-0 -n redis-cluster -- redis-cli -c -p 6379 -a redis_123
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379>
127.0.0.1:6379> keys *
1) "k_13"
2) "k_5"
3) "k_9"
4) "k_17"
5) "k_16"
6) "k_4"
7) "k_1"
8) "k_8"
127.0.0.1:6379>
127.0.0.1:6379> get k_13
"v_13"
127.0.0.1:6379>
127.0.0.1:6379> get k_5
"v_5"
127.0.0.1:6379>
127.0.0.1:6379>
127.0.0.1:6379>
3.3、批量删除数据
#批量删除数据
for i in {1..20};do kubectl exec -it redis-cluster-0 -n redis-cluster -- redis-cli -c -p 6379 -a redis_123 -c del k_${i}; done
四、Pod发生重启时IP不同步到redis集群内部问题处理
集群节点关系对应关系如下:
master | slave |
redis-cluster-0 (192.169.104.24) | redis-cluster-4 (192.169.166.152) |
redis-cluster-1 (192.169.166.150) | redis-cluster-5 (192.169.104.26) |
redis-cluster-2 (192.169.166.151) | redis-cluster-3 (192.169.104.25) |
1、删除redis-cluster-0节点模拟节点故障
1.1、正常的集群节点状态
1.2、删除redis-cluster-0
1.3、Pod容器的IP已经改变而redis集群中的IP没有变化
虽然redis-cluster-0容器已经重新创建,但是redis集群连接信息并没有发生变化,因为在部署时没有设置--cluster-announce-ip,$(POD_IP)参数所以pod在重新创建时没有向集群暴露自己的IP
2、--cluster-announce-ip,$(POD_IP)参数详解
在 K8S 部署 Redis 时,--cluster-announce-ip
和$(POD_IP)
的含义如下:
2.1、--cluster-announce-ip详解
--cluster-announce-ip
:这是 Redis 启动时的一个参数,用于指定 Redis 节点向集群中其他节点宣告自己的 IP 地址。在 Kubernetes 环境中,Pod 的 IP 地址可能会发生变化,比如在 Pod 重启、节点故障转移等情况下。通过设置--cluster-announce-ip
参数,Redis 节点可以及时将自己新的 IP 地址告知集群中的其他节点,确保集群能够正确地进行数据路由和节点间的通信,维持集群的正常运行。
2.2、$(POD_IP)详解
$(POD_IP)
:这是一个环境变量引用,通常在 Kubernetes 的 Pod 配置中使用。它会在 Pod 启动时被替换为该 Pod 实际分配到的 IP 地址。在 Redis 的部署配置中,将$(POD_IP)
作为--cluster-announce-ip
的值,就是告诉 Redis 以当前 Pod 的 IP 地址来向集群宣告自己的地址。
2.3、POD_IP环境变量,并从status.podIP字段获取值
在 values.yaml
文件中,找到Redis容器的环境变量配置部分,添加 POD_IP
环境变量。示例如下:
redis:
image: redis:latest
args:
- "--cluster-announce-ip"
- "$(POD_IP)"
- "--protected-mode"
- "no"
env:
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
3、解决集群在Pod重启时IP改变不能同步到集群问题
上述说到缺少--cluster-announce-ip和$(POD_IP)参数导致Pod在重启时不能将新的IP同步到redis集群中,所以在部署时需要在启动命令中加入这两个参数,在环境变量中要定义POD_IP 环境变量,并从 status.podIP 字段获取值。
3.1、在启动命令中加入--cluster-announce-ip和$(POD_IP)参数
3.2、定义环境变量
3.2.1、在添加完启动命令之后选择编辑yaml文件
3.2.2、在yaml文件中添加如下内容
#在args变量之后添加下边的内容
env:
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: TZ
value: "Asia/Shanghai"
根据在yaml中添加环境变量生成如下内容,但是在KubeSphere中找不到fieldRef选项所以在yaml中添加即可。
3.3、 删除redis-cluster-0节点模拟节点故障
Pod重新启动后看集群中的IP是否发生变化
3.3.1、删除之前IP为192.169.104.6
3.3.2、删除redis-cluster-0容器查看集群中IP的变化
容器重新启动之后的IP为192.169.104.9
集群中的IP已经发生改变
4、集群缩容
4.1、将之前的6个节点缩容到3个节点
4.2、删除掉之前在集群中写入的数据
4.3、恢复redis-cluster-3节点查看数据是否会被同步
启动redis-cluster-3节点
查看到redis3上的数据已经被同步
5、集群扩容
5.1、将集群节点扩容到6个
5.2、扩容之后查看写入的数据是否已经同步到
扩容之后写入的数据能正常同步!!