简体   繁体   English

在docker conatiners中连接到以哨兵模式运行的Redis主节点时出现问题

[英]Issue while connecting to redis master node running in sentinel mode in docker conatiners

I am running redis in docker containers and I am using redis sentinel mode. 我在Docker容器中运行Redis,并且正在使用Redis Sentinel模式。 I have setup the following configuration - 我已经设置了以下配置-

3 redis sentinels nodes
1 redis master node
2 redis slave nodes

I am running all these in my local machine. 我正在本地计算机上运行所有这些。 So in total 6 docker containers running through docker-compose in bridge networking mode. 因此,总共有6个docker容器在桥联网模式下通过docker-compose运行。 All conatiners has port mappings to outside. 所有容器都具有到外部的端口映射。

All containers can access each other as they are in the same bridge docker network created during running of docker-compose up . 所有容器都可以彼此访问,因为它们位于docker-compose up运行期间创建的同一桥docker网络中。

I have created a Java client using Redisson library to access redis. 我已经使用Redisson库创建了Java客户端来访问Redis。 Configured the client to use redis-sentinel mode as follows - 将客户端配置为使用redis-sentinel模式,如下所示-

Config config = new Config();
config.useSentinelServers()
       .setMasterName("redis-master")
       .addSentinelAddress("redis://127.0.0.1:26379")
       .addSentinelAddress("redis://127.0.0.1:26380")
       .addSentinelAddress("redis://127.0.0.1:26381")

RedissonClient client = Redisson.create(config);

This is where I am facing the issue. 这就是我面临的问题。 Whenever I try to run some commands on redis through this client, the request goes through sentinel nodes which gives me current redis master node address. 每当我尝试通过此客户端在Redis上运行一些命令时,请求都会通过哨兵节点,从而为我提供当前的Redis主节点地址。 But my java client cannot communicate to redis master directly as the ip returned by sentinel node is the internel docker network ip for master node which is not accessible outside docker network and it fails with similar exception as below - 但是我的Java客户端无法直接与Redis主机进行通信,因为哨兵节点返回的IP是主机节点的内部docker网络ip,无法在docker网络外部访问,并且失败,出现以下类似异常-

Exception in thread "main" org.redisson.client.RedisConnectionException: Unable to connect to Redis server: 172.21.0.2/172.21.0.2:6379
    at org.redisson.connection.pool.ConnectionPool$2$1.operationComplete(ConnectionPool.java:161)
    at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:511)

How to fix this issue? 如何解决这个问题? Do I need to run it in some different network mode? 我需要在其他网络模式下运行它吗? or some way to translate this internal docker ip to the actual ip of machine running docker conatiners? 或某种方式将此内部docker ip转换为运行docker conatiners的计算机的实际ip?

I ran into this issue today as well, attempting to get this set up for a test instance. 我今天也遇到了这个问题,试图为测试实例进行设置。 My initial compose file was based on https://blog.alexseifert.com/2016/11/14/using-redis-sentinel-with-docker-compose/ with modifications to suit my needs. 我最初的撰写文件基于https://blog.alexseifert.com/2016/11/14/using-redis-sentinel-with-docker-compose/,并进行了修改以满足我的需要。 I was able to find a workaround by 1) binding the ports to my host machine, 2) setting the depends_on flag in docker-compose, and 3) setting my sentinel.conf to point to the hostname that my master was running on: https://docs.docker.com/compose/startup-order/ 我能够找到一种解决方法,方法是:1)将端口绑定到我的主机,2)在docker-compose中设置depends_on标志,以及3)设置我的sentinel.conf指向我的主服务器正在运行的主机名: https ://docs.docker.com/compose/startup-order/

It's a little hard to explain, but I'll try my best: Your master/replica will look something like this in docker-compose: 有点难以解释,但是我会尽力而为:您的主/副本在docker-compose中看起来像这样:

  redis-master:
    image: redis:5.0.4-alpine
    volumes:
      - <mounted-data-directory>
      - "<local-master-config-directory>/redis.conf:/usr/local/etc/redis/redis.conf"
    ports:
      - "6379:6379"
    command:
      - redis-server
      - /usr/local/etc/redis/redis.conf

  redis-replica:
    image: redis:5.0.4-alpine
    links:
      - redis-master
    volumes:
      - <mounted-data-directory>
      - "<local-replica-config-directory>:/usr/local/etc/redis/redis.conf"
    ports:
      - "6380:6380"
    depends_on:
      - redis-master
    command:
      - redis-server
      - /usr/local/etc/redis/redis.conf
      - --slaveof redis-master 6379

For my sentinels I gave each Dockerfile and a sentinel.conf (each having different ports): Dockerfile: 对于我的哨兵,我给了每个Dockerfile和一个sentinel.conf(每个都有不同的端口):Dockerfile:

FROM redis:5.0.4-alpine
RUN mkdir -p /redis
WORKDIR /redis
COPY sentinel.conf .
RUN chown redis:redis /redis/*
ENTRYPOINT ["redis-server", "/redis/sentinel.conf", "--sentinel"]

sentinel.conf sentinel.conf

port 26379
dir /tmp
bind 0.0.0.0
sentinel monitor mymaster <hostname> 6379 2
sentinel down-after-milliseconds mymaster 1000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 10000

It's worth noting that I attempted to do this with 127.0.0.1 and localhost and I don't think either worked, so I had the hostname set on the machine I ran this on. 值得注意的是,我尝试使用127.0.0.1和localhost来执行此操作,但我认为两者都不起作用,因此我在运行该程序的计算机上设置了主机名。 I was kind of trying any and everything at that point. 那时我有点尝试任何事情。

Each sentinel (I had three) had a separate entry referencing their build contexts and mapping the port in sentinel.conf to the local port. 每个哨兵(我有三个)都有一个单独的条目,这些条目引用其构建上下文并将sentinel.conf中的端口映射到本地端口。 So in docker-compose my sentinels looked like this: 因此在docker-compose中,我的前哨看起来像这样:

 # Instance 1
  redis-sentinel:
    build:
      context: <path-to-context>
    links:
      - redis-master
    ports:
      - "26379:26379"
    depends_on:
      - redis-replica

What I did was definitely a hack and I wouldn't do it in production. 我所做的肯定是黑客,我不会在生产中这样做。 I'm pretty sure there's a much better networking solution for docker, I just didn't want to go too far down the rabbit hole for what I needed to test. 我很确定有一个针对docker的更好的网络解决方案,我只是不想为需要测试的内容走得太远。 Hope this helps. 希望这可以帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM