rueidis icon indicating copy to clipboard operation
rueidis copied to clipboard

Is it possible to follow cluster mode redirects with rueidis?

Open Ghilteras opened this issue 1 year ago • 8 comments

Hey guys I have an Elasticache instance in cluster mode and we are using rueidis to connect via HAProxy (because the client is in another VPC) and we get redirects to a shard from the configuration endpoint so the connection goes back to the client and then the client tries to connect directly to the shard, but it fails because HAProxy only forwards to the configuration endpoint.

Example with redis-cli:

redis-cli -h elasticache-cluster.us-east-2.aws.k8s.sendgrid.net --tls -p 6379 -a 'password' -c

> get "some key"

-> Redirected to slot [15500] located at elasticache-cluster-0001-001.6wgagi.use2.cache.amazonaws.com:6379
Could not connect to Redis at elasticahe-cluster-0001-001.6wgagi.use2.cache.amazonaws.com:6379: SSL_connect failed: Connection reset by peer

Is there a way to tell rueidis to follow the redirect? Since this is Redis TCP protocol I don't think we can instrument HAProxy to do so because it only handles raw TCP forwards. Would it make sense to use a Redis proxy instead of HAProxy here?

Ghilteras avatar May 08 '24 19:05 Ghilteras

Hi @Ghilteras, rueidis does follow the redirect. The error you saw is the proof. And you are right. You can't proxy an Elasticache Cluster with just one HAProxy in total. You need one HAProxy for each Elasticache node and a private DNS resolver that solves Elasticache addresses to corresponding HAProxies or you may consider VPC peering so that you will not need to setup HAProxies.

I don't recommend Redis proxy since it is not actively maintained.

rueian avatar May 09 '24 13:05 rueian

Thanks for the answer. How about Envoy Redis plugin? https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/other_protocols/redis#arch-overview-redis

Ghilteras avatar May 09 '24 18:05 Ghilteras

Specifically the enable redirect option https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/redis_proxy/v3/redis_proxy.proto#envoy-v3-api-field-extensions-filters-network-redis-proxy-v3-redisproxy-connpoolsettings-enable-redirection

Ghilteras avatar May 09 '24 19:05 Ghilteras

Worth trying. Remember to set ForceSingleClient to true on rueidis. https://github.com/redis/rueidis/blob/1ae39a75e5e7501abd5bd0dd419dd4cc8a3ed7f8/rueidis.go#L167

rueian avatar May 09 '24 23:05 rueian

@rueian may I ask how would that flag be useful with Envoy?

Ghilteras avatar May 10 '24 18:05 Ghilteras

Hi @Ghilteras,

rueidis sends CLUSTER SLOTS to redis in order to determine which client implementation (cluster or single) to use. In your case, you can't use the cluster client implementation because you use Envoy to hide cluster details.

Setting the ForceSingleClient to true allows rueidis to skip the CLUSTER SLOTS process and just use the single client implementation to connect to your Envoy.

rueian avatar May 11 '24 06:05 rueian

Hi @Ghilteras, does envoy work for you?

rueian avatar May 14 '24 12:05 rueian

yes it seems it works. We just need to wrap Envoy into an ingress controller (we're currently using nginx which does not have envoy, so we have envoy as sidecar of nginx which is not ideal) to expose elasticache through the ingress (we can't use the Gateway API due to our k8s version being 1.21)

Ghilteras avatar May 17 '24 17:05 Ghilteras

Glad to know it works. However, I am not sure if it is possible to wrap a Redis proxy into a k8s ingress. I thought it could only expose HTTP. Exposing your Envoy with a k8s service of type=Loadbalancer may be much easier.

rueian avatar May 26 '24 15:05 rueian

ingresses normally expose L7 yes, but if you create a LB you can instruct it to passthrough any traffic (like a NLB would do with L4 traffic) which would work for TCP as well. You need a controller to secure the traffic though (in our case we don't have it) if the LB is public facing

Ghilteras avatar May 28 '24 18:05 Ghilteras