Redis Pods无法加入Redis集群

时间:2020-01-20 04:55:37

标签: kubernetes redis minikube kubernetes-statefulset

我想在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 create cluster命令。

 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

这些都是pod的ips。有了这个,我就能启动集群了。但是一旦我使用

手动删除单个吊舱
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无法自动加入集群吗?

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

2 个答案:

答案 0 :(得分:1)

我强烈建议您使用Sentinel而不是Redis中的cluster命令来考虑为此使用HA选项。 Sentinel正是为此目的而设计的。

根据我的经验,Redis的总体架构在Kubernetes网络内部并不理想。告诉Redis实例,尤其是以编程方式告诉您的从属实例,可能是一场噩梦(就像您已经看到的必须手动触发集群一样),尤其是当您认为Pod到Pod的通信不符合Kubernetes网络体系结构时。

我对集群命令在Kubernetes内部的行为方式(尤其是Pod的短暂特性)如何运作并不充满信心。

我实际上维护着一张舵图,试图规避这些问题。这提供了一种机制,还可以从群集外部广播您的Redis。您可以找到它here

扩展几种方案说明为什么不起作用:

  1. 如果丢失了原始主机,您将如何告诉您的应用程序连接到新主机?除非您有一些抽象层单独查询它们,然后询问谁是主数据库。 Sentinel的运行实际上是需要做的工作,而Sentinel的目的是规避这个确切的问题。

  2. 如果删除从属服务器,由于它是通过IP绑定的,因此您将完全失去该从属服务器,因为将为为群集定义的CIDR中的新IP绑定创建一个新的veth。 6个节点变为5。您可以通过在CIDR上用/ 24地址定义节点来解决此问题,但是基本上每个Redis实例都将部署一个节点,这似乎不符合协调器的要求。

答案 1 :(得分:1)

我已经解决了这个问题,并使用此有状态集合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

我所做的唯一更改是添加 在启动Redis服务器时-cluster-config-file /var/cluster-config.conf 参数。