LoginSignup
1
1

More than 5 years have passed since last update.

クラウドサーバー上でMongoDBクラスタを構築してみた

Posted at

はじめに

オンプレミス環境では、システムを構築する前にサーバー調達から物理作業・OSインストールが完了しないと構築作業が進めないのですが、クラウド環境では、ボタンを押すだけでネットワークからサーバーまで短時間で準備できます。そして、最近の「Infrastructure as Code」で、ボタンも押す必要がなくなりました。設定ファイルを記述することでサーバーやネットワーク構成が自動的にプロビージョンニングされるようになり、コマンドを実行するだけで「インフラストラクチャー」ができあがってしまいます。

個人的にはこれを見てすごく興味深いので、MongoDBクラスタをコード実行で構築できるようにしたくやってみました。ちょうど@mosuke5さんのterraformレポジトリのサンプルがあったので、サンプルを見ながらやってみました。

構成

image.png

Mongodbのレプリケーション構成では、最低レプリカ3台が必要です。そして、可用性を担保するため、それぞれのレプリカが別のスイッチに刺さる必要があります。そのため、Alibabaクラウド上では、以下の図どおりのコンポネントを作ります

architecture_mongo_cluster.png

コンポーネント

  • VPCネットワーク。CIDR: 10.0.0.0/16
  • それぞれのレプリカのプライベートネットワーク
    • 10.0.0.0/19: プライマリレプリカ
    • 10.0.32.0/19: セカンダリレプリカ
    • 10.0.64.0/19: セカンダリレプリカ
  • mongoクラスタ用のECSインスタンス
    • テストのため、1CPU-1GBメモリを使います
  • mongoクラスタのECSはグローバルIPを持つと外からデータストアへアクセスができてしまうため、プライベートIPしか付与しません。ソフトウェア更新やmongoインストールするために、それぞれのゾーンにSNATゲートウェイを構築します。SNATのECSがmongoクラスタへ影響しないように、別のサブネットワークにおきます。
    • パブリックCIDR: 10.0.128.0/20

構築

Terraformによる自動構築

設計したコンポーネントに従ってalicloud providersを使用して実装します。

詳細のソースコードはmosuke5さんのレポジトリに参照すればよいですが、providersは以下のふうになります。


resource "alicloud_vpc" "vpc" {
  name = "mongovpc"
  cidr_block = "${var.vpc_cidr}"
}

# vswitchの作成。mongo-primary
resource "alicloud_vswitch" "mongo-primary-switch" {
  name              = "mongo-primary-switch"
  vpc_id            = "${alicloud_vpc.vpc.id}"
  cidr_block        = "${var.mongo_primary_cidr}"
  availability_zone = "${var.zones[0]}"
}

# vswitchの作成。mongo-secondary0
resource "alicloud_vswitch" "mongo-secondary0-switch" {
  name              = "mongo-secondary0-switch"
  vpc_id            = "${alicloud_vpc.vpc.id}"
  cidr_block        = "${var.mongo_secondary0_cidr}"
  availability_zone = "${var.zones[1]}"
}
...

上記のプログラムを terraform apply --var-file="terraform.tfvars" を実行することで、図の構成が作成されます。

VSwitch/VRouter
image.png

サーバー
image.png

レプリカ設定

terraform を実行した後では、mongodbクラスタ (サーバー、ミドルウェア)ができあがります。クラスタの設定は ansibleとかで自動化できます。ただ、今回は手動でやります。

まず、mongodbは全インターフェイスで通信できるように、bindIpを削除し、replication set名を設定します。設定語にmongodbを起動します。この作業をmongodbの3台をそれぞれ行います。

[mongoadmin@mongo-primary ~]$ sudo vim /etc/mongodb.conf
net:
  port: 27017
#  bindIp: 127.0.0.1  # Listen to local interface only, comment to listen on all interfaces.

replication:
  replSetName: testrepl

# :wq
[mongoadmin@mongo-primary ~]$ sudo systemctl start mongod.service
[mongoadmin@mongo-primary ~]$ sudo systemctl status mongod.service
● mongod.service - High-performance, schema-free document-oriented database
   Loaded: loaded (/usr/lib/systemd/system/mongod.service; enabled; vendor preset: disabled)
   Active: active (running) since Mon 2017-06-05 10:02:25 CST; 3s ago
     Docs: https://docs.mongodb.org/manual
  Process: 9504 ExecStartPre=/usr/bin/chmod 0755 /var/run/mongodb (code=exited, status=0/SUCCESS)
  Process: 9502 ExecStartPre=/usr/bin/chown mongod:mongod /var/run/mongodb (code=exited, status=0/SUCCESS)
  Process: 9501 ExecStartPre=/usr/bin/mkdir -p /var/run/mongodb (code=exited, status=0/SUCCESS)
 Main PID: 9509 (mongod)
   CGroup: /system.slice/mongod.service
           └─9509 /usr/bin/mongod --quiet -f /etc/mongod.conf run

Jun 05 10:02:25 mongo-primary systemd[1]: Starting High-performance, schema-free document-oriented database...
Jun 05 10:02:25 mongo-primary systemd[1]: Started High-performance, schema-free document-oriented database.
Jun 05 10:02:25 mongo-primary mongod[9506]: about to fork child process, waiting until server is ready for connections.
Jun 05 10:02:25 mongo-primary mongod[9506]: forked process: 9509

次には、mongoシェルでreplication設定を行います。

[mongoadmin@mongo-primary ~]$ mongo
MongoDB shell version v3.4.4
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.4.4
Welcome to the MongoDB shell.
...
>
> rs.initiate( {
...    _id : "testrepl",
...    members: [
...        { _id : 0, host : "10.0.26.159:27017" },
...        { _id : 1, host : "10.0.43.6:27017" },
...        { _id : 2, host : "10.0.91.206:27017" }
...    ]
... })
{ "ok" : 1 }
> rs.status()
..
{
            "_id" : 0,
            "name" : "10.0.26.159:27017",
            "health" : 1,
...
},
{
            "_id" : 1,
            "name" : "10.0.43.6:27017",
            "health" : 1,
...
},
{
            "_id" : 2,
            "name" : "10.0.91.206:27017",
            "health" : 1,
...
}

それぞれの"health": 1となっていることを確認します。

secondaryで当インスタンスがslaveインスタンスなことを設定します。

testrepl:SECONDARY> db.getMongo().setSlaveOk()

動作確認

testCollectionmongo-primaryサーバーで作って、データがsecondaryへコピーされることを確認します

testrepl:PRIMARY> db.testCollection.insertOne({what: "Test mongodb", status: "ok"})
{
    "acknowledged" : true,
    "insertedId" : ObjectId("5934bf70cefc8e44e631908e")
}

secondarytestCollectionをクエリしてみます。

testrepl:SECONDARY> db.testCollection.find()
{ "_id" : ObjectId("5934bf70cefc8e44e631908e"), "what" : "Test mongodb", "status" : "ok" }

おわりに

terraformを使ってシンプルなmongoクラスタを作ってみました。terraformを使うことで、クラウドサーバーの購入・設定のような作業を自動化できます。

1
1
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
1
1