11
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

運用中のMongoDBのレプリカセットを行う in Docker

Posted at

MongoDB4.0で遂にトランザクションに対応したので、先日アップデートを行った。
こちらの記事↓
MongoDBをバージョン4.0にアップグレード in Docker

ただ、Mongoを1台で起動しているため、今のままではトランザクションは使えないのだ。
トランザクションに対応するためには、レプリカセットしなければならない。

今まで面倒で行っていなかったレプリカセットを行おうと思う。

レプリカセットの構成

最小限の構成として、プライマリー1台、セカンダリー2台、アービター1台で作成します。

プライマリーとかアービターについてはこちら
https://qiita.com/hakozaki/items/c41a5e6e7f0fad557c43

また、Dockerを使っているので、コンテナ1台につき1DBにして、ネットワークでそれぞれを繋ぐ構成でいきます。

docker-compose.ymlを編集する

現在のコンテナの設定は、

docker-compose.yml
  mongo:
    restart: always
    image: mongo
    volumes:
      - /var/www/data/mongo:/data/db

いたってシンプルです。
3台共通のネットワークに繋げるために、dockerコマンドでmongo_linkというネットワークを作成します。

$ docker network create mongo_link

そして、docker-compose.ymlを編集

docker-compose.yml
  mongo:
    restart: always
    image: mongo
    volumes:
      - /var/www/data/mongo:/data/db
    # 3行追加
    networks:
      - default
      - mongo_link
networks:
  mongo_link:
    external: true

- default←これなんぞ?と思った方いると思いますが、docker-composeではコンテナを作成したときに、勝手にDIRECTORYNAME_defaultというネットワーク内にいることになります。
- defaultを書かなければ、他のコンテナからアクセスできなく恐れがあるので、docker-compose.yml内に別のコンテナを含んでいる場合は設定しておきましょう。

さらに、セカンダリーとアービター用のコンテナの追加とレプリカセット用の引数をセットします。
すると、docker-compose.ymlは最終的にこんな感じになります。

docker-compose.yml
  mongo:
    restart: always
    image: mongo
    volumes:
      - /var/www/data/mongo:/data/db
    networks:
      - default
      - mongo_link
    command: --replSet mongo-set

  mongo-secondary:
    restart: always
    image: mongo
    volumes:
      - /var/www/data/mongo-secondary:/data/db
    networks:
      - default
      - mongo_link
    command: --replSet mongo-set

  mongo-arbiter:
    restart: always
    image: mongo
    networks:
      - default
      - mongo_link
    command: --replSet mongo-set

networks:
  mongo_link:
    external: true

プライマリーは、--replSet mongo-setというのを追加してレプリカセットできるようにしています。

セカンダリーはほぼプライマリーと同じですが、DBのデータを保存する空のディレクトリmongo-secondary/を用意しておきます。

アービターは、データを保持しないので、volumesは不要となります。

レプリカセットをセット

コンテナを生成しましょう

$ docker-compose up -d

mongoが再起動するとアクセスできない時間ができます。運用中の場合は、速やかに下記の作業を行ってください

# mongoコンテナにアクセス
$ docker-compose exec mongo bash
# mongo起動
% mongo
> rs.initiate()   # レプリカセットの初期化

一旦これで、mongo1台で稼働中となります。
(念ため、接続できているかアプリケーションの確認は行いましょう)

ここからセカンダリーとアービターをレプリカセットの中に追加していきます。

mongo-set:PRIMARY> rs.add({ host: 'mongo-secondary:27017' })
mongo-set:PRIMARY> rs.add({ host: 'mongo-arbiter:27017', arbiterOnly: true })

確認
membersの中に設定したセカンダリーとアービターがいれば成功です。

mongo-set:PRIMARY> rs.status()
{
	"set" : "mongo-set",
	"date" : ISODate("2018-08-17T10:02:29.297Z"),
	"myState" : 1,
	"term" : NumberLong(1),
	"syncingTo" : "",
        .
        .
        .
	"members" : [
		{
			"_id" : 0,
			"name" : "1b00277ff073:27017",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"uptime" : 987,
			"optime" : {
				"ts" : Timestamp(1534500141, 2),
				"t" : NumberLong(1)
			},
			"optimeDate" : ISODate("2018-08-17T10:02:21Z"),
			"syncingTo" : "",
			"syncSourceHost" : "",
			"syncSourceId" : -1,
			"infoMessage" : "",
			"electionTime" : Timestamp(1534499609, 2),
			"electionDate" : ISODate("2018-08-17T09:53:29Z"),
			"configVersion" : 3,
			"self" : true,
			"lastHeartbeatMessage" : ""
		},
		{
			"_id" : 1,
			"name" : "mongo-secondary:27017",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 18,
			"optime" : {
				"ts" : Timestamp(1534500141, 2),
				"t" : NumberLong(1)
			},
			"optimeDurable" : {
				"ts" : Timestamp(1534500141, 2),
				"t" : NumberLong(1)
			},
			"optimeDate" : ISODate("2018-08-17T10:02:21Z"),
			"optimeDurableDate" : ISODate("2018-08-17T10:02:21Z"),
			"lastHeartbeat" : ISODate("2018-08-17T10:02:27.858Z"),
			"lastHeartbeatRecv" : ISODate("2018-08-17T10:02:28.361Z"),
			"pingMs" : NumberLong(0),
			"lastHeartbeatMessage" : "",
			"syncingTo" : "1b00277ff073:27017",
			"syncSourceHost" : "1b00277ff073:27017",
			"syncSourceId" : 0,
			"infoMessage" : "",
			"configVersion" : 3
		},
		{
			"_id" : 2,
			"name" : "mongo-arbiter:27017",
			"health" : 1,
			"state" : 7,
			"stateStr" : "ARBITER",
			"uptime" : 7,
			"lastHeartbeat" : ISODate("2018-08-17T10:02:27.859Z"),
			"lastHeartbeatRecv" : ISODate("2018-08-17T10:02:27.887Z"),
			"pingMs" : NumberLong(0),
			"lastHeartbeatMessage" : "",
			"syncingTo" : "",
			"syncSourceHost" : "",
			"syncSourceId" : -1,
			"infoMessage" : "",
			"configVersion" : 3
		}
	],
	"ok" : 1,
	"operationTime" : Timestamp(1534500141, 2),
	"$clusterTime" : {
		"clusterTime" : Timestamp(1534500141, 2),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}

レプリカセットできていますね。

セカンダリーからも読み込みできるように設定する

レプリカセットは完了しましたが、このままでは、プライマリー以外からは、DBの中身を参照することができませんので、参照できるように設定します。

$ docker-compose exec mongo-secondary bash                                                                                                                                                                                  % mongo
mongo-set:SECONDARY> db.getMongo().setSlaveOk()

確認

> use DATABASE
> db.COL.count()
113

参照できました。
さらに、セカンダリーのデータを保存するために用意した、mongo-secondaryというディレクトリがあるとおもいますが、、、

$ ls mongo-secondary
WiredTiger                             collection-15--2012905472052276688.wt  collection-34--2012905472052276688.wt  index-17--2012905472052276688.wt       index-3--2012905472052276688.wt        index-5--2012905472052276688.wt
WiredTiger.lock                        collection-18--2012905472052276688.wt  collection-37--2012905472052276688.wt  index-19--2012905472052276688.wt       index-30--2012905472052276688.wt       index-7--2012905472052276688.wt
WiredTiger.turtle                      collection-2--2012905472052276688.wt   collection-4--2012905472052276688.wt   index-21--2012905472052276688.wt       index-32--2012905472052276688.wt       index-9--2012905472052276688.wt
WiredTiger.wt                          collection-20--2012905472052276688.wt  collection-6--2012905472052276688.wt   index-22--2012905472052276688.wt       index-33--2012905472052276688.wt       journal/
WiredTigerLAS.wt                       collection-23--2012905472052276688.wt  collection-8--2012905472052276688.wt   index-24--2012905472052276688.wt       index-35--2012905472052276688.wt       mongod.lock
_mdb_catalog.wt                        collection-25--2012905472052276688.wt  diagnostic.data/                       index-26--2012905472052276688.wt       index-36--2012905472052276688.wt       sizeStorer.wt
collection-0--2012905472052276688.wt   collection-28--2012905472052276688.wt  index-1--2012905472052276688.wt        index-27--2012905472052276688.wt       index-38--2012905472052276688.wt       storage.bson
collection-14--2012905472052276688.wt  collection-31--2012905472052276688.wt  index-16--2012905472052276688.wt       index-29--2012905472052276688.wt       index-39--2012905472052276688.wt

こちらにもデータが保存されていることがわかりますね。

以上で、レプリカセットが完了となります。
お疲れ様でした。

11
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?