MongoDB レプリカ・セット

このレシピは、MongoDB インスタンスのレプリカ・セットを Docker Swarm にデプロイして制御することを目的としています。

要件

ウェルカム・ページを読み、インストール・ガイドで説明されている手順に従ってください。

使い方

まず、Docker Swarm (docker >= 1.13) を既にセットアップしておく必要があります。セットアップが必要な場合は、ローカルの swarm をセットアップするための簡単な方法についてはツール・セクションをチェックしてください。

$ miniswarm start 3
$ eval $(docker-machine env ms-manager0)

次に、この同じフォルダから単純に次のコマンドを実行します...

$ source settings.env  # In Windows, simply execute settings.bat instead.
$ docker stack deploy -c docker-compose.yml mongo-rs

イメージがノードでプルされ、サービスが展開されている間、少し時間を置いてください。数分後に、いつものようにすべてのサービスが稼働しているかどうかを確認できます...

$ docker service ls
ID            NAME                            MODE        REPLICAS  IMAGE
fjxof1n5ce58  mongo-rs_mongo             global      3/3       mongo:latest
yzsur7rb4mg1  mongo-rs_mongo-controller  replicated  1/1       martel/mongo-replica-ctrl:latest

ウォークスルー

以前に示したように、レシピは基本的に2つのサービス、すなわち mongo インスタンス用とレプリカ・セット用の2つのサービスで構成されています。

mongo サービスは "global" モードで展開されます。つまり、Docker はクラスタ内の swarm ノードごとに mongod のインスタンスを1つ実行します。

swarm のマスター・ノードでは、mongodb のレプリカ・セットを設定して維持するための Python ベースのコントローラ・スクリプトがデプロイされます。

コントローラが mongo-rs_controller サービスのログを精査したことを確認しましょう。これはいずれかで行うことができます...

$ docker service logs mongo-rs_controller

または、以下を実行します...

$  docker logs $(docker ps -f "name=mongo-rs_controller" -q)
INFO:__main__:Waiting some time before starting
INFO:__main__:Initial config: {'version': 1, '_id': 'rs', 'members': [{'_id': 0, 'host': '10.0.0.5:27017'}, {'_id': 1, 'host': '10.0.0.3:27017'}, {'_id': 2, 'host': '10.0.0.4:27017'}]}
INFO:__main__:replSetInitiate: {'ok': 1.0}

ご覧のとおり、レプリカ・セットは、同じオーバーレイ・ネットワーク上で動作するコンテナによって表される 3つのレプリカで構成されていました。mongo コンテナのいずれかで mongo コマンドを実行して、同じ結果を表示するために rs.status() を実行することもできます。

$ docker exec -ti d56d17c40f8f mongo rs:SECONDARY> rs.status()

レプリカ・セットの再スケーリング

新しいノードを swarm に追加して、docker が mongo サービスの新しいタスクをどのようにデプロイし、コントローラーがそれを自動的にレプリカ・セットに追加するかを見てみましょう。

# First get the token to join the swarm
$ docker swarm join-token worker

# Create the new node
$ docker-machine create -d virtualbox ms-worker2
$ docker-machine ssh ms-worker2

docker@ms-worker2:~$ docker swarm join \
--token INSERT_TOKEN_HERE \
192.168.99.100:2377

docker@ms-worker2:~$ exit

ホストに戻って、数分後に...

$ docker service ls
ID            NAME                            MODE        REPLICAS  IMAGE
fjxof1n5ce58  mongo-rs_mongo             global      4/4       mongo:latest
yzsur7rb4mg1  mongo_mongo-controller  replicated  1/1       martel/mongo-replica-ctrl:latest

$ docker logs $(docker ps -f "name=mongo_mongo-controller" -q)
...
INFO:__main__:To add: {'10.0.0.8'}
INFO:__main__:New config: {'version': 2, '_id': 'rs', 'members': [{'_id': 0, 'host': '10.0.0.5:27017'}, {'_id': 1, 'host': '10.0.0.3:27017'}, {'_id': 2, 'host': '10.0.0.4:27017'}, {'_id': 3, 'host': '10.0.0.8:27017'}]}
INFO:__main__:replSetReconfig: {'ok': 1.0}

ノードがダウンすると、レプリカ・セットは mongo によってアプリケーションのレベルで自動的に再構成されます。一方、Docker は、ノードごとに1つしか実行されないため、レプリカのスケジュールを変更しません。

: swarm のすべてのノードにレプリカを配置したくない場合は、現在の解決策は、制約とノード・タグの組み合わせを使用することです。これについて、Github の issue で詳しく読むことができます。

詳細は、mongo-rs-controller-swarm リポジトリ、特に docker-compose.yml ファイルまたは replica_ctrl.py コントローラのスクリプトを参照してください。