OpenUDS HA

Материал из ALT Linux Wiki
Stub.png
Данная страница находится в разработке.
Эта страница ещё не закончена. Информация, представленная здесь, может оказаться неполной или неверной.

HA-кластер с OpenUDS

Компоненты OpenUDS можно настроить в режиме высокой доступности (HA).

Для обеспечения высокой доступности среды VDI, в дополнение к настройке нескольких OpenUDS-Server и OpenUDS-Tunnel необходимо настроить репликацию базы данных. Также следует настроить балансировщик нагрузки, который будет управлять и распределять подключения к компонентам OpenUDS-Server и OpenUDS-Tunnel.

В этом документе приведён пример настройки работы OpenUDS в режиме высокой доступности с программным балансировщиком нагрузки (HAProxy) и базой данных MySQL.

Системные требования

Основные элементы OpenUDS HA

Основные элементы:

  1. MySQL сервер — база данных является одним из наиболее важных компонентов среды VDI с OpenUDS. Поэтому настоятельно рекомендуется иметь резервную копию этого компонента либо посредством полной резервной копии машины, либо конфигурации активной/пассивной реплики. В данном руководстве описана настройка двух серверов MySQL, главного и подчиненного, в режиме активной/пассивной репликации.
  2. HAProxy-сервер — сервер, отвечающий за распределение соединений OpenUDS-Server и OpenUDS-Tunnel. Через него осуществляется доступ пользователя/администратора к OpenUDS и выполняются подключения к различным сервисам. На серверах HAProxy также будет настроен IP-адрес, который будет активен только на основном сервере. В случае отказа этого сервера IP-адрес будет автоматически активирован на другом сервере HAProxy.
  3. OpenUDS Server — наличие нескольких машин OpenUDS-Server обеспечит непрерывный доступ пользователей к OpenUDS, даже при отказе одного из OpenUDS-Server.
  4. OpenUDS Tunnel — наличие нескольких машин OpenUDS-Tunnel позволит получить доступ к службам (рабочим столам или приложениям) через туннелированные соединения и HTML5, даже при отказе одного из OpenUDS-Tunnel.
Примечание: Если пользователь подключается к сервису (рабочему столу или приложению) и сервер OpenUDS-Tunnel, через который он подключен, падает, соединение будет потеряно. Но при повторном подключении доступ будет автоматически восстановлен через другой активный сервер OpenUDS-Tunnel.


Системные требования
Компонент Количество ОЗУ ЦП Диск
MySQL Server 2 1 ГБ 2 vCPUs 10 ГБ
HAProxy 2 1 ГБ 2 vCPUs 10 ГБ
OpenUDS Server 2 2 ГБ 2 vCPUs 8 ГБ
OpenUDS Tunnel 2 2 ГБ 2 vCPUs 10 ГБ
Примечание: Для HAProxy необходимо 3 IP-адреса, по одному для каждого сервера (Master-Slave) и общий виртуальный IP-адрес, который будет использоваться для балансировки.


Конфигурация MySQL сервера

Узел Имя IP-адрес
Основной (Master) mysql01 192.168.0.128
Вторичный (Slave) mysql02 192.168.0.129

На обоих серверах установить mysql/mariadb:

# apt-get install mariadb
# systemctl enable --now mariadb.service
# mysql_secure_installation

Настройка репликации между серверами

Главный узел (Master)

В файле /etc/my.cnf.d/server.cnf:

  • закомментировать параметр skip-networking;
  • раскомментировать параметры server-id и log_bin;
  • убедиться, что для параметра server-id установлено значение 1;
  • раскомментировать параметр bind-address и указать IP-адрес сервера (в этом случае главного):
bind-address 192.168.0.128

Перезагрузить службу MySQL:

# systemctl restart mariadb

Создать нового пользователя, c правами которого будет производится репликация:

  1. Войти в консоль MySQL с правами root:
    $ mysql -p
    
  2. Создать пользователя (в примере пользователь replica с паролем uds):
    MariaDB [(none)]> CREATE USER 'replica'@'%' IDENTIFIED BY 'uds';
    Query OK, 0 rows affected (0.009 sec)
    
  3. Предоставить права “replication slave” пользователю:
    MariaDB [(none)]> GRANT REPLICATION SLAVE ON *.* TO 'replica'@'%' IDENTIFIED BY 'uds';
    Query OK, 0 rows affected (0.002 sec)
    
  4. Выполнить следующую команду, чтобы получить информацию об имени двоичного файла и его позиции:
    MariaDB [(none)]> SHOW MASTER STATUS\G
    *************************** 1. row ***************************
                File: mysql-bin.000002
            Position: 328
        Binlog_Do_DB:
    Binlog_Ignore_DB:
    1 row in set (0.001 sec)
    

В данном примере:

  • mysql-bin.000002 — имя файла;
  • 328 — позиция.

Эти данные будут необходимы для настройки Slave-сервера.

Примечание: Просмотреть лог можно, выполнив команду:
# mysqlbinlog --no-defaults /var/lib/mysql/db/mysql-bin.000002


Вторичный узел (Slave)

В файле /etc/my.cnf.d/server.cnf:

  • закомментировать параметр skip-networking;
  • раскомментировать параметры log_bin и server-id;
  • в параметре server-id установить значение 2:
server-id = 2
  • раскомментировать параметр bind-address и указать IP-адрес сервера (в этом случае вторичного):
bind-address 192.168.0.129

Перезагрузить службу MySQL:

# systemctl restart mariadb

Настроить параметры, которые вторичный сервер (Slave) будет использовать для подключения к основному серверу (Master):

  1. Войти в консоль MySQL с правами root:
    $ mysql -p
    
  2. Остановить репликацию:
    MariaDB [(none)]> STOP SLAVE;
    Query OK, 0 rows affected, 1 warning (0.001 sec)
    
  3. Настроить репликацию между основным сервером и вторичным сервером:
    MariaDB [(none)]>CHANGE MASTER TO MASTER_HOST='192.168.0.128', MASTER_USER='replica', MASTER_PASSWORD='uds', MASTER_LOG_FILE='mysql-bin.000002', MASTER_LOG_POS=328;
    Query OK, 0 rows affected (0.020 sec)
    
    где
    • 192.168.0.128 — IP-адрес основного сервера;
    • replica — пользователь, с правами которого будет производится репликация;
    • uds — пароль пользователя replica;
    • myslq-bin.000002 — имя файла полученного на предыдущем шаге;
    • 328 — позиция двоичного файла.
  4. Запустить репликацию:
    MariaDB [(none)]> START SLAVE;
    Query OK, 0 rows affected (0.001 sec)
    
  5. Убедиться, что конфигурация верна:
    MariaDB [(none)]> SHOW SLAVE STATUS\G
    *************************** 1. row ***************************
                    Slave_IO_State: Waiting for master to send event
                       Master_Host: 192.168.0.128
                       Master_User: replica
                       Master_Port: 3306
                     Connect_Retry: 60
                   Master_Log_File: mysql-bin.000004
               Read_Master_Log_Pos: 328
                    Relay_Log_File: mysqld-relay-bin.000006
                     Relay_Log_Pos: 555
             Relay_Master_Log_File: mysql-bin.000004
                  Slave_IO_Running: Yes
                 Slave_SQL_Running: Yes
    
    

IP-адрес основного сервера должен быть указан корректно, параметры Slave_IO_Running и Slave_SQL_Running должны быть установлены в значение «Yes».

Проверка репликации

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

  1. Получить доступ к консоли MySQL главного сервера и создать новую тестовую БД «replicatest»:
    MariaDB [(none)]> CREATE DATABASE replicatest;
    Query OK, 1 row affected (0.001 sec)
    
  2. Убедиться, что БД создана:
    MariaDB [(none)]> SHOW DATABASES;
    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | mysql              |
    | performance_schema |
    | replicatest        |
    +--------------------+
    4 rows in set (0.001 sec)
    
  3. Получить доступ к консоли MySQL вторичного сервера и убедиться, что БД, созданная на основном сервере, успешно реплицировалась на этот сервер:
    MariaDB [(none)]> SHOW DATABASES;
    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | mysql              |
    | performance_schema |
    | replicatest        |
    +--------------------+
    4 rows in set (0.002 sec)
    
Примечание: После проверки работы репликации можно удалить БД «replicatest», выполнив команду на основном сервере:
MariaDB [(none)]> DROP DATABASE replicatest;


Теперь можно создать на основном сервере БД:

 
mysql> CREATE DATABASE dbuds CHARACTER SET utf8 COLLATE utf8_general_ci;
mysql> CREATE USER 'dbuds'@'%' IDENTIFIED BY 'password';
mysql> GRANT ALL PRIVILEGES ON dbuds.* TO 'dbuds'@'%';
mysql> FLUSH PRIVILEGES;

И подключить серверы OpenUDS к БД основного сервера.

Отказ сервера

При недоступности одного из серверов БД необходимо выполнить ряд задач. Задачи, которые следует выполнить, зависят от того к какому серверу (Master или Slave) нет доступа.

Главный узел (Master)

Если недоступен основной сервер БД (Master), то будет потерян доступ к среде VDI. В этом случае необходимо вручную подключить OpenUDS-Server к вторичной БД (Slave), в которой находится вся информация среды VDI до момента падения основной БД. Чтобы настроить новое подключение к БД на OpenUDS-Server следует в конфигурационном файле /var/server/server/settings.py указать параметры новой БД (это необходимо сделать на всех серверах OpenUDS-Server).

После изменения IP-адреса БД необходимо перезапустить сервер (это необходимо сделать на всех серверах OpenUDS-Server).

После перезапуска сервера доступ к среде VDI будет восстановлен.

Затем необходимо настроить новый сервер для репликации БД.

Для этого есть несколько вариантов, в том числе:

  1. Настроить текущий сервер БД как главный и создать новый сервер-реплику, который нужно настроить и восстановить БД из резервной копии с существующими данными (поскольку реплицируются только новые данные).
  2. Напрямую сделать резервную копию текущего сервера БД (предварительно остановив все машины OpenUDS-Server). Создать новый сервер БД Master, восстановить туда резервную копию БД и перенастроить репликацию.
Примечание: Чтобы не потерять какие-либо данные, перед применением любого метода перестроения репликации, рекомендуется сделать резервную копию БД. Для получения резервной копии можно использовать следующую команду:
# mysqldump -u dbuds -ppassword --databases dbuds > dbuds_dump.sql

При создании резервной копии все машины OpenUDS-Server должны быть выключены. Таким образом, обеспечивается согласованность данных и отсутствие различий в данных между главным и подчиненным серверами перед настройкой реплики.


Вторичный узел (Slave)

Если недоступен вторичный сервер БД (Slave), доступ к среде VDI сохранится, но будет необходимо перенастроить вторичный сервер-реплику. Перед выполнением данной настройки необходимо восстановить резервную копию с текущим состоянием основной БД, так как будут синхронизированы только новые данные реплики (существующие данные не будут реплицированы в базе данных).

Важно, чтобы во время всего этого процесса машины OpenUDS-Server были выключены, чтобы не возникало различий между БД Master и Slave серверов.

Настройка серверов HAProxy

Узел Имя IP-адрес
Основной (Master) Haproxy01 192.168.0.52
Вторичный (Slave) Haproxy02 192.168.0.53

192.168.0.49 — виртуальный IP-адрес по которому будут доступны серверы OpenUDS. Нижеперечисленные действия необходимо выполнить на обоих узлах, за исключением создания сертификата, который должен быть создан только на одном из серверов. Конфигурация компонента Keepalived для вторичного сервера будет использовать режим SLAVE.

На основном узле сгенерировать сертификат:

# openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /root/ssl.key -out /root/ssl.crt

Создать файл .pem, выполнив команду (предварительно может понадобиться создать каталог /etc/openssl/private):

# cat /root/ssl.crt /root/ssl.key > /etc/openssl/private/haproxy.pem
Примечание: Сертификат, созданный на первичном сервере HAProxy, необходимо скопировать в каталог /etc/openssl/private на вторичном сервере. Если используется собственный сертификат, его необходимо скопировать на оба сервера (основной и дополнительный).


Внимание! Порты, используемые HAProxy (в примере 80, 443, 1443, 10443), должны быть свободны.


На обоих узлах:

  1. Установить пакеты haproxy и keepalived:
    # apt-get install haproxy keepalived
    
  2. Заменить содержимое файла /etc/haproxy/haproxy.cfg следующим:
    global
            log /dev/log    local0
            log /dev/log    local1 notice
            chroot /var/lib/haproxy
            stats socket /var/lib/haproxy/admin.sock mode 660 level admin  
            stats timeout 30s
            maxconn 2048
            user _haproxy
            group _haproxy
            daemon
    
            # Default SSL material locations
    #        ca-base /etc/openssl/certs
    #        crt-base /etc/openssl/private
    
            # Default ciphers to use on SSL-enabled listening sockets.
            # For more information, see ciphers(1SSL). This list is from:
            #  https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
            ssl-default-bind-options ssl-min-ver TLSv1.2 prefer-client-ciphers
    #        ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA267:TLS_AES_267_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA267
            ssl-default-bind-ciphers ECDH+AESGCM:ECDH+CHACHA20:ECDH+AES267:ECDH+AES128:!aNULL:!SHA1:!AESCCM
    
            # ssl-default-server-options ssl-min-ver TLSv1.2
            # ssl-default-server-ciphersuites TLS_AES_128_GCM_SHA267:TLS_AES_267_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA267
            # ssl-default-server-ciphers ECDH+AESGCM:ECDH+CHACHA20:ECDH+AES267:ECDH+AES128:!aNULL:!SHA1:!AESCCM
    
           tune.ssl.default-dh-param 2048
    
    
    defaults
            log     global
            mode    http
            option  httplog
            option  dontlognull
            option  forwardfor
            retries 3
            option  redispatch
    
            stats enable
            stats uri /haproxystats
            stats realm Strictly\ Private
            stats auth stats:haproxystats
    
            timeout connect 5000
            timeout client  50000
            timeout server  50000
    
    frontend http-in
            bind *:80
            mode http
            http-request set-header X-Forwarded-Proto http
            default_backend openuds-backend
    frontend https-in
            bind *:443 ssl crt /etc/openssl/private/haproxy.pem
            mode http
            http-request set-header X-Forwarded-Proto https
            default_backend openuds-backend
    
    frontend tunnel-in
            bind *:1443
            mode tcp
            option tcplog
            default_backend tunnel-backend-ssl
    
    frontend tunnel-in-guacamole    # HTML5
            bind *:10443
            mode tcp
            option tcplog
            default_backend tunnel-backend-guacamole
    backend openuds-backend
            option http-keep-alive
            balance roundrobin
            server udss1 192.168.0.85:80 check inter 2000 rise 2 fall 5
            server udss2 192.168.0.86:80 check inter 2000 rise 2 fall 5
    backend tunnel-backend-ssl
            mode tcp
            option tcplog
            balance roundrobin
            server udst1 192.168.0.87:443 check inter 2000 rise 2 fall 5
            server udst2 192.168.0.88:443 check inter 2000 rise 2 fall 5
    
    backend tunnel-backend-guacamole
            mode tcp
            option tcplog
            balance source
            server udstg1 192.168.0.87:8080 check inter 2000 rise 2 fall 5
            server udstg2 192.168.0.88:8080 check inter 2000 rise 2 fall 5
    
  3. Добавить в файл /etc/sysctl.conf строку:
    net.ipv4.ip_nonlocal_bind = 1
    
  4. Для применения настроек выполнить:
    # sysctl -p
    
  5. Настроить службу Keepalived. Для этого создать файл /etc/keepalived/keepalived.conf. Содержимое файла зависит от узла, который настраивается:
    • на главном узле:
      global_defs {
          # Keepalived process identifier
          lvs_id haproxy_DH
      }
      # Script used to check if HAProxy is running
      vrrp_script check_haproxy {
          script "killall -0 haproxy"
          interval 2
          weight 2
      }
      # Виртуальный интерфейс
      # The priority specifies the order in which the assigned interface to take over in a failover
      vrrp_instance VI_01 {
          state MASTER
          interface enp0s3
          virtual_router_id 51
          priority 101
          # Виртуальный IP-адрес
          virtual_ipaddress {
              192.168.0.49
          }
          track_script {
              check_haproxy
          }
      }
      
      где interface enp0s3 — сетевой интерфейс (узнать имя сетевого интерфейса можно, выполнив команду ip a).
    • на вторичном узле:
      global_defs {
          # Keepalived process identifier
          lvs_id haproxy_DH_passive
      }
      # Script used to check if HAProxy is running
      vrrp_script check_haproxy {
          script "killall -0 haproxy"
          interval 2
          weight 2
      }
      # Виртуальный интерфейс
      # The priority specifies the order in which the assigned interface to take over in a failover
      vrrp_instance VI_01 {
          state SLAVE
          interface eth0
          virtual_router_id 51
          priority 100
          # Виртуальный IP-адрес
          virtual_ipaddress {
              192.168.0.49
          }
          track_script {
              check_haproxy
          }
      }
      
      где interface eth0 — сетевой интерфейс (узнать имя сетевого интерфейса можно, выполнив команду ip a).
  6. Для запуска сервисов выполнить команды:
    # systemctl enable --now haproxy 
    # systemctl enable --now keepalived
    
  7. Убедиться, что балансирующий виртуальный IP активен на основном сервере:
    $ ip a |grep enp0s3
    2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
        inet 192.168.0.52/24 brd 192.168.0.255 scope global noprefixroute enp0s3
        inet 192.168.0.49/32 scope global enp0s3
    

Настройка OpenUDS-Server и OpenUDS-Tunnel

После настройки сервера БД с репликой и серверов HAProxy в качестве балансировщиков можно приступить к установке и настройке компонентов OpenUDS-Server и OpenUDS-Tunnel.

Настройка OpenUDS-Server

Узел Имя IP-адрес
Основной (Master) udss01 192.168.0.85
Вторичный (Slave) udss02 192.168.0.86

На обоих узлах:

  1. Установить OpenUDS Server:
    # apt-get install openuds-server-nginx
    
  2. Отредактировать /etc/openuds/settings.py, указав корректные данные для подключения к основному MySQL-серверу:
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql', 
            'OPTIONS': {
                'isolation_level': 'read committed',
            },
            'NAME': 'dbuds',  # Or path to database file if using sqlite3.
            'USER': 'dbuds',  # Not used with sqlite3.
            'PASSWORD': 'password',  # Not used with sqlite3.
            'HOST': '192.168.0.128',  # Set to empty string for localhost. Not used with sqlite3.
            'PORT': '3306',  # Set to empty string for default. Not used with sqlite3.
        }
    }
    
  3. "Заполнить" базу данных первоначальными данными (выполнить только на одном узле!):
    # su -s /bin/bash - openuds
    $ cd /usr/share/openuds
    $ python3 manage.py migrate
    
  4. Запустить gunicorn:
     # systemctl enable --now openuds-web.service
    
  5. Запустить nginx:
     # ln -s ../sites-available.d/openuds.conf /etc/nginx/sites-enabled.d/openuds.conf
     # systemctl enable --now nginx.service
    
  6. Запустить менеджер задач OpenUDS:
     # systemctl enable --now openuds-taskmanager.service
    
  7. Подключиться к серверу OpenUDS http://<Виртуальный IP-адрес> (в примере http://192.168.0.49).

Настройка OpenUDS-Tunnel

Узел Имя IP-адрес
Основной (Master) udst01 192.168.0.87
Вторичный (Slave) udst02 192.168.0.88

На обоих узлах:

  1. Установить OpenUDS Tunnel:
    # apt-get install openuds-tunnel
    
  2. Привести файл /etc/uds.conf к виду:
     http://192.168.0.49/pam
    
    где 192.168.0.49 — виртуальный IP-адрес.
  3. Переименовать каталог /var/lib/tomcat/webapps/openuds-tunnel в /var/lib/tomcat/webapps/transport:
    # mv /var/lib/tomcat/webapps/openuds-tunnel /var/lib/tomcat/webapps/transport
    
  4. Запустить сервисы:
    # systemctl enable --now guacd tomcat
    


Внимание! Перед запуском tomcat необходимо остановить службу ahttpd:
# systemctl disable --now ahttpd


Примечание: При создании транспорта «HTML5 RDP (tunneled)» в поле «Tunnel Server» следует указывать виртуальный IP-адрес и порт, указанный в разделе frontend tunnel-in-guacamole файла /etc/haproxy/haproxy.cfg (в данном примере: 10443):

OpenUDS. HTML5 RDP — вкладка «Tunnel»

Пример подключения с использованием HTML5:

OpenUDS. Пример подключения с использованием HTML5