Отказоустойчивый кластер OpenNebula используя алгоритм Raft

Отказоустойчивый кластер OpenNebula используя алгоритм Raft

Roman Bogachev VMware Specialist | Drone Pilot | Traveler

Настройка High Available облачной платформы OpenNebula используя распределенный консенсусный протокол для обеспечения отказоустойчивости и согласованности состояния Raft.

Что такое Raft?

Raft - это консенсусный алгоритм, который предназначен для простого понимания. Он эквивалентен привычному Paxos в отказоустойчивости и производительности. Разница заключается в том, что он разлагается на относительно независимые подзадачи и четко рассматривает все основные части, необходимые для практических систем.

Визуализация Raft

Консенсусный алгоритм построен на основе двух концепций:

Состояние системы, в OpenNebula состояние системы - это данные, хранящиеся в таблицах базы данных (пользователи, ACL или виртуальные машины в системе).

Log, последовательность операторов SQL, которые последовательно применяются к базе данных OpenNebula на всех серверах для развития состояния системы.

Чтобы сохранить согласованное представление системы между серверами, изменения состояния системы выполняются через специальный узел, лидер (в дальнейшем Leader). Серверы в кластере OpenNebula выбирают один узел, чтобы быть лидером. Лидер периодически посылает запросы (heartbeats) другим серверам, последователям (в дальнейшем Follower), чтобы сохранить свое лидерство. Если лидер не может послать запрос, последователи продвигаются к кандидатам и начинают новые выборы.

Всякий раз, когда система изменяется (например, в систему добавляется новый виртуальный сервер), лидер обновляет журнал и реплицирует запись у большинства последователей, прежде чем записывать её в базу данных. Таким образом, латентность операций БД увеличивается, но состояние системы безопасно реплицируется, и кластер может продолжить свою работу в случае сбоя узла.

Рекомендации и требования

Рекомендуемый размер для разворачивания кластера - это минимум 3 или 5 серверов, что обеспечивает отказоустойчивость при сбое 1-2 серверов. Добавлять дополнительные сервера или удалять старые можно после запуска кластера.

Для настройки High Available требуется:

  • Нечетное количество серверов (от 3-х минимум).
  • Рекомендуется идентичная конфигурация серверов (объем памяти, вычислительная мощность).
  • Идентичная настройка программного обеспечения серверов (различие в поле SERVER_ID файла /etc/one/oned.conf).
  • Рекомендуется использовать соединение с базой данных того же типа, MySQL (Galera сервер не требуется).
  • Серверы должны иметь беспарольный доступ для связи друг с другом.
  • Плавающий IP, который будет назначен лидеру (Floating IP).
  • Общая файловая система(Ceph, NFS и пр.)
  • Sunstone без проксирования должен быть установлен и запущен на всех узлах кластера.

Настройка High Available кластера

В данном примере я покажу как настроить HA кластер из 5-и серверов:

  • 10.0.1.10 vmm01.devservers.network
  • 10.0.1.20 vmm02.devservers.network
  • 10.0.1.30 vmm03.devservers.network
  • 10.0.1.40 vmm04.devservers.network
  • 10.0.1.50 vmm05.devservers.network
  • 10.0.1.100 Floating IP

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

Шаг 1. Первоначальная конфигурация Leader

Запускаем сервис OpenNebula и добавляем локальный сервер в существующую или новую зону.

1
2
3
$ onezone list
C ID NAME ENDPOINT
* 0 DevserversNetwork Zone http://localhost:2633/RPC2

Добавляем сервер, который будет лидером в рабочую зону.
В данном случае зона с ID 0 и сервер vmm01.devservers.network

1
$ onezone server-add 0 --name vmm01.devservers.network --rpc http://10.0.1.10:2633/RPC2

Проверяем:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ onezone show 0
ZONE 0 INFORMATION
ID : 0
NAME : DevserversNetwork Zone


ZONE SERVERS
ID NAME ENDPOINT
0 vmm01.devserver http://10.0.1.10:2633/RPC2

HA & FEDERATION SYNC STATUS
ID NAME STATE TERM INDEX COMMIT VOTE FED_INDEX
0 vmm01.devserver solo 0 -1 0 -1 -1

ZONE TEMPLATE
ENDPOINT="http://localhost:2633/RPC2"

Останавливаем сервис opennebula и обновляем конфигурацию SERVER_ID в файле /etc/one/oned.conf.

1
2
3
4
5
6
FEDERATION = [
MODE = "STANDALONE",
ZONE_ID = 0,
SERVER_ID = 0, # измените параметр с -1 to 0, где 0 - это ID сервера
MASTER_ONED = ""
]

Активируем Raft-хуки для того, чтобы добавить плавающий адрес в кластер.

1
2
3
4
5
6
7
8
9
10
11
# Executed when a server transits from follower->leader
RAFT_LEADER_HOOK = [
COMMAND = "raft/vip.sh",
ARGUMENTS = "leader eth0 10.0.1.100/24"
]

# Executed when a server transits from leader->follower
RAFT_FOLLOWER_HOOK = [
COMMAND = "raft/vip.sh",
ARGUMENTS = "follower eth0 10.0.1.100/24"
]

Запускаем сервис opennebula и проверяем зону.
Насколько мы видим, то сервер vmm01.devservers.network стал Leader-сервером.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ onezone show 0
ZONE 0 INFORMATION
ID : 0
NAME : DevserversNetwork Zone


ZONE SERVERS
ID NAME ENDPOINT
0 vmm01.devserver http://10.0.1.10:2633/RPC2

HA & FEDERATION SYNC STATUS
ID NAME STATE TERM INDEX COMMIT VOTE FED_INDEX
0 vmm01.devserver leader 1 243 243 0 -1

ZONE TEMPLATE
ENDPOINT="http://localhost:2633/RPC2"

Так же ему был присвоен плавающий адрес (Floating IP).

1
2
3
$ ip -o a sh eth0|grep 10.0.1
2: eth0 inet 10.0.1.10/24 brd 10.0.1.255 scope global noprefixroute dynamic eth0\ valid_lft 3488sec preferred_lft 3488sec
2: eth0 inet 10.0.1.100/24 scope global secondary eth0\ valid_lft forever preferred_lft forever

Шаг 2. Добавление дополнительных серверов

Данная процедура удалит полностью базу на сервере и заменит её актуальной с Leader-сервера.

Рекомендуется добавлять по одному хосту за раз, чтобы избежать конфликта в базе данных. После добавления хоста и проверки статуса - приступайте к следующему серверу.

На Leader создайте полный бэкап актуальной базы и перенесите его на другие сервера вместе с файлами из директории /var/lib/one/.one/

1
2
3
4
$ onedb backup -u oneadmin -d opennebula -p oneadmin
MySQL dump stored in /var/lib/one/mysql_localhost_opennebula_2018-9-20_17:15:20.sql
Use 'onedb restore' or restore the DB using the mysql command:
mysql -u user -h server -P port db_name < backup_file

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

1
2
3
4
5
6
$ scp mysql_localhost_opennebula_2018-9-20_17:15:20.sql <ip>:/tmp
...
$ scp mysql_localhost_opennebula_2018-9-20_17:15:20.sql vmm02.devservers.network:/var/lib/one/
$ scp mysql_localhost_opennebula_2018-9-20_17:15:20.sql vmm03.devservers.network:/var/lib/one/
$ scp mysql_localhost_opennebula_2018-9-20_17:15:20.sql vmm04.devservers.network:/var/lib/one/
$ scp mysql_localhost_opennebula_2018-9-20_17:15:20.sql vmm05.devservers.network:/var/lib/one/

Удаляем на хостах директорию /var/lib/one/.one и копируем её же с Leader-сервера (сохраняйте при копировании привилегии oneadmin:oneadmin):

1
2
3
4
5
6
7
8
9
10
11
$ ssh <ip> rm -rf /var/lib/one/.one
$ scp -r /var/lib/one/.one/ <ip>:/var/lib/one/
...
$ ssh vmm02.devservers.network rm -rf /var/lib/one/.one
$ ssh vmm03.devservers.network rm -rf /var/lib/one/.one
$ ssh vmm04.devservers.network rm -rf /var/lib/one/.one
$ ssh vmm05.devservers.network rm -rf /var/lib/one/.one
$ scp -r /var/lib/one/.one/ vmm02.devservers.network:/var/lib/one/
$ scp -r /var/lib/one/.one/ vmm03.devservers.network:/var/lib/one/
$ scp -r /var/lib/one/.one/ vmm04.devservers.network:/var/lib/one/
$ scp -r /var/lib/one/.one/ vmm05.devservers.network:/var/lib/one/

Останавливаем сервис opennebula на Follower хостах и ресторим скопированную базу.

1
2
$ onedb restore -f -u oneadmin -p oneadmin -d opennebula /var/lib/one/mysql_localhost_opennebula_2018-9-20_17:15:20.sql 
MySQL DB opennebula at localhost restored.

Переходим на Leader сервере и добавляем в зону новые хосты (рекомендую добавлять сервера по-одному!)

1
$ onezone server-add 0 --name vmm02.devservers.network --rpc http://10.0.1.20:2633/RPC2

Проверяем зону на Leader-сервере. Новый сервер находится в состоянии ошибки, так как OpenNebula на новом сервере не запущена. Запомните идентификатор сервера, в этом случае он равен 1.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ onezone show 0
ZONE 0 INFORMATION
ID : 0
NAME : DevserversNetwork Zone


ZONE SERVERS
ID NAME ENDPOINT
0 vmm01.devserver http://10.0.1.10:2633/RPC2
1 vmm02.devserver http://10.0.1.20:2633/RPC2

HA & FEDERATION SYNC STATUS
ID NAME STATE TERM INDEX COMMIT VOTE FED_INDEX
0 vmm01.devserver leader 1 376 372 0 -1
1 vmm02.devserver error - - - - -

ZONE TEMPLATE
ENDPOINT="http://localhost:2633/RPC2"

Ошибка будет отображаться пр причине того, что сервис OpenNebula не запущен на Follower хосте. Это нормально.

Переключаемся на добавленный Follower-сервер и обновляем конфигурацию SERVER_ID в файле /etc/one/oned.conf, указывая в качестве SERVER_ID значение из предыдущего шага, исходя из предыдущего шага. Обязательно включаем хуки Raft, как это было выполнено на Leader.

Запускаем сервис OpenNebula на Follower-сервере и проверяем на Leader-сервере состояние зоны.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ onezone show 0
ZONE 0 INFORMATION
ID : 0
NAME : DevserversNetwork Zone


ZONE SERVERS
ID NAME ENDPOINT
0 vmm01.devserver http://10.0.1.10:2633/RPC2
1 vmm02.devserver http://10.0.1.20:2633/RPC2

HA & FEDERATION SYNC STATUS
ID NAME STATE TERM INDEX COMMIT VOTE FED_INDEX
0 vmm01.devserver leader 1 379 372 0 -1
1 vmm02.devserver follower 1 299 299 0 -1

ZONE TEMPLATE
ENDPOINT="http://localhost:2633/RPC2"

Может случиться так, что значения TERM/INDEX/COMMIT не соответствуют указанным выше. Это не важно! Они будут автоматически синхронизироваться при изменении базы данных.

Повторяем Шаг 2 для того, чтобы добавить дополнительные сервера в кластер.

Обратите внимание, что вы можете добавлять сервера в кластер, только в случае его нормальной работы. Это означает, что работает Leader, а остальные находятся в состоянии Follower. Если в состоянии error присутствует хотя бы один сервер - исправьте это перед продолжением.

В конечном итоге результат будет приблизительно следующим:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ onezone show 0
ZONE 0 INFORMATION
ID : 0
NAME : DevserversNetwork Zone


ZONE SERVERS
ID NAME ENDPOINT
0 vmm01.devserver http://10.0.1.10:2633/RPC2
1 vmm02.devserver http://10.0.1.20:2633/RPC2
2 vmm03.devserver http://10.0.1.30:2633/RPC2
3 vmm04.devserver http://10.0.1.40:2633/RPC2
4 vmm05.devserver http://10.0.1.50:2633/RPC2

HA & FEDERATION SYNC STATUS
ID NAME STATE TERM INDEX COMMIT VOTE FED_INDEX
0 vmm01.devserver follower 3 477 477 1 -1
1 vmm02.devserver leader 3 477 477 1 -1
2 vmm03.devserver follower 3 477 477 1 -1
3 vmm04.devserver follower 3 477 477 -1 -1
4 vmm05.devserver follower 3 283 283 -1 -1

ZONE TEMPLATE
ENDPOINT="http://localhost:2633/RPC2"

OpenNebula Docs