MongoDB 3系を CentOS7 にインストール

# はじめに
MongoDB3.4 を CentOS7 にインストールしようとしたところ、特に WARNING を消す部分でいろいろと四苦八苦したのでメモ

CentOS のバージョンは以下の通り。さくらのVPSです。

```
# cat /etc/redhat-release
CentOS Linux release 7.3.1611 (Core)
```

# 1. MongoDB のインストールと起動
公式の記事に従って yum を使って MongoDB のインストールを行います。
[Install MongoDB Community Edition on Red Hat Enterprise or CentOS Linux — MongoDB Manual 3.4](https://docs.mongodb.com/manual/tutorial/install-mongodb-on-red-hat/)

## 1.1. MongoDB を yum でインストール
まずは、 /etc/yum.repos.d のディレクトリの下にファイルを追加して、yum のレポジトリを追加します。

```
# vi /etc/yum.repos.d/mongodb-org-3.4.repo
```

```/etc/yum.repos.d/mongodb-org-3.4.repo
[mongodb-org-3.4]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.4/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-3.4.asc
```

yum でインストール

```
# yum install -y mongodb-org
```

この後、公式のリファレンスでは [SELinux](https://access.redhat.com/documentation/ja-JP/Red_Hat_Enterprise_Linux/6/html/Security-Enhanced_Linux/sect-Security-Enhanced_Linux-Working_with_SELinux-Enabling_and_Disabling_SELinux.html) の設定について書かれていますが、おそらくサーバの初期設定をしたときに SELinux を無効化している方が多いと思いますので、ここは飛ばします（自分もやっていない）。

## 1.2. MongoDB の起動と自動起動の設定

MongoDB の起動

```
# systemctl start mongod
```

MongoDB の自動起動

```
# systemctl enable mongod
```

MongoDB のバージョンの確認

```
# mongo --version
MongoDB shell version v3.4.1
```

MongoDB のシェルの起動

```
# mongo
MongoDB shell version v3.4.1
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.4.1
Server has startup warnings:
2017-01-11T18:01:33.949+0900 I CONTROL  [initandlisten]
2017-01-11T18:01:33.949+0900 I CONTROL  [initandlisten] ** WARNING: Access control is not enabled for the database.
2017-01-11T18:01:33.949+0900 I CONTROL  [initandlisten] **          Read and write access to data and configuration is unrestricted.
2017-01-11T18:01:33.949+0900 I CONTROL  [initandlisten]
2017-01-11T18:01:33.949+0900 I CONTROL  [initandlisten]
2017-01-11T18:01:33.949+0900 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.
2017-01-11T18:01:33.949+0900 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
2017-01-11T18:01:33.949+0900 I CONTROL  [initandlisten]
2017-01-11T18:01:33.949+0900 I CONTROL  [initandlisten]
2017-01-11T18:01:33.949+0900 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
2017-01-11T18:01:33.949+0900 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
2017-01-11T18:01:33.949+0900 I CONTROL  [initandlisten]
> 
```

起動できました。無事に MongoDB のインストールができたようです。

# 2. WARNING: We suggest setting it to 'never' を消す
シェルを起動したときに WARING が出てしまっています。今度はこれを解消します。これも公式が解消方法を出していますが、公式のやり方だと一部うまくいかない部分がありました。そのため、別の記事も参考にしています。

[Disable Transparent Huge Pages (THP) — MongoDB Manual 3.4](https://docs.mongodb.com/manual/tutorial/transparent-huge-pages/)
[MongoDB 3.0 をインストール - Carpe Diem](http://christina04.hatenablog.com/entry/2015/03/12/130033)

> Transparent Huge Pages (THP) is a Linux memory management system that reduces the overhead of Translation Lookaside Buffer (TLB) lookups  on machines with large amounts of memory by using larger memory pages.
> However, database workloads often perform poorly with THP, because they tend to have sparse rather than contiguous memory access patterns. You should disable THP on Linux machines to ensure best performance with MongoDB.

CentOS(redhat系)の Linux では、[THP(Transparent Huge Pages)](https://access.redhat.com/documentation/ja-JP/Red_Hat_Enterprise_Linux/6/html/Performance_Tuning_Guide/s-memory-transhuge.html) というページ管理システムを採用しているのですが、どうやらこれが MongoDB と相性が悪いようです。


## 2.1. 初期化するスクリプトの作成
/etc/init.d ディレクトリにスクリプトを作成します。
公式のものをコピペしてやってみましたが、WARNING の一部が消えなかったので他の記事を参考に以下のようにしました。

```
# vi /etc/init.d/disable-transparent-hugepages
```

```/etc/init.d/disable-transparent-hugepages
#!/bin/bash
### BEGIN INIT INFO
# Provides:          disable-transparent-hugepages
# Required-Start:    $local_fs
# Required-Stop:
# X-Start-Before:    mongod mongodb-mms-automation-agent
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Disable Linux transparent huge pages
# Description:       Disable Linux transparent huge pages, to improve
#                    database performance.
### END INIT INFO

case $1 in
  start)
    if test -f /sys/kernel/mm/transparent_hugepage/enabled; then
      echo never > /sys/kernel/mm/transparent_hugepage/enabled
    fi
    if test -f /sys/kernel/mm/transparent_hugepage/defrag; then
      echo never > /sys/kernel/mm/transparent_hugepage/defrag
    fi

    re='^[0-1]+$'
    if [[ $(cat ${thp_path}/khugepaged/defrag) =~ $re ]]
    then
      # RHEL 7
      echo 0  > ${thp_path}/khugepaged/defrag
    else
      # RHEL 6
      echo 'no' > ${thp_path}/khugepaged/defrag
    fi

    unset re
    unset thp_path
    ;;
esac
```

パーミッションの変更

```
# chmod 755 /etc/init.d/disable-transparent-hugepages
```

サービス設定の追加
（chkconfig については[こちら](http://qiita.com/shell/items/30031862d91cedf9ceef)の記事がわかりやすかったです）

```
# chkconfig --add disable-transparent-hugepages
# chkconfig --list
disable-transparent-hugepages	0:off	1:off	2:on	3:on	4:on	5:on	6:off
```

`# /sbin/service disable-transparent-hugepages start ` をしたかどうかは忘れました...すいません



## 2.2. tuned と ktune の設定
> If using tuned or ktune, you must perform this step in addition to installing the init script.

tuned または ktune を使用している場合には、2.1 に加えて以下の設定もする必要があります。
（tuned または ktune に関しては[こちら](https://access.redhat.com/documentation/ja-JP/Red_Hat_Enterprise_Linux/6/html/Power_Management_Guide/Tuned.html)）

> tuned and ktune are dynamic kernel tuning tools available on Red Hat and CentOS that can disable transparent huge pages. 
> To disable transparent huge pages in tuned or ktune, you need to edit or create a new profile that sets THP to never.

新しいプロファイルの作成が必要なようです。

```
# mkdir /etc/tuned/no-thp
# vi /etc/tuned/no-thp/tuned.conf
```

```/etc/tuned/no-thp/tuned.conf
[main]
include=virtual-guest

[vm]
transparent_hugepages=never
```

[tuned-adm](https://access.redhat.com/documentation/ja-JP/Red_Hat_Enterprise_Linux/6/html/Power_Management_Guide/tuned-adm.html) コマンドを使って、プロファイルの切り替えを行います。

```
# tuned-adm profile no-thp
```

変更されたかテストしています。never に [] がついていればうまくいっています。

```
# cat /sys/kernel/mm/transparent_hugepage/enabled
always madvise [never]
# cat /sys/kernel/mm/transparent_hugepage/defrag
always madvise [never]
```

## 2.3. MongoDB の再起動とシェルの確認
MongoDB を再起動

```
# systemctl restart mongod
```

シェルを起動して、WARNING が消えたか確認

```
# mongo
MongoDB shell version v3.4.1
connecting to: mongodb://127.0.0.1:27017/
MongoDB server version: 3.4.1
Server has startup warnings:
2017-01-11T18:24:52.860+0900 I CONTROL  [initandlisten]
2017-01-11T18:24:52.860+0900 I CONTROL  [initandlisten] ** WARNING: Access control is not enabled for the database.
2017-01-11T18:24:52.860+0900 I CONTROL  [initandlisten] **          Read and write access to data and configuration is unrestricted.
2017-01-11T18:24:52.860+0900 I CONTROL  [initandlisten]
> 
```

WARNING: We suggest setting it to 'never' の2つは消えたようです。

もし、WARNING が消えない場合はログからエラーを確認してください

```
# tail /var/log/mongodb/mongod.log
```



# 3. WARNING: Access control is not enabled for the database. を消す
MongoDB 3系から出た WARNING だと思います。どうやら、MongoDB のセキュリティ面の問題らしいです。openssl コマンドを使って内部認証を行えるようにします。こちらも見つけにくかったですが、公式の記事がありました。
[Enable Internal Authentication — MongoDB Manual 3.0](https://docs.mongodb.com/v3.0/tutorial/enable-internal-authentication/)

keyfile の場所はこちらの記事を参考にしています。
[mongodb3.0.x 設定ファイルテンプレ - Qiita](http://qiita.com/crumbjp/items/135b76b0f9bca0c912f9)

## 3.1. keyfile の作成

keyfileの作成

```
# mkdir -p /usr/local/mongodb/conf
# openssl rand -base64 741 > /usr/local/mongodb/conf/mongodb-keyfile
```

公式には chown がないのですが、私の場合はこれがないと permission denied というエラーが出ました。

```
# chmod 600 /usr/local/mongodb/conf/mongodb-keyfile
# chown -R mongod.mongod /usr/local/mongodb/conf/mongodb-keyfile
```

## 3.2. 設定ファイルに追加し、再起動
設定ファイルに追加します。 security のコメントアウトを外すことを忘れないでください。

```
# vi /etc/mongod.conf
```

```/etc/mongod.conf
security:
  keyFile: /usr/local/mongodb/conf/mongodb-keyfile
```

MongoDB を再起動

```
# systemctl restart mongod
```

シェルの起動

```
# mongo
MongoDB shell version v3.4.1
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.4.1
> 
```

WARNING が消えた！（もしかしたら、ユーザ認証を追加しないといけないかも）


# 4. ユーザ認証の追加
今のままだと誰でも Mongo のデータに触ることができるため、とても危険です。私も1度 Mongo を標的としたマルウェアに感染したため、全てのデータが消えました。ユーザ認証ははじめに追加しましょう。こちらも公式に方法が書いてあります。

[Enable Auth — MongoDB Manual 3.4](https://docs.mongodb.com/manual/tutorial/enable-authentication/)

## 4.1. 管理ユーザの作成
管理ユーザを作成します。admin データベースにユーザを管理する権限（ userAdminAnyDatabase )を持ったユーザを追加します。 password の部分はご自分で用意したものを設定してください。


```
# mongo

> use admin
switched to db admin

> db.createUser({user:"myUserAdmin",pwd:"password",roles:[{role:"userAdminAnyDatabase",db:"admin"}]})
Successfully added user: {
	"user" : "myUserAdmin",
	"roles" : [
		{
			"role" : "userAdminAnyDatabase",
			"db" : "admin"
		}
	]
}
```

MongoDB の設定ファイルを更新します。

```
# vi /etc/mongod.conf
```

```/etc/mongod.conf
security:
  keyFile: /usr/local/mongodb/conf/mongodb-keyfile
  authorization: enabled
```

MongoDB を再起動します。

```
# systemctl restart mongod
```

次からはログインが必要になります。mongo のシェルを起動してから `db.auth()` を使ってログインする方法と、mongo のシェルを起動するときにログインする方法の2種類があります。

**mongo のシェルを起動してから `db.auth()` を使ってログインする方法**
`db.auth()` のあとに `1` と出れば成功

```
# mongo
> use admin
switched to db admin

> db.auth("myUserAdmin","password")
1
```

**mongo のシェルを起動するときにログインする方法**
シェルがちゃんと起動すれば成功

```
# mongo -u "myUserAdmin" -p "password" --authenticationDatabase "admin"
```

## 4.2 一般ユーザの作成
Mongo はデータベースごとにユーザを作成するようです。テストユーザを作成して、権限の確認をしましょう。
`readWrite` はデータベースの読み書きができます。'read' だと読み込みだけです。

```
# mongo -u "myUserAdmin" -p "password" --authenticationDatabase "admin"

> use test

> db.createUser({user:"myTester",pwd:"xyz123",roles:[{role:"readWrite",db:"test"}]})
Successfully added user: {
	"user" : "myTester",
	"roles" : [
		{
			"role" : "readWrite",
			"db" : "test"
		}
	]
}
```

一度シェルを閉じてから再度ログインしてみましょう。

```
# mongo -u "myTester" -p "xyz123" --authenticationDatabase "test"

> db.foo.insert( { x: 1, y: 1 } )
WriteResult({ "nInserted" : 1 })

> show collections
foo

> db.foo.find()
{ "_id" : ObjectId("58762b81a5a33029aaf665ee"), "x" : 1, "y" : 1 }
```

ちゃんとデータが見れました。次は、一度シェルを閉じてから再度ログインしてみましょう。

```
# mogno

> use test
switched to db test

> show collections
2017-01-11T21:58:19.707+0900 E QUERY    [main] Error: listCollections failed: {
	"ok" : 0,
	"errmsg" : "not authorized on test to execute command { listCollections: 1.0, filter: {} }",
	"code" : 13,
	"codeName" : "Unauthorized"
} :

> db.foo.find()
Error: error: {
	"ok" : 0,
	"errmsg" : "not authorized on test to execute command { find: \"foo\", filter: {} }",
	"code" : 13,
	"codeName" : "Unauthorized"
}
```

今度はテストユーザで認証していないため、コレクションを見ることができませんでした。

最後にテストユーザを削除することを忘れずに。

```
# mongo -u "myUserAdmin" -p "password" --authenticationDatabase "admin"

> db.dropUser("myuser")
```

参考元
***
[Install MongoDB Community Edition on Red Hat Enterprise or CentOS Linux — MongoDB Manual 3.4](https://docs.mongodb.com/manual/tutorial/install-mongodb-on-red-hat/)
[Disable Transparent Huge Pages (THP) — MongoDB Manual 3.4](https://docs.mongodb.com/manual/tutorial/transparent-huge-pages/)
[MongoDB 3.0 をインストール - Carpe Diem](http://christina04.hatenablog.com/entry/2015/03/12/130033)
[Enable Internal Authentication — MongoDB Manual 3.0](https://docs.mongodb.com/v3.0/tutorial/enable-internal-authentication/)
[mongodb3.0.x 設定ファイルテンプレ - Qiita](http://qiita.com/crumbjp/items/135b76b0f9bca0c912f9)
[Enable Auth — MongoDB Manual 3.4](https://docs.mongodb.com/manual/tutorial/enable-authentication/)