【问题标题】:Bitnami Redis Sentinel & Sidekiq on KubernetesKubernetes 上的 Bitnami Redis Sentinel 和 Sidekiq
【发布时间】:2022-03-09 04:51:32
【问题描述】:

所以现在我们正试图让 Bitnami Redis Sentinel 集群与我们的 Rails 应用程序 + Sidekiq 一起工作。

我们尝试了不同的方法,但我们并不清楚,我们应该如何为 Sidekiq 指定哨兵(关键部分在这里,哨兵节点是只读的,所以我们不能将它们用于 sidekiq,因为作业状态得到写)。

由于在 Kubernetes 上只有 2 种服务可用:“redis”和“redis-headless”(不确定它们有何不同?) - 我如何像这样指定哨兵:

Sidekiq.configure_server do |config|
  config.redis = {
    url: "redis",
    sentinels: [
      { host: "?", port: 26379 } # why do we have to specify it here seperately, since we should be able to get a unified answer via a service, or?
      { host: "?", port: 26379 }  
      { host: "?", port: 26379 } 
    }
  }
end

如果有人能对此有所了解,那就太好了。据我了解,bitnami redis sentiel 只返回主服务器的 IP,然后应用程序必须处理对该主服务器的相应写入https://github.com/bitnami/charts/tree/master/bitnami/redis#master-replicas-with-sentinel) - 但我真的不明白关于如何使用 sidekiq 做到这一点?

【问题讨论】:

  • 您是否设法让 Sidekiq 与您的 Redis Sentinel 集群完美配合?

标签: ruby-on-rails kubernetes redis bitnami redis-sentinel


【解决方案1】:

Kubernetes Service 和 Headless Service 的区别

让我们从阐明无头服务和服务之间的区别开始。

服务允许一个人连接到一个 Pod,而无头服务返回所有可用 pod 的可用 IP 地址列表,从而允许自动发现。

Marco Luksa 更详细的解释已发布在 SO here

与服务的每个连接都被转发到一个随机选择的后备 pod。但是,如果客户端需要连接到所有这些 pod 怎么办?如果后备吊舱本身需要每个都连接到所有其他后备吊舱怎么办。通过服务连接显然不是做到这一点的方法。是什么?

为了让客户端连接到所有 pod,它需要计算出每个 pod 的 IP。一种选择是让客户端调用 Kubernetes API 服务器并通过 API 调用获取 pod 列表及其 IP 地址,但是因为您应该始终努力使您的应用程序与 Kubernetes 无关,所以使用 API 服务器并不理想

幸运的是,Kubernetes 允许客户端通过 DNS 查找来发现 pod IP。通常,当您对服务执行 DNS 查找时,DNS 服务器会返回一个 IP — 服务的集群 IP。但是,如果您告诉 Kubernetes 您的服务不需要集群 IP(您可以通过在服务规范中将 clusterIP 字段设置为 None 来做到这一点),DNS 服务器将返回 pod IP,而不是单个服务 IP。 DNS 服务器不会返回单个 DNS A 记录,而是返回服务的多个 A 记录,每个记录都指向当时支持该服务的单个 pod 的 IP。因此,客户端可以进行简单的 DNS A 记录查找并获取属于该服务的所有 pod 的 IP。然后,客户端可以使用该信息连接到其中一个、多个或全部。

将服务规范中的 clusterIP 字段设置为 None 会使服务无头,因为 Kubernetes 不会为其分配集群 IP,客户端可以通过该 IP 连接到支持它的 pod。

Marco Luksa 的“Kubernetes in Action”

如何指定哨兵

正如Redis documentation 所说:

使用 Sentinel 支持时,您需要指定要连接的哨兵列表。该列表不需要枚举所有 Sentinel 实例,但需要枚举一些实例,以便如果一个已关闭,客户端将尝试下一个。客户端能够记住最后一个能够正确回复的 Sentinel,并将其用于下一个请求。

所以我们的想法是提供你所拥有的,如果你扩大 redis pod,那么你不需要重新配置 Sidekiq(如果你使用 Redis 进行缓存,则不需要重新配置 Rails)。

结合在一起

现在您只需要一种方法从 Ruby 中的无头服务获取 IP 地址,并配置 Redis 客户端哨兵。

幸运的是,从 Ruby 2.5.0 开始,Resolv class 可用并且可以为您做到这一点。

irb(main):007:0> Resolv.getaddresses "redis-headless"
=> ["172.16.105.95", "172.16.105.194", "172.16.9.197"]

这样你就可以做到:

Sidekiq.configure_server do |config|
  config.redis = {
    # This `host` parameter is used by the Redis gem with the Redis command
    # `get-master-addr-by-name` (See https://redis.io/topics/sentinel#obtaining-the-address-of-the-current-master)
    # in order to retrieve the current Redis master IP address.
    host: "mymaster",
    sentinels: Resolv.getaddresses('redis-headless').map do |address|
      { host: address, port: 26379 }
    end
  }
end

这将创建一个哈希数组,其 IP 地址为 host:,26379 为 port:

【讨论】:

  • 谁看起来不错,以后会试试这个!!谢谢!工作时将标记为已接受!
  • 很高兴为您提供帮助!
  • 嗯,但如果我这样做,当我需要写一些东西时,我会以某种方式得到一个只读错误。如果我想写,我必须使用哪个端口?如果我设置正常的port: 26379 我得到Redis::CommandError (ERR unknown command `smembers`, with args beginning with: `cron_jobs`,):,使用6379我得到副本只读错误?
  • 您必须使用 Sentinel 端口。请参阅有关 Sentienl 的 Ruby gem "redis-rb" 文档:github.com/redis/redis-rb#sentinel-support
  • @BvuRVKyUVlViVIc7 我更新了最后一个代码块,将url 属性替换为host 并更改了值。请阅读该行上方的评论。
猜你喜欢
  • 2020-03-08
  • 1970-01-01
  • 2015-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-01
  • 2019-10-23
  • 1970-01-01
相关资源
最近更新 更多