【问题标题】:Redis Pods are not able to join Redis clusterRedis Pod 无法加入 Redis 集群
【发布时间】:2020-05-06 02:27:52
【问题描述】:

我想在 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。有了这个我就可以启动我的集群了。但是一旦我使用

手动删除单个 pod
kubernetes delete pod <podname> 

例如删除IP地址为:172.17.0.6:6379的redis节点,本应是master。删除后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 加入集群吗?

【问题讨论】:

  • 我强烈建议考虑使用 Sentinel 而不是 Redis 中的集群命令的 HA 选项。 Sentinel 要好得多,旨在做到这一点。我不确定这将如何在 Kubernetes 内部发挥作用,尤其是对于 pod 的短暂性。这个舵图就是一个很好的例子:github.com/helm/charts/tree/master/stable/redis-ha
  • @Dandy 你应该把它作为答案发布。
  • @BMW 我已经用更多的上下文添加了我的答案。我认为即使您链接的 URL 也会有问题,因为 Redis 需要知道 pod 的 IP,如果您删除一个从站,它会发生变化,然后您会完全失去该从站。最好使用主机名,这意味着使用服务,这意味着更多的模板管道,但是你的 Redis 需要知道它自己的服务。等等等等。
  • @dandy 我用过 statefulset。即使 pod 重新启动,它也会获得相同的 ip 地址,因此应该自动加入集群。

标签: kubernetes redis minikube kubernetes-statefulset


【解决方案1】:

我已经解决了这个问题,并使用这个 stateful set yaml 创建了一个 redis 集群。 问题是我没有在持久卷中安装 cluster config 文件。集群配置文件包含其他节点的位置。现在集群配置文件将在 Pod 重新启动时保持不变。

由于 redis 集群在 gossip 协议上工作。只需一个活动节点即可获取整个集群的配置。

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

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。

【讨论】:

    【解决方案2】:

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

    总体而言,根据我的经验,Redis 的架构并不能很好地融入 Kubernetes 网络。告诉 Redis 实例你的从属服务器在哪里,特别是以编程方式可能是一场噩梦(正如你所看到的必须手动触发集群),尤其是当你认为 pod 到 pod 的通信不符合 Kubernetes 网络层次结构时。

    我对集群命令将如何在 Kubernetes 中发挥作用没有信心,尤其是对于 pod 的短暂性。

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

    扩展几个关于为什么这不起作用的场景:

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

    2. 1234563 6 个节点变为 5 个。您可以通过在 CIDR 上使用 /24 地址定义节点来解决此问题,但是您基本上是在为每个 Redis 实例部署一个节点,这似乎违背了协调者的观点。

    【讨论】:

    • 是的,在 6 节点 redis-cluster 的情况下,当从属设备被删除时,新的 redis pod 将获得新的 IP 地址。但是在 redis 中,每个节点都被识别为一个 40 位的固定哈希,称为节点 ID。因此,当 redis pod 重新启动时,节点 ID 保持不变。它还具有不同节点的信息,并将获取其余节点的信息。因此将再次作为从属加入集群。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-10
    • 1970-01-01
    • 2016-07-07
    • 2019-04-24
    • 1970-01-01
    • 1970-01-01
    • 2020-03-15
    相关资源
    最近更新 更多