Шаблоны и клонирование виртуальных машин

Полное руководство по созданию шаблонов виртуальных машин и клонированию: подготовка ВМ, создание шаблонов в VMware, Hyper-V, KVM, автоматизация развертывания и Live Migration

Средний
Шаблоны и клонирование виртуальных машин
Руководство по созданию и использованию шаблонов виртуальных машин
Шаблон виртуальной машины — это один из самых эффективных инструментов современной виртуализации, позволяющий существенно ускорить развертывание инфраструктуры и стандартизировать конфигурации. Создание шаблона виртуальной машины один раз экономит десятки часов работы при массовом развертывании серверов, рабочих станций или тестовых сред. В этой статье мы подробно рассмотрим процесс создания шаблонов виртуальных машин, различные методы клонирования, использование Live Migration для миграций без простоя, а также автоматизацию этих процессов. Вы узнаете, как правильно подготовить виртуальную машину для создания шаблона, как работать с шаблонами в VMware vSphere, Hyper-V и KVM, и какие лучшие практики применять для эффективного управления виртуальной инфраструктурой. Шаблон виртуальной машины представляет собой предварительно настроенную ВМ с установленной операционной системой, базовым программным обеспечением и конфигурацией безопасности. Создание шаблона виртуальной машины позволяет развертывать десятки идентичных серверов за минуты вместо часов ручной установки и настройки. Это особенно ценно для администраторов виртуализации, которые управляют большими инфраструктурами и нуждаются в быстром масштабировании.

Что такое шаблон виртуальной машины и зачем он нужен

Типичные сценарии использования шаблонов

1. Массовое развертывание веб-серверов
Применение:Развертывание 50 идентичных веб-серверов с nginx, PHP и настроенным SSL за 2 часа вместо недели ручной установки
Почему:Стандартизация конфигурации и быстрое масштабирование
productionscaling
2. Создание тестовых сред
Применение:Мгновенное развертывание изолированных тестовых окружений для разработчиков с предустановленными инструментами
Почему:Экономия времени разработчиков и стандартизация среды
developmenttesting
3. Развертывание кластеров
Применение:Создание 10-узлового Kubernetes кластера или Hadoop кластера с идентичной базовой конфигурацией
Почему:Гарантия идентичности узлов кластера
clusteringhigh-availability
4. Виртуальные рабочие места (VDI)
Применение:Развертывание сотен виртуальных рабочих мест с предустановленным офисным ПО и настройками безопасности
Почему:Стандартизация рабочих мест и централизованное управление
vdidesktop

Подготовка виртуальной машины для создания шаблона

Sysprep для Windows
# Генерализация Windows Server для создания шаблона
C:\Windows\System32\Sysprep\sysprep.exe /generalize /oobe /shutdown /mode:vm

# Альтернативный вариант с файлом ответов для автоматизации
C:\Windows\System32\Sysprep\sysprep.exe /generalize /oobe /shutdown /unattend:C:\unattend.xml

# Для проверки состояния генерализации (до sysprep)
Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform' -Name 'SkipRearm'

generalize-linux.sh
#!/bin/bash
# Скрипт генерализации Linux для создания шаблона ВМ

# Остановка логирования
systemctl stop rsyslog

# Очистка SSH host keys
rm -f /etc/ssh/ssh_host_*

# Очистка machine-id (будет создан новый при первом запуске)
truncate -s 0 /etc/machine-id
rm -f /var/lib/dbus/machine-id

# Удаление правил udev для сетевых интерфейсов
rm -f /etc/udev/rules.d/70-persistent-net.rules

# Очистка логов
find /var/log -type f -exec truncate -s 0 {} \;
rm -f /var/log/*.log
rm -f /var/log/*/*.log

# Очистка истории команд
history -c
rm -f /root/.bash_history
rm -f /home/*/.bash_history

# Очистка временных файлов
rm -rf /tmp/*
rm -rf /var/tmp/*

# Очистка кэша пакетных менеджеров
apt-get clean      # Debian/Ubuntu
yum clean all      # RHEL/CentOS

# Очистка cloud-init (если используется)
cloud-init clean --logs --seed

# Удаление hostname
hostnamectl set-hostname localhost.localdomain

# Очистка сетевых настроек
rm -f /etc/sysconfig/network-scripts/ifcfg-eth*  # RHEL/CentOS
rm -f /etc/netplan/*.yaml  # Ubuntu с netplan

# Выключение системы
shutdown -h now

Важно: Генерализация необратима

После запуска Sysprep или скрипта генерализации Linux исходная виртуальная машина становится непригодной для работы в исходном виде. Всегда создавайте резервную копию или snapshot ВМ перед генерализацией! После генерализации ВМ должна быть сразу преобразована в шаблон — не запускайте её повторно.

Создание шаблона виртуальной машины в различных платформах

Создание шаблона в VMware vSphere

PowerCLI для создания шаблона VMware
# Подключение к vCenter
Connect-VIServer -Server vcenter.company.com -User administrator@vsphere.local

# Конвертация ВМ в шаблон
$vm = Get-VM -Name 'Windows-Server-2022-Base'
$vm | Set-VM -ToTemplate -Confirm:$false

# Альтернативный способ с указанием расположения
New-Template -Name 'WS2022-WebServer-Template-v1.0' -VM $vm -Location 'Templates'

# Развертывание ВМ из шаблона
$template = Get-Template -Name 'WS2022-WebServer-Template-v1.0'
New-VM -Name 'WebServer-01' -Template $template `
  -ResourcePool 'Production' `
  -Datastore 'DataStore01' `
  -DiskStorageFormat Thin

# Применение кастомизации при развертывании
$spec = Get-OSCustomizationSpec -Name 'Windows-Standard-Spec'
New-VM -Name 'WebServer-02' -Template $template `
  -OSCustomizationSpec $spec `
  -ResourcePool 'Production' `
  -Datastore 'DataStore01'

Создание шаблона в Hyper-V

PowerShell для создания шаблона Hyper-V
# Метод 1: Экспорт ВМ как шаблона
# Убедитесь, что ВМ выключена и генерализована
Export-VM -Name 'Windows-Server-2022-Base' -Path 'C:\HyperV\Templates\'

# Создание новой ВМ из экспортированного шаблона
$templatePath = 'C:\HyperV\Templates\Windows-Server-2022-Base'
Import-VM -Path "$templatePath\Virtual Machines\*.vmcx" `
  -Copy `
  -GenerateNewId `
  -VhdDestinationPath 'C:\HyperV\VMs\WebServer-01' `
  -VirtualMachinePath 'C:\HyperV\VMs\WebServer-01'

# Переименование импортированной ВМ
Rename-VM -Name 'Windows-Server-2022-Base' -NewName 'WebServer-01'

# Метод 2: Использование VHDX как шаблона
# Копирование базового VHDX
$templateVhdx = 'C:\HyperV\Templates\WS2022-Base.vhdx'
$newVhdx = 'C:\HyperV\VMs\WebServer-02\WebServer-02.vhdx'
Copy-Item -Path $templateVhdx -Destination $newVhdx

# Создание новой ВМ с скопированным диском
New-VM -Name 'WebServer-02' `
  -MemoryStartupBytes 4GB `
  -Generation 2 `
  -VHDPath $newVhdx `
  -SwitchName 'Production-Network'

# Настройка параметров ВМ
Set-VM -Name 'WebServer-02' -ProcessorCount 2 -DynamicMemory
Set-VMMemory -VMName 'WebServer-02' -MinimumBytes 2GB -MaximumBytes 8GB

Создание шаблона в KVM/QEMU

Создание шаблона в KVM
# Подготовка: выключение и генерализация ВМ
virsh shutdown ubuntu-22-04-base

# Создание шаблона через клонирование диска
sudo qemu-img convert -O qcow2 /var/lib/libvirt/images/ubuntu-22-04-base.qcow2 \
  /var/lib/libvirt/templates/ubuntu-22-04-template.qcow2

# Сжатие и оптимизация шаблона
sudo qemu-img convert -O qcow2 -c /var/lib/libvirt/images/ubuntu-22-04-base.qcow2 \
  /var/lib/libvirt/templates/ubuntu-22-04-template.qcow2

# Установка шаблона только для чтения (опционально)
sudo chmod 444 /var/lib/libvirt/templates/ubuntu-22-04-template.qcow2

# Создание новой ВМ на основе шаблона (backing file)
sudo qemu-img create -f qcow2 \
  -b /var/lib/libvirt/templates/ubuntu-22-04-template.qcow2 \
  -F qcow2 /var/lib/libvirt/images/webserver-01.qcow2 20G

# Клонирование XML конфигурации ВМ
virsh dumpxml ubuntu-22-04-base > /tmp/webserver-01.xml

# Редактирование XML (замена имени, UUID, MAC-адреса, пути к диску)
sed -i 's/ubuntu-22-04-base/webserver-01/g' /tmp/webserver-01.xml
sed -i "s|/var/lib/libvirt/images/ubuntu-22-04-base.qcow2|/var/lib/libvirt/images/webserver-01.qcow2|g" /tmp/webserver-01.xml

# Определение новой ВМ
virsh define /tmp/webserver-01.xml

# Запуск новой ВМ
virsh start webserver-01

Клонирование виртуальных машин: методы и подходы

Клонирование ВМ в VMware через PowerCLI
# Подключение к vCenter
Connect-VIServer -Server vcenter.company.com

# Полное клонирование ВМ
$sourceVM = Get-VM -Name 'ProductionApp-Master'
New-VM -Name 'ProductionApp-Clone' `
  -VM $sourceVM `
  -ResourcePool 'Production' `
  -Datastore 'DataStore01' `
  -DiskStorageFormat Thin

# Связанное клонирование (через snapshot)
# Шаг 1: Создание snapshot базовой ВМ
$snapshot = New-Snapshot -VM $sourceVM -Name 'Base for clones' -Description 'Parent for linked clones'

# Шаг 2: Создание linked clone на основе snapshot
New-VM -Name 'TestEnvironment-01' `
  -VM $sourceVM `
  -LinkedClone `
  -ReferenceSnapshot $snapshot `
  -ResourcePool 'Development' `
  -Datastore 'DataStore02'

# Массовое создание linked clones для тестирования
1..10 | ForEach-Object {
  New-VM -Name "DevEnv-$_" `
    -VM $sourceVM `
    -LinkedClone `
    -ReferenceSnapshot $snapshot `
    -ResourcePool 'Development'
}
Клонирование ВМ в Hyper-V
# Метод 1: Экспорт и импорт с копированием (Full Clone)
Export-VM -Name 'AppServer-Master' -Path 'C:\Temp\Export'

Import-VM -Path 'C:\Temp\Export\AppServer-Master\Virtual Machines\*.vmcx' `
  -Copy `
  -GenerateNewId `
  -VhdDestinationPath 'C:\HyperV\VMs\AppServer-Clone'

Rename-VM -Name 'AppServer-Master' -NewName 'AppServer-Clone'

# Метод 2: Копирование VHDX и создание новой ВМ
# Остановка исходной ВМ (опционально, для консистентности)
Stop-VM -Name 'AppServer-Master'

# Копирование VHDX
Copy-Item 'C:\HyperV\VMs\AppServer-Master\disk.vhdx' `
  -Destination 'C:\HyperV\VMs\AppServer-Clone\disk.vhdx'

# Создание новой ВМ с скопированным диском
New-VM -Name 'AppServer-Clone' `
  -MemoryStartupBytes 8GB `
  -Generation 2 `
  -VHDPath 'C:\HyperV\VMs\AppServer-Clone\disk.vhdx' `
  -SwitchName 'Production'

# Метод 3: Differencing disk для linked clone
New-VHD -Path 'C:\HyperV\VMs\TestVM-01\disk.vhdx' `
  -ParentPath 'C:\HyperV\VMs\AppServer-Master\disk.vhdx' `
  -Differencing

New-VM -Name 'TestVM-01' `
  -MemoryStartupBytes 4GB `
  -Generation 2 `
  -VHDPath 'C:\HyperV\VMs\TestVM-01\disk.vhdx'
Клонирование ВМ в KVM
# Метод 1: virt-clone (автоматический Full Clone)
virt-clone --original appserver-master \
  --name appserver-clone \
  --file /var/lib/libvirt/images/appserver-clone.qcow2

# Метод 2: Ручное клонирование с копированием диска
# Выключение исходной ВМ
virsh shutdown appserver-master

# Копирование диска
sudo cp /var/lib/libvirt/images/appserver-master.qcow2 \
  /var/lib/libvirt/images/appserver-clone.qcow2

# Экспорт и модификация XML
virsh dumpxml appserver-master > /tmp/appserver-clone.xml

# Изменение имени, UUID, MAC-адреса в XML (вручную или через sed)
sed -i 's/appserver-master/appserver-clone/g' /tmp/appserver-clone.xml
sed -i 's|/var/lib/libvirt/images/appserver-master.qcow2|/var/lib/libvirt/images/appserver-clone.qcow2|g' /tmp/appserver-clone.xml

# Удаление UUID (будет сгенерирован новый)
sed -i '/<uuid>/d' /tmp/appserver-clone.xml

# Определение новой ВМ
virsh define /tmp/appserver-clone.xml

# Метод 3: Linked Clone через backing file
sudo qemu-img create -f qcow2 \
  -b /var/lib/libvirt/images/appserver-master.qcow2 \
  -F qcow2 /var/lib/libvirt/images/testvm-01.qcow2

# Создание ВМ с linked диском (модификация XML и define)

Когда использовать шаблоны, а когда клонирование

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

Live Migration виртуальных машин при клонировании и развертывании

Live Migration в VMware (vMotion)
# Подключение к vCenter
Connect-VIServer -Server vcenter.company.com

# Простая миграция ВМ на другой хост
$vm = Get-VM -Name 'WebServer-01'
$targetHost = Get-VMHost -Name 'esxi-host-02.company.com'
Move-VM -VM $vm -Destination $targetHost

# Миграция с изменением датастора (Storage vMotion)
$targetDatastore = Get-Datastore -Name 'DataStore02'
Move-VM -VM $vm -Datastore $targetDatastore

# Одновременная миграция хоста и хранилища
Move-VM -VM $vm -Destination $targetHost -Datastore $targetDatastore

# Массовая миграция ВМ, развернутых из шаблона
$vms = Get-VM | Where-Object {$_.Name -like 'WebServer-*'}
$targetHost = Get-VMHost -Name 'esxi-host-03.company.com'
$vms | ForEach-Object {
  Move-VM -VM $_ -Destination $targetHost -RunAsync
}

# Автоматическая балансировка через DRS
$cluster = Get-Cluster -Name 'Production-Cluster'
Set-Cluster -Cluster $cluster -DrsEnabled:$true -DrsAutomationLevel FullyAutomated
Live Migration в Hyper-V
# Настройка Live Migration на хосте
Enable-VMMigration
Set-VMHost -VirtualMachineMigrationAuthenticationType Kerberos
Set-VMHost -UseAnyNetworkForMigration $true

# Указание сети для миграции (рекомендуется выделенная сеть)
$migrationSubnet = '192.168.100.0/24'
Set-VMHost -MaximumVirtualMachineMigrations 2 `
  -VirtualMachineMigrationPerformanceOption SMB

# Простая Live Migration на другой хост
$vm = Get-VM -Name 'AppServer-01'
Move-VM -Name $vm.Name -DestinationHost 'hyperv-host-02.company.com'

# Storage Migration (перемещение VHDX на другое хранилище)
Move-VMStorage -VMName 'AppServer-01' `
  -DestinationStoragePath 'D:\HyperV\VMs\AppServer-01'

# Одновременная миграция хоста и хранилища
Move-VM -Name 'AppServer-01' `
  -DestinationHost 'hyperv-host-02.company.com' `
  -DestinationStoragePath 'D:\HyperV\VMs\AppServer-01' `
  -IncludeStorage

# Массовая миграция ВМ
$vms = Get-VM | Where-Object {$_.Name -like 'AppServer-*'}
$targetHost = 'hyperv-host-03.company.com'
$vms | ForEach-Object {
  Move-VM -Name $_.Name -DestinationHost $targetHost -AsJob
}
Live Migration в KVM
# Настройка Live Migration требует общего хранилища (NFS, GlusterFS, Ceph)
# и правильной настройки libvirt на обоих хостах

# Проверка возможности миграции
virsh dominfo webserver-01

# Простая Live Migration на другой хост
virsh migrate --live --persistent --undefinesource \
  webserver-01 \
  qemu+ssh://kvm-host-02.company.com/system

# Миграция с указанием параметров производительности
virsh migrate --live --persistent --undefinesource \
  --bandwidth 1000 \
  --parallel --parallel-connections 4 \
  webserver-01 \
  qemu+ssh://kvm-host-02.company.com/system

# Миграция с туннелированием (без прямого доступа между хостами)
virsh migrate --live --persistent --undefinesource \
  --p2p --tunnelled \
  webserver-01 \
  qemu+ssh://kvm-host-02.company.com/system

# Storage Migration (копирование дисков на новое хранилище)
virsh migrate --live --persistent \
  --copy-storage-all \
  webserver-01 \
  qemu+ssh://kvm-host-02.company.com/system

# Скрипт массовой миграции
for vm in $(virsh list --name | grep webserver); do
  virsh migrate --live --persistent --undefinesource \
    $vm qemu+ssh://kvm-host-03.company.com/system &
done
wait

Ограничения Live Migration

Live migration виртуальных машин не работает в некоторых сценариях: при использовании локальных дисков без репликации, при подключении физических устройств USB/PCI passthrough, при несовместимости версий гипервизора между хостами, при использовании некоторых специфичных настроек CPU. Всегда тестируйте миграцию перед продакшен-использованием.

Миграция без простоя: использование шаблонов для плановых миграций

Скрипт репликации данных для миграции
#!/bin/bash
# Скрипт репликации данных для миграции без простоя

# Параметры
SOURCE_HOST="old-vm.company.com"
SOURCE_PATH="/var/www/html"
TARGET_PATH="/var/www/html"
EXCLUDE_FILE="/root/rsync-exclude.txt"

# Первая полная синхронизация (выполняется заранее)
echo "[$(date)] Starting initial sync..."
rsync -avz --progress --delete \
  --exclude-from=$EXCLUDE_FILE \
  root@$SOURCE_HOST:$SOURCE_PATH/ $TARGET_PATH/

# Инкрементальные синхронизации (выполняются регулярно)
while true; do
  echo "[$(date)] Running incremental sync..."
  rsync -avz --delete \
    --exclude-from=$EXCLUDE_FILE \
    root@$SOURCE_HOST:$SOURCE_PATH/ $TARGET_PATH/
  
  # Проверка количества изменений
  CHANGES=$(rsync -avz --dry-run --delete \
    root@$SOURCE_HOST:$SOURCE_PATH/ $TARGET_PATH/ | grep -c '^>')
  
  echo "[$(date)] Changes detected: $CHANGES"
  
  # Если изменений мало, готовы к финальному переключению
  if [ $CHANGES -lt 10 ]; then
    echo "[$(date)] Ready for final cutover - minimal changes detected"
  fi
  
  # Ожидание перед следующей синхронизацией
  sleep 300  # 5 минут
done

Реальный сценарий: Миграция датацентра без простоя

1. Реальный сценарий: Миграция датацентра без простоя
Применение:Компания мигрирует 200 продакшен-серверов из устаревшего датацентра на новое оборудование в другой локации. Требование: простой не более 5 минут для каждого приложения.
Почему:Создано 15 шаблонов виртуальных машин для разных типов серверов (веб, БД, приложения). На новом оборудовании развернуто 200 ВМ из шаблонов. Настроена репликация данных в реальном времени (database replication для БД, rsync для файлов). Тестирование проводилось месяц. Переключение выполнялось поэтапно: сначала тестовые среды, потом некритичные приложения, наконец критичные системы. Для каждого приложения переключение занимало 3-5 минут (изменение DNS + проверка).
Нулевое влияние на пользователей благодаря постепенному переключениюВозможность тщательного тестирования перед переключением продакшенаСтарая инфраструктура работала 2 недели параллельно для возможности откатаМиграция заняла 3 месяца вместо 6 месяцев при традиционном подходеЭкономия на простое: избежали потерь в $500K из-за остановки бизнеса

Автоматизация создания шаблонов и клонирования

main.tf
# Провайдер VMware vSphere
terraform {
  required_providers {
    vsphere = {
      source  = "hashicorp/vsphere"
      version = "~> 2.0"
    }
  }
}

provider "vsphere" {
  user           = var.vsphere_user
  password       = var.vsphere_password
  vsphere_server = var.vsphere_server
  allow_unverified_ssl = true
}

# Получение ссылок на ресурсы
data "vsphere_datacenter" "dc" {
  name = "Production"
}

data "vsphere_datastore" "datastore" {
  name          = "DataStore01"
  datacenter_id = data.vsphere_datacenter.dc.id
}

data "vsphere_compute_cluster" "cluster" {
  name          = "Production-Cluster"
  datacenter_id = data.vsphere_datacenter.dc.id
}

data "vsphere_network" "network" {
  name          = "Production-Network"
  datacenter_id = data.vsphere_datacenter.dc.id
}

# Шаблон для клонирования
data "vsphere_virtual_machine" "template" {
  name          = "WS2022-WebServer-Template-v1.0"
  datacenter_id = data.vsphere_datacenter.dc.id
}

# Создание нескольких ВМ из шаблона
resource "vsphere_virtual_machine" "web_servers" {
  count            = 5
  name             = "webserver-${count.index + 1}"
  resource_pool_id = data.vsphere_compute_cluster.cluster.resource_pool_id
  datastore_id     = data.vsphere_datastore.datastore.id
  
  num_cpus = 4
  memory   = 8192
  guest_id = data.vsphere_virtual_machine.template.guest_id
  
  network_interface {
    network_id   = data.vsphere_network.network.id
    adapter_type = data.vsphere_virtual_machine.template.network_interface_types[0]
  }
  
  disk {
    label            = "disk0"
    size             = 100
    thin_provisioned = true
  }
  
  clone {
    template_uuid = data.vsphere_virtual_machine.template.id
    
    customize {
      windows_options {
        computer_name  = "webserver-${count.index + 1}"
        workgroup      = "WORKGROUP"
        admin_password = var.admin_password
      }
      
      network_interface {
        ipv4_address = "192.168.1.${10 + count.index}"
        ipv4_netmask = 24
      }
      
      ipv4_gateway = "192.168.1.1"
      dns_server_list = ["8.8.8.8", "8.8.4.4"]
    }
  }
}
deploy-vms.yml
---
# Ansible playbook для автоматизированного развертывания ВМ из шаблона
- name: Deploy VMs from template
  hosts: localhost
  gather_facts: no
  
  vars:
    vcenter_hostname: "vcenter.company.com"
    vcenter_username: "administrator@vsphere.local"
    vcenter_password: "{{ vault_vcenter_password }}"
    datacenter: "Production"
    cluster: "Production-Cluster"
    template_name: "Ubuntu-22.04-Template-v1.0"
    vm_count: 10
    
  tasks:
    - name: Clone VMs from template
      community.vmware.vmware_guest:
        hostname: "{{ vcenter_hostname }}"
        username: "{{ vcenter_username }}"
        password: "{{ vcenter_password }}"
        validate_certs: no
        datacenter: "{{ datacenter }}"
        cluster: "{{ cluster }}"
        folder: "/VMs/WebServers"
        name: "webserver-{{ item }}"
        template: "{{ template_name }}"
        state: poweredon
        hardware:
          memory_mb: 8192
          num_cpus: 4
        networks:
          - name: "Production-Network"
            ip: "192.168.1.{{ 10 + item }}"
            netmask: "255.255.255.0"
            gateway: "192.168.1.1"
            dns_servers:
              - "8.8.8.8"
              - "8.8.4.4"
        customization:
          hostname: "webserver-{{ item }}"
        wait_for_ip_address: yes
      loop: "{{ range(1, vm_count + 1) | list }}"
      
    - name: Configure deployed VMs
      community.vmware.vmware_guest_powerstate:
        hostname: "{{ vcenter_hostname }}"
        username: "{{ vcenter_username }}"
        password: "{{ vcenter_password }}"
        validate_certs: no
        name: "webserver-{{ item }}"
        state: powered-on
      loop: "{{ range(1, vm_count + 1) | list }}"
windows-template.pkr.hcl
# Packer template для создания шаблона Windows Server
source "vsphere-iso" "windows2022" {
  vcenter_server      = "vcenter.company.com"
  username            = "administrator@vsphere.local"
  password            = "${var.vcenter_password}"
  insecure_connection = true
  
  datacenter = "Production"
  cluster    = "Production-Cluster"
  datastore  = "DataStore01"
  
  vm_name       = "WS2022-Template-${formatdate("YYYYMMDD", timestamp())}"
  guest_os_type = "windows9Server64Guest"
  
  CPUs      = 2
  RAM       = 4096
  disk_controller_type = ["lsilogic-sas"]
  storage {
    disk_size             = 100000
    disk_thin_provisioned = true
  }
  
  network_adapters {
    network      = "Production-Network"
    network_card = "vmxnet3"
  }
  
  iso_paths = [
    "[DataStore01] ISO/Windows-Server-2022.iso",
    "[DataStore01] ISO/VMware-tools.iso"
  ]
  
  floppy_files = [
    "./answer_files/autounattend.xml",
    "./scripts/install-vmware-tools.ps1"
  ]
  
  communicator   = "winrm"
  winrm_username = "Administrator"
  winrm_password = "${var.admin_password}"
  winrm_timeout  = "4h"
  
  shutdown_command = "C:\\Windows\\System32\\Sysprep\\sysprep.exe /generalize /oobe /shutdown /mode:vm"
  shutdown_timeout = "1h"
  
  convert_to_template = true
}

build {
  sources = ["source.vsphere-iso.windows2022"]
  
  provisioner "powershell" {
    scripts = [
      "./scripts/install-updates.ps1",
      "./scripts/install-software.ps1",
      "./scripts/configure-security.ps1",
      "./scripts/cleanup.ps1"
    ]
  }
  
  post-processor "manifest" {
    output = "manifest.json"
  }
}

Best practices автоматизации

Используйте Infrastructure as Code для всех операций создания шаблона виртуальной машины и развертывания. Храните код в системе контроля версий (Git). Применяйте тестирование шаблонов перед продакшен-использованием. Документируйте процессы и зависимости. Используйте секрет-менеджмент (HashiCorp Vault, AWS Secrets Manager) для паролей и ключей. Автоматизируйте не только создание, но и обновление и удаление устаревших шаблонов.

Управление шаблонами: версионирование и обновление

template-lifecycle.sh
#!/bin/bash
# Скрипт для управления версиями и обновлениями шаблонов

TEMPLATE_BASE_NAME="Ubuntu-22.04-WebServer"
CURRENT_VERSION="v1.1.0"
NEW_VERSION="v1.2.0"
CHANGELOG="Обновлены патчи безопасности, добавлен monitoring agent"

# Развертывание ВМ из текущего шаблона для обновления
echo "Deploying VM from template ${TEMPLATE_BASE_NAME}-${CURRENT_VERSION}..."
virt-clone --original "${TEMPLATE_BASE_NAME}-${CURRENT_VERSION}" \
  --name "${TEMPLATE_BASE_NAME}-update-work" \
  --file /var/lib/libvirt/images/${TEMPLATE_BASE_NAME}-update-work.qcow2

# Запуск ВМ для обновления
virsh start "${TEMPLATE_BASE_NAME}-update-work"
sleep 60  # Ожидание загрузки

# Применение обновлений через SSH
VM_IP=$(virsh domifaddr "${TEMPLATE_BASE_NAME}-update-work" | grep -oP '\d+\.\d+\.\d+\.\d+' | head -1)

echo "Applying updates to VM at $VM_IP..."
ssh root@$VM_IP "apt-get update && apt-get upgrade -y && apt-get autoremove -y"

# Установка дополнительного ПО если требуется
ssh root@$VM_IP "apt-get install -y zabbix-agent"

# Очистка и генерализация
ssh root@$VM_IP "bash /root/generalize-linux.sh"

# Ожидание выключения
while virsh list --all | grep -q "${TEMPLATE_BASE_NAME}-update-work.*running"; do
  echo "Waiting for VM to shutdown..."
  sleep 10
done

# Создание нового шаблона
echo "Creating new template ${TEMPLATE_BASE_NAME}-${NEW_VERSION}..."
sudo qemu-img convert -O qcow2 -c \
  /var/lib/libvirt/images/${TEMPLATE_BASE_NAME}-update-work.qcow2 \
  /var/lib/libvirt/templates/${TEMPLATE_BASE_NAME}-${NEW_VERSION}.qcow2

# Установка прав только для чтения
sudo chmod 444 /var/lib/libvirt/templates/${TEMPLATE_BASE_NAME}-${NEW_VERSION}.qcow2

# Запись метаданных
cat > /var/lib/libvirt/templates/${TEMPLATE_BASE_NAME}-${NEW_VERSION}.json <<EOF
{
  "name": "${TEMPLATE_BASE_NAME}",
  "version": "${NEW_VERSION}",
  "date": "$(date -I)",
  "author": "$USER",
  "changelog": "${CHANGELOG}",
  "base_os": "Ubuntu 22.04",
  "software": [
    "Apache 2.4.52",
    "PHP 8.2",
    "Zabbix Agent 6.0"
  ],
  "disk_size_gb": 50,
  "status": "testing"
}
EOF

echo "New template created: ${TEMPLATE_BASE_NAME}-${NEW_VERSION}"
echo "Status: testing"
echo "Next steps: Deploy test VM, run validation tests, promote to production"

# Удаление временной ВМ
virsh undefine "${TEMPLATE_BASE_NAME}-update-work"
rm /var/lib/libvirt/images/${TEMPLATE_BASE_NAME}-update-work.qcow2

Автоматизация обновления шаблонов

Рассмотрите автоматизацию ежемесячного цикла обновления шаблонов через CI/CD pipeline: автоматическое развертывание ВМ из шаблона, применение обновлений, запуск тестов функциональности, генерализация, создание нового шаблона. При успешном прохождении тестов новый шаблон автоматически продвигается из testing в production. Это обеспечивает актуальность шаблонов без ручного труда.

Лучшие практики и рекомендации

          Типичные ошибки, которых следует избегать

          НЕ запускайте ВМ после генерализации перед конвертацией в шаблон — это может испортить генерализацию. НЕ используйте один шаблон виртуальной машины для всех целей — создавайте специализированные шаблоны (веб-сервер, БД, приложения). НЕ забывайте генерализацию — все ВМ из такого шаблона будут иметь одинаковые идентификаторы. НЕ храните шаблоны только на одном хранилище — резервируйте в другую локацию. НЕ игнорируйте обновления шаблонов — устаревший шаблон с уязвимостями хуже чем отсутствие шаблона.

          Решение типичных проблем

          Проблема

          ВМ, развернутые из шаблона, имеют одинаковые идентификаторы

          Возможные причины

          • Не выполнена генерализация перед созданием шаблона виртуальной машины
          • Sysprep не был запущен для Windows шаблона
          • SSH host keys не были удалены для Linux шаблона
          • Machine-id не был очищен в Linux

          Решение

          Необходимо пересоздать шаблон с правильной генерализацией. Для Windows: запустите Sysprep с опциями /generalize /oobe /shutdown перед созданием шаблона. Для Linux: выполните скрипт генерализации, удаляющий SSH keys (rm -f /etc/ssh/ssh_host_*), очищающий machine-id (truncate -s 0 /etc/machine-id), удаляющий сетевые правила. Если проблема уже возникла на развернутых ВМ, вручную измените идентификаторы на каждой ВМ или используйте NewSID для Windows.

          Как избежать

          Всегда следуйте процедуре генерализации перед созданием шаблона. Тестируйте каждый новый шаблон: разверните 2-3 ВМ и проверьте уникальность SID, MAC-адресов, SSH keys. Автоматизируйте процесс генерализации через скрипты для исключения человеческого фактора.

          Проблема

          Ошибка при клонировании: недостаточно места на диске

          Возможные причины

          • Full clone требует полного размера диска исходной ВМ
          • Недостаточно места на целевом датасторе
          • Временные файлы клонирования занимают дополнительное место

          Решение

          Освободите место на целевом хранилище: удалите старые snapshots, неиспользуемые ВМ, временные файлы. Используйте thin provisioning вместо thick provisioning для экономии места. Рассмотрите использование linked clone вместо full clone для тестовых сред. Переместите клонирование на другой датастор с большим свободным пространством. Сожмите исходный диск перед клонированием (qemu-img convert с сжатием для KVM, Storage vMotion с компактированием для VMware).

          Как избежать

          Мониторьте использование датасторов и планируйте расширение заранее. Регулярно очищайте старые snapshots и неиспользуемые ВМ. Используйте thin provisioning по умолчанию. Создавайте шаблоны минимального размера — устанавливайте только необходимое ПО.

          Проблема

          Live Migration завершается с ошибкой или занимает очень долго

          Возможные причины

          • Недостаточная пропускная способность сети миграции
          • Несовместимость CPU между хостами
          • Проблемы с аутентификацией (Kerberos, SSH keys)
          • ВМ с очень высокой нагрузкой на память (много изменений во время миграции)

          Решение

          Проверьте сетевое подключение между хостами: ping, iperf для проверки пропускной способности. Убедитесь в совместимости CPU: включите EVC в VMware, Processor Compatibility в Hyper-V. Проверьте настройки аутентификации: для Hyper-V убедитесь что Kerberos настроен, для KVM проверьте SSH keys. Для сильно загруженных ВМ временно снизьте нагрузку перед миграцией. Увеличьте bandwidth миграции в настройках (virsh migrate --bandwidth для KVM).

          Как избежать

          Используйте выделенную сеть 10 Гбит/с для миграции. Настройте EVC на кластере VMware для гарантированной совместимости CPU. Регулярно тестируйте live migration в тестовой среде. Планируйте миграции на периоды низкой нагрузки.

          Проблема

          ВМ не загружается после развертывания из шаблона

          Возможные причины

          • Несовместимость оборудования (версия hardware compatibility)
          • Проблемы с драйверами виртуального оборудования
          • Некорректная генерализация повредила системные файлы
          • Проблемы с виртуальными дисками (corruption)

          Решение

          Проверьте версию virtual hardware — шаблон может требовать более новую версию ESXi/Hyper-V. Убедитесь что установлены VMware Tools/Hyper-V Integration Services/QEMU Guest Agent. Попробуйте изменить тип виртуального диска контроллера (IDE vs SCSI vs NVMe). Проверьте логи загрузки ВМ для диагностики. Если проблема в шаблоне — пересоздайте его с правильной конфигурацией. Используйте recovery mode для диагностики и восстановления загрузчика.

          Как избежать

          Тестируйте каждый новый шаблон виртуальной машины перед использованием в продакшене. Используйте совместимую версию virtual hardware. Документируйте требования к инфраструктуре для каждого шаблона.

          Заключение

          FAQ

          1В чем разница между шаблоном виртуальной машины и клонированием?

          Шаблон виртуальной машины — это эталонный образ с генерализованной ОС, предназначенный для многократного создания новых стандартизированных ВМ. Шаблон находится в режиме только для чтения и не может быть запущен. Клонирование — это процесс создания копии конкретной существующей ВМ со всеми её данными и настройками. Шаблоны используются для развертывания типовых серверов (веб-серверы, БД), клонирование — для копирования конкретной настроенной системы.

          2Обязательно ли выполнять генерализацию перед созданием шаблона?

          Да, генерализация абсолютно необходима. Без генерализации все ВМ, развернутые из шаблона, будут иметь одинаковые уникальные идентификаторы (SID в Windows, MAC-адреса, SSH ключи в Linux, machine-id), что приведет к конфликтам в сети, проблемам аутентификации и безопасности. Для Windows используйте Sysprep, для Linux — скрипт удаления уникальных идентификаторов. Создание шаблона виртуальной машины без генерализации — критическая ошибка.

          3Сколько времени занимает создание шаблона виртуальной машины?

          Первоначальное создание шаблона занимает 2-4 часа: установка ОС (30-60 мин), установка обновлений и ПО (60-120 мин), настройка и очистка (30 мин), генерализация и конвертация в шаблон (10-20 мин). Однако эта инвестиция времени окупается при первом же использовании: развертывание ВМ из шаблона занимает 5-15 минут вместо 2-4 часов ручной установки. При развертывании 10 серверов экономия составит 20-40 часов работы.

          4Можно ли использовать Live Migration между разными платформами виртуализации?

          Нет, прямая live migration виртуальных машин работает только в рамках одной платформы: VMware vMotion между ESXi хостами, Hyper-V Live Migration между Hyper-V хостами, KVM между KVM хостами. Миграция между разными платформами (например, VMware в Hyper-V) требует конвертации ВМ с остановкой (через VMware vCenter Converter, Hyper-V VM Import) или постепенной миграции через шаблоны с переключением трафика.

          5Как часто нужно обновлять шаблоны виртуальных машин?

          Рекомендуется обновлять шаблоны минимум ежемесячно для установки патчей безопасности. Для критичных уязвимостей создавайте обновленную версию шаблона внепланово. При выходе новых версий ОС или важного ПО создавайте мажорную версию шаблона (v2.0.0). Храните 2-3 актуальные версии одновременно для возможности отката. Используйте систему версионирования (semantic versioning) и документируйте изменения в каждой версии.

          6В чем разница между full clone и linked clone?

          Full clone создает полностью независимую копию ВМ со всеми файлами и дисками. Занимает много места (50-200 ГБ) и времени (10-60 мин), но полностью автономен — можно удалить исходную ВМ. Подходит для продакшена. Linked clone создает новую ВМ, использующую базовый диск исходной ВМ, записывая только изменения. Занимает мало места (5-20 ГБ) и создается быстро (1-5 мин), но зависит от исходной ВМ — её нельзя удалить. Подходит только для тестирования и разработки.

          7Что делать если миграция без простоя невозможна из-за несовместимости инфраструктуры?

          Используйте подход с шаблонами и переключением трафика: создайте шаблон виртуальной машины из текущих систем, разверните новые ВМ на целевой инфраструктуре, настройте репликацию данных между старыми и новыми ВМ, тщательно протестируйте новую инфраструктуру, выполните финальную синхронизацию данных, переключите трафик (DNS, балансировщик нагрузки). Миграция без простоя достигается переключением на уровне сети, а не физическим перемещением ВМ. Простой составит 3-10 минут.

          8Можно ли хранить пароли и ключи в шаблоне для автоматизации?

          Категорически нет! Никогда не включайте пароли, SSH ключи, API keys, сертификаты или другие чувствительные данные в шаблон виртуальной машины. Это критическая уязвимость безопасности — любой с доступом к шаблону получит credentials. Используйте secret management системы (HashiCorp Vault, Azure Key Vault, AWS Secrets Manager) и инжектируйте секреты после развертывания через automation (Ansible, cloud-init). Шаблоны должны содержать только публичную конфигурацию.

          9Какой объем дискового пространства нужен для библиотеки шаблонов?

          Зависит от количества и типа шаблонов. Один Windows Server шаблон занимает 40-60 ГБ, Linux — 10-30 ГБ. Для типичной инфраструктуры нужно 5-15 базовых шаблонов по 2-3 версии каждого. Итого: (10 шаблонов × 30 ГБ средний размер × 2 версии) = 600 ГБ. Добавьте 30% резерв для временных файлов и работы. Рекомендация: выделите 1-2 ТБ для библиотеки шаблонов на быстром хранилище (SSD). Используйте дедупликацию и сжатие для экономии места.

          10Как автоматизировать создание шаблона виртуальной машины от начала до конца?

          Используйте Packer от HashiCorp — инструмент для автоматизированного создания образов. Создайте Packer template, описывающий: установку ОС с ISO образа или облачного образа, установку обновлений и ПО через provisioners (shell scripts, Ansible, PowerShell), конфигурацию системы, очистку и генерализацию, конвертацию в шаблон платформы. Запуск 'packer build template.pkr.hcl' автоматически создаст готовый шаблон за 30-90 минут. Интегрируйте с CI/CD для автоматического создания новых версий при изменении конфигурации.