Apps: "MongoDB v.3.6".
Задача: установка и базовая настройка СУБД "MongoDB" с последующим тестированием функционала создания структур данных, их резервного копирования и восстановления.
Последовательность дальнейших действий такова:
1. Установка СУБД "MongoDB".
2. Включение механизма аутентификации.
3. Настройка "прозрачной" аутентификации.
4. Создание БД и пользователей.
5. Настройка резервного копирования и проверка восстановления.
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
# 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
....
# Прослушиваемый сервисом 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
# vi /etc/systemd/system/mongod.service.d/socket.conf
[Service]
RuntimeDirectory=mongodb
RuntimeDirectoryMode=0755
RuntimeDirectory=mongodb
RuntimeDirectoryMode=0755
Применяем изменения конфигурации "Systemd" и перезапускаем "MongoDB":
# systemctl daemon-reload
# systemctl restart mongod
# systemctl restart mongod
При просмотре статуса сервиса можно заметить, что часть его конфигурации переопределена (строка "drop-in"):
# systemctl status mongod
# journalctl -xe
# 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
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
... 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
> db.createUser( { user: "root", pwd: "rootPassword", roles: [ { role:"root", db:"admin" } ] } )
> exit
Если в БД уже зарегистрированы пользователи, то следующими командами можно будет просмотреть их перечень, сменить пароль или удалить, при необходимости:
> use admin
> show users
> db.changeUserPassword( "someUser", "userPassword" )
> db.dropUser( "someUser" )
> exit
> show users
> db.changeUserPassword( "someUser", "userPassword" )
> db.dropUser( "someUser" )
> exit
После создания учётной записи суперпользователя СУБД следует перезапустить "MongoDB" в режиме, включающим доступ к данным только после аутентификации и проверки привелегий.
# vi /etc/mongod.conf
....
security:
authorization: enabled
....
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" )
> 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" } )
> use example_net
> db.init.insert( { sitename: "example.net" } )
Теперь в списке "баз данных" будет также фигурировать наша "example_net", в перечне её коллекций данных свежесозданная "init", а внутри таковой найдётся документ "sitename":
> show dbs
> show collections
> db.init.find()
> show collections
> db.init.find()
Создаём пользователя СУБД в контексте предназначаемой ему "базы данных" и предоставляем к таковой доступ на чтение и запись:
> use example_net
> db.createUser( { user: "example_net", pwd: "userPassword", roles: [ { role: "readWrite", db: "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()
> show collections
> db.init.find()
После того, как пользователь перестал быть нужным, его можно удалить:
> use example_net
> db.runCommand( { dropUser: "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)
... writing example_net.init to
... done dumping example_net.init (1 document)
Тестируя функционал, удалим одну из пользовательских БД в действующем сервисе:
# mongo
> use example_net
> db.runCommand( { dropDatabase: 1 } )
> 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
... 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".