29.09.2022

Миграция виртуальных серверов в oVirt

server one
HOSTKEY
Арендуйте выделенные и виртуальные серверы с моментальным деплоем в надежных дата-центрах класса TIER III в Москве и Нидерландах. Принимаем оплату за услуги HOSTKEY в Нидерландах в рублях на счет российской компании. Оплата с помощью банковских карт, в том числе и картой МИР, банковского перевода и электронных денег.

Автор — Султан Усманов, специалист отдела DevOps компании Hostkey

У нас в компании Hostkey возникла необходимость в переводе серверов со старой инфраструктуры oVirt Engine версии 4.2 на новую инфраструктуру oVirt Engine версии 4.5. Эта миграция не просто смена минорного релиза — изменилось очень многое:

  • появились новые фичи и доработки в API;
  • был осуществлен переход на EL8.

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

Рассматривалось и было применено несколько вариантов миграции:

  1. Работа с Export Domain в oVirt.
  2. Создание автоматизации для переноса машин через экспорт/импорт OVA через oVirt API.

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

Export Domain — это домен хранения. В интернете достаточно много ресурсов, посвященных работе Export Domain в oVirt. Он в основном используется для переноса виртуальных машин в разные центры обработки данных или среды oVirt, и только когда создаются резервные копии виртуальных машин (этот домен может использовать исключительно протокол NFS). Работает на основе NFS и только один Export Domain может быть добавлен в DataCenter. Для добавления Export Domain в инфраструктуру необходимо предварительно установить сервер и развернуть на нем службу NFS, а также выдать необходимые права на каталог, который указывается в разделе Export Path в настройках.

Процедура добавления Export Domain на oVirt Engine сервере, с которого планируем экспортировать

Пример добавления Export Domain в web-интерфейсе oVirt:

В случае успешного добавления будет показан статус Active:

Для экспорта виртуального сервера на Export Domain необходимо пройти в раздел Compute – Virtual Machines:

Далее необходимо подготовить сервер к экспорту: найти и выключить его. Пример отключенного сервера:

После в этом же окне с правой стороны, под иконкой пользователя, следует кликнуть на «бургер» и выбрать раздел Export to Export Domain:

Далее требуется указать Export Domain, куда экспортировать сервер, и дождаться выполнения экспорта.

Затем необходимо перейти в раздел Compute — Data Centers, выбрать Data Centers, куда мы прикрепляли наш Export Domain, выбрать его и перевести в Maintenance-мод.

1. Выбираем нужный нам Data Center и заходим в него:

2. Выбираем наш Export Domain и в правом верхнему углу кликаем на кнопку Maintenance:

3. На рисунке ниже можно увидеть статус Export Domain переведенного в режим Maintenance:

4. Перейдя в Maintenance mode, кликаем на Detach и указываем причину, по которой мы отключаем диск:

5. После отключения в разделе Storage — Storage Domains на нашем Export Domain мы должны увидеть значок, указывающий на то, что раздел отключен:

Затем необходимо перейти в oVirt Engine, куда мы планируем перенести наш виртуальный сервер, и проделать те же действия, но уже прикрепить Export Domain.

Процедура добавления Export Domain на oVirt Engine сервере, на который планируем импортировать

1. Выбираем нужный нам Data Center, куда планируем импортировать наш сервер, переходим в раздел в Compute – Data Centers и кликаем на нужный:

2. В открывшемся окне в разделе Storage кликаем на Attach Export и выбираем Export Domain, нажимаем ОК:

3. Через 5–15 секунд (статус и время выполнения можно посмотреть в меню Task) в разделе Compute — Data Centers проходим в наш Data Centers, затем — в раздел Storages. Там должен появиться пункт Export Domain:

4. Кликаем на него и переходим в раздел VM Import:

5. Выбираем нужный виртуальный сервер и с правой стороны кликаем на Import:

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

  • Target Cluster;
  • CPU Profile, если он был настроен.

После выбираем нужный сервер и нажимаем на кнопку Import:

7. Переходим в раздел Compute — Virtual Machines и дожидаемся окончания импорта виртуального сервера. После вносим правки, если они необходимы, и запускаем сервер.

На этом процедура экспорта и импорта виртуального сервера средствами Export Domain завершена.

Написание скрипта и Playbook’а в Ansible для миграции через OVA.

Поскольку экспорт серверов проводился с oVirt Engine версии 4.2 на более новые версии oVirt Engine 4.4 и 4.5, работать только с Ansible Playbook было нельзя: у версии 4.2 нет поддержки модулей экспорта виртуальных серверов в формате OVA. Мы решили экспортировать виртуальные серверы со старой версии Engine средствами API. Для этого мы написали соответствующие скрипты. Для нового сервера импорт делался средствами Ansible Playbook и готовыми скриптами Python.

Ниже — примеры написания скрипта на Bash и вариант Ansible Playbook’а.

Bash-скрипт в качестве входных данных получает следующую информацию:

  • Engine-источник и назначения;
  • Guest_id (имя виртуального сервера);
  • host_name_dst (сервер назначения).

Полученные данные помещаются в файл с переменными vars/var.yml, которые в дальнейшем будут использоваться Ansible Playbook’ом.

Для экспорта необходимо предварительно установить сервер и развернуть на нем службу NFS. Выдать необходимые права на каталог (мы прописали — rw,async,no_subtree_check,anonuid=36,anongid=36,all_squash). В дальнейшем будем монтировать его в раздел /mnt/nfs на серверах Engine, а также на физическом хосте, с которого планируется экспорт виртуального сервера.

#!/usr/bin/env bash
 ##Source
 engine_fqdn_src=enginesrc.test.local
 engine_api_src="https://${engine_fqdn_src}/ovirt-engine/api"
 guest_id=$1
 ##Destination
 engine_fqdn_dst=enginedst.test.local
 engine_api_dst="https://${engine_fqdn_dst}/ovirt-engine/api"
 host_name_dst=$2
	
 ##Common vars
 engine_user=admin@internal
 engine_pass=pass
 export_path=/mnt/nfs/
	OVIRT_SEARCH() {
	 local engine_api=$1
	 local api_target=$2
		local search
	 if [[ ! -z $3 ]]&&[[ ! -z $4 ]];then
		 local search="?search=$3=$4"
	 fi
		curl -ks --user "$engine_user:$engine_pass" \
		 -X GET -H 'Version: 4' -H 'Content-Type: application/JSON' \
		 -H  'Accept: application/JSON' "${engine_api}/${api_target}${search}" |\
		 jq -Mc
 }
	
 ##Sourc
 vm_data=$(OVIRT_SEARCH $engine_api_src vms name $guest_id)
 disk_data=$(OVIRT_SEARCH $engine_api_src disks name $guest_id)
 vm_id=$(echo $vm_data | jq -r '.vm[].id')
 host_id=$(echo $vm_data | jq -r '.vm[].host.id')
 host_name_src=$(OVIRT_SEARCH $engine_api_src hosts/$host_id | jq -r '.name')
	
 ##Destination
 host_data_dst=$(OVIRT_SEARCH $engine_api_dst hosts name $host_name_dst)
 host_address_dst=$(echo $host_data_dst | jq -r '.host[].address')
 cluster_id_dst=$(echo $host_data_dst | jq -r '.host[].cluster.id' )
 data_center_id_dst=$(OVIRT_SEARCH $engine_api_dst clusters/$cluster_id_dst | jq -r '.data_center.id')
 data_domain_name_dst=$(OVIRT_SEARCH $engine_api_dst datacenters/$data_center_id_dst/storagedomains | jq -r '.storage_domain[].name')
 cluster_name_dst=$(OVIRT_SEARCH $engine_api_dst  clusters/$cluster_id_dst | jq -r '.name')
	
 post_data="<action><host><name>${host_name_src}</name></host><directory>${export_path}</directory><filename>${guest_id}</filename></action>"
 post_data_shutdown="<action/>"
 post_data_vmname="<vm><name>${guest_id}-</name></vm>"
	
 ##Shutdown vm
 curl -ks --user "$engine_user:$engine_pass" \
 -X POST -H 'Version: 4' \
 -H 'Content-Type: application/xml' -H 'Accept: application/xml' \
 --data $post_data_shutdown \
 ${engine_api_src}/vms/${vm_id}/shutdown
	
 ##Change vm name
 curl -ks --user "$engine_user:$engine_pass" \
 -X PUT -H 'Version: 4' \
 -H 'Content-Type: application/xml' -H 'Accept: application/xml' \
 --data $post_data_vmname \
 ${engine_api_src}/vms/${vm_id}
	
 ##Export vm
 curl -ks --user "$engine_user:$engine_pass" \
 -X POST -H 'Version: 4' \
 -H 'Content-Type: application/xml' -H 'Accept: application/xml' \
 --data $post_data \
 ${engine_api_src}/vms/${vm_id}/export
	
 ## Put result in var/var.yml
 cat << EOF > vars/var.yml
 url_src: htps://$engine_src/ovirt-engine/api
 url_dst: https://$engine_dst/ovirt-engine/api
 #username:
 #password:
 insecure: true
	
 ## VM Parameters:
 cluster_name: $cluster_name_dst
 disk_id: $disk_id
 vm_id: $vm_id
 disk_format: "qcow2"
 data_domain: $cluster_name_dst
 vm_name: $guest_id
 EOF

Ansible Playbook для импорта виртуального сервера

Ниже приведен пример Playbook’а, который забирает данные с файла vars/var.yml и подставляет их согласно переменным, указанным в файле. Цель Playbook’а — создать конфигурационный файл, который используется engine сервером для импорта OVA-файла. После запускается Python-скрипт (upload_ova_as_vm_or_template.py), который импортирует сервер со всеми настройками. Далее зачищается конфиг-файл и файл с образом системы. После проводится настройка графического интерфейса и выполняется запуск сервера.

- hosts: engine_dst
 
  tasks:
  
  — name: Obtain SSO token
    ovirt_auth:
      url: "{{ url_dst }}"
      username: "{{ username }}"
      password: "{{ password }}"
      insecure: "{{ insecure }}"
 
  — name:  Wait for export to be finished
    include_tasks: tasks/check_ova_export_status.yml
 
  — name: Ovirt config file creation
    include_tasks: tasks/ovirt_conf_creation.yml
    tags:
       ovirt_config_creation
 
  — name: Upload disk image
    command: "python3 /usr/share/doc/python3-ovirt-engine-sdk4/examples/upload_ova_as_vm_or_template.py -c engine --sd-name {{ data_domain }} /mnt/nfs/{{ vm_name }} --cluster-name {{ cluster_name }}"
 
  — name: Remove config
    file:
      path: "/root/.config/ovirt.conf"
      state: absent
 
  — name: Remove disk image from NFS
    file: 
      path: /mnt/nfs/{{vm_name}} 
      state: absent
 
  — name: Change VM Name
    ovirt_vm:
      auth: "{{ ovirt_auth }}"
      id: "{{ vm_id }}"
      name: "{{ vm_name }}"
 
  — name: Set console configuration for both Spice and VNC
    ovirt_vm:
      auth: "{{ ovirt_auth }}"
      name: "{{ vm_name }}"
      graphical_console:
        protocol:
          - spice
          - vnc
 
  — name: Run VM
    ovirt_vm:
      auth: "{{ ovirt_auth }}"
      cluster: "{{ cluster_name }}"
      state: running
      name: "{{ vm_name }}"
 
  — name: Revoke SSo token
    ovirt_auth:
      state: absent
      ovirt_auth: "{{ ovirt_auth }}"

В Playbook’e также используются Task’и. Ниже приведено их описание:

1) Задача, которая проверяет статус экспорта виртуального сервера — check_ova_export_status.yml.

- name: Check ova export status
  shell: |
    counter=7
 
    while true;do
    if [[ $(ls -l /mnt/nfs/ | grep -Pc '\b{{ vm_name }}$\b') -eq 1 ]];then
    let "successes+=1"
    else
    successes=0
    fi
    if [[ $successes -eq $counter ]];then
    break
    fi
    sleep 10
    done

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

- name: create config directory if absent
  file:
    path: "/root/.config/"
    state: directory
 
- name: ovirt config creation
  template:
    src: ../templates/ovirt.conf.j2
    dest: "/root/.config/ovirt.conf"
    owner: root
    group: root
    mode: '0644'

Пример конфигурационного файла ovirt.conf.j2 , размещенного в templates:

# Example configuration file.
#
# Example scripts will read this configuration from:
#
#   ~/.config/ovirt.conf.
#
# You can keep multiple configuration sections in this file.
#
# To use configuration "engine1" use:
#
#   ./example_script.py --config engine1 ...
	
# This engine configuration section shows all available options.
[engine]
	
# oVirt engine API URL (required).
engine_url = https://{{ engine_fqdn_dst }}
	
# oVirt engine API username (required).
username = {{ username }}
	
# oVirt enigne API password. If not specified the example script will get the
# password from stdin (optional).
password =  {{ password }}
	
# Verify server certificate and host name (optional, default yes).
secure = yes
	
# CA certificated for verifying for verifying server. No need to specify if the
# certificate was added to the host trust store (optional, default empty).
cafile = /etc/pki/ovirt-engine/ca.pem
	
# This engine configuration section uses only the required options, and disable
# server certificates verification.
#[engine2]
#engine_url = https://engine2
#username = admin@internal
#secure = no

Эту автоматизацию можно вынести в Jenkins или в похожий сервис для миграции руками младших специалистов, а также расширить дополнительными действиями по обновлению базы данных оборудования и т. д. Через Ansible легко организовать добавление и проверку NFS-mount, например, через autofs, сделав механизм миграции подходящим для большого числа хостов виртуализации, как в нашем случае. Если же вы не знакомы с Ansible и написание Playbook вызывает сложности, для миграции можно использовать распространенный инструмент — Export Domain.

Данные варианты использовались для экспорта и импорта серверов. Описанный выше подход позволил нам разработать и применить удобную схему для перевода серверов со старой инфраструктуры oVirt Engine версии 4.2 на новую — oVirt Engine версии 4.5. Время переноса каждого сервера зависит от объема жесткого диска. Например, сервер с 9 Гб переносится за 11 минут, в это время включены все дополнительные настройки, которые могут потребоваться для миграции.

Арендуйте выделенные и виртуальные серверы с моментальным деплоем в надежных дата-центрах класса TIER III в Москве и Нидерландах. Принимаем оплату за услуги HOSTKEY в Нидерландах в рублях на счет российской компании. Оплата с помощью банковских карт, в том числе и картой МИР, банковского перевода и электронных денег.

Другие статьи

30.11.2022

WindowsPE Live-CD в инфраструктуре Jenkins/Foreman

Устройство сборки WindowsPE-дистрибутива в Linux-инфраструктуре, автоматизация этого процесса с помощью Jenkins и разворачивание систем на базе MS Windows через этот хэлпер.

29.11.2022

Архитектура мониторинга Windows-инфраструктуры компании Hostkey

Как настроить мониторинг основных параметров серверов, которые работают на ОС Windows Server

29.11.2022

Использование брокера сообщений RabbitMQ для мониторинга с Prometheus и Grafana

Как организовать мониторинг и сбор метрик кластера RabbitMQ, а также проверять количество непрочитанных сообщений

11.11.2022

Как игнорировать tmpfs, udf, iso9660 при работе с метриками файловой системы

Как избежать проблем при развертывании операционных систем через Foreman при работе с ОС Windows.

31.10.2022

Мониторинг служб Linux c помощью Prometheus

Мониторинг отдельных служб и реализация системы предупреждений на серверах Linux с помощью Prometheus.

HOSTKEY Выделенные серверы в Европе, России и США Готовые выделенные серверы и серверы индивидуальных конфигураций на базе процессоров AMD, Intel, карт GPU, Бесплатной защитой от DDoS -атак и безлимитный соединением на скорости 1 Гбит/с 30
4.3 48 48
Upload