Erro de conexão com o Redis externo

Olá Comunidade,

Temos uma configuração do Discourse em Kubernetes. Estamos executando um deployment com a imagem de contêiner do Discourse, usando Redis externo e PostgreSQL externo.
Para gerenciar o Redis HA, implantamos 3 nós em um StatefulSet gerenciado com Sentinel. Além disso, adicionamos um deployment do HAProxy entre o Discourse e o Redis com a seguinte configuração:

global
      log stdout format raw local0
      maxconn 102400
      maxsessrate 500
      maxconnrate 2000
      maxsslrate 2000

    resolvers mydns
      parse-resolv-conf
      hold valid 5s
      accepted_payload_size 8192

    defaults
      log global
      mode tcp
      timeout client 2h
      timeout connect 360s
      timeout server 2h
      default-server init-addr none
      retries 3

    frontend stats
        bind *:1024
        mode http
        http-request use-service prometheus-exporter if { path /metrics }
        stats enable
        stats uri /stats
        stats refresh 10s

    listen redis_master
      bind *:6379
      mode tcp

      option tcp-check
      tcp-check connect
      tcp-check send AUTH\ XXXXXXXXXXX\r\n

      tcp-check expect string +OK
      tcp-check send PING\r\n

      tcp-check expect string +PONG
      tcp-check send info\ replication\r\n

      tcp-check expect string role:master
      tcp-check send QUIT\r\n

      tcp-check expect string +OK
      server redis_node_0 discoursev2-redis-node-0.discoursev2-redis-headless.discoursev2.svc.cluster.local:6379 resolvers mydns check inter 1s fall 1 rise 1
      server redis_node_1 discoursev2-redis-node-1.discoursev2-redis-headless.discoursev2.svc.cluster.local:6379 resolvers mydns check inter 1s fall 1 rise 1
      server redis_node_2 discoursev2-redis-node-2.discoursev2-redis-headless.discoursev2.svc.cluster.local:6379 resolvers mydns check inter 1s fall 1 rise 1

    listen redis_slave
      bind *:6380
      mode tcp
      option tcp-check
      tcp-check connect
      tcp-check send AUTH\ cUvNwwd4ujTbqshTbYjeTTrX8tDlKAcYvvAUOGuk\r\n

      tcp-check expect string +OK
      tcp-check send PING\r\n

      tcp-check expect string +PONG
      tcp-check send QUIT\r\n

      tcp-check expect string +OK
      server redis_node_0 discoursev2-redis-node-0.discoursev2-redis-headless.discoursev2.svc.cluster.local:6379 resolvers mydns check inter 1s fall 1 rise 1
      server redis_node_1 discoursev2-redis-node-1.discoursev2-redis-headless.discoursev2.svc.cluster.local:6379 resolvers mydns check inter 1s fall 1 rise 1
      server redis_node_2 discoursev2-redis-node-2.discoursev2-redis-headless.discoursev2.svc.cluster.local:6379 resolvers mydns check inter 1s fall 1 rise 1

Nosso problema é que toda vez que fazemos um rollout no deployment do Discourse, as threads do Unicorn não conseguem se conectar ao Redis. Elas tentam reconectar e, após algum tempo, todas finalmente se conectam. Aqui estão alguns erros que vemos nos logs:

/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/redis-4.8.1/lib/redis/client.rb:398:in `rescue in establish_connection'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/unicorn-6.1.0/lib/unicorn/http_server.rb:684:in `init_worker_process'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/unicorn-6.1.0/lib/unicorn/http_server.rb:547:in `spawn_missing_workers'
config/unicorn.conf.rb:299:in `block in reload'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/unicorn-6.1.0/lib/unicorn/http_server.rb:721:in `worker_loop'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/redis-4.8.1/lib/redis/client.rb:379:in `establish_connection'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/redis-4.8.1/lib/redis/client.rb:115:in `block in connect'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/redis-4.8.1/lib/redis/client.rb:295:in `reconnect'
/var/www/discourse/lib/discourse.rb:906:in `after_fork'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/unicorn-6.1.0/bin/unicorn:128:in `<top (required)>'
/var/www/discourse/vendor/bundle/ruby/3.3.0/bin/unicorn:25:in `<main>'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/redis-4.8.1/lib/redis/client.rb:344:in `with_reconnect'
E, [2024-07-24T15:42:22.524194 #531] ERROR -- : Error connecting to Redis on discoursev2-haproxy.discoursev2.svc.cluster.local:6379 (Socket::ResolutionError) (Redis::CannotConnectError)
/var/www/discourse/lib/discourse_redis.rb:217:in `reconnect'
/var/www/discourse/vendor/bundle/ruby/3.3.0/bin/unicorn:25:in `load'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/redis-4.8.1/lib/redis/client.rb:114:in `connect'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/unicorn-6.1.0/lib/unicorn/http_server.rb:143:in `start'
I, [2024-07-24T15:42:23.499254 #422]  INFO -- : Loading Sidekiq in process id 422
2024-07-24 15:42:23 +0000: Starting Prometheus global reporter pid: 439
Booting Sidekiq 6.5.12 with Sidekiq::RedisConnection::RedisAdapter options {:host=>"discoursev2-haproxy.discoursev2.svc.cluster.local", :port=>6379, :password=>"REDACTED", :namespace=>"sidekiq"}
E, [2024-07-24T15:42:23.530765 #810] ERROR -- : Error connecting to Redis on discoursev2-haproxy.discoursev2.svc.cluster.local:6379 (Socket::ResolutionError) (Redis::CannotConnectError)
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/redis-4.8.1/lib/redis/client.rb:398:in `rescue in establish_connection'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/redis-4.8.1/lib/redis/client.rb:115:in `block in connect'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/unicorn-6.1.0/lib/unicorn/http_server.rb:684:in `init_worker_process'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/unicorn-6.1.0/lib/unicorn/http_server.rb:547:in `spawn_missing_workers'
/var/www/discourse/vendor/bundle/ruby/3.3.0/bin/unicorn:25:in `<main>'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/redis-4.8.1/lib/redis/client.rb:344:in `with_reconnect'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/redis-4.8.1/lib/redis/client.rb:295:in `reconnect'
config/unicorn.conf.rb:299:in `block in reload'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/redis-4.8.1/lib/redis/client.rb:379:in `establish_connection'
/var/www/discourse/lib/discourse.rb:906:in `after_fork'
/var/www/discourse/vendor/bundle/ruby/3.3.0/bin/unicorn:25:in `load'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/unicorn-6.1.0/bin/unicorn:128:in `<top (required)>'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/redis-4.8.1/lib/redis/client.rb:114:in `connect'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/unicorn-6.1.0/lib/unicorn/http_server.rb:721:in `worker_loop'
/var/www/discourse/lib/discourse_redis.rb:217:in `reconnect'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/unicorn-6.1.0/lib/unicorn/http_server.rb:143:in `start'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/unicorn-6.1.0/lib/unicorn/http_server.rb:143:in `start'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/redis-4.8.1/lib/redis/client.rb:344:in `with_reconnect'
config/unicorn.conf.rb:299:in `block in reload'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/redis-4.8.1/lib/redis/client.rb:398:in `rescue in establish_connection'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/redis-4.8.1/lib/redis/client.rb:379:in `establish_connection'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/redis-4.8.1/lib/redis/client.rb:295:in `reconnect'
/var/www/discourse/lib/discourse_redis.rb:217:in `reconnect'
E, [2024-07-24T15:42:24.540440 #887] ERROR -- : Error connecting to Redis on discoursev2-haproxy.discoursev2.svc.cluster.local:6379 (Socket::ResolutionError) (Redis::CannotConnectError)

Também testamos remover o HAProxy e apontar diretamente para o nó mestre do Redis, e observamos o mesmo problema. Além disso, desabilitamos o gateway Istio entre o Discourse e o Redis. Em ambos os cenários, após algum tempo, todas as threads do Unicorn conseguem estabelecer a conexão com o Redis.

Alguém pode nos dar alguma orientação sobre este problema? Precisamos de alguma configuração especial no Redis? Esta é a nossa configuração atual:

appendonly yes
appendfsync no
aof-rewrite-incremental-fsync yes
save ""

Finalmente, gostaríamos de saber:

  1. Qual é a maneira recomendada de ter o Redis em modo HA? Pelo que sabemos, o cluster Redis não é suportado.
  2. Em caso de usar uma configuração de nó único do Redis, quais serão as consequências de perder o Redis por alguns segundos? O Discourse repopulará o conteúdo se formos para um Redis stateless onde toda vez que ele for reiniciado, ele perde todas as informações?

Muito obrigado desde já.

Olá Comunidade,

Gostaria de dar seguimento à minha postagem anterior sobre a nossa configuração do Discourse no Kubernetes, onde estamos enfrentando problemas de conectividade entre os threads do Unicorn e o Redis durante as implementações de implantação. Apesar de tentarmos várias configurações, incluindo a remoção do HAProxy e a desativação do gateway Istio, o problema persiste.

Agradeceríamos muito qualquer orientação ou recomendação para resolver este problema. Especificamente:

  1. Precisamos de alguma configuração especial para o Redis para suportar nossa configuração?
  2. Qual é a abordagem recomendada para garantir alta disponibilidade com o Redis, considerando que o Redis Cluster não é suportado?
  3. Se optarmos por uma configuração de nó único do Redis, qual seria o impacto de uma breve interrupção do Redis? O Discourse repopulará os dados em um ambiente Redis sem estado onde todos os dados são perdidos após a reinicialização?

Suas percepções seriam inestimáveis enquanto continuamos a solucionar este problema.

Agradeço antecipadamente pelo seu apoio.