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管理的!
相关文章推荐
- Go游戏服务器开发的一些思考(六):Docker Swarm Mode
- Go游戏服务器开发的一些思考(九):Docker桥接网络及固定IP (二)
- Go游戏服务器开发的一些思考(九):Docker桥接网络及固定IP (二)
- Go游戏服务器开发的一些思考(七):Redis
- Go游戏服务器开发的一些思考(十八):Docker内网环境搭建(备忘)
- Go游戏服务器开发的一些思考(八):Docker桥接网络及固定IP
- Go游戏服务器开发的一些思考(三十七):无缝世界场景构建与同步(四)
- Go游戏服务器开发的一些思考(二十八):登录流程(一)
- Go游戏服务器开发的一些思考(二十):Docker Swarm部署Etcd示例
- Go游戏服务器开发的一些思考(二十一):Go语言的两处脑残设定
- Go游戏服务器开发的一些思考(五):goroutine看似美好的陷阱
- Go游戏服务器开发的一些思考(三十六):无缝世界场景构建与同步(三)
- Go游戏服务器开发的一些思考(十五):gochart图表制作
- Go游戏服务器开发的一些思考(三十):排行榜服务器设计思路
- Go游戏服务器开发的一些思考(二十二):Godep包管理介绍
- Go游戏服务器开发的一些思考(三十五):无缝世界场景构建与同步(二)
- Go游戏服务器开发的一些思考(十二):行为树behavior3go介绍
- Go游戏服务器开发的一些思考(十四):IO游戏同步(二)
- Go游戏服务器开发的一些思考(十六):IO游戏服务器架构
- Go游戏服务器开发的一些思考(二十七):Go Redis ORM库(二)