是否可以使用Istio Search Mesh在Kubernetes中创建Redis集群?

时间:2019-10-23 18:16:33

标签: kubernetes redis istio

我正在尝试在安装了Istio Mesh的Kubernetes上配置Redis集群。 Redis群集可以在没有Istio的情况下创建,并且每个Pod都会自动注入一个Istio代理(Envoy)。但是,在安装Istio并将Istio代理连接到每个Redis Pods的情况下,Redis群集无法通过CLI的CLUSTER MEET命令正确地“满足”。

例如,我有Redis Pod A(插槽0-10919)和Redis Pod B(插槽10920-16383)。这是尝试在它们之间执行CLUSTER MEET命令后得出的结果(群集符合ClusterIPForRedisPodB 6379)。

对于Redis Pod A,集群信息已更新,其中包括Redis Pod B:

Redis Pod A

相反,对于Redis Pod B,群集信息不会更新,并且不包括Redis Pod A:

Redis Pod B

我能够在两个Pod之间为端口16379和6379发送curl和netcat响应。此外,Envoy似乎也打开了这些端口。

1 个答案:

答案 0 :(得分:0)

我已经复制了您的问题,并找到了解决问题的方法。

让我首先解释造成问题的原因。

Redis八卦协议的工作方式如下: 当您在 redis1 上输入cluster meet <ip> <port>时, redis1 打开一个与 redis2 的tcp连接。 在正常情况下,当 redis2 接收到连接时,它将接受该连接,并查找正在连接的源IP地址。 并且还会打开一个与该地址的tcp连接,以便在这种情况下与 redis1 建立连接。 (有关闲话协议inredis的工作原理的更多信息,请参见redis documentation, 或在this article中)

这里是 istio 部分。 默认情况下,Istio将使节配置为典型代理,您可以阅读 istio documentation

interception mode

Istio默认情况下是使用REDIRECT proxing并作为文档中的状态:

  

此模式在重定向过程中会丢失源IP地址

这是我们的问题根源。

redis2 收到连接后,会认为它来自本地主机。 Envoy丢失了 redis1 的源IP地址,并且 redis2 现在无法 打开与 redis1 的连接。

现在,我们有一些选择:

  1. 您可以尝试将代理模式更改为TPROXY(我尝试过,但是无法正常工作)
  2. 使用redis内置的配置变量

让我们仔细看看第二个选项,因为这对我有用。 在redis.conf中 文件,您可以在此部分找到:

  

集群DOCKER / NAT支持

     

在某些部署中,Redis群集节点地址发现失败,因为   地址是NAT-ted或因为端口已转发(典型情况是   Docker和其他容器)。

     

为了使Redis Cluster在这样的环境下工作,   每个节点都需要知道其公共地址的配置。的   以下两个选项用于此范围,分别是:

     
      
  • cluster-announce-ip
  •   
  • 集群通告端口
  •   
  • 集群公告总线端口
  •   
     

每个指示节点有关其地址,客户端端口和集群消息的信息   巴士港。然后将信息发布在总线数据包的标题中   这样其他节点就能正确映射该节点的地址   发布信息。

     

如果未使用上述选项,则正常的Redis群集自动检测   将会代替。

     

请注意,重新映射后,总线端口可能不在的固定偏移量   客户端端口+ 10000,因此您可以根据需要指定任何端口和总线端口   有关如何重新映射它们的信息。如果未设置总线端口,则固定偏移量为   通常会使用10000。

     

示例:

     

cluster-announce-ip 10.1.1.5
  cluster-announce-port 6379
  cluster-announce-bus-port 6380

我们需要将cluster-announce-ip变量设置为redis的pod自己的IP地址。

您可以这样做,例如,像这样修改redis-cluster ConfigMap (它是this article的修改后的redis configmap):

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: redis-cluster
data:
  update-node.sh: |
      #!/bin/sh
      REDIS_NODES="/data/nodes.conf"
      sed -i -e "/myself/ s/[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}/${POD_IP}/" ${REDIS_NODES}
      cp /conf/redis.conf /redis.conf # <------HERE-----
      sed -i "s/MY_IP/${POD_IP}/" /redis.conf # <------HERE-----
      exec "$@"
  redis.conf: |+
      cluster-enabled yes
      cluster-require-full-coverage no
      cluster-node-timeout 15000
      cluster-config-file /data/nodes.conf
      cluster-migration-barrier 1
      appendonly yes
      protected-mode no
      cluster-announce-ip MY_IP # <------HERE-----

还要记住像这样将容器的command更改为指向正确的redis.conf文件:

command: ["/conf/update-node.sh", "redis-server", "/redis.conf"]

每个redis节点现在都将通告该地址,因为它自己拥有,因此其他redis节点现在将知道如何与其连接。

让我知道是否有帮助。