UMGUM.COM 

Инсталляция MongoDB ( Установка и базовая настройка СУБД "MongoDB", с последующим тестированием функционала. )

30 июня 2017  (обновлено 25 декабря 2019)

OS: "Linux Ubuntu 16/18 (Xenial/Bionic) LTS".
Apps: "MongoDB v.3.6".

Задача: установка и базовая настройка СУБД "MongoDB" с последующим тестированием функционала создания структур данных, их резервного копирования и восстановления.

Последовательность дальнейших действий такова:

1. Установка СУБД "MongoDB".
2. Включение механизма аутентификации.
3. Настройка "прозрачной" аутентификации.
4. Создание БД и пользователей.
5. Настройка резервного копирования и проверка восстановления.


Установка и настройка СУБД "MongoDB".

В наборах APT-дистрибутивов стабильных версий "Linux" предлагаемые версии "MongoDB" обычно устаревшие и лучше устанавливать таковую из подключаемых репозиториев разработчиков:

# apt-get install gnupg
# wget -qO - https://www.mongodb.org/static/pgp/server-3.6.asc | sudo apt-key add -
# echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.6 multiverse" > /etc/apt/sources.list.d/mongodb-org-3.6.list
# apt-get update
# apt-get install mongodb-org

После развёртывания из дистрибутивного пакета сервис "MongoDB" запускается с прослушиванием запросов на локальных "сетевой петле" и "файловом сокете" - он сразу вполне работоспособен, но я предпочитаю изменить месторасположение файла "файлового сокета", по умолчанию размещаемого в неудобной для автоматизации директории "/tmp":

# vi /etc/mongod.conf

....
# Прослушиваемый сервисом IP-адрес и TCP-порт
# (разрешаем подключаться только с "localhost")
net:
  port: 27017
  bindIp: 127.0.0.1
  ipv6: false
# Явно активируем и задаём месторасположение unix-сокета
# (итоговое имя: "/var/run/mongodb/mongodb-27017.sock")
  unixDomainSocket:
    enabled: true
    pathPrefix: /var/run/mongodb
    filePermissions: 0777
....

Указанная нами для размещения unix-сокета директория по умолчанию отсутствует. Создадим файловую структуру, переопределяющую имеющуюся конфигурацию "Systemd", указывая обеспечить наличие поддиректории "mongodb" в специальной runtime-структуре "/var/run|/run":

# mkdir -p /etc/systemd/system/mongod.service.d
# vi /etc/systemd/system/mongod.service.d/socket.conf

[Service]
RuntimeDirectory=mongodb
RuntimeDirectoryMode=0755

Применяем изменения конфигурации "Systemd" и перезапускаем "MongoDB":

# systemctl daemon-reload
# systemctl restart mongod

При просмотре статуса сервиса можно заметить, что часть его конфигурации переопределена (строка "drop-in"):

# systemctl status mongod
# journalctl -xe

Убеждаемся, что сервис принимает запросы так, как нам удобно:

# netstat -apn | grep -i listen | grep -i mongo

tcp ... 127.0.0.1:27017 0.0.0.0:* LISTEN .../mongod
unix ... STREAM LISTENING .../mongod /run/mongodb/mongodb-27017.sock

Включение механизма аутентификации в СУБД "MongoDB".

По умолчанию "MongoDB" запускается в режиме полностью свободного доступа, без ограничений на чтение и модификацию данных - об этом нас будет постоянно предупреждать CLI-утилита "mongo":

$ mongo

....
... CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database.
... CONTROL [initandlisten] **          Read and write access to data and configuration is unrestricted.
>
> show dbs
admin  0.000GB
config 0.000GB
local  0.000GB

Сразу после первичной инсталляции в "MongoDB" пользователи отсутствуют. Заведём для начала суперпользователя (в версиях от "4.2" вместо указания пароля открытым текстом стало возможно запрашивать его интерактивно посредством вызова функции "passwordPrompt()"):

$ mongo --quiet
> use admin
> db.createUser( { user: "root", pwd: "rootPassword", roles: [ { role:"root", db:"admin" } ] } )
> exit

Если в БД уже зарегистрированы пользователи, то следующими командами можно будет просмотреть их перечень, сменить пароль или удалить, при необходимости:

> use admin
> show users
> db.changeUserPassword( "someUser", "userPassword" )
> db.dropUser( "someUser" )
> exit

После создания учётной записи суперпользователя СУБД следует перезапустить "MongoDB" в режиме, включающим доступ к данным только после аутентификации и проверки привелегий.

# vi /etc/mongod.conf

....
security:
  authorization: enabled
....

Для применения изменений требуется перезапуск сервиса:

# systemctl restart mongod

Для подключения к "MongoDB" посредством интерактивной CLI-утилиты "mongo" практикуется два варианта аутентификации. Можно при вызове утилиты "mongo" сразу задать логин и пароль (если пароль не указывать, он будет запрошен в процессе подключения) в виде параметров:

$ mongo --quiet --port 27017 -u "root" -p --authenticationDatabase "admin"

Также можно вначале запустить CLI-утилиту "mongo", а в консоли запросить подключение к целевой "базе" с последующей процедурой аутентификации:

$ mongo --quiet
> use admin
> db.auth( "root", "rootPassword" )

Вместо TCP-порта можно подключаться через unix-сокет:

$ mongo --quiet mongodb://%2Fvar%2Frun%2Fmongodb%2Fmongodb-27017.sock/admin -u "root" -p

В примере выше часть символов "/" заменена спецсимволами "%2F" - такова особенность синтаксиса строки обращения к unix-сокету CLI-утилиты "mongo", с обязательным кодированием типичных экранируемых символов. Другие программные клиенты, например у PHP, принимают строку адреса unix-сокета без экранирования и кодирования.

Наладка "прозрачной" аутентификации в контексте системного суперпользователя.

Идеологически в "Linux"-е предполагается, что пользователь "root" (или член одноимённой группы) имеет техническую возможность получить доступ к любым локальным ресурсам и для него нет смысла при работе с таковыми использовать дополнительную парольную аутентификацию.

Например, в контексте суперпользователя при обращении к СУБД "MySQL" или "PostgreSQL" через "файловый сокет" или "локальную сетевую петлю" по умолчанию пароль не запрашивается - это удобно для автоматизации фоновых процедур.

В "MongoDB" включение сквозного режима доступа для определённого круга пользователей не предусмотрено, но похожего поведения от клиентских приложений можно добиться, предприняв следующие действия.

В доступном только системному суперпользователю месте размещаем файл с паролем для подключения к "MongoDB":

# vi /root/.mongodb

rootPassword

Естественно, доступ к файлу с паролем обязательно ограничиваем:

# chmod go-rwx /root/.mongodb

Создаём подмену команды вызова CLI-утилиты "mongo" в предпочитаемой среде исполнения (в примере "Bash"):

# echo -e "\n# MongoDB client CLI pass-through authentication hook:\nalias mongo=\"mongo --quiet mongodb://%2Fvar%2Frun%2Fmongodb%2Fmongodb-27017.sock/admin -u root -p\$(cat /root/.mongodb)\"" >> ~/.bash_aliases

Теперь при запуске утилиты "mongo" в контексте суперпользователя будет осуществлено автоматическое подключение к БД "admin" через локальный "файловый сокет" с прозрачной, с точки зрения клиента, аутентификацией в роли "root".

Аналогичный подход с прозрачной аутентификацией можно использовать и для других утилит "MongoDB", вроде "mongoimport" или "mongodump".

Создание "баз данных" и пользователей в "MongoDB".

Прежде всего следует учесть специфику СУБД "MongoDB" - в ней "база данных" не создаётся на постоянной основе до того, как в ней не будет сохранён хотя бы один документ. Эта особенность некритична, но для подтверждения успешности создания структуры лучше бы сразу размещать в ней одну запись.

Создаём пользовательскую БД (условно для сайта "example.net"), коллекцию данных (с произвольным именем, в нашем случае "init") в ней и сохраняем однострочный документ:

# mongo
> use example_net
> db.init.insert( { sitename: "example.net" } )

Теперь в списке "баз данных" будет также фигурировать наша "example_net", в перечне её коллекций данных свежесозданная "init", а внутри таковой найдётся документ "sitename":

> show dbs
> show collections
> db.init.find()

Создаём пользователя СУБД в контексте предназначаемой ему "базы данных" и предоставляем к таковой доступ на чтение и запись:

> use example_net
> db.createUser( { user: "example_net", pwd: "userPassword", roles: [ { role: "readWrite", db: "example_net" } ] } )

Пробуем подключиться к целевой БД с указанием логина и пароля нового пользователя:

$ mongo localhost/example_net -u example_net -p
> show collections
> db.init.find()

После того, как пользователь перестал быть нужным, его можно удалить:

> use example_net
> db.runCommand( { dropUser: "example_net" } )

Резервное копирование и восстановление БД "MongoDB".

Подготовим директорию резервной копии:

# mkdir -p /var/backups/mongodump

Выгрузим полную резервную копию всех "баз данных":

# mongodump --verbose --host localhost --port 27017 --username root --password "`cat /root/.mongodb`" --authenticationDatabase=admin --out /var/backups/mongodump

С ключём "--db" можно выгрузить резервную копию только одной БД:

# mongodump --verbose --host localhost --port 27017 --username root --password "`cat /root/.mongodb`" --authenticationDatabase=admin --db=example_net --out /var/backups/mongodump

... dumping up to 1 collections in parallel
... writing example_net.init to
... done dumping example_net.init (1 document)

Тестируя функционал, удалим одну из пользовательских БД в действующем сервисе:

# mongo
> use example_net
> db.runCommand( { dropDatabase: 1 } )

Восстановим только что удалённую "базу данных", воспользовавшись ранее созданной резервной копией:

# mongorestore -v -h localhost -u root -p "`cat /root/.mongodb`" --authenticationDatabase=admin --nsInclude "example_net.*" /var/backups/mongodump

... preparing collections to restore from
... found collection example_net.init bson to restore to example_net.init
... found collection metadata from example_net.init to restore to example_net.init
... reading metadata for example_net.init from /var/backups/mongodump/example_net/init.metadata.json
... creating collection example_net.init using options from metadata
... restoring example_net.init from /var/backups/mongodump/example_net/init.bson
... no indexes to restore
... finished restoring example_net.init (1 document)
... done

Это работает.

Дополнительная информация.

Сервис "Amazon DocumentDB" совместим с API "MongoDB v.3.6".


Заметки и комментарии к публикации:


Оставьте свой комментарий ( выразите мнение относительно публикации, поделитесь дополнительными сведениями или укажите на ошибку )