Введение

Облачные сервисы ПК СВ "Брест" имеют встроенный механизм обеспечения отказоустойчивости высокой доступности. Для его задействования разворачивается нечетное количество экземпляров Front-end, которые взаимодействуя между собой по алгоритму RAFT, обеспечивают доступность сервисов управления облаком при отказе менее половины узлов.

 Узлы, взаимодействуя по алгоритму RAFT, определяют лидера, который обслуживает все входящие запросы, для чего выделяется "плавающий" (переходящий от узла к узлу) IP-адрес. Каждый узел имеет свой экземпляр БД, который реплицируется сервисами, обслуживающими облако.

Требования

  • Настроен по крайней мере 1 контроллер домена FreeIPA.
  • Настроена Фронтальная машина облака (далее — Первый узел).
  • Имеется дополнительно 2N узлов, настроенных в соответствии с Установка ОС (далее — Второй и последующие узлы).
  • Ни на одном узле не развернут сервис apache2 в режиме "AstraMode off".
  • Выделен ip для настройки плавающего адреса.

Подготовка узлов

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

Если установка ведется на выделенных для этой роли серверах, потребуется обмен SSH-ключами учетной записи root между ними. Этого не требуется, если установка ведется на узлах виртуализации.

Выполнить:

ssh-keygen

KEY=$(sudo cat /root/.ssh/id_rsa.pub)

ssh <local-admin>@<front-1-hostname> "sudo bash -c \"echo $KEY >> /root/.ssh/authorized_keys\""

ssh <local-admin>@<front-2-hostname> "sudo bash -c \"echo $KEY >> /root/.ssh/authorized_keys\""

...

ssh <local-admin>@<front-N-hostname> "sudo bash -c \"echo $KEY >> /root/.ssh/authorized_keys\""
CODE

Затем перейти на каждый уже настроенный узел и выполнить на нем:

KEY=$(sudo cat /root/.ssh/id_rsa.pub)

ssh <local-admin>@<hostname> "sudo bash -c \"echo $KEY >> /root/.ssh/authorized_keys\""
CODE

Здесь <hostname> — имя текущего узла, на котором выполняется данная инструкция.

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

Настройка RAFT

Настроить отказоустойчивость облачных сервисов.

Создание зоны

На Первом узле выполнить:

onezone server-add 0 --name <front-1-hostname>.<domain> --rpc http://<front-1-ip>:2633/RPC2
CODE

Проверить добавление узла в зону:

onezone show 0
CODE

Включение RAFT

  1. Остановить сервисы на Первом узле:

    systemctl stop opennebula unicorn-opennebula
    CODE
  2. Указать идентификатор сервера в зоне в файле /etc/one/oned.conf на Первом узле:

    FEDERATION = [
    	MODE = "STANDALONE",
    	ZONE_ID = 0,
    	SERVER_ID = 0, # измените параметр с -1 to 0, где 0 - это ID сервера
    	MASTER_ONED = ""
    ]
    CODE
  3. В этом же файле активировать Raft-hooks для того, чтобы добавить плавающий адрес в кластер на Первом узле:

    # Executed when a server transits from follower->leader
    RAFT_LEADER_HOOK = [
    	COMMAND = "raft/vip.sh",
    	ARGUMENTS = "leader <interface> <floating-ip>/<netmask>"
    ]
    
    # Executed when a server transits from leader->follower
    RAFT_FOLLOWER_HOOK = [
    	COMMAND = "raft/vip.sh",
    	ARGUMENTS = "follower <interface> <floating-ip>/<netmask>"
    ]
    CODE
    где
    <interface> — имя интерфейса, на котором будет активироваться плавающий адрес;
    <floating-ip> — плавающий IP-адрес;
    <netmask> — маска сети, заданная числом от 0 до 32.

  4. Далее запустить сервисы:

    systemctl start opennebula unicorn-opennebula
    CODE
  5. Проверить зону и наличие плавающего адреса:

    onezone show 0
    ip a
    CODE

Перенос данных на Второй и последующие узлы

  1. На Первом узле сохранить БД:

    sudo -u postgres /usr/bin/pg_dump --dbname=onedb  --format=plain --blobs --verbose --clean --create --file="/tmp/leader_db.backup"
    CODE
  2. Скопировать БД на Второй и последующие узлы:

    scp /tmp/leader_db.backup <front-2-hostname>.<domain>:/tmp/
    
    scp /tmp/leader_db.backup <front-3-hostname>.<domain>:/tmp/
    
    ...
    
    scp /tmp/leader_db.backup <front-N-hostname>.<domain>:/tmp/
    CODE
  3. Остановить службы на Втором и последующих узлах:

    ssh <front-2-hostname>.<domain> systemctl stop opennebula unicorn-opennebula
    ssh <front-3-hostname>.<domain> systemctl stop opennebula unicorn-opennebula
    ...
    
    ssh <front-N-hostname>.<domain> systemctl stop opennebula unicorn-opennebula
    CODE
  4. Заменить аутентификационные файлы:

    ssh <front-2-hostname>.<domain> rm -rf /var/lib/one/.one
    ssh <front-3-hostname>.<domain> rm -rf /var/lib/one/.one
    
    ...
    
    ssh <front-N-hostname>.<domain> rm -rf /var/lib/one/.one
    
    scp -r /var/lib/one/.one/ <front-2-hostname>.<domain>:/var/lib/one/
    scp -r /var/lib/one/.one/ <front-3-hostname>.<domain>:/var/lib/one/
    
    ...
    
    scp -r /var/lib/one/.one/ <front-N-hostname>.<domain>:/var/lib/one/
    CODE
  5. Восстановить на Втором и последующих узлах БД:

    Если в команде pg_restore не используется ключ --if-exists и какие-либо объекты не присутствуют в целевой БД, это может привести к появлению сообщений об ошибках (не критичных).

    ssh <front-2-hostname>.<domain> sudo -u postgres /usr/bin/psql --file="/tmp/leader_db.backup"
    ssh <front-3-hostname>.<domain> sudo -u postgres /usr/bin/psql --file="/tmp/leader_db.backup"
    
    ...
    ssh <front-N-hostname>.<domain> sudo -u postgres /usr/bin/psql --file="/tmp/leader_db.backup"
    CODE

Добавление Второго и последующих узлов

  1. Добавлять новые узлы в зону по одному. Для этого на Первом узле выполнить:

    onezone server-add 0 --name <front-N-hostname>.<domain> --rpc http://<front-N-ip>:2633/RPC2
    CODE
  2. Проверить назначенный узлу идентификатор ID:

    # onezone show 0
    ZONE 0 INFORMATION                                                              
    ID                : 0                   
    NAME              : OpenNebula          
    
    
    ZONE SERVERS                                                                    
    ID NAME                        ENDPOINT                                                       
     0 <front-1-hostname>.<domain> http://xx.xx.xx.xx:2633/RPC2
     1 <front-2-hostname>.<domain> http://xx.xx.xx.xx:2633/RPC2
    
    HA & FEDERATION SYNC STATUS                                                     
    ID NAME                        STATE      TERM       INDEX      COMMIT     VOTE  FED_INDEX 
     0 <front-1-hostname>.<domain> leader     5          3162       3162       0     -1
     1 <front-2-hostname>.<domain> error                
    
    
    ZONE TEMPLATE                                                                   
    ENDPOINT="http://localhost:2633/RPC2"
    CODE

    В данном примере узлу <front-2-hostname>.<domain> был назначен ID=1.

  3. Перейти на добавляемый узел и обновить конфигурацию:

    /etc/one/oned.conf

    FEDERATION = [
    	MODE = "STANDALONE",
    	ZONE_ID = 0,
    	SERVER_ID = 1, # измените параметр с -1 на ID узла
    	MASTER_ONED = ""
    ]
    CODE
  4. Включить hook:

    /etc/one/oned.conf

    # Executed when a server transits from follower->leader
    RAFT_LEADER_HOOK = [
    	COMMAND = "raft/vip.sh",
    	ARGUMENTS = "leader <interface> <floating-ip>/<netmask>"
    ]
    
    # Executed when a server transits from leader->follower
    RAFT_FOLLOWER_HOOK = [
    	COMMAND = "raft/vip.sh",
    	ARGUMENTS = "follower <interface> <floating-ip>/<netmask>"
    ]
    CODE

    где
    <interface> — имя интерфейса, на котором будет активироваться плавающий адрес;
    <floating-ip> — плавающий IP-адрес;
    <netmask> — маска сети, заданная числом от 0 до 32.

  5. Запустить сервисы:

    systemctl start opennebula unicorn-opennebula
    CODE
  6. После этого вернуться на Первый узел и проверить статус зоны:

    # onezone show 0
    ZONE 0 INFORMATION                                                              
    ID                : 0                   
    NAME              : OpenNebula          
    
    
    ZONE SERVERS                                                                    
    ID NAME                        ENDPOINT                                                       
     0 <front-1-hostname>.<domain> http://xx.xx.xx.xx:2633/RPC2
     1 <front-2-hostname>.<domain> http://xx.xx.xx.xx:2633/RPC2
    
    HA & FEDERATION SYNC STATUS                                                     
    ID NAME                        STATE      TERM       INDEX      COMMIT     VOTE  FED_INDEX 
     0 <front-1-hostname>.<domain> leader     5          3162       3162       0     -1
     1 <front-2-hostname>.<domain> follower   5          3162       3162       0     -1                
    
    
    ZONE TEMPLATE                                                                   
    ENDPOINT="http://localhost:2633/RPC2"
    CODE
  7. Повторить все действия данного пункта для следующего узла.

Настройка веб-сервисов

Далее необходимо настроить на первом узле RAFT веб-серверы для корректной работы с плавающим IP.

  1. Требуется создать самоподписанный сертификат для плавающего адреса (<floating-name>.<domain>):

    openssl req -x509 -nodes -newkey rsa:2048 -days 3650 -keyout /etc/apache2/ssl/<floating-name>.key -out /etc/apache2/ssl/<floating-name>.crt
    CODE
  2. Ввести: 

    Country Name (2 letter code) [AU]: — страна/регион (не обязательно)
    State or Province Name (full name) [Some-State]: — штат (не обязательно)
    Locality Name (eg, city) []: — город (не обязательно)
    Organization Name (eg, company) [Internet Widgits Pty Ltd]: — имя организации (не обязательно)
    Organizational Unit Name (eg, section) []: — подразделение организации (не обязательно)
    Common Name (e.g. server FQDN or YOUR name) []: — Обязательное поле, это имя, по которому к серверу будут обращаться <floating-name>.<domain>
    Email Address []: — адрес электронной почты (не обязательно)
    CODE
  3. Просмотреть сертификат: 

    openssl x509 -noout -text -in /etc/apache2/ssl/<floating-name>.crt
    CODE
  4. Скопировать сертификат и ключ для плавающего имени с первого на все остальные узлы RAFT:

    scp /etc/apache2/ssl/float.crt <front-2-name>:/etc/apache2/ssl/<floating-name>.crt
    
    scp /etc/apache2/ssl/float.crt <front-3-name>:/etc/apache2/ssl/<floating-name>.crt
    
    ...
    
    scp /etc/apache2/ssl/float.crt <front-N-name>:/etc/apache2/ssl/<floating-name>.crt
    CODE
    scp /etc/apache2/ssl/float.key <front-2-name>:/etc/apache2/ssl/<floating-name>.key
    
    scp /etc/apache2/ssl/float.key <front-3-name>:/etc/apache2/ssl/<floating-name>.key
    
    ...
    
    scp /etc/apache2/ssl/float.key <front-N-name>:/etc/apache2/ssl/<floating-name>.key
    CODE

Настройка Apache2

На каждом узле RAFT необходимо создать дополнительный конфигурационный файл веб-сервера Apache2 для использования плавающего имени.

  1. Для этого необходимо скопировать файл /etc/apache2/sites-available/000-default.conf в тот же каталог и присвоить имя — 001-default.conf, его содержимое отредактировать, заменив FQDN на плавающий, а также расположение сертификата для плавающего имени. Ниже приведен пример настройки файла:

    /etc/apache2/sites-available/001-default.conf

    <VirtualHost *:80>
            ServerName <floating-name>.<domain>
            Redirect permanent / https://<floating-name>.<domain>
    </VirtualHost>
    <VirtualHost _default_:443>
            ServerName <floating-name>.<domain>
            ServerAdmin webmaster@localhost
            <Directory />
                    Options FollowSymLinks
                    AllowOverride None
            </Directory>
     
            DocumentRoot /usr/lib/one/sunstone/public
     
            SSLEngine on
            SSLCertificateFile /etc/apache2/ssl/<floating-name>.crt
            SSLCertificateKeyFile /etc/apache2/ssl/<floating-name>.key
     
            <Proxy balancer://unicornservers>
                    BalancerMember http://127.0.0.1:9869
            </Proxy>
     
            ProxyPass /brestcloud !
            ProxyPass / balancer://unicornservers/
            ProxyPassReverse / balancer://unicornservers/
            ProxyPreserveHost on
     
            <Proxy *>
                    AuthType Kerberos
                    KrbAuthRealms <DOMAIN>
                    KrbServiceName HTTP/<floating-name>.<domain>
                    Krb5Keytab /etc/apache2/apache2.keytab
                    KrbMethodNegotiate on
                    KrbMethodK5Passwd off
                    KrbSaveCredentials on
                    require valid-user
                    AllowOverride all
     
                    RewriteEngine On
                    RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
                    RewriteRule ^/(.*)$ balancer://unicornservers%{REQUEST_URI} [P,QSA,L]
                    RewriteCond %{LA-U:REMOTE_USER} (.+)
                    RewriteRule . - [E=RU:%1]
                    RequestHeader add X-Forwarded_Remote-User %{RU}e
            </Proxy>
     
     
            ScriptAlias /brestcloud/ /usr/lib/one/brestcloud/
            <Directory /usr/lib/one/brestcloud/>
                    Options +ExecCGI
                    AddHandler cgi-script .cgi
                    AuthType Kerberos
                    KrbAuthRealms <DOMAIN>
                    KrbServiceName HTTP/<floating-name>.<domain>
                    Krb5Keytab /etc/apache2/apache2.keytab
                    KrbMethodNegotiate on
                    KrbMethodK5Passwd off
                    KrbSaveCredentials on
                    require valid-user
                    AllowOverride all
            </Directory>
     
            ErrorLog ${APACHE_LOG_DIR}/error.log
     
            # Possible values include: debug, info, notice, warn, error, crit,
            # alert, emerg.
            LogLevel warn
     
            CustomLog ${APACHE_LOG_DIR}/access.log combined
    </VirtualHost>
    CODE
  2. Добавить созданную конфигурацию в действующие конфигурации командой:   

    a2ensite 001-default.conf                      #(этой командой будет добавлена ссылка в каталог /etc/apache2/sites-enabled/)
    CODE
  3. Сохранить изменения и протестировать конфигурацию Apache. Протестировать конфигурацию на наличие различных синтаксических ошибок, иначе веб-сервер не запустится:

    apachectl configtest
    CODE
  4. Перезапустить apache2.service:

     systemctl restart apache2
    CODE
  5. Повторить действия данного пункта для следующих узлов RAFT.

Получение билетов

  1. Получить необходимые kerberos-билеты, для чего перейти по одной из ссылок: Настройки для FreeIPA или Настройки для ALD.
  2. После получения билетов вызвать утилиту на каждом из участников RAFT по очереди:

    ktutil
    CODE
  3. Объединить с ее помощью билеты:

    rkt /etc/apache2/apache2.<floating-name>.keytab
    rkt /etc/apache2/apache2.<front-N-hostname>.keytab
    wkt /etc/apache2/apache2.keytab
    q
    CODE
  4. Поменять владельца и права на полученный файл:

    chown www-data:www-data /etc/apache2/apache2.keytab
    chmod 440 /etc/apache2/apache2.keytab
    CODE
  5. После всех настроек перезапустить сервис:

    systemctl restart apache2
    CODE
  6. Узел настроен. Далее повторить все действия данного пункта для следующего узла.

Проверка

Для проверки работы отказоустойчивости необходимо проделать следующие шаги:

ДействиеОжидаемый результат
1Войти в доменную машину с учетной записью brestadminПользователь авторизован в ОС.
2Перейти по адресу http://<floating-ip>.<domain>Отображается окно входа в систему управления облаком.
3Нажать кнопку LoginПользователь авторизован.
4Подключиться по ssh к любому узлу кластера и проверить, какой узел является лидером с помощью команды
sudo onezone show 0
Отображается информация о зоне. Имеется один узел в состоянии leader, остальные узлы в состоянии follower.
5Физически выключить узел, являющийся лидером-
6

Подключиться по ssh к любому узлу кластера и проверить, какой узел является лидером с помощью команды
sudo onezone show 0

Отображается информация о зоне. Имеется один узел в состоянии leader, один узел в состоянии error, остальные узлы в состоянии followerПри отключении узла (leader) состояние других узлов (follower) будет candidate. Спустя некоторое время определяется leader, остальные переходят в статус follower.
7Перейти по ssh на узел, являющийся лидером-
8

Проверить наличие плавающего IP-адреса командой
ip a

В информации об интерфейсах присутствует плавающий IP.
9Вернуться в браузер и обновить страницуОтображается окно входа в систему управления облаком.
10Нажать кнопку LoginПользователь авторизован.
11Включить отключенный узел-
12

Убедиться, что узел вернулся в кластер командной
sudo onezone show 0

Отображается информация о зоне. Имеется один узел в состоянии leader, остальные узлы в состоянии follower.


Важно

После выполнения данной инструкций вернитесь на предыдущую статью.