はじめまして、@chaltosです。
今回はDockerコンテナでRedisクラスタを構築した際の手順について書きます。
「set
, get
などが問題なく実行できればよい」という状況での作業メモ的なものなので、レプリケーションやバックアップなどはまったく考慮してません。
環境
OS | Mac OS X 10.9.2 |
Docker | 1.8.2 |
DockerMachine | 0.4.1 |
やってみる
Redis Cluster Tutorialによると、配布されているソースコードにはredis-tribやcreate-clusterというユーティリティが同梱されていて、以下のようなコマンドでノードの追加やスロットの割当てができるらしいです。便利ですね。
$ ./redis-trib.rb create 127.0.0.1:7000 127.0.0.1:7001 ...
$ create-cluster start $ create-cluster create
ですが、公式のDockerコンテナではRedisのビルド後にソースコードを削除しているため、これらに頼ることはできません。
仕方ないので手動でやります。
設定ファイル
デフォルトの設定ではクラスタリングできないので、まずは設定ファイルを用意します。
cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000
イメージの作成・起動
--volume
オプションで設定ファイルのあるディレクトリをマウントします。
上記の設定ファイルでredis-server
を実行すると、/data/nodes.conf
が生成されます。
このファイルの所有者はredis:redis
です。
--volume $(pwd):/data
とすると/data
の所有者が1000:staff
になってしまってnodes.conf
を生成できないので、--volume $(pwd):/data/conf
としておきます。
$ docker create --name node_6379 -p 6379:6379 --volume $(pwd):/data/conf redis:3 redis-server /data/conf/redis.conf $ docker create --name node_6380 -p 6380:6379 --volume $(pwd):/data/conf redis:3 redis-server /data/conf/redis.conf $ docker create --name node_6381 -p 6381:6379 --volume $(pwd):/data/conf redis:3 redis-server /data/conf/redis.conf $ docker start node_6379 node_6380 node_6381
クラスタリング
スロットの割当
まず各ノードにスロットを割当てます。
$ docker exec node_6379 redis-cli cluster addslots {0..5500} OK $ docker exec node_6380 redis-cli cluster addslots {5501..11000} OK $ docker exec node_6381 redis-cli cluster addslots {11001..16383} OK
OKっぽいですね、確認しましょう。
$ docker exec node_6379 redis-cli cluster nodes cf2e950621381be04ea1031ae80cb945f9743b83 :6379 myself,master - 0 0 0 connected 0-5500 $ docker exec node_6380 redis-cli cluster nodes 0969adb771d38a49e70f235b39665156ded5a43a :6379 myself,master - 0 0 0 connected 5501-11000 $ docker exec node_6381 redis-cli cluster nodes d9c4125051222bbc36cd0d0172e406baa9d89579 :6379 myself,master - 0 0 0 connected 11001-16383
ちゃんと割当てできてるように見えます。
ノードの追加
クラスタにノードを追加していきます。
$ docker exec node_6380 redis-cli cluster meet `docker-machine ip $DOCKER_MACHINE_NAME` 6379 OK $ docker exec node_6381 redis-cli cluster meet `docker-machine ip $DOCKER_MACHINE_NAME` 6379 OK
OKっぽいですね。
$ docker exec node_6379 redis-cli cluster nodes cf2e950621381be04ea1031ae80cb945f9743b83 :6379 myself,master - 0 0 0 connected 0-5500 $ docker exec node_6380 redis-cli cluster nodes 0969adb771d38a49e70f235b39665156ded5a43a :6379 myself,master - 0 0 0 connected 5501-11000 $ docker exec node_6381 redis-cli cluster nodes d9c4125051222bbc36cd0d0172e406baa9d89579 :6379 myself,master - 0 0 0 connected 11001-16383
変わってません。
やりなおす
どうもNAT越しだとうまくいかない(?)ようです。
--net host
を追加して、ブリッジしないようにしてみます。
ついでに各ノードで異なるポートを使用するようにしておきます。
$ for n in `seq 6379 6381`; do mkdir $n && echo "port $n" > $n/redis.conf && cat redis.conf >> &n/redis.conf; done $ docker stop node_6379 node_6380 node_6381 $ docker rm node_6379 node_6380 node_6381 $ docker create --name node_6379 --volume $(pwd)/6379:/data/conf --net host redis:3 redis-server /data/conf/redis.conf $ docker create --name node_6380 --volume $(pwd)/6380:/data/conf --net host redis:3 redis-server /data/conf/redis.conf $ docker create --name node_6381 --volume $(pwd)/6381:/data/conf --net host redis:3 redis-server /data/conf/redis.conf $ docker start node_6379 node_6380 node_6381 $ docker exec node_6379 redis-cli -p 6379 cluster addslots {0..5500} $ docker exec node_6380 redis-cli -p 6380 cluster addslots {5501..11000} $ docker exec node_6381 redis-cli -p 6381 cluster addslots {11001..16383} $ docker exec node_6380 redis-cli -p 6380 cluster meet `docker-machine ip $DOCKER_MACHINE_NAME` 6379 $ docker exec node_6381 redis-cli -p 6381 cluster meet `docker-machine ip $DOCKER_MACHINE_NAME` 6379
$ docker exec node_6379 redis-cli -p 6379 cluster nodes ca0a4f11069103e902ea83de9023b34a7aa01d06 192.168.99.100:6379 myself,master - 0 0 0 connected 0-5500 465ab243a99efec4e7cfa00491304b8dcffd0701 192.168.99.100:6381 master - 0 1444015783288 2 connected 11001-16383 c185ffd045e2ce324dce43ae5374253df8da2af2 192.168.99.100:6380 master - 0 1444015784307 1 connected 5501-11000 $ docker exec node_6380 redis-cli -p 6380 cluster nodes 465ab243a99efec4e7cfa00491304b8dcffd0701 192.168.99.100:6381 master - 0 1444015806729 2 connected 11001-16383 ca0a4f11069103e902ea83de9023b34a7aa01d06 192.168.99.100:6379 master - 0 1444015805713 0 connected 0-5500 c185ffd045e2ce324dce43ae5374253df8da2af2 192.168.99.100:6380 myself,master - 0 0 1 connected 5501-11000 $ docker exec node_6381 redis-cli -p 6381 cluster nodes c185ffd045e2ce324dce43ae5374253df8da2af2 192.168.99.100:6380 master - 0 1444015823353 1 connected 5501-11000 465ab243a99efec4e7cfa00491304b8dcffd0701 192.168.99.100:6381 myself,master - 0 0 2 connected 11001-16383 ca0a4f11069103e902ea83de9023b34a7aa01d06 192.168.99.100:6379 master - 0 1444015824374 0 connected 0-5500
先ほどとは違い、どのノードも他のノードを認識できてるようです。
実際にset
とかget
してみる
-c
は必須です。忘れるとリダイレクトせずにエラーを返します。
$ docker exec -it node_6379 redis-cli -c -p 6379 127.0.0.1:6379> set hoge 1 OK 127.0.0.1:6379> set hoge2 2 -> Redirected to slot [11000] located at 192.168.99.100:6380 OK 192.168.99.100:6380> set hoge3 3 -> Redirected to slot [15065] located at 192.168.99.100:6381 OK 192.168.99.100:6381> get hoge -> Redirected to slot [1525] located at 192.168.99.100:6379 "1" 192.168.99.100:6379> get hoge2 -> Redirected to slot [11000] located at 192.168.99.100:6380 "2" 192.168.99.100:6380> get hoge3 -> Redirected to slot [15065] located at 192.168.99.100:6381 "3"
きちんと他のノードにリダイレクトしてくれてますね。