主要处理问题:
解决 Pod 重启之后,IP 发生变化。
使用 Redis-cluster-Proxy 解决 Redis-Cluster 外部不能访问问题。
PVC的方式进行持久化处理。
redis 启动时指定 IP。
CNI:容器网络接口,主要利用calico组件的两个kubernetes注解:
cni.projectcalico.org/ipAddrs; 注释:单个 pod 固定 IP。
cni.projectcalico.org/ipv4pools。 注释:多个 pod 固定 IP 地址池 。
因 Redis Cluster 请求时,会自动重定向:
通过 NodePort 对外发布 Redis 服务,但是在 K8S 外部也无法连接 Redis PodIP。因此需要通过 redis-cluster-proxy 来实现代理访问。
创建 NFS 文件存储主要是为了 Redis-Cluster 集群提供稳定的后端存储,当Redis的Pod重启或迁移后,依然能获得原先的数据。这里,我们先要创建NFS,然后通过使用PV为 Redis-Cluster 挂载一个远程的NFS路径。
### 下载
yum install -y rpcbind nfs-utils
### 创建需要共享的文件夹
mkdir -p /nfs/k8s/redis/pv{1..9}
### 填写配置文件
[root@NFS-harbor ~]# cat /etc/exports
/nfs/k8s/redis/pv1 192.168.1.0/24(rw,sync,no_root_squash)
/nfs/k8s/redis/pv2 192.168.1.0/24(rw,sync,no_root_squash)
/nfs/k8s/redis/pv3 192.168.1.0/24(rw,sync,no_root_squash)
/nfs/k8s/redis/pv4 192.168.1.0/24(rw,sync,no_root_squash)
/nfs/k8s/redis/pv5 192.168.1.0/24(rw,sync,no_root_squash)
/nfs/k8s/redis/pv6 192.168.1.0/24(rw,sync,no_root_squash)
/nfs/k8s/redis/pv7 192.168.1.0/24(rw,sync,no_root_squash)
/nfs/k8s/redis/pv8 192.168.1.0/24(rw,sync,no_root_squash)
/nfs/k8s/redis/pv9 192.168.1.0/24(rw,sync,no_root_squash)
### 启动 NFS
systemctl start rpcbind
systemctl start nfs
### 本地测试
[root@NFS-harbor ~]# showmount -e 127.0.0.1
Export list for 127.0.0.1:
/nfs/k8s/redis/pv9 192.168.1.0/24
/nfs/k8s/redis/pv8 192.168.1.0/24
/nfs/k8s/redis/pv7 192.168.1.0/24
/nfs/k8s/redis/pv6 192.168.1.0/24
/nfs/k8s/redis/pv5 192.168.1.0/24
/nfs/k8s/redis/pv4 192.168.1.0/24
/nfs/k8s/redis/pv3 192.168.1.0/24
/nfs/k8s/redis/pv2 192.168.1.0/24
/nfs/k8s/redis/pv1 192.168.1.0/24
我这里创建了 9 个 PV 卷,这里不做描述:
[wyh@k8s-master-01 redis]$ cat pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv1
spec:
capacity:
storage: 300M
accessModes:
- ReadWriteOnce
nfs:
server: 192.168.1.88
path: "/nfs/k8s/redis/pv1"
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv2
spec:
capacity:
storage: 300M
accessModes:
- ReadWriteOnce
nfs:
server: 192.168.1.88
path: "/nfs/k8s/redis/pv2"
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv3
spec:
capacity:
storage: 300M
accessModes:
- ReadWriteOnce
nfs:
server: 192.168.1.88
path: "/nfs/k8s/redis/pv3"
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv4
spec:
capacity:
storage: 300M
accessModes:
- ReadWriteOnce
nfs:
server: 192.168.1.88
path: "/nfs/k8s/redis/pv4"
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv5
spec:
capacity:
storage: 300M
accessModes:
- ReadWriteOnce
nfs:
server: 192.168.1.88
path: "/nfs/k8s/redis/pv5"
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv6
spec:
capacity:
storage: 300M
accessModes:
- ReadWriteOnce
nfs:
server: 192.168.1.88
path: "/nfs/k8s/redis/pv6"
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv7
spec:
capacity:
storage: 300M
accessModes:
- ReadWriteOnce
nfs:
server: 192.168.1.88
path: "/nfs/k8s/redis/pv7"
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv8
spec:
capacity:
storage: 300M
accessModes:
- ReadWriteOnce
nfs:
server: 192.168.1.88
path: "/nfs/k8s/redis/pv8"
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv9
spec:
capacity:
storage: 300M
accessModes:
- ReadWriteOnce
nfs:
server: 192.168.1.88
path: "/nfs/k8s/redis/pv9"
请看一下我注释的部分,是网上的通过脚本来解决 POD IP 变更的问题,只解决了本身的 POD IP,而集群连接还是没有解决,我这里有自定义的名称空间,请注意!
[wyh@k8s-master-01 redis_6.2.4]$ cat ConfigMap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: redis-cluster
namespace: judicial
labels:
app: redis-cluster
data:
# fix-ip.sh: |
# #!/bin/sh
# CLUSTER_CONFIG="/data/nodes.conf"
# if [ -f ${CLUSTER_CONFIG} ]; then
# if [ -z "${POD_IP}" ]; then
# echo "Unable to determine Pod IP address!"
# exit 1
# fi
# echo "Updating my IP to ${POD_IP} in ${CLUSTER_CONFIG}"
# sed -i.bak -e "/myself/ s/[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}/${POD_IP}/" ${CLUSTER_CONFIG}
# fi
# exec "$@"
redis.conf: |+
### 绑定IP
bind 0.0.0.0
### 绑定端口
port 6379
### 限制内存大小
maxmemory 1GB
### 启用保护模式
protected-mode yes
### 启用密码认证
### 主要是针对master对应的slave节点设置的,在slave节点数据同步的时候用到
masterauth 123456
### 启用密码认证
### 对登录权限做限制,redis每个节点的requirepass可以是独立、不同的
requirepass 123456
logfile /var/log/redis.log
appendonly yes
daemonize yes
# 启用Cluster
cluster-enabled yes
cluster-config-file /data/nodes.conf
cluster-migration-barrier 1
cluster-require-full-coverage no
cluster-node-timeout 500000
着重看一下 POD 固定 IP 的配置文件,这里使主要利用calico组件的两个。
后边我会单独写一期 calico 设置 IP 地址池的文档去介绍如何实现。
cni.projectcalico.org/ipAddrs :指定 pod ip地址
cni.projectcalico.org/ipv4pools :多个 pod 时 固定IP池
---
apiVersion: v1
kind: Service
metadata:
name: redis-cluster
namespace: judicial
labels:
app: redis-cluster
spec:
ports:
- port: 6379
targetPort: 6379
name: client
- port: 16379
targetPort: 16379
name: gossip
clusterIP: None
selector:
app: redis-cluster
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis-cluster
namespace: judicial
labels:
app: redis-cluster
spec:
serviceName: redis-cluster
replicas: 6
selector:
matchLabels:
app: redis-cluster
template:
metadata:
labels:
app: redis-cluster
### 指定 pod ip地址
annotations:
### 指定单个 pod ip 地址
#"cni.projectcalico.org/ipAddrs": "[\"10.96.1.100\"]"
### 设置多pod固定IP池,这里部署两个IP地址池,固定为六个可用IP,防止 Pod 重启之后,pod ip地址变化,导致 redis 集群连接失败
"cni.projectcalico.org/ipv4pools": "[\"new-pool1\",\"new-pool2\"]"
spec:
containers:
- name: redis
image: 192.168.1.88/redis/redis:6.2.4
ports:
- containerPort: 6379
name: client
- containerPort: 16379
name: gossip
command:
#- "/conf/fix-ip.sh"
- "redis-server"
args:
- "/conf/redis.conf"
- "--cluster-announce-ip"
- "$(POD_IP)"
env:
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
### 就绪指针探测
readinessProbe:
exec:
command:
- sh
- -c
- "redis-cli -h $(hostname) ping"
### 用来表示初始化延迟的时间,也就是告诉监测从多久之后开始运行,单位是秒
initialDelaySeconds: 15
### 用来表示监测的超时时间,如果超过这个时长后,则认为监测失败
timeoutSeconds: 5
livenessProbe:
exec:
command:
- sh
- -c
- "redis-cli -h $(hostname) ping"
initialDelaySeconds: 20
periodSeconds: 3
volumeMounts:
- name: conf
mountPath: /conf
readOnly: false
- name: data
mountPath: /data
readOnly: false
volumes:
- name: conf
configMap:
name: redis-cluster
defaultMode: 0755
volumeClaimTemplates:
- metadata:
name: data
labels:
name: redis-cluster
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 300M
使用 正则过滤出想要的 IP 地址及端口,这个我采用六个节点三主三从的方式进行创建集群。
### -a 后面跟密码
kubectl exec -it redis-cluster-0 -- redis-cli --cluster create --cluster-replicas 1 -a 123456 $((kubectl get pods -l app=redis-cluster -o jsonpath='{range.items[*]}{.status.podIP}:6379 ') | awk '{print $1" "$2" "$3" "$4" "$5" "$6" "}')
主要实现通过 Redis-Cluster-Proxy 中间件如何实现在集群外部对 Redis-Cluster 进行访问。
这里需要强调一下,由于 Redis-Cluster-Proxy 目前比较新,目前官网还没有一个正式版本可以使用,这里我是从 Docker Hub 上下载了一个进行使用,这里不在做演示,自己也可以自定义 Dockerfile 去制作镜像。配置文件这里我指定的是我的 POD IP。
[wyh@k8s-master-01 redis-cluster-proxy]$ cat configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: redis-proxy
namespace: judicial
data:
proxy.conf: |
#cluster redis-cluster:6379
cluster 10.10.10.0:6379
cluster 10.10.10.1:6379
cluster 10.10.10.2:6379
cluster 10.10.10.3:6379
cluster 10.10.10.4:6379
cluster 10.10.10.5:6379
# 配置为Redis Cluster Service
bind 0.0.0.0
# redis-cluster-proxy 对外暴露端口
port 7777
# 线程数量
threads 8
daemonize no
enable-cross-slot yes
# 配置Redis Cluster 认证密码
auth GuoLian@2021
auth-user default
#log-level error
[wyh@k8s-master-01 redis-cluster-proxy]$ cat Deployment.yaml
---
# Redis-Proxy NodePort
apiVersion: v1
kind: Service
metadata:
name: redis-proxy
namespace: judicial
spec:
type: NodePort # 对K8S外部提供服务
ports:
- name: redis-proxy
nodePort: 30001 # 对外提供的端口
port: 7777
protocol: TCP
targetPort: 7777
selector:
app: redis-proxy
---
# Redis-Proxy Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-proxy
namespace: judicial
spec:
replicas: 2
selector:
matchLabels:
app: redis-proxy
template:
metadata:
labels:
app: redis-proxy
spec:
imagePullSecrets:
- name: harbor
containers:
- name: redis-proxy
image: 192.168.1.88/redis/redis-cluster-proxy:v2
imagePullPolicy: Always
command: ["redis-cluster-proxy"]
args:
- -c
- /data/proxy.conf # 指定启动配置文件
ports:
- name: redis-7777
containerPort: 7777
protocol: TCP
volumeMounts:
- name: redis-proxy-conf
mountPath: /data/
volumes: # 挂载proxy配置文件
- name: redis-proxy-conf
configMap:
name: redis-proxy
这里测试连接登录,以及写入数据查看数据。
[root@glzx02 ~]# redis-cli -h 192.168.1.80 -p 30001 -c
192.168.1.80:30001> set aaa 123
OK
192.168.1.80:30001> get aaa
"123"
主要对 POD IP 重启改变和 Redis-Cluster-Proxy 代理进行说明:
### 删除集群重新启动
[wyh@k8s-master-01 redis_6.2.4]$ kubectl delete -f redis-cluster.yaml
service "redis-cluster" deleted
statefulset.apps "redis-cluster" deleted
[wyh@k8s-master-01 redis_6.2.4]$ kubectl apply -f redis-cluster.yaml
service/redis-cluster created
statefulset.apps/redis-cluster created
### 查看集群状态是否正常
[wyh@k8s-master-01 redis_6.2.4]$ kubectl exec -it redis-cluster-0 bash
root@redis-cluster-0:/data# redis-cli -c
127.0.0.1:6379> CLUSTER nodes
4b129009613ded445c84db21a89836f58d6caddc 10.10.10.2:6379@16379 slave 774e53350b385b1c1a453792d7dc74334748ab06 0 1629380407000 3 connected
2d392e5e21af88f28af044cd6f1ca748a67c02c3 10.10.10.1:6379@16379 master - 0 1629380407550 2 connected 5461-10922
c83440702852c535be4da7a76f06c299f5d84c88 :0@0 slave,noaddr 2d392e5e21af88f28af044cd6f1ca748a67c02c3 1629380242083 1629380242083 2 disconnected
8366a9f40a8a46f830ae418b83bbbbfbba2afbce 10.10.10.3:6379@16379 slave 81176db06cf2dd7227a492443b3ed2e49062ef40 0 1629380406546 1 connected
774e53350b385b1c1a453792d7dc74334748ab06 10.10.10.0:6379@16379 master - 0 1629380406000 3 connected 10923-16383
81176db06cf2dd7227a492443b3ed2e49062ef40 10.10.10.5:6379@16379 myself,master - 0 1629380404000 1 connected 0-5460
### 此时查看 有一个 slave 节点处于连接中断状态,此时集群仍可正常使用,将有问题的节点删除集群,并重启此 Pod
127.0.0.1:6379> CLUSTER FORGET c83440702852c535be4da7a76f06c299f5d84c88
OK
### 接下来查找出对应有问题的 pod ,进行删除重建
[wyh@k8s-master-01 redis_6.2.4]$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
redis-cluster-0 1/1 Running 0 6m24s 10.10.10.5 k8s-work-05 <none> <none>
redis-cluster-1 1/1 Running 0 6m1s 10.10.10.1 k8s-work-03 <none> <none>
redis-cluster-2 1/1 Running 0 5m37s 10.10.10.0 k8s-work-01 <none> <none>
redis-cluster-3 1/1 Running 0 5m18s 10.10.10.2 k8s-work-04 <none> <none>
redis-cluster-4 1/1 Running 0 4m57s 10.10.10.3 k8s-work-02 <none> <none>
redis-cluster-5 1/1 Running 0 4m34s 10.10.10.4 k8s-work-06 <none> <none>
### 由上图可知,为 redis-cluster-5,对其进行删除,k8s 会对其重新创建
[wyh@k8s-master-01 redis_6.2.4]$ kubectl delete pod redis-cluster-5
pod "redis-cluster-5" deleted
### 创建完成之后,节点会根据配置文件加入集群
### 此时查看集群状态正常
127.0.0.1:6379> CLUSTER nodes
4b129009613ded445c84db21a89836f58d6caddc 10.10.10.2:6379@16379 slave 774e53350b385b1c1a453792d7dc74334748ab06 0 1629381013792 3 connected
c83440702852c535be4da7a76f06c299f5d84c88 10.10.10.4:6379@16379 slave 2d392e5e21af88f28af044cd6f1ca748a67c02c3 0 1629381014796 2 connected
2d392e5e21af88f28af044cd6f1ca748a67c02c3 10.10.10.1:6379@16379 master - 0 1629381015801 2 connected 5461-10922
8366a9f40a8a46f830ae418b83bbbbfbba2afbce 10.10.10.3:6379@16379 slave 81176db06cf2dd7227a492443b3ed2e49062ef40 0 1629381014000 1 connected
774e53350b385b1c1a453792d7dc74334748ab06 10.10.10.0:6379@16379 master - 0 1629381013000 3 connected 10923-16383
81176db06cf2dd7227a492443b3ed2e49062ef40 10.10.10.5:6379@16379 myself,master - 0 1629381014000 1 connected 0-5460
cluster 10.10.10.0:6379
cluster 10.10.10.1:6379
cluster 10.10.10.2:6379
cluster 10.10.10.3:6379
cluster 10.10.10.4:6379
cluster 10.10.10.5:6379
以上就是我这期的内容,如果大家有更好的解决方案,欢迎大家一起来探讨解答。谢谢!