Дерево страниц
Перейти к концу метаданных
Переход к началу метаданных

Количество реплик следует выбирать с учетом таблицы ниже:

Кол-во репликКол-во необходимых голосов для выбора нового PrimaryКол-во реплик, которые можно потерять с сохранением работоспособности
110
220
321
431
532
642
743
853
954
1064
1165
1275
1376

По-умолчанию голосовать могут только 7 реплик, поэтому добавление большего их количество не требуется.

Максимальное количество реплик в наборе - 50.

Схема работы с 3 репликами:


I. Подготовка реплик

Примечание 1

На Ubuntu 22.04 устанавливается без костылей только MongoDB 6.0.4+, поэтому рекомендуется выбрать Ubuntu 20.04

Примечание 2

Для использования MongoDB 5.0+ в ВМ под управление Proxmox требуется указать тип процессора host (вместо kvm64), так как начиная с этой версии требуются AVX инструкции

1. Устанавливаем MongoDB на сервера, которые будут выполнять роль реплик:

MongoDB 6.0:

sudo apt update
sudo apt -y install gnupg
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/6.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-6.0.list
curl -sSL https://www.mongodb.org/static/pgp/server-6.0.asc  -o mongoserver.asc
gpg --no-default-keyring --keyring ./mongo_key_temp.gpg --import ./mongoserver.asc
gpg --no-default-keyring --keyring ./mongo_key_temp.gpg --export > ./mongoserver_key.gpg
sudo mv mongoserver_key.gpg /etc/apt/trusted.gpg.d/
sudo apt update
sudo apt install mongodb-org

MongoDB 5.0:

sudo apt update
sudo apt -y install wget curl gnupg2 software-properties-common apt-transport-https ca-certificates lsb-release
curl -fsSL https://www.mongodb.org/static/pgp/server-5.0.asc|sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/mongodb.gpg
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/5.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-5.0.list
sudo apt update
sudo apt -y install mongodb-org

MongoDB 4.4 (работает без AVX):

sudo apt update
sudo apt-get install gnupg
curl -fsSL https://pgp.mongodb.com/server-4.4.asc | sudo gpg -o /usr/share/keyrings/mongodb-server-4.4.gpg --dearmor
echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-4.4.gpg ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/4.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.4.list
sudo apt-get update
sudo apt-get install -y mongodb-org

2. Включаем сервис MongoDB:

sudo systemctl enable mongod

3. В файле /etc/mongod.conf необходимо:

  • Изменить строку с bindIp: 127.0.0.1 на bindIp: 0.0.0.0
  • Добавить строки:
replication:
  replSetName: iotRepl

4. Запускаем сервис MongoDB:

sudo systemctl start mongod


Если будет производиться переход с уже существующей БД, то настройка реплик завершена, дальнейшие действия описаны в пункте IIb.

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

5. Подключаемся к любой из реплик при помощи mongosh:

mongosh mongodb://[ip любой из реплик]:[port mongodb любой из реплик]

6. Инициируем набор реплик командой (в данном примере реплик всего 3):

rs.initiate(
   {
      _id: "iotRepl",
      version: 1,
      members: [
         { _id: 0, host : "[ip первой реплики]:[port mongodb первой реплики]" },
         { _id: 1, host : "[ip второй реплики]:[port mongodb второй реплики]" },
         { _id: 2, host : "[ip третьей реплики]:[port mongodb третьей реплики]" }
      ]
   }
)

7. Периодически вводя команду rs.status() дождаться пока одна реплика перейдет в статус PRIMARY, а все остальные - в SECONDARY (смотреть поле stateStr)

IIa. Установка платформы с нуля (для версий 1.29 и ниже)

Шаги аналогичны обычным до пункта "7. Запуск и установка (только от root)", однако после этого необходимо изменить параметры БД в файле [путь до ansible-iot]/vars/default.yml:

  • Включить внешнюю MongoDB:

    external:
        enable: true
  • Указать адреса всех реплик в поле addr:

    addr: "[ip первой реплики]:[port mongodb первой реплики],[ip второй реплики]:[port mongodb второй реплики],[ip третьей реплики]"

    Внимание

    Порт последней реплики в поле addr не указывается!

  • Указать порт последней реплики в поле port:

    port: [port mongodb третьей реплики]

Далее необходимо  в файле [путь до ansible-iot]/templates/iot/default-for-docker.yml.j2  в разделе iot-core заменить:

  host: "{{ mongodb_addr }}" 

на

  host: "{{ mongodb_addr }}:{{ mongodb_port }}/{{ coreInternal.core.db.name }}?socketTimeoutMS=20000&replicaSet=iotRepl&w=majority&appName=" 

И в файле [путь до ansible-iot]/templates/iot/docker-compose/base_config.yml.j2  для сервиса broker в environments заменить:

      - SPRING_DATA_MONGODB_URI=mongodb://${MONGODB_ADDR}:${MONGODB_PORT}

на

      - SPRING_DATA_MONGODB_URI=mongodb://${MONGODB_ADDR}:${MONGODB_PORT}/?socketTimeoutMS=20000&replicaSet=iotRepl&w=majority


После этого можно продолжать обычный процесс установки ядра, оно должно автоматически начать работать с набором реплик MongoDB.

IIb. Переход с уже существующей БД (для версий 1.29 и ниже)

Перед выполнением последующих шагов рекомендуется сделать бекап.

1. Переходим в папку установки ядра (обычно это /storage/iot)

2. Необходимо в файле docker-compose.yml:

  • В volumes сервиса db добавить строку:

          - "${INSTALL_DIR}/mongodb/repl_entrypoint.sh:/entrypoint.sh"
  • Если порт MongoDB не был экспортирован ранее, то необходимо добавить ports в сервис db:

        ports:
          - 27017:27017

3. По пути mongodb/repl_entrypoint.sh кладем скрипт:

mongodb/repl_entrypoint.sh
#!/bin/sh

env | grep -e IOT_CORE_DB -e MQTT_BROKER_DB -e DISK_USAGE_THRESHOLD_* > /mongo_backup_env

#Starting cron for backups
service cron start

#Starting mongod in background with replSet parameter
mongod --bind_ip_all --port 27017 --replSet iotRepl &

#Check mongo shells
if [ -e /bin/mongo ]
then
    echo "Using old mongo shell"
    MONGO_SHELL=mongo
else
    echo "Using new mongosh"
    MONGO_SHELL=mongosh
fi

#Waiting for mongo to startup
until $MONGO_SHELL --eval "print(\"[INFO] Successfully connected\")"
do
    sleep 1
done

#Checking if we should initiate replica set and initiating it
$MONGO_SHELL <<EOF
let shouldInitiate = undefined;

try {
    rs.conf();
    print("[INFO] Replica set is already initiated, skipping...");
    shouldInitiate = false;
} catch (ex) {
    if (ex.message.includes("--replSet")) {
        print("[ERROR] Unable to initiate replica set! "+ex);
        shouldInitiate = false;
    } else if (ex.message.includes("no replset config has been received")) {
        print("[INFO] Replica set is not initiated yet.");
        shouldInitiate = true;
    } else {
        print("[ERROR] Unknown error! "+ex)
    }
}

if (shouldInitiate) {
    print("[INFO] Initiating replica set!");
    let initResult = rs.initiate();
    print("[INFO] Replica set initiated");
}
EOF

#Waiting for mongod process in background to be stopped
wait

exec "$@"

4. Делаем скрипт исполняемым:

chmod +x /storage/iot/mongodb/repl_entrypoint.sh

5. Выполняем команду для пересоздания контейнера с MongoDB в виде реплики:

docker compose up -d db

Внимание

Платформа будет недоступна во время пересоздания контейнера (примерно до 15 секунд)

6. Подключаемся при помощи mongosh к оригинальной БД:

mongosh mongodb://[ip оригинальной БД]:[port mongo оригинальной БД]

7. Изменяем адрес оригинальной БД в наборе реплик с локального ([container hash]:27017) на внешний:

cfg = rs.conf()
cfg.members[0].host = "[ip оригинальной БД]:[port mongo оригинальной БД]"
rs.reconfig(cfg)

Примечание

Остальные реплики должны иметь доступ к оригинальной БД по этому адресу

8. Добавляем остальные реплики:

rs.add( { host: "[ip первой реплики]:[port mongodb первой реплики]" } )
rs.add( { host: "[ip второй реплики]:[port mongodb второй реплики]" } )
rs.add( { host: "[ip третьей реплики]:[port mongodb третьей реплики]" } )

9. Периодически вводя команду rs.status() дождаться пока одна реплика перейдет в статус PRIMARY, а все остальные - в SECONDARY (смотреть поле stateStr)

10. Необходимо изменить параметры БД в файле [путь до ansible-iot]/vars/default.yml:

  • Включить внешнюю MongoDB:

    external:
        enable: true
  • Указать адреса всех реплик в поле addr:

    addr: "[ip первой реплики]:[port mongodb первой реплики],[ip второй реплики]:[port mongodb второй реплики],[ip третьей реплики]"

    Внимание

    Порт последней реплики в поле addr не указывается!

  • Указать порт последней реплики в поле port:

    port: [port mongodb третьей реплики]

11. Необходимо  в файле [путь до ansible-iot]/templates/iot/default-for-docker.yml.j2  в разделе iot-core заменить:

  host: "{{ mongodb_addr }}" 

на

  host: "{{ mongodb_addr }}:{{ mongodb_port }}/{{ coreInternal.core.db.name }}?socketTimeoutMS=20000&replicaSet=iotRepl&w=majority&appName=" 

12. Необходимо  в файле [путь до ansible-iot]/templates/iot/docker-compose/base_config.yml.j2  для сервиса broker в environments заменить:

      - SPRING_DATA_MONGODB_URI=mongodb://${MONGODB_ADDR}:${MONGODB_PORT}

на

      - SPRING_DATA_MONGODB_URI=mongodb://${MONGODB_ADDR}:${MONGODB_PORT}/?socketTimeoutMS=20000&replicaSet=iotRepl&w=majority

13. Останавливаем платформу при помощи:

ansible-playbook [путь до ansible-iot]/stop_iot.yml

14. Подключаемся при помощи mongosh к новой PRIMARY реплике и удаляем оригинальную БД из набора реплик при помощи команды:

rs.remove("[ip оригинальной БД]:[port mongo оригинальной БД]")

15. Запускаем платформу при помощи:

ansible-playbook [путь до ansible-iot]/install_iot.yml

III. Настройка бэкапа реплики

1. По пути /etc/cron.daily/iot-backupdb кладем скрипт:

/etc/cron.daily/iot-backupdb
#!/bin/sh

set -a
. /mongo_backup_env
set +a

mongobackups_path="/var/backups/mongobackups"

backup_db() {
    db_name=$1
    path_backup="${mongobackups_path}/${db_name}/"
    mkdir -p ${path_backup}

    current_date=$(date +%Y-%m-%d_%H-%M)

    # backup database
    backup_archive_name=${path_backup}${db_name}_${current_date}.gz
    mongodump --db=${db_name} --gzip --archive=${backup_archive_name}

    days=$2
    # remove all backup archives older ${days}
    find ${path_backup} -regex ".*\.gz" -mtime +${days} -delete
}

if [ "${DISK_USAGE_THRESHOLD_CRITICAL}" -gt 0 ] && [ "${DISK_USAGE_THRESHOLD_WARN}" -gt "${DISK_USAGE_THRESHOLD_CRITICAL}" ]
then
    disk_avail_space=`df --output=avail ${mongobackups_path} | sed '2!d'`
    disk_size=`df --output=size ${mongobackups_path} | sed '2!d'`
    free_disk_space_percent=`echo "scale=2;${disk_avail_space}*100/${disk_size}" | bc -l`
    backup_days=`echo "scale=0;(${free_disk_space_percent}-${DISK_USAGE_THRESHOLD_CRITICAL})*7/(${DISK_USAGE_THRESHOLD_WARN}-${DISK_USAGE_THRESHOLD_CRITICAL})" | bc -l`

    if [ "${backup_days}" -gt "7" ]
    then
        backup_days=7
    fi
else
    backup_days=7
fi

if [ "${backup_days}" -ge "0" ]
then

    #Check mongo shells
    if [ -e /bin/mongo ]
    then
        echo "Using old mongo shell"
        MONGO_SHELL=mongo
    else
        echo "Using new mongosh"
        MONGO_SHELL=mongosh
    fi

    #Checking if current replica is secondary
    $MONGO_SHELL --eval "quit(rs.status().myState == 1 ? 0 : 1)"

    if [ "$?" -eq "0" ]; then
        echo "Only SECONDARY replicas are backed up"
        exit 1
    fi

    backup_db ${IOT_CORE_DB} ${backup_days}
    backup_db ${MQTT_BROKER_DB} ${backup_days}
else
    rm -rf ${mongobackups_path}/*
fi

2. Делаем скрипт исполняемым:

sudo chmod +x /etc/cron.daily/iot-backupdb

3. По пути /mongo_backup_env кладем параметры бэкапа:

/mongo_backup_env
IOT_CORE_DB=iot-core
MQTT_BROKER_DB=iot-broker
DISK_USAGE_THRESHOLD_WARN=20
DISK_USAGE_THRESHOLD_CRITICAL=10

4. Создаем папку для бэкапов:

sudo mkdir /var/backups/mongobackups

IV. Сбор информации

1. Подключаемся при помощи mongosh к любой из реплик для проверки статуса:

rs.printSecondaryReplicationInfo()

2. Подключаемся при помощи mongosh к любой из реплик для проверки статуса PRIMARY:

db.runCommand("ismaster")

V. Обновление с репликами

1. Необходимо изменить параметры БД в файле [путь до ansible-iot]/vars/default.yml:

  • Включить внешнюю MongoDB:

    external:
        enable: true
  • Указать адреса всех реплик в поле addr:

    addr: "[ip первой реплики]:[port mongodb первой реплики],[ip второй реплики]:[port mongodb второй реплики],[ip третьей реплики]"

    Внимание

    Порт последней реплики в поле addr не указывается!

  • Указать порт последней реплики в поле port:

    port: [port mongodb третьей реплики]

Далее необходимо  в файле [путь до ansible-iot]/templates/iot/default-for-docker.yml.j2  в разделе iot-core заменить:

  host: "{{ mongodb_addr }}" 

на

  host: "{{ mongodb_addr }}:{{ mongodb_port }}/{{ coreInternal.core.db.name }}?socketTimeoutMS=20000&replicaSet=iotRepl&w=majority&appName=" 

И в файле [путь до ansible-iot]/templates/iot/docker-compose/base_config.yml.j2  для сервиса broker в environments заменить:

      - SPRING_DATA_MONGODB_URI=mongodb://${MONGODB_ADDR}:${MONGODB_PORT}

на

      - SPRING_DATA_MONGODB_URI=mongodb://${MONGODB_ADDR}:${MONGODB_PORT}/?socketTimeoutMS=20000&replicaSet=iotRepl&w=majority


После этого можно продолжать обычный процесс обновления ядра, оно будет использовать набор реплик MongoDB с существующими данными.

  • Нет меток