您的位置:首页 > 运维架构 > Docker

Go游戏服务器开发的一些思考(二十五):Redis的Docker Swarm部署

2017-11-12 18:59 1071 查看

痛点

在redis 4出来之前,redis哨兵、redis集群 是无法通过简单的方式支持Docker Swarm的。原因是Docker Swarm的NAT端口映射机制,会导致redis无法正确获取宿主IP、端口。

在redis 4之后,官方通过在redis.conf 、redis_sentinel.conf中,新增了slave-announce-ip、slave-announce-port、sentinel announce-ip、sentinel announce-port字段,让使用者通过配置填写,来告知redis,其在NAT模式下时的宿主IP、端口。从而为redis支持Docker Swarm铺平道路。

此外,还有一个事实,redis容器A开在宿主A上,在宿主A上保存了持久化数据。之后,若宿主A故障后,redis容器A是不可以转移到其他宿主上去的。随便的转移重开服务,会导致持久化数据的丢失。

这与Docker Swarm默认的故障转移机制是冲突的。

指定具体宿主节点

Docker Swarm的编排脚本,提供了一种可以根据条件来选择宿主节点的方法:

在宿主机上设置唯一标签

编排脚本的deploy - placement - constraints 中,设置该服务只能在某一标签的宿主机上可以开启

这样,就可以变相的关闭掉故障转移的功能

如何设置、应用标签

下面以ubuntu系统为例:

编辑 /etc/docker/daemon.json,增加lables字段,类似如下:

{
"labels": [ "host_ip=192.168.1.4" ]
}


这里增加了一个标签host_ip。标签的命名、个数等都是根据使用需求自定义的。

这里需要唯一标识一台宿主机,因此定义一个host_ip标签

重启docker,使标签生效

service docker restart


编排脚本类似如下:

services:
redis1:
image: redis
deploy:
placement:
constraints: [engine.labels.host_ip==192.168.1.4]


以上。redis1的容器就只会被开在ip为192.168.1.4的宿主机上。

redis主从编排脚本示例

编排脚本docker-stack-redis.yml,内容如下:

version: "3.3"
services:

redis1:
image: redis
deploy:
placement:
constraints: [engine.labels.host_ip==IP1]
endpoint_mode: vip
replicas: 1
restart_policy:
condition: on-failure
delay: 60s
ports:
- "16379:6379"
networks:
- net
command: redis-server --save "" --maxmemory 5gb --timeout 0 --tcp-keepalive 60 --bind 0.0.0.0 --slave-announce-ip IP1 --slave-announce-port 16379

redis2:
image: redis
deploy:
placement:
constraints: [engine.labels.host_ip==IP2]
endpoint_mode: vip
replicas: 1
restart_policy:
condition: on-failure
delay: 60s
ports:
- "26379:6379"
networks:
- net
command: redis-server --save "" --maxmemory 5gb --timeout 0 --tcp-keepalive 60 --bind 0.0.0.0 --slave-announce-ip IP2 --slave-announce-port 26379 --slaveof redis1 6379

redis3:
image: redis
deploy:
placement:
constraints: [engine.labels.host_ip==IP3]
endpoint_mode: vip
replicas: 1
restart_policy:
condition: on-failure
delay: 60s
ports:
- "36379:6379"
networks:
- net
command: redis-server --save "" --maxmemory 5gb --timeout 0 --tcp-keepalive 60 --bind 0.0.0.0 --slave-announce-ip IP3 --slave-announce-port 36379 --slaveof redis1 6379

networks:
net:


启动脚本install-redis.sh,内容如下:

#!/bin/bash

[ "$HOST_IP1" ] || HOST_IP1="192.168.1.4"
[ "$HOST_IP2" ] || HOST_IP2="192.168.1.4"
[ "$HOST_IP3" ] || HOST_IP3="192.168.1.4"

cp -f docker-stack-redis.yml docker-stack-redis.yml.temp
sed -i 's/IP1/'$HOST_IP1'/g' docker-stack-redis.yml.temp
sed -i 's/IP2/'$HOST_IP2'/g' docker-stack-redis.yml.temp
sed -i 's/IP3/'$HOST_IP3'/g' docker-stack-redis.yml.temp
docker stack deploy -c ./docker-stack-redis.yml.temp redis
rm -rf ./docker-stack-redis.yml.temp


redis哨兵编排脚本示例

编排脚本docker-stack-redis-sentinel.yml,内容如下:

version: "3"
services:

sentinel1:
image: redis
deploy:
placement:
constraints: [engine.labels.host_ip==IP1]
replicas: 1
restart_policy:
condition: on-failure
ports:
- "46379:26379"
volumes:
- data1:/data
networks:
- net
command: /bin/bash -c "touch /data/redis_sentinel.conf && redis-server /data/redis_sentinel.conf --sentinel monitor NAME IP PORT NUM --sentinel down-after-milliseconds NAME 5000 --sentinel parallel-syncs NAME 1 --sentinel failover-timeout NAME 180000 --sentinel announce-ip IP1 --sentinel announce-port 46379"

sentinel2:
image: redis
deploy:
placement:
constraints: [engine.labels.host_ip==IP2]
replicas: 1
restart_policy:
condition: on-failure
ports:
- "46380:26379"
volumes:
- data2:/data
networks:
- net
command: /bin/bash -c "touch /data/redis_sentinel.conf && redis-server /data/redis_sentinel.conf --sentinel monitor NAME IP PORT NUM --sentinel down-after-milliseconds NAME 5000 --sentinel parallel-syncs NAME 1 --sentinel failover-timeout NAME 180000 --sentinel announce-ip IP2 --sentinel announce-port 46380"

sentinel3:
image: redis
deploy:
placement:
constraints: [engine.labels.host_ip==IP3]
replicas: 1
restart_policy:
condition: on-failure
ports:
- "46381:26379"
volumes:
- data3:/data
networks:
- net
command: /bin/bash -c "touch /data/redis_sentinel.conf && redis-server /data/redis_sentinel.conf --sentinel monitor NAME IP PORT NUM --sentinel down-after-milliseconds NAME 5000 --sentinel parallel-syncs NAME 1 --sentinel failover-timeout NAME 180000 --sentinel announce-ip IP3 --sentinel announce-port 46381"

networks:
net:
volumes:
data1:
data2:
data3:


启动脚本install-redis-sentinel.sh,内容如下:

#!/bin/bash

[ "$SENTINEL_NAME" ] || SENTINEL_NAME="mysentinel"
[ "$MASTER_IP" ] || MASTER_IP="192.168.1.4"
[ "$MASTER_PORT" ] || MASTER_PORT="16379"
[ "$QUORUM" ] || QUORUM="2"
[ "$HOST_IP1" ] || HOST_IP1="192.168.1.4"
[ "$HOST_IP2" ] || HOST_IP2="192.168.1.4"
[ "$HOST_IP3" ] || HOST_IP3="192.168.1.4"

cp -f docker-stack-redis-sentinel.yml docker-stack-redis-sentinel.yml.temp
sed -i 's/IP1/'$HOST_IP1'/g' docker-stack-redis-sentinel.yml.temp
sed -i 's/IP2/'$HOST_IP2'/g' docker-stack-redis-sentinel.yml.temp
sed -i 's/IP3/'$HOST_IP3'/g' docker-stack-redis-sentinel.yml.temp
sed -i 's/NAME/'$SENTINEL_NAME'/g' docker-stack-redis-sentinel.yml.temp
sed -i 's/IP/'$MASTER_IP'/g' docker-stack-redis-sentinel.yml.temp
sed -i 's/PORT/'$MASTER_PORT'/g' docker-stack-redis-sentinel.yml.temp
sed -i 's/NUM/'$QUORUM'/g' docker-stack-redis-sentinel.yml.temp
docker stack deploy -c ./docker-stack-redis-sentinel.yml.temp redis-sentinel
rm -rf ./docker-stack-redis-sentinel.yml.temp


redis集群编排脚本示例

redis集群配置启动方式,只是最后多了一步,敲一个命令使redis(s)组成集群。

基本属于重复劳动,等用到时再提供之。

脚本来源

以上脚本均可在下面github上找到,且均经过测试,失效、主从切换测试等。

地址如下:

https://github.com/fananchong/go-x/tree/master/tools/redis

总结

在游戏运维阶段,使用一款可视化的redis管理工具,自然时最佳选择。特别是,运维的redis数量众多的情况。

这里之所以编写Redis的Docker Swarm部署,主要有以下几个原因:

练习Docker Swarm编排脚本。

redis这种应用可归为一类别,即练习了一堆这种性质的应用

开发时,一时用到,先去部署一款运维工具,显然太重了。

本文主要验证了redis是完整可以使用Docker Swarm方式,启动、并接受Docker Swarm管理的!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐