我正在尝试在安装了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 B,群集信息不会更新,并且不包括Redis Pod A:
我能够在两个Pod之间为端口16379和6379发送curl和netcat响应。此外,Envoy似乎也打开了这些端口。
答案 0 :(得分:0)
我已经复制了您的问题,并找到了解决问题的方法。
让我首先解释造成问题的原因。
Redis八卦协议的工作方式如下:
当您在 redis1 上输入cluster meet <ip> <port>
时,
redis1 打开一个与 redis2 的tcp连接。
在正常情况下,当 redis2 接收到连接时,它将接受该连接,并查找正在连接的源IP地址。
并且还会打开一个与该地址的tcp连接,以便在这种情况下与 redis1 建立连接。
(有关闲话协议inredis的工作原理的更多信息,请参见redis documentation,
或在this article中)
这里是 istio 部分。
默认情况下,Istio将使节配置为典型代理,您可以阅读
istio documentation:
Istio默认情况下是使用REDIRECT
proxing并作为文档中的状态:
此模式在重定向过程中会丢失源IP地址
这是我们的问题根源。
redis2 收到连接后,会认为它来自本地主机。 Envoy丢失了 redis1 的源IP地址,并且 redis2 现在无法 打开与 redis1 的连接。
现在,我们有一些选择:
TPROXY
(我尝试过,但是无法正常工作)让我们仔细看看第二个选项,因为这对我有用。
在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节点现在将知道如何与其连接。
让我知道是否有帮助。