docker-compose搭建redis集群(用于开发、测试环境)

前言:本文记录了如何使用docker-compose和redis官方镜像和第三方redis-trib镜像组建3主3从的redis集群并设置密码.

1、创建文件结构

[root@localhost redis]# pwd
/apps/usr/redis
[root@localhost redis]# ll
total 72
-rw-r--r--. 1 root root   426 Aug  5 16:28 docker-compose.yml
drwxr-xr-x. 2 root root    42 Aug  5 16:54 node1
drwxr-xr-x. 2 root root    42 Aug  5 16:54 node2
drwxr-xr-x. 2 root root    42 Aug  5 16:55 node3
drwxr-xr-x. 2 root root    42 Aug  5 16:55 node4
drwxr-xr-x. 2 root root    42 Aug  5 16:55 node5
drwxr-xr-x. 2 root root    42 Aug  5 16:55 node6
-rw-r--r--. 1 root root   193 Aug  5 16:57 readfirst.txt
-rw-r--r--. 1 root root 61797 May 16 00:07 redis.conf
[root@localhost redis]# 

node1--node6 各redis节点

docker-compose.yml 

redis.conf 默认redis配置

2、配置redic.conf文件

  1. 到http://download.redis.io/redis-stable/redis.conf下载官方redis.conf文件
  2. 拷贝到各个node文件夹下,分别配置如下内容,以端口6061为例(默认为6379
# bind 127.0.0.1 //加上注释#
protected-mode no //关闭保护模式
port 6061  //绑定自定义端口
#daemonize yes //禁止redis后台运行
pidfile /var/run/redis_6061.pid 
cluster-enabled yes //开启集群 把注释#去掉
cluster-config-file nodes_6061.conf //集群的配置 配置文件首次启动自动生成 

配置文件是最容易出问题的,这里面有一些注意事项:

  • requirepass和masterauth不能启用 

因为使用redis-trib连接集群时是不能指定密码的,如果开启了requirepass或者masterauth会导致集群连接失败,所以应该等集群创建好后再修改密码,这个后文会说

  • bind 

表示设置redis监听哪个ip,设置了监听之后,只有使用这些ip才能访问这个redis服务,不指定则默认所有ip都能访问该redis服务 
注意:这里的ip指的是redis的ip而非访问方的ip,bind并不直接限制哪些ip能够访问redis,显示ip访问是限制监听后的效果,如果想限制ip访问应使用Linux防火墙功能. 
比方说,在生产条件下的redis服务器有3个ip(外网ip 122.122.122.122,局域网ip192.128.0.1,本地ip127.0.0.1),则为了安全,bind后面只应该写局域网ip和本地ip,这样就只有局域网用户(包括本机)可以通过192.128.0.1访问redis服务,间接起到限制ip访问的作用.

  • protected-mode

作用: 
禁止公网访问redis cache,加强redis安全的
启用条件: 
没有bind IP
没有设置requirepass访问密码
解释: 
由于前面提及的原因,保护模式会开启导致无法通过公网访问,故这里需要关闭保护模式,但注意集群建好后要及时添加密码,增强安全性

  • daemonize 和 pidfile 

实测开启守护模式(daemonize yes)容器会启动失败,因为是使用docker,所以前台启动也没什么关系,pidfile的文件名和端口号一致是一个良好的习惯
 

 3、编写Dockerfile

#以node1为例
[root@localhost node1]# pwd
/apps/usr/redis/node1
[root@localhost node1]# more Dockerfile 
#基础镜像
FROM redis

#将自定义conf文件拷入
COPY redis.conf /usr/local/etc/redis/redis.conf

#修复时区
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo 'Asia/Shanghai' >/etc/timezone

#修改文件权限,使之可以通过config rewrite重写
RUN chmod 777 /usr/local/etc/redis/redis.conf

# Redis客户端连接端口
EXPOSE 6061
# 集群总线端口:redis客户端连接的端口 + 10000
EXPOSE 16061

#使用自定义conf启动
CMD [ "/usr/local/bin/redis-server", "/usr/local/etc/redis/redis.conf" ]

注意:

集群总线端口 
Redis集群中每个redis实例(可能一台机部署多个实例)会使用两个Tcp端口,一个用于给客户端(redis-cli或应用程序等)使用的端口,另一个是用于集群中实例相互通信的内部总线端口,且第二个端口比第一个端口一定大10000.内部总线端口通信使用特殊协议,以便实现集群内部高带宽低时延的数据交换。所以配置redis实例时只需要指明第一个端口就可以了。 
但是由于我们使用的是docker,所以要将这个端口暴露出来,否则集群无法建立(使用redis-trib时会一直显示Waiting for the cluster to join)
修改redis.conf文件权限,否则后面写入访问密码到文件的时候会提示Permission denied

4、编写docker-compose.yml文件

[root@localhost redis]# pwd
/apps/usr/redis
[root@localhost redis]# more docker-compose.yml 
version: '3.7'

services:
  redis-node1:
    build: ./node1
    ports:
      - 6061:6061
      - 16061:16061
    container_name: redis-node1
    restart: always
    tty: true
    networks:
      extnetwork:
        ipv4_address: 172.19.0.11  #指定固定IP
  redis-node2:
    build: ./node2
    ports:
      - 6062:6062
      - 16062:16062
    container_name: redis-node2
    restart: always
    tty: true
    networks:
      extnetwork:
        ipv4_address: 172.19.0.12
  redis-node3:
    build: ./node3
    ports:
      - 6063:6063
      - 16063:16063
    container_name: redis-node3
    restart: always
    tty: true
    networks:
      extnetwork:
        ipv4_address: 172.19.0.13
  redis-node4:
    build: ./node4
    ports:
      - 6064:6064
      - 16064:16064
    container_name: redis-node4
    restart: always
    tty: true
    networks:
      extnetwork:
        ipv4_address: 172.19.0.14
  redis-node5:
    build: ./node5
    ports:
      - 6065:6065
      - 16065:16065
    container_name: redis-node5
    restart: always
    tty: true
    networks:
      extnetwork:
        ipv4_address: 172.19.0.15
  redis-node6:
    build: ./node6
    ports:
      - 6066:6066
      - 16066:16066
    container_name: redis-node6
    restart: always
    tty: true
    networks:
      extnetwork:
        ipv4_address: 172.19.0.16
networks:
  extnetwork:    #自定义网络环境
    ipam:
      config:
        - subnet: 172.19.0.0/16
[root@localhost redis]# 

5、启动

在redis目录下(即docker-compose.yml同级目录),运行

[root@localhost redis]# pwd
/apps/usr/redis
[root@localhost redis]# docker-compose up -d


[root@localhost redis]# docker ps
CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS              PORTS                                                        NAMES
22fe97cac263        redis_redis-node4      "docker-entrypoint.s…"   About an hour ago   Up About an hour    0.0.0.0:6064->6064/tcp, 0.0.0.0:16064->16064/tcp, 6379/tcp   redis_redis-node4_1
dc32229f2ac8        redis_redis-node2      "docker-entrypoint.s…"   About an hour ago   Up About an hour    0.0.0.0:6062->6062/tcp, 0.0.0.0:16062->16062/tcp, 6379/tcp   redis_redis-node2_1
3eb4661da9ed        redis_redis-node1      "docker-entrypoint.s…"   About an hour ago   Up About an hour    0.0.0.0:6061->6061/tcp, 0.0.0.0:16061->16061/tcp, 6379/tcp   redis_redis-node1_1
e09f67c90dbf        redis_redis-node5      "docker-entrypoint.s…"   About an hour ago   Up About an hour    0.0.0.0:6065->6065/tcp, 0.0.0.0:16065->16065/tcp, 6379/tcp   redis_redis-node5_1
671a4a880aa4        redis_redis-node6      "docker-entrypoint.s…"   About an hour ago   Up About an hour    0.0.0.0:6066->6066/tcp, 0.0.0.0:16066->16066/tcp, 6379/tcp   redis_redis-node6_1
995b9e97fa44        redis_redis-node3      "docker-entrypoint.s…"   About an hour ago   Up About an hour    0.0.0.0:6063->6063/tcp, 0.0.0.0:16063->16063/tcp, 6379/tcp   redis_redis-node3_1
cc244c275c49        zookeeper:3.5.3-beta   "/docker-entrypoint.…"   5 weeks ago         Up 2 hours          2888/tcp, 3888/tcp, 0.0.0.0:2183->2181/tcp                   zookeeper_3
a3ffc8080f04        zookeeper:3.5.3-beta   "/docker-entrypoint.…"   5 weeks ago         Up 2 hours          2888/tcp, 0.0.0.0:2181->2181/tcp, 3888/tcp                   zookeeper_1
03f34a88a2fb        zookeeper:3.5.3-beta   "/docker-entrypoint.…"   5 weeks ago         Up 2 hours          2888/tcp, 3888/tcp, 0.0.0.0:2182->2181/tcp                   zookeeper_2
[root@localhost redis]# 

可以看到此时请求访问密码和访问master密码是空白的,另外集群状态是失败 
这个时候使用redis会报"CLUSTERDOWN Hash slot not served"错误

6、创建集群

在此首先需要查看redis各节点IP

[root@localhost redis]# docker ps

[root@localhost redis]# docker inspect 01527dfc2f31 9e5eb69610e8 975babd130bc e2b9d2b28470 aa00057c3319 9c2a1d4a40bd | grep -e "IPAddress" -e "Image"
        "Image": "sha256:fac3b8c3d00f2e2d5477b30730b13253680d6349717142e1b460f834198f3cac",
            "Image": "redis_redis-node6",
            "SecondaryIPAddresses": null,
            "IPAddress": "",
                    "IPAddress": "172.19.0.16",
        "Image": "sha256:f8f51e618508faa320a5826c95818a175b55805190439b4aa8548d6d9ca6c327",
            "Image": "redis_redis-node1",
            "SecondaryIPAddresses": null,
            "IPAddress": "",
                    "IPAddress": "172.19.0.11",
        "Image": "sha256:a5b073f201f599c7752a8336474bfc4d71b60dac4a21bdeb818f2fca045084b2",
            "Image": "redis_redis-node2",
            "SecondaryIPAddresses": null,
            "IPAddress": "",
                    "IPAddress": "172.19.0.12",
        "Image": "sha256:1ad0b65f20b1f0a3bcb5302fd741dffcb993c1eca36f59b0ba8dd28a7f0dc0b1",
            "Image": "redis_redis-node4",
            "SecondaryIPAddresses": null,
            "IPAddress": "",
                    "IPAddress": "172.19.0.14",
        "Image": "sha256:17e8e50419bddda5a93c492f34888ef90d63139624422bc7a28c1b88f062951d",
            "Image": "redis_redis-node3",
            "SecondaryIPAddresses": null,
            "IPAddress": "",
                    "IPAddress": "172.19.0.13",
        "Image": "sha256:5e7631cb5ebb869f26dba50dd781d05360139965a7d5ff7a6ff39cdafcc0fef3",
            "Image": "redis_redis-node5",
            "SecondaryIPAddresses": null,
            "IPAddress": "",
                    "IPAddress": "172.19.0.15",

[root@localhost redis]# 

创建集群

[root@localhost redis]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
2514144f2710        bridge              bridge              local
8f18d5d4a41c        host                host                local
f6adefbb5345        none                null                local
ab68814edfb8        redis_extnetwork    bridge              local
9273f18b5674        zookeeper_default   bridge              local

#ip 根据实际情况修改  --net 指定网络,注意网络名称
[root@localhost redis]#  docker run -it --rm --net redis_extnetwork zvelo/redis-trib create --replicas 1 172.19.0.11:6061 172.19.0.12:6062 172.19.0.13:6063 172.19.0.14:6064 172.19.0.15:6065 172.19.0.16:6066

7、验证集群

[root@localhost redis]# docker exec -it 9e5eb69610e8 /bin/bash
root@9e5eb69610e8:/data# n/
root@9e5eb69610e8:/usr/local/bin# ls
docker-entrypoint.sh  gosu  redis-benchmark  redis-check-aof  redis-check-rdb  redis-cli  redis-sentinel  redis-server
root@22fe97cac263:/usr/local/bin# ./redis-cli -c -p 6064 
127.0.0.1:6064> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_ping_sent:2463
cluster_stats_messages_pong_sent:2465
cluster_stats_messages_meet_sent:3
cluster_stats_messages_sent:4931
cluster_stats_messages_ping_received:2463
cluster_stats_messages_pong_received:2466
cluster_stats_messages_meet_received:2
cluster_stats_messages_received:4931
127.0.0.1:6064> 

8、设置集群密码

使用redis-trib.rb工具构建集群,集群构建完成前不要配置密码,集群构建完毕再通过config set + config rewrite命令逐个机器设置密码
如果对集群设置密码,那么requirepass和masterauth都需要设置,否则发生主从切换时,就会遇到授权问题
各个节点的密码都必须一致,否则Redirected就会失败
 

#以一个节点为例

# -c 集群模式
./redis-cli -c -p 6061 -h 172.17.0.5

# 
config set masterauth ****
config set requirepass ****
# 验证
auth ****
# 回写到配置文件
config rewrite

注:连通性,本地使用redis集群的连通性问题,参考windows连通CentOS虚拟机中的docker容器 开通172.17.0.0 网段

 

你可能感兴趣的:(docker,redis)