Уход с VMware после Broadcom: проверенный план миграции

Уход с VMware после Broadcom: проверенный план миграции

Уход с VMware после Broadcom: проверенный план миграции

Коротко (проверено 2026-11-03): после покупки VMware компания Broadcom прекратила продажу бессрочных лицензий, свела линейку продуктов к двум пакетам по подписке, закрыла старую программу облачных партнёров в Европе, а этой осенью убрала из публичного доступа VDDK - библиотеку для работы с дисками, через которую большинство инструментов миграции читает диски VMware. Сегодня The Register сообщает об открытой замене этой библиотеки, работающей только на чтение. Впрочем, не каждый путь ухода требует VDDK: экспорт в OVA плюс конвертация диска вообще не используют код VMware. Ниже: изменения с датами, реалистичные целевые платформы для команды в ЕС, пошаговый переезд и конвертер, который мы запустили на настоящем экспорте в формате VMware.

Источник. "Architect creates open-source replacement for VM migration tool VMware has hidden" (Simon Sharwood, The Register, 2026-11-03). На остальные факты даны ссылки там, где они упоминаются. Ваш собственный договор может отличаться от публичных условий, поэтому уточняйте детали лицензирования у своего реселлера.

Что изменила Broadcom: хронология

Дата Изменение Источник
2023-12-11 Конец продаж бессрочных лицензий и продления поддержки; предложение сокращено до подписок VMware Cloud Foundation (VCF) и vSphere Foundation (VVF) Новости Broadcom, Krish Prasad
2025-03-28 Дистрибьютор Arrow сообщает партнёрам, что с 2025-04-10 минимальный заказ вырастает с 16 до 72 ядер на продуктовую линейку The Register
2026-01-26 Договоры облачных провайдеров (VCSP) в ЕЭЗ не продлеваются; открытые сделки нужно закрыть до 2026-03-31; дальше программа только по приглашениям The Register, 2026-01-31
Aug-Sep 2026 VDDK убран из публичной загрузки: "The VDDK is not a customer entitlement" (VDDK не входит в права клиента), доступ через отдельных партнёров TAP TechTarget, 2026-09-09
2026-11-03 OpenVDDK от Andrija Panić: совместимая замена libvixDiskLib.so.8.0.3 только для чтения под лицензией Apache, которая "contains no VMware code" (не содержит кода VMware) The Register, 2026-11-03

Две оговорки. О минимуме в 72 ядра сообщил дистрибьютор, а не страница Broadcom, которую нам удалось найти: статья Broadcom о подсчёте ядер (KB 313548, проверено 2026-11-03) гласит "You must license a minimum of 16 physical cores for each CPU" (нужно лицензировать минимум 16 физических ядер на каждый CPU), а некоторые реселлеры утверждают, что минимальный заказ в 72 ядра снова отменили. Просите письменно указать количество ядер в коммерческом предложении. Кроме того, европейская история ещё не закончена: в июле 2025 года отраслевое объединение облачных провайдеров CISPE обратилось в Общий суд ЕС с требованием отменить одобрение сделки Еврокомиссией (дело T-503/25); решения мы пока не нашли.

Почему VDDK важен и какие пути обходятся без него

Библиотека VDDK, libvixDiskLib, позволяет инструменту читать диски ВМ, которые ещё работают в vSphere. The Register называет среди инструментов, которые её загружают, virt-v2v, nbdkit, импортеры Forklift / MTV, Apache CloudStack и собственные скрипты компаний. Расширение Microsoft VM Conversion для Windows Admin Center (из vCenter в Hyper-V, с тёплой синхронизацией через Change Block Tracking) до сих пор помечено как preview в его документации (обновлено 2026-02-20), а материалы о запуске называют VDDK среди предварительных требований. OpenVDDK - новый вариант для всех них, хотя автор сам предупреждает, что отчёты тестировщиков "not independently audited customer endorsements" (не являются независимо проверенными отзывами клиентов).

Пути вообще без VDDK, согласно документации virt-v2v по вводу из VMware (проверено 2026-11-03): экспорт OVA (-i ova), файлы ВМ на NFS или через SSH (-i vmx, -it ssh), NFC и обычный путь через vCenter HTTPS, который документация называет "the slowest method" (самый медленный способ). Мастер импорта ESXi в Proxmox VE, анонсированный 2024-03-27, читает диски через ESXi API с помощью собственной файловой системы пользовательского пространства на Rust и был протестирован с ESXi от 6.5 до 8.0 (форум Proxmox).

Куда переезжать: пять реалистичных вариантов

Целевая платформа Подходит, когда На что обратить внимание
Proxmox VE (KVM) на вашем оборудовании 3+ хоста, команда хочет GUI и кластеризацию Обновления, хранилище (ZFS, Ceph) и поддержка на вас
OpenStack Много арендаторов, всё через API Тяжёл в эксплуатации; окупается только на масштабе
Hyper-V (Windows Server) Преимущественно Windows, лицензии Datacenter уже оплачены Инструменту Microsoft сначала нужны драйверы Hyper-V в гостевых Linux
Облачные серверы (KVM) От нескольких до нескольких десятков ВМ, нет желания обслуживать гипервизор Один импорт на каждую ВМ, новые IP-адреса
Выделенные серверы + собственный гипервизор Стабильная нагрузка, нужна вся машина Гипервизор вы эксплуатируете и обновляете сами

Перенос ВМ за пять шагов

  1. Инвентаризация и уборка. Зафиксируйте прошивку (BIOS или EFI), контроллер диска, тип сетевой карты, статические IP и любую лицензию, привязанную к MAC-адресу. Удалите или консолидируйте снимки, чтобы экспортировать один актуальный диск.
  2. Подготовьте гостевую систему, пока она ещё работает на VMware. Windows: установите драйверы virtio (virtio-win) сейчас; гостевая Windows, перенесённая на диск virtio без них, не загрузится. Linux: драйверы virtio есть в ядре, но initramfs в режиме host-only может их не содержать; проверьте через lsinitramfs или lsinitrd и при необходимости пересоберите его.
  3. Экспорт или подключение. Выключите ВМ и экспортируйте OVF / OVA (в vSphere Client "Export OVF Template" или через ovftool), либо позвольте virt-v2v или мастеру Proxmox забрать её самостоятельно.
  4. Конвертация. Только диск - через qemu-img, всю гостевую систему - через virt-v2v (он также настраивает драйверы), или напрямую в Proxmox из OVF.
  5. Загрузка через консоль, затем уборка. Проверьте имя сетевого интерфейса и IP, удалите VMware Tools или open-vm-tools, установите qemu-guest-agent.
qemu-img convert -p -f vmdk -O qcow2 disk1.vmdk disk1.qcow2
virt-v2v -i ova VM.ova -o local -os /var/tmp -of qcow2
qm importovf 120 VM.ovf local-lvm

Это задокументированные формы из руководства каждого инструмента; эти три команды мы здесь не запускали. Конвертация, которую мы действительно запустили, приведена ниже.

Проверено: что на самом деле делает конвертация (ova2raw.js)

Чтобы показать, из чего состоит процесс, мы написали конвертацию примерно в 100 строках на Bun без зависимостей. Скрипт открывает OVA (обычный tar), проверяет манифест SHA-256, выводит оборудование, которое запрашивает OVF, распаковывает streamOptimized VMDK зерно за зерном в разреженный raw-образ и проверяет GPT. Мы подали ему официальный OVA Ubuntu 24.04, настоящий экспорт в формате VMware: noble-server-cloudimg-amd64.ova, сборка от 2026-10-17, SHA-256 которой совпал с SHA256SUMS от Ubuntu. Сохраните как ova2raw.js:

// ova2raw.js - check a VMware OVA export and turn its disk into a raw image for KVM
// usage: bun ova2raw.js <export.ova> <out.raw>
import { openSync, readSync, writeSync, ftruncateSync, closeSync, fstatSync } from 'node:fs'
import { inflateSync } from 'node:zlib'
import { createHash } from 'node:crypto'

const [ova, out] = process.argv.slice(2)
const fd = openSync(ova, 'r')
const read = (pos, len) => {
  const b = Buffer.alloc(len)
  readSync(fd, b, 0, len, pos)
  return b
}

// 1. an OVA is a plain tar: list its members
const files = {}
for (let o = 0; o + 512 <= fstatSync(fd).size; ) {
  const h = read(o, 512)
  if (h.every(x => x === 0)) break
  const name = h.toString('utf8', 0, 100).replace(/\0.*$/s, '')
  const size = parseInt(h.toString('ascii', 124, 136).replace(/\0.*$/s, '').trim(), 8)
  files[name] = { pos: o + 512, size }
  o += 512 + Math.ceil(size / 512) * 512
}
const find = ext => Object.keys(files).find(n => n.endsWith(ext))
const text = n => read(files[n].pos, files[n].size).toString('utf8')
console.log('OVA members:', Object.entries(files).map(([n, f]) => `${n} (${f.size} B)`).join(', '))

// 2. the .mf manifest: every member's SHA-256 must match
const mf = find('.mf')
for (const line of mf ? text(mf).split('\n') : []) {
  const m = line.match(/^SHA(1|256)\((.+)\)\s*=\s*([0-9a-f]+)/i)
  if (!m || !files[m[2]]) continue
  const h = createHash('sha' + m[1])
  const f = files[m[2]]
  for (let p = 0; p < f.size; p += 1 << 24) h.update(read(f.pos + p, Math.min(1 << 24, f.size - p)))
  console.log(`  manifest ${m[2]}: ${h.digest('hex') === m[3].toLowerCase() ? 'OK' : 'MISMATCH'}`)
}

// 3. the .ovf descriptor: what the VM expects from its hardware
const ovf = text(find('.ovf'))
const items = [...ovf.matchAll(/<(?:ovf:)?Item\b[\s\S]*?<\/(?:ovf:)?Item>/g)].map(x => x[0])
const tag = (s, t) => s.match(new RegExp(`<(?:rasd:)?${t}>([^<]*)<`))?.[1]
const kind = { 3: 'CPU', 4: 'RAM', 5: 'IDE controller', 6: 'SCSI controller', 10: 'NIC', 17: 'disk', 20: 'SATA controller' }
console.log('OVF:', ovf.match(/vmw:osType="([^"]+)"/)?.[1] ?? '?', '| firmware',
  ovf.match(/key="firmware" ovf:value="([^"]+)"/)?.[1] ?? 'bios (default)')
for (const it of items) {
  const k = kind[tag(it, 'ResourceType')]
  if (k) console.log(`  ${k.padEnd(16)} ${tag(it, 'ElementName') ?? ''} ${tag(it, 'ResourceSubType') ?? ''} ${tag(it, 'VirtualQuantity') ?? ''}`.trimEnd())
}

// 4. the streamOptimized VMDK: a header, then compressed grains and markers
const vmdk = files[find('.vmdk')]
const hd = read(vmdk.pos, 512)
if (hd.readUInt32LE(0) !== 0x564d444b) throw new Error('not a sparse VMDK (no KDMV magic)')
const capacity = Number(hd.readBigUInt64LE(12)) * 512
const desc = read(vmdk.pos + Number(hd.readBigUInt64LE(28)) * 512, Number(hd.readBigUInt64LE(36)) * 512)
console.log(`VMDK ${desc.toString().match(/createType="([^"]+)"/)?.[1]}, virtual size ${capacity} B, grain ${Number(hd.readBigUInt64LE(20)) * 512} B`)

const ofd = openSync(out, 'w')
ftruncateSync(ofd, capacity) // sparse: unwritten grains stay holes = zeros
let pos = Number(hd.readBigUInt64LE(64)) * 512
let grains = 0
let written = 0
while (pos < vmdk.size) {
  const m = read(vmdk.pos + pos, 512)
  const val = Number(m.readBigUInt64LE(0))
  const size = m.readUInt32LE(8)
  if (size) { // compressed grain: lba, size, zlib data
    const raw = inflateSync(read(vmdk.pos + pos + 12, size))
    writeSync(ofd, raw, 0, raw.length, val * 512)
    grains++
    written += raw.length
    pos += Math.ceil((12 + size) / 512) * 512
  } else if (m.readUInt32LE(12) === 0) break // end-of-stream marker
  else pos += 512 + val * 512 // grain table / directory / footer: metadata only
}
closeSync(ofd)
console.log(`Wrote ${out}: ${grains} grains, ${written} B of data in ${capacity} B`)

// 5. check the result: a valid GPT, and the file systems where the partitions say they are
const rfd = openSync(out, 'r')
const at = (p, l) => { const b = Buffer.alloc(l); readSync(rfd, b, 0, l, p); return b }
const gpt = at(512, 92)
const crc = Buffer.from(gpt)
crc.writeUInt32LE(0, 16)
console.log(`GPT "${gpt.toString('ascii', 0, 8)}", header CRC ${(Bun.hash.crc32(crc) >>> 0) === gpt.readUInt32LE(16) ? 'OK' : 'BAD'}`)
const n = gpt.readUInt32LE(80)
const es = gpt.readUInt32LE(84)
const ents = at(Number(gpt.readBigUInt64LE(72)) * 512, n * es)
console.log(`  partition array CRC ${(Bun.hash.crc32(ents) >>> 0) === gpt.readUInt32LE(88) ? 'OK' : 'BAD'}`)
for (let i = 0; i < n; i++) {
  const e = ents.subarray(i * es, (i + 1) * es)
  if (e.subarray(0, 16).every(x => x === 0)) continue
  const first = Number(e.readBigUInt64LE(32))
  const last = Number(e.readBigUInt64LE(40))
  const sb = at(first * 512 + 1024, 136)
  const fs = sb.readUInt16LE(56) === 0xef53 ? `ext4 label "${sb.toString('ascii', 120, 136).replace(/\0.*$/s, '')}"`
    : at(first * 512, 512).toString('ascii', 82, 87) === 'FAT32' ? 'FAT32 (EFI system partition)'
    : e.toString('ascii', 0, 16) === 'Hah!IdontNeedEFI' ? 'BIOS boot (GRUB for legacy BIOS)' : 'unknown'
  console.log(`  p${i + 1} ${String((last - first + 1) * 512 / 2 ** 20 | 0).padStart(5)} MiB  ${fs}`)
}
bun ova2raw.js noble-server-cloudimg-amd64.ova noble.raw

Результат, запущено на облачном сервере DCXV с Bun 1.4.4 2026-11-03:

OVA members: ubuntu-noble-24.04-cloudimg.ovf (11186 B), ubuntu-noble-24.04-cloudimg.mf (213 B), ubuntu-noble-24.04-cloudimg.vmdk (590749696 B)
  manifest ubuntu-noble-24.04-cloudimg.vmdk: OK
  manifest ubuntu-noble-24.04-cloudimg.ovf: OK
OVF: ubuntu64Guest | firmware bios (default)
  CPU              2 virtual CPU(s)  2
  RAM              1024MB of memory  1024
  SCSI controller  SCSI Controller 0 VirtualSCSI
  IDE controller   VirtualIDEController 1
  IDE controller   VirtualIDEController 0
  disk             Hard Disk 1
  NIC              Ethernet 1 VmxNet3
VMDK streamOptimized, virtual size 10737418240 B, grain 65536 B
Wrote noble.raw: 28663 grains, 1878458368 B of data in 10737418240 B
GPT "EFI PART", header CRC OK
  partition array CRC OK
  p1  2558 MiB  ext4 label "cloudimg-rootfs"
  p14     4 MiB  BIOS boot (GRUB for legacy BIOS)
  p15   106 MiB  FAT32 (EFI system partition)
  p16   913 MiB  ext4 label "BOOT"

Три запуска заняли от 14.6 до 16.2 s реального времени на этом сервере. Raw-файл имеет размер 10 GiB и занимает 1.8 GB на диске.

Что вывод подсказывает ещё до переключения

  1. VmxNet3 и VirtualSCSI - это устройства VMware. На KVM они становятся virtio-net и virtio-blk или virtio-scsi. Гостевой системе нужны драйверы для обоих ещё до первой загрузки, а сетевой интерфейс обычно получает новое имя, поэтому статический IP, привязанный к старому имени, не поднимется. Первую загрузку делайте через консоль.
  2. Прошивка должна совпадать. Этот OVF ничего не задаёт, значит, это BIOS; на диске есть и раздел BIOS boot, и системный раздел EFI, поэтому он загрузится в любом случае. ВМ, экспортированной с firmware=efi, на целевой платформе нужен UEFI (OVMF), иначе она не найдёт загрузчик.
  3. Тонкий диск остаётся тонким, только если вы за этим следите. 10 GiB виртуально, 1.8 GB данных. Копируйте инструментами, учитывающими разреженность (cp --sparse=always, rsync -S), или используйте qcow2, иначе вы будете передавать и хранить нули.
  4. Манифест - ваша проверка передачи. Сверяйте SHA-256 после каждого копирования между площадками: оборванная загрузка без всяких жалоб конвертируется в диск, который сбоит позже.

Планируйте простой

Холодный переезд складывается из экспорта + передачи + конвертации + первой загрузки. Замерьте каждый этап на одной тестовой ВМ, затем умножьте. Арифметика передачи (наша, без накладных расходов протокола): 1.8 GB на 1 Gbit/s - это около 15 s, 1 TB - около 2.2 часа. Тёплые инструменты копируют, пока ВМ работает, и в конце отправляют только изменённые блоки; тестировщики The Register сообщают о холодных и тёплых прогонах с Forklift и MTV. Для баз данных и нагруженных приложений репликация плюс переключение DNS лучше любого копирования дисков: сначала уменьшите TTL (см. распространение DNS и TTL) и пройдите чек-листы из инструкции по миграции на облачный сервер.

Когда подходят облачные или выделенные серверы DCXV

  • Несколько ВМ, нет команды для гипервизора: наши облачные серверы работают на KVM с дисками virtio. В панели Переустановка -> "Свой образ (URL)" принимает файл qcow2, raw или vmdk по https; образ больше диска тарифа увеличивает диск и тарифицируется как расширение диска, а сетевые настройки применяются, только если в образе есть cloud-init. Тарифы от EUR 15.00/мес (2 vCPU, 4 GB RAM, 40 GB; проверено 2026-11-03, без НДС).
  • Десятки ВМ или собственный кластер Proxmox: выделенные серверы от EUR 210/мес с гипервизором на ваш выбор.
  • Гостевые Windows: мы перепродаём лицензии Windows Server; обратитесь до переезда, чтобы лицензия была готова с первого дня.

Оба варианта работают в наших дата-центрах Tier III в Праге и Ковилье.

Спланируйте переезд вместе с нами

Запустите ova2raw.js на одной экспортированной ВМ и отправьте строки с оборудованием из его вывода на sales@dcxv.com, либо запустите облачный сервер и проверьте импорт самостоятельно.

Уход с VMware после Broadcom: проверенный план миграции
clouddedicatedinfrastructure

Уход с VMware после Broadcom: проверенный план миграции

Broadcom отменил бессрочные лицензии, урезал партнёров и спрятал VDDK. Как перенести ВМ на KVM, Proxmox или Hyper-V: даты, факты и проверенный конвертер OVA.

Распространение DNS: 3 секунды Cloudflare против вашего TTL
networkingcloudinfrastructure

Распространение DNS: 3 секунды Cloudflare против вашего TTL

Cloudflare сократил задержку сборки DNS до 3,3 с. Но переезд на новый сервер ждёт TTL, негативный кеш и делегирование .com на 2 дня. Измерено на двух зонах.

10 000 выступлений в советах США: что важно клиентам ЦОД
clouddedicatedinfrastructure

10 000 выступлений в советах США: что важно клиентам ЦОД

Новый датасет кодирует 10 202 выступления в советах США о дата-центрах: 90,5% против, вода на первом месте. Мы пересчитали данные и объясняем, что это меняет.

Поддержка и биллинг AWS: проверенный гайд для команд из ЕС
cloudpricingcompare

Поддержка и биллинг AWS: проверенный гайд для команд из ЕС

Планы поддержки AWS и цены, задержки данных биллинга, исходящий трафик, скрипт для проверки расходов и когда подходит провайдер из ЕС с фиксированной ценой.

Задержка памяти на облачном сервере: измерено, а не угадано
clouddedicatedinfrastructure

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

Популярный пост утверждает, что занятый CPU часто просто ждёт RAM. Мы измерили задержку от L1 до DRAM на нашем облачном сервере и объясняем, что это меняет.