Привет, Хабр. Сегодня мы, Дмитрий Романовский и Дмитрий Тарасов, расскажем о возможности создания окружения с гипервизором OpenStack (далее по тексту - базовая ВМ с предустановленным и настроенным OpenStack), которое можно клонировать с сохранением работоспособности.

Под сохранением работоспособности здесь мы понимаем возможность создания сразу нескольких клонов, которые могут существовать в одной VLAN и не мешать работе друг друга. В нашем случае, важным дополнительным фактором была необходимость развертывания OpenStack в сети с внешним DHCP сервером. В этом сценарии подразумевалось динамическое получение IP-адреса как для самого гипервизора, так и для виртуальных машин под его управлением.

Потребность в многочисленном клонировании OpenStack связана со спецификой нашей деятельности - мы тестируем СРК Кибер Бэкап. В рамках тестирования мы проверяем корректность выполнения операций резервного копирования и восстановления ВМ. Так как одновременно может быть запущено несколько тестов, то при работе с одним гипервизором они могут начать конфликтовать друг с другом. А в нашей парадигме «Каждому тесту – свое изолированное окружение» удается избежать этих проблем.

Предлагаемое решение:

  • с одной стороны - упрощает нашу инфраструктуру и код – нет необходимости в поддержке подсетей, пулов статических адресов, и в то же время снимает ограничения на количество клонов - мы ограничены только подсетью, настроенной на DHCP-сервере;

  • с другой - немного усложняет деплой и первоначальную настройку самого OpenStack.

В силу того, что в официальных источниках (да и на многочисленных форумах) мы не нашли ни то что исчерпывающей, но практически никакой информации по такого рода конфигурации и собирали все практически по крупицам (в том числе эмпирическим путем), хотим поделиться с вами полученным опытом.

Выбираем ПО

Как известно, существует 2 популярные версии установщиков OpenStack: DevStack и PackStack. Мы остановились на установщике PackStack, так как он поддерживает возможность установки через файл answers, внутри которого можно задать буквально каждый параметр: настройки сети, хранилищ, паролей и так далее.

  • Документация к PackStack;

  • Гипервизор - oVirt, zVirt, VMWare, и т.п., на котором будет развернута базовая ВМ OpenStack;

  • ISO-образ установщика CentOS Linux release 8.5.2111. Данную ОС мы выбрали по двум причинам:

    • она основана на Red Hat Enterprise Linux (RHEL) и рекомендована разработчиками PackStack;

    • она бесплатная.

  • При деплое мы выбрали механизм сетевого взаимодействия Open vSwitch, так как у нас был опыт работы с ним на других гипервизорах.

Минимальные требования к ресурсам

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

  • CPU: 8 (cores per socket=1)

  • RAM: 16 GB

  • SSD:

    • 300 GB - тип разделов: part/lvm (размечается автоматически при установке CentOS), файловая система: xfs --- здесь будет установлен сам OpenStack и хранилище для образов томов – iso, qcow, qcow2 и т.д.

    • 150 GB - тип раздела: lvm, файловая система: xfs - для дисков виртуальных машин и для снапшотов (cinder-pool)

Чтобы вложенные в OpenStack ВМ могли получать IP-адреса с внешнего DHCP-сервера, в vSwitch вашего гипервизора необходимо включить режим Promiscuous mode.

Шаги по установке

  1. На своем гипервизоре создаем новую вложенную ВМ для будущего OpenStack и подключаем ISO с CentOS Linux последней версий (8.5.2111 на момент написания). При установке выбираем режим Server без GUI.

  2. Проверяем, что новая нода с CentOs 8.5 получила IP-адрес с внешнего DHCP-сервера:

  3. Обновляем файл конфигурации чтобы включить SSH и доступ по паре логин/пароль: 

    nano /etc/ssh/sshd_config

    Перезапускаем службу для применения настроек:

    systemctl restart sshd

  4. Добавляем альтернативные репозитории - это требуется из-за того, что официальной поддержки CentOS уже нет:
    sed -i 's/^mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*

    sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*

  5. Устанавливаем все доступные обновления:
    yum update -y
    systemctl reboot

  6. Добавляем альтернативные репозитории снова - на случай, если они перезаписались во время обновления:

    sed -i 's/^mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*

    sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*

  7. Устанавливаем дополнительные пакеты и делаем необходимые настройки:
    dnf install network-scripts -y

    systemctl stop firewalld

    systemctl disable firewalld

    dnf config-manager --enable powertools

    sudo sed -i 's/^SELINUX=.*/SELINUX=disabled/g' /etc/selinux/config

    dnf update -y

    reboot

  8. Настраиваем репозиторий OpenStack на релиз Victoria 5.4.0:
    dnf install -y centos-release-openstack-victoria-1-2.el8.noarch

  9. Добавляем альтернативные репозитории - на случай, если они снова перезаписались во время настройки репозитория OpenStack:

    sed -i 's/^mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*

    sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*

  10. Развертываем установщик:
    dnf install -y openstack-packstack

  11. Выключаем NetworkManager и включаем network-scripts - это необходимо для корректной работы Open vSwitch, который мы выбрали в нашем сценарии:
    systemctl disable NetworkManager
    systemctl stop NetworkManager
    systemctl enable network
    systemctl start network
    reboot

  12. Формируем файл answers с дефолтными опциями для деплоя OpenStack:
    packstack --gen-answer-file=packstack-answers.txt

  13. Обновляем необходимые опции. Внимание: все должно быть в UTF-8, иначе деплоер выдаст ошибку с неочевидным текстом.

    Для всех сервисов OpenStack изменяем IP-адрес, выданный по DHCP, на 127.0.0.1 (localhost). Это необходимо для автоматического назначения IP-адреса каждому клону из нашей будущей базовой ВМ:
    CONFIG_CONTROLLER_HOST=127.0.0.1
    CONFIG_COMPUTE_HOSTS=127.0.0.1
    CONFIG_NETWORK_HOSTS=127.0.0.1
    CONFIG_AMQP_HOST=127.0.0.1
    CONFIG_MARIADB_HOST=127.0.0.1
    CONFIG_REDIS_HOST=127.0.0.1

    В OpenStack настраиваем сетевой адаптер на внешнюю сеть для будущих вложенных ВМ (заменить ens192 ниже на название вашего сетевого интерфейса):
    CONFIG_NEUTRON_ML2_TYPE_DRIVERS=vxlan,flat
    CONFIG_NEUTRON_ML2_TENANT_NETWORK_TYPES=vxlan
    CONFIG_NEUTRON_OVS_BRIDGE_MAPPINGS=extnet:br-ex
    CONFIG_NEUTRON_OVS_BRIDGE_IFACES=br-ex:ens192
    CONFIG_NEUTRON_OVS_EXTERNAL_PHYSNET=extnet

    Выбераем механизм сетевого взаимодействия:
    CONFIG_NEUTRON_ML2_MECHANISM_DRIVERS=openvswitch
    CONFIG_NEUTRON_L2_AGENT=openvswitch

    Отменяем создание демонстрационных сетей, подсетей, роутера и образа cirros:
    CONFIG_PROVISION_DEMO=n

  14. Запускаем установку PackStack с обновленным файлом answers:
    packstack --answer-file=packstack-answers.txt

    В нашем окружении установка длится примерно 20 минут. После успешной установки отобразится такое или схожее сообщение:

    **** Installation completed successfully ******

    Additional information:

    * Time synchronization installation was skipped. Please note that unsynchronized time on server instances might be problem for some OpenStack components.

    * File /root/keystonerc_admin has been created on OpenStack client host 127.0.0.1. To use the command line tools you need to source the file.

    * To access the OpenStack Dashboard browse to http://127.0.0.1/dashboard.

    Please, find your login credentials stored in the keystonerc_admin in your home directory.

    * The installation log file is available at: /var/tmp/packstack/20 230 915–120 923–0rnwv3m9/openstack‑setup.log

    * The generated manifests are available at: /var/tmp/packstack/20 230 915–120 923–0rnwv3m9/manifests

    Обратите внимание: выше шрифтом выделено как после установки OpenStack подсказывает, где взять логин и пароль для первого входа в гипервизор.

    Конфигурация OpenStack на базовой ВМ после первичного деплоя

    1. Чтобы сделать доступным веб-интерфейс необходимо поменять адрес localhost (127.0.0.1) на фактический внешний IP-адрес - в примерах ниже = 10.77.237.155.  В файле конфигурации horizon в секцию Server aliases добавляем следующую строку:
      nano /etc/httpd/conf.d/15-horizon_vhost.conf
      ServerAlias 10.77.237.155
      systemctl restart httpd.service

    2. Меняем адрес localhost (127.0.0.1) на фактический внешний IP-адрес в файле конфигурации /etc/nova/nova.conf. Это необходимо для обеспечения возможности подсоединения к вложенным ВМ через noVNC-протокол для их настройки:
      server_listen=127.0.0.1
      novncproxy_base_url=http://127.0.0.1:6080/vnc_auto.html

      Перезапускаем все сервисы nova:
      systemctl restart openstack-nova*

    3. Изменяем пароль для учетной записи admin:
      •    узнаем сгенерированный пароль
      nano keystonerc_admin

      •    заходим в веб-интерфейс и изменяем пароль

      Сохраняем новый пароль в файле keystonerc_admin.

    4. Настраиваем внешнюю сеть в OpenStack.
      Создаем сеть external network (тип: Flat, без подсетей):

    5. Выключаем port_security с помощью CLI OpenStack. В веб-интерфейсе такой возможности нет:

      Если это не сделать, то при создании ВМ будем получать ошибку nova-compute сервиса:

      Выключаем port security (предварительно, авторизуемся в API):
      . keystonerc_admin
      openstack network set --disable-port-security d1102546-e081-4b9e-be96-9cd3aada889c

    6. При необходимости можно подготовить собственный шаблон (flavor) для ваших будущих ВМ. Flavor – это, по сути, шаблон параметров железа, необходимых для работы той машины, которую планируется создавать:
      openstack flavor create --vcpus 2 --ram 4096 --disk 20 --public --id 7 aqa1.flavor

      Проверяем через веб-интерфейс что шаблон создан:

      Проверяем через веб-интерфейс что шаблон создан:

    7. Устанавливаем пакет nmap.

      Для нашей конфигурации (динамические IP-адреса) OpenStack не будет показывать IP-адрес для вложенной ВМ в API и в веб-интерфейсе. Поэтому, предлагается установить nmap – это позволит узнать IP-адреса вложенных ВМ:
      yum install nmap -y

    8. Загружаем в OpenStack необходимые образы для ВМ. Например, мы использовали образ Debian10x64 QCOW2:

    9. Учитываем специфику запуска новой ВМ в конфигурации с внешней сетью (DHCP).

      В связи с тем, что нам необходимо, чтобы вложенные ВМ получали уникальные IP-адреса с нашего DHCP сервера (даже если мы создали несколько клонов OpenStack), пришлось выполнить несколько шагов, чтобы обойти баг OpenStack

      В OpenStack запрещено привязывать к вложенным ВМ сети без подсетей. Подсети нас не устраивают, потому что внутри подсетей свой DHCP, поэтому высок шанс, что ВМ на клонах OpenStack возьмут чужие IP-адреса. Ведь DHCP OpenStack ничего не знают про корпоративный DHCP. Через веб-интерфейс вообще невозможно создать ВМ без сети (или с сетью без подсети):

      Через CLI также получаем ошибку:

      Но через CLI создать ВМ все же можно, если в конфигурации сеть будет единственной (просто не нужно явно ее указывать, она автоматически привяжется, и проверки на наличие подсетей не произойдет).

      Получаем следующие ограничения:
      •    С нашей конфигурацией невозможно создать ВМ из веб-интерфейса;
      •    IP-адрес ВМ можно узнать только подключившись к ней через веб-интерфейс OpenStack, используя noVNC-протокол либо с помощью стороннего пакета nmap.

      Пример: как с помощью nmap мы определяем IP-адрес для вложенной ВМ в OpenStack:
      nmap -sn SUBNET | grep -i -B 2 "OSTACK_PORT_MAC_ADDRESS" | grep -oE "((1?[0-9][0-9]?|2[0-4][0-9]|25[0-5]).){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])"

      где SUBNET - подсеть, по которой ведем поиск, OSTACK_PORT_MAC_ADDRESS - MAC-адрес сетевого порта OpenStack, который был назначен ВМ в момент её создания.

      Учитывая все ограничения выше, создаем и запускаем ВМ командой (пример):
      openstack server create --image c5d8b154-fc7c-48a8-837a-ccb201b89f57 --flavor 7 --boot-from-volume 20 test_vm1

На этом этапе наша базовая ВМ с OpenStack готова. Видим, что веб‑интерфейс OpenStack не выводит IP‑адрес созданной ВМ. Но внутри машины IPадрес назначен — это мы узнаем благодаря использованию nmap. Можно выключить машину (Soft ShutDown) и создать снапшот.

Шаги при клонировании ВМ с OpenStack

Теперь опишем шаги, которые необходимо выполнить на склонированной ВМ для обеспечения ее работоспособности. Мы выбрали подход с созданием bash-скрипта, который необходимо запускать на каждом новом клоне. Этот скрипт выполняет следующие шаги:

#!/bin/bash

# Включаем Exception handling, чтобы получать расширенные сообщения по падениям скрипта
set -e

# Перенаправляем логирование в отдельный файл, чтобы при необходимости можно было его скачать
exec 3>&1 4>&2
trap 'exec 2>&4 1>&3' 0 1 2 3
exec 1>repair_openstack.log 2>&1

# Вспомогательная функция для проверки того, что сетевому интерфейсу назначен новый IP-адрес
function newIpIsNotNull {    if [[ "$new_ip" == "" ]]; then
        echo "Failure. New ip-address is empty. Interrupting the script...";
        exit 1;
    else
        echo "New ip-address: $new_ip";
    fi
}

# Берем существующий MAC-адрес с br-ex интерфейса
echo "updating MAC-address for br-ex..."
old_mac=$(ifconfig br-ex | grep ether | grep -o "..:..:..:..:..:..")
echo "Old MAC-address: $old_mac"

# Берем MAC-адрес, автоматически назначенный на внешний сетевой интерфейс гипервизором после клонирования (в нашем случае ens192)
new_mac=$(ifconfig ens192 | grep ether | grep -o "..:..:..:..:..:..")
echo "New mac-address: $new_mac" 

# Заменяем MAC-адрес на br-ex == MAC-адрес с ens192
sed -i "s/$old_mac/$new_mac/g" /etc/sysconfig/network-scripts/ifcfg-br-execho "MAC for br-ex updated successfully."

# Перезапускаем сервис сети
echo "restarting network service..."
service network restart
echo "network service restarted successfully."

# Ждем назначения IP-адреса на br-ex интерфейс
echo "getting new ip-address..."
new_ip=$(ifconfig br-ex | grep -oE '((1?[0-9][0-9]?|2[0-4][0-9]|25[0-5]).){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])' | head -1)
echo "new ip founded."

# Падаем, если IP-адрес не назначился (в коде автотестов мы перезапускаем весь скрипт целиком, чтобы исключить проблемы нестабильности сети/инфраструктуры)
echo "check new ip-address is not empty..."
newIpIsNotNull
echo "new ip-address verification completed successfully."

# После успешного получения IP-адреса обновляем /etc/hosts
echo "replacing ip-address in /etc/hosts..."
sed -i -e "s/\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\} packstack/$new_ip packstack/g" /etc/hosts
echo "IP replaced successfully in /etc/hosts."

# Обновляем конфигурацию horizon
echo "replacing ip-address in apache (Horizon) conf..."
sed -i -e "s/  ServerAlias 10.77.[0-9]\{1,3\}.[0-9]\{1,3\}/  ServerAlias $new_ip/g" /etc/httpd/conf.d/15-horizon_vhost.conf
echo "IP replaced successfully in /etc/httpd/conf.d/15-horizon_vhost.conf"

# Обновляем конфигурацию nova
echo "replacing IP in nova conf"
sed -i -e "s/server_listen=\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}/server_listen=$new_ip/g" /etc/nova/nova.conf
sed -i -e "s/server_proxyclient_address=\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}/server_proxyclient_address=$new_ip/g" /etc/nova/nova.conf
sed -i -e "s/novncproxy_base_url=http:\/\/\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}/novncproxy_base_url=http:\/\/$new_ip/g" /etc/nova/nova.conf
echo "IP replaced successfully in /etc/nova/nova.conf"

# Заменяем localhost (127.0.0.1) в базе keystone в таблице endpoint в столбце URL (необходимо для подключения к OpenStack API из автотестов - тесты запускаются на отдельной машине)
echo "replacing ip-address in API endpoints"
mysql -uroot keystone -e "UPDATE endpoint SET url = REPLACE(url, '127.0.0.1', '$new_ip');";
echo "IP replaced successfully in column 'url' of table 'endpoint' of database 'keystone'"

# Все, ожидаем успешное завершение выполнения скрипта
echo "script completed successfully."

В результате мы получаем возможность создания сразу нескольких клонов, которые могут существовать в одном VLAN и не мешать работе друг друга. За уникальностью IP-адресов следит наш "родительский" гипервизор, на котором мы разворачиваем клоны гипервизоров OpenStack. Уникальность IP-адресов обеспечивается уникальностью MAC-адресов (именно поэтому мы их и меняем в скрипте после клонирования для br-ex - копируем с основного интерфейса), чтобы наш внешний DHCP всегда выдавал новый IP-адрес на основе нового MAC-адреса.

Итак, мы научились клонировать окружения OpenStack с сохранением работоспособности. Надеемся, что наш рассказ был вам полезен, и до новых встреч.

Комментарии (0)