Redis Pod 无法加入 Redis 集群



我想在 kubernetes 中创建 6 个节点的 redis 集群。我正在使用Minikube运行Kubernetes

下面是我创建 6 节点群集的实现。

kind: StatefulSet
metadata:
generation: 1
labels:
app: demo-app
name: demo-app
namespace: default
spec:
podManagementPolicy: OrderedReady
replicas: 6
revisionHistoryLimit: 10
selector:
matchLabels:
app: demo-app
serviceName: ""
template:
metadata:
creationTimestamp: null
labels:
app: demo-app
spec:
containers:
- command:
- redis-server
- --port 6379
- --cluster-enabled yes
- --cluster-node-timeout 5000
- --appendonly yes
- --appendfilename appendonly-6379.aof
image: redis:latest
imagePullPolicy: Always
name: demo-app
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- name: redis-pvc
mountPath: /var
- image: nginx:1.12
imagePullPolicy: IfNotPresent
name: redis-exporter
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
updateStrategy:
rollingUpdate:
partition: 0
type: RollingUpdate
volumeClaimTemplates:
- metadata: 
name: redis-pvc
spec: 
accessModes: 
- ReadWriteOnce
resources:
requests:
storage: 1Gi

创建有状态集后,我正在从其中一个 pod 内部执行 redis 创建集群命令。

redis-cli --cluster create 172.17.0.4:6379 172.17.0.5:6379  172.17.0.6:6379  172.17.0.7:6379  172.17.0.8:6379  172.17.0.9:6379 --cluster-replicas 1

这些都是豆荚的 ip。有了这个,我就可以启动我的集群了。但是一旦我手动删除了一个 pod 使用

kubernetes delete pod <podname> 

例如,删除 IP 地址为 172.17.0.6:6379 的 redis 节点,该节点应该是主节点。删除 redis 集群后,集群状态为:

127.0.0.1:6379> cluster nodes
1c8c238c58d99181018b37af44c2ebfe049e4564 172.17.0.9:6379@16379 slave 4b75e95772887e76eb3d0c9518d13def097ce5fd 0 1579496695000 6 connected
96e6be88d29d847aed9111410cb0f790db068d0e 172.17.0.8:6379@16379 slave 0db23edf54bb57f7db1e2c9eb182ce956229d16e 0 1579496696596 5 connected
c8be98b16a8fa7c1c9c2d43109abafefc803d345 172.17.0.7:6379@16379 master - 0 1579496695991 7 connected 10923-16383
0db23edf54bb57f7db1e2c9eb182ce956229d16e 172.17.0.4:6379@16379 myself,master - 0 1579496694000 1 connected 0-5460
4daae1051e6a72f2ffc0675649e9e2dad9430fc4 172.17.0.6:6379@16379 master,fail - 1579496680825 1579496679000 3 disconnected
4b75e95772887e76eb3d0c9518d13def097ce5fd 172.17.0.5:6379@16379 master - 0 1579496695000 2 connected 5461-10922

一段时间后,它变为:

127.0.0.1:6379> cluster nodes
1c8c238c58d99181018b37af44c2ebfe049e4564 172.17.0.9:6379@16379 slave 4b75e95772887e76eb3d0c9518d13def097ce5fd 0 1579496697529 6 connected
96e6be88d29d847aed9111410cb0f790db068d0e 172.17.0.8:6379@16379 slave 0db23edf54bb57f7db1e2c9eb182ce956229d16e 0 1579496696596 5 connected
c8be98b16a8fa7c1c9c2d43109abafefc803d345 172.17.0.7:6379@16379 master - 0 1579496698031 7 connected 10923-16383
0db23edf54bb57f7db1e2c9eb182ce956229d16e 172.17.0.4:6379@16379 myself,master - 0 1579496697000 1 connected 0-5460
4daae1051e6a72f2ffc0675649e9e2dad9430fc4 :0@0 master,fail,noaddr - 1579496680825 1579496679000 3 disconnected
4b75e95772887e76eb3d0c9518d13def097ce5fd 172.17.0.5:6379@16379 master - 0 1579496697028 2 connected 5461-10922

由于 redis 集群提供自动故障转移,但 pod 的 redis 无法自动加入集群?

还是我应该手动将该 Pod 加入集群?

我已经解决了这个问题,并使用此有状态集 yaml 创建了一个 redis 集群。 问题是我没有在持久卷中挂载群集配置文件。群集配置文件包含其他节点的位置。现在,群集配置文件将在 Pod 重新启动后保留。

由于 Redis 集群在八卦协议上工作。它只需要一个活动节点即可获取整个群集的配置。

现在有状态集的最终配置是:

apiVersion: apps/v1
kind: StatefulSet
metadata:
generation: 1
labels:
app: demo-app
name: demo-app
namespace: default
spec:
podManagementPolicy: OrderedReady
replicas: 6 
revisionHistoryLimit: 10
selector:
matchLabels:
app: demo-app
serviceName: ""
template:
metadata:
creationTimestamp: null
labels:
app: demo-app
spec:
containers:
- command:
- redis-server
- --port 6379
- --cluster-enabled yes
- --cluster-node-timeout 5000
- --appendonly yes
- --cluster-config-file /var/cluster-config.conf
- --appendfilename appendonly-6379.aof
image: redis
imagePullPolicy: Always
name: demo-app
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- name: redis-pvc
mountPath: /var
- image: nginx:1.12
imagePullPolicy: IfNotPresent
name: redis-exporter
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
updateStrategy:
rollingUpdate:
partition: 0
type: RollingUpdate
volumeClaimTemplates:
- metadata: 
name: redis-pvc
spec: 
accessModes: 
- ReadWriteOnce
resources:
requests:
storage: 1Gi

我所做的唯一更改是添加 --cluster-config-file/var/cluster-config.conf参数,同时启动 redis-server。

我强烈建议考虑使用 Sentinel 而不是 Redis 中的集群命令来考虑使用 HA 选项。Sentinel正是为了做到这一点而设计的。

总的来说,根据我的经验,Redis的架构在Kubernetes网络中并不合适。告诉 Redis 实例您的从属服务器的位置,尤其是以编程方式告诉 Redis 实例可能是一场噩梦(正如您已经看到必须手动触发集群一样(,尤其是当您认为 Pod 到 Pod 的通信不符合 Kubernetes 网络层次结构时。

我对集群命令在 Kubernetes 中的行为方式没有信心,尤其是 pod 的短暂性。

我实际上维护了一个试图规避这些问题的掌舵图。这提供了一种机制,用于从集群外部广播您的 Redis 。你可以在这里找到它。

要扩展几个场景来说明为什么这不起作用:

  1. 如果丢失了原始主节点,您将如何告诉应用程序连接到新的主节点?除非你有一些抽象层单独查询它们,询问谁是主人。Sentinel确实需要更多的工作,它就是为了规避这个确切的问题而构建的。

  2. 如果您删除从属服务器,由于这是通过IP绑定的,您将完全失去该从站,因为将创建一个绑定到为集群定义的CIDR中的新IP的新设备。 6 个节点变为 5 个。您可以通过在 CIDR 上使用/24 地址定义节点来解决此问题,但您基本上是为每个 Redis 实例部署一个节点,这似乎违背了 orchstrator 的观点。

最新更新