Хабр, привет!

На связи центр компетенций VMware "Инфосистемы Джет".

В этой статье расскажем о тонкостях подключения LUN из системы хранения данных (СХД) к хостам ESXi, которые управляются через vCenter Server. За прошлый год мы не раз сталкивались с проблемами у заказчиков, которых можно было бы избежать при правильной настройке. Как именно — расскажем ниже, не забывая и про теорию.

Скрытый текст

Глоссарий

LUN (Logical Unit Number) — логический диск для конечных потребителей. В СХД с некоторым набором физических дисков мы можем объединить их в единый логический том нужного нам размера и «отдать» в использование нашей системе виртуализации.

Датастор (Datastore) — сущность, используемая на стороне VMware vSphere для хранения данных и размещения виртуальных машин (ВМ).

Mapping – процесс презентации блочного устройства хосту или группе хостов со стороны СХД.

VMFS — файловая система, созданная VMware, используемая на датасторах в VMware vSphere и оптимизированная для работы с большими файлами (дисками ВМ) в кластерной среде.

В VMware vSphere LUN'ы в основном используются для создания VMFS-датасторов. Есть альтернативные способы хранения данных ВМ — vSAN, NFS, vVOL — но использование VMFS-датасторов на LUN, презентованных с СХД, является традиционным вариантом. Создать VMFS-датастор возможно на любом доступном хосту блочном устройстве, будь то локальный диск или LUN. Использование локальных дисков для размещения ВМ в продуктивных средах нерационально из-за невозможности организации доступа к локальному датастору для всего кластера ESXi-хостов. Поэтому, когда выбор останавливается именно на традиционных датасторах, нам необходимо иметь LUN'ы, которые правильно презентованы нашим хостам. В качестве среды передачи данных при таком подходе можно использовать: Fiber Channel (FC), Fiber Channel over Ethernet (FCoE) или iSCSI. На примере FC покажем схематично основные компоненты:

Рис. 1. Общая схема SAN
Рис. 1. Общая схема SAN

По приведенной схеме можно понять, где именно живут LUN.

Вне зависимости от используемой среды передачи (FC, FCoE, iSCSI) в определенный момент мы получаем конфигурацию, при которой СХД видит и знает все ESXi-хосты, которые будут с ней работать, а хосты — СХД. Важный момент в том, что изначально хосты видят только СХД, но ничего не знают о созданных на ней блочных устройствах, пока массив сам не «расскажет» об этом. При этом каждому LUN назначается определенный идентификатор — LUN ID. В большинстве случаев процесс настройки маппинга включает в себя следующие этапы:

  • На стороне СХД создается Host Group, в которую включаются все хосты или определенная группа хостов.

  • На стороне СХД создается LUN Group, в которую включаются все LUN, планируемые для использования ESXi-хостами.

  • Каждой Host Group назначаются необходимые им группы LUN'ов.

  • После выполнения Rescan на стороне хостов или перелогина хостов в FC-фабрику ESXi-хосты видят презентованные LUN'ы и могут с ними работать.

Важный момент, с которым мы многократно встречались у наших заказчиков:

Все LUNы должны быть презентованы всем хостам в рамках одного VC под единым LUN ID. Это требование  прописано в документации VMware, но, к сожалению, не всем о нем известно. Источник:  For LUNs that are shared among multiple hosts, make sure that LUN IDs are consistent across all hosts.

После теоретической части переходим к практике.

Проблема

Представим, что у нас имеются 3 ESXi-хоста любой из актуальных версий (проблема применима ко всем версиям VMware vSphere). Они собраны в Host Group с именем «HG1» на стороне СХД. Также у нас есть 3 LUN, созданных на этой СХД и объединенных в группу «SG1». Во многих системах хранения назначение LUN ID происходит автоматически при маппинге Storage группы Host группе. Предположим, что мы настроили маппинг, и все хосты увидели созданные LUN'ы под LUN ID 1, 2 и 3. Дальше у нас появляется необходимость расширить нашу среду виртуализации с помощью новых хостов. Мы добавляем еще 3 ESXi-хоста и объединяем их на стороне массива в группу «HG2». Если при маппинге на стороне СХД LUN ID назначается автоматически, то при подаче SG1 на HG2 вероятнее всего LUN'ы будут презентованы под новыми ID, например, 4, 5, 6. И вот у нас есть LUN, который старым хостам виден под LUN ID 1, а новым трём — под LUN ID 4.

Казалось бы, ничего страшного. Мы не увидим никаких ошибок или предупреждений в vSphere. Датасторы создаются и удаляются. Но существует ряд операций, при выполнении которых могут возникнуть проблемы.  Например, расширение датастора. Так, если он создан на LUN, который видится разными ESXi хостами в рамках одного VC под различными LUN ID, то при попытке расширения UI не предложит нам блочных устройств. Показываем наглядно:

Рис. 2. Кластер ESXi-хостов.
Рис. 2. Кластер ESXi-хостов.

* Оставим имя только одного из них, так как на нем конфигурация будет отличаться.

Каждому из хостов презентован LUN naa.60060e80100cfdf0053047e700000006. Первому и второму хосту предоставлен доступ под LUN ID 3, а третьему — под LUN ID 12:

Рис. 3. Проблемный LUN на ESXi-03.
Рис. 3. Проблемный LUN на ESXi-03.
Рис. 4. Проблемный LUN на остальных хостах.
Рис. 4. Проблемный LUN на остальных хостах.

На этом блочном устройстве создали VMFS датастор размером 40 GB:

Рис. 5. Свойства проблемного датастора.
Рис. 5. Свойства проблемного датастора.

После расширения LUN до 50 GB и попытки увеличить размер датастора мы получим пустоту в окне выбора устройства для расширения файловой системы:

Рис.6. LUN после расширения.
Рис.6. LUN после расширения.
Рис. 7. Расширение датастора на проблемном LUN.
Рис. 7. Расширение датастора на проблемном LUN.
Рис. 8. Проблемный датастор не показан в списке устройств.
Рис. 8. Проблемный датастор не показан в списке устройств.

При корректной конфигурации это окно должно выглядеть так:

Рис. 9. Расширение LUN, презентованного корректно.
Рис. 9. Расширение LUN, презентованного корректно.

Сразу можно обратить внимание на то, что один из параметров, приведенный на рисунке 9 — LUN ID. То есть это поле в принципе не предполагает наличие нескольких значений. Сейчас мы посмотрим глубже и увидим, что происходит в этот момент «под капотом». 

Ковыряние

Включив trivia-логирование на VC, мы находим в vpxd-логе следующие события:

2026-01-14T09:15:02.524+03:00 verbose vpxd[50172] [Originator@6876 sub=Default opID=mipmnquk-56jh-h5-14] [VpxVmomi] Invoking; <<5262ff0a-6f23-01c0-4f60-bbcb3fb8c88f, <TCP '127.0.0.1 : 8085'>, <TCP '127.0.0.1 : 49704'>>, datastoreSystem-14, vim.host.DatastoreSystem.queryAvailableDisksForVmfs>
2026-01-14T09:15:02.524+03:00 trivia vpxd[50172] [Originator@6876 sub=VpxProfiler opID=mipmnquk-56jh-h5-14] Ctr: TotalTime = 0 ms
2026-01-14T09:15:02.524+03:00 info vpxd[58673] [Originator@6876 sub=vpxLro opID=mipmnquk-56jh-h5-14] [VpxLRO] -- BEGIN lro-16765133 -- datastoreSystem-14 -- vim.host.DatastoreSystem.queryAvailableDisksForVmfs -- 5262ff0a-6f23-01c0-4f60-bbcb3fb8c88f(52b782ca-865a-e87c-70b2-3b9a67f206f7) 

2026-01-14T09:15:03.622+03:00 trivia vpxd[63105] [Originator@6876 sub=Http2Session #6 opID=vb-27320:urn:vmomi:HostStorageSystem:storageSystem-14:62ebb1f5-36d0-4fb7-8a06-35e8e2ebc104.properties:01-f5] [Stream #3070961] Write called with 2 bytes
2026-01-14T09:15:03.622+03:00 verbose vpxd[58673] [Originator@6876 sub=Vmomi opID=mipmnquk-56jh-h5-14] [ClientAdapterBase::InvokeOnSoap] Invoke done (##.##.##.##, vim.host.DatastoreSystem.queryAvailableDisksForVmfs)

2026-01-14T09:15:03.632+03:00 verbose vpxd[58673] [Originator@6876 sub=Vmomi opID=mipmnquk-56jh-h5-14] Invoke done; <<5262ff0a-6f23-01c0-4f60-bbcb3fb8c88f, <TCP '127.0.0.1 : 8085'>, <TCP '127.0.0.1 : 49704'>>, datastoreSystem-14, vim.host.DatastoreSystem.queryAvailableDisksForVmfs>

В этом фрагменте VC пытается найти доступные для расширения ресурсы (queryAvailableDisksForVmfs). DatastoreSystem-14 в нашем случае означает, что запрос информации в БД делается на основании данных хоста с идентификатором (Moref) Host-14. Включив логирование statement в PostgreSQL, мы заглянем в его лог и посмотрим, что же конкретно в этот момент запрашивается из БД:

2026-01-14 06:15:03.623 UTC 696722d5.7abd 0 VCDB vc [local] 31421 269 LOG: statement: BEGIN;declare "SQL_CUR0x7f21f0297c70" cursor with hold for SELECT t1.DEVICE_BACKING_LUN_UUID, t2.CANONICAL_NAME FROM ((SELECT DISTINCT DEVICE_BACKING_LUN_UUID FROM VPXV_VM_RDM_LUN_INFO WHERE DEVICE_BACKING_LUN_UUID IS NOT NULL) UNION (SELECT DISTINCT DEVICE_BACKING_LUN_UUID FROM VPXV_SN_RDM_LUN_INFO WHERE DEVICE_BACKING_LUN_UUID IS NOT NULL)) t1 LEFT JOIN (SELECT DISTINCT CANONICAL_NAME, UUID FROM VPXV_DS_LUN_INFO) t2 ON t1.DEVICE_BACKING_LUN_UUID = t2.UUID ;fetch 1024 in "SQL_CUR0x7f21f0297c70"
2026-01-14 06:15:03.625 UTC 696722d5.7abd 0 VCDB vc [local] 31421 270 LOG: statement: close "SQL_CUR0x7f21f0297c70"
2026-01-14 06:15:03.625 UTC 696722d5.7abd 0 VCDB vc [local] 31421 271 LOG: statement: ROLLBACK
2026-01-14 06:15:03.626 UTC 696722d5.7abd 0 VCDB vc [local] 31421 272 LOG: statement: BEGIN;declare "SQL_CUR0x7f21f0297c70" cursor with hold for select distinct SL.UUID, SLD.QUALITY, SL.CANONICAL_NAME FROM VPX_HOST_SCSI_LUN SL, VPX_HOST_SCSI_DISK_PARTITION SDP, VPX_HOST_SCSILUN_DESCRIPTOR SLD WHERE SL.CANONICAL_NAME = SDP.DISK_NAME AND SL.HOST_ID = SDP.HOST_ID AND SL.ID = SLD.ID AND SL.UUID=SLD.DESCRIPTOR_ID_VAL ;fetch 1024 in "SQL_CUR0x7f21f0297c70"
2026-01-14 06:15:03.626 UTC 696722d5.7abd 0 VCDB vc [local] 31421 273 LOG: statement: close "SQL_CUR0x7f21f0297c70"
2026-01-14 06:15:03.626 UTC 696722d5.7abd 0 VCDB vc [local] 31421 274 LOG: statement: ROLLBACK
2026-01-14 06:15:03.627 UTC 696722d5.7abd 0 VCDB vc [local] 31421 275 LOG: statement: BEGIN;declare "SQL_CUR0x7f21f0297c70" cursor with hold for select DISTINCT UUID FROM VPXV_DS_LUN_INFO WHERE URL = 'ds:///vmfs/volumes/69661695-5a503194-ce6d-f875886e8e6e/' ;fetch 1024 in "SQL_CUR0x7f21f0297c70"
2026-01-14 06:15:03.627 UTC 696722d5.7abd 0 VCDB vc [local] 31421 276 LOG: statement: close "SQL_CUR0x7f21f0297c70"
2026-01-14 06:15:03.627 UTC 696722d5.7abd 0 VCDB vc [local] 31421 277 LOG: statement: ROLLBACK
2026-01-14 06:15:03.628 UTC 696722d5.7abd 0 VCDB vc [local] 31421 278 LOG: statement: BEGIN;declare "SQL_CUR0x7f21f0297c70" cursor with hold for select DISTINCT CANONICAL_NAME FROM VPXV_DS_LUN_INFO WHERE URL = 'ds:///vmfs/volumes/69661695-5a503194-ce6d-f875886e8e6e/' ;fetch 1024 in "SQL_CUR0x7f21f0297c70"
2026-01-14 06:15:03.628 UTC 696722d5.7abd 0 VCDB vc [local] 31421 279 LOG: statement: close "SQL_CUR0x7f21f0297c70"
2026-01-14 06:15:03.628 UTC 696722d5.7abd 0 VCDB vc [local] 31421 280 LOG: statement: ROLLBACK
2026-01-14 06:15:03.628 UTC 696722d5.7abd 0 VCDB vc [local] 31421 281 LOG: statement: BEGIN;declare "SQL_CUR0x7f21f0297c70" cursor with hold for select UUID, CANONICAL_NAME from VPX_HOST_SCSI_LUN where HOST_ID = '14' ;fetch 1024 in "SQL_CUR0x7f21f0297c70"
2026-01-14 06:15:03.629 UTC 696722d5.7abd 0 VCDB vc [local] 31421 282 LOG: statement: close "SQL_CUR0x7f21f0297c70"
2026-01-14 06:15:03.629 UTC 696722d5.7abd 0 VCDB vc [local] 31421 283 LOG: statement: SAVEPOINT _EXEC_SVP_0x7f21f01a3bb0;declare "SQL_CUR0x7f21f0297c70" cursor with hold for SELECT DISTINCT T1.DESCRIPTOR_ID_VAL, T2.CANONICAL_NAME FROM VPX_HOST_SCSILUN_DESCRIPTOR T1, (SELECT UUID, CANONICAL_NAME FROM VPX_HOST_SCSI_LUN WHERE HOST_ID IN (SELECT HOST_ID FROM VPXV_HOST_DATASTORE WHERE DS_ID = '43019' ) GROUP BY UUID, CANONICAL_NAME HAVING COUNT(1) = (SELECT COUNT(1) FROM VPXV_HOST_DATASTORE WHERE DS_ID = '43019' )) T2 WHERE T1.DESCRIPTOR_ID_VAL = T2.UUID AND T1.QUALITY NOT IN ('lowQuality', 'unknownQuality') ;fetch 1024 in "SQL_CUR0x7f21f0297c70"
2026-01-14 06:15:03.631 UTC 696722d5.7abd 0 VCDB vc [local] 31421 284 LOG: statement: close "SQL_CUR0x7f21f0297c70"
2026-01-14 06:15:03.631 UTC 696722d5.7abd 0 VCDB vc [local] 31421 285 LOG: statement: ROLLBACK
2026-01-14 06:15:03.631 UTC 696722d5.7abd 0 VCDB vc [local] 31421 286 LOG: statement: BEGIN;declare "SQL_CUR0x7f21f0297c70" cursor with hold for select DISTINCT CANONICAL_NAME FROM VPXV_DS_LUN_INFO WHERE UUID = '020003000060060e80100cfdf0053047e700000006444636303046' ;fetch 1024 in "SQL_CUR0x7f21f0297c70"
2026-01-14 06:15:03.632 UTC 696722d5.7abd 0 VCDB vc [local] 31421 287 LOG: statement: close "SQL_CUR0x7f21f0297c70"
2026-01-14 06:15:03.632 UTC 696722d5.7abd 0 VCDB vc [local] 31421 288 LOG: statement: ROLLBACK

Разберём каждый из запросов по порядку:

declare "SQL_CUR0x7f21f0297c70" cursor with hold for SELECT t1.DEVICE_BACKING_LUN_UUID, t2.CANONICAL_NAME FROM ((SELECT DISTINCT DEVICE_BACKING_LUN_UUID FROM VPXV_VM_RDM_LUN_INFO WHERE DEVICE_BACKING_LUN_UUID IS NOT NULL) UNION (SELECT DISTINCT DEVICE_BACKING_LUN_UUID FROM VPXV_SN_RDM_LUN_INFO WHERE DEVICE_BACKING_LUN_UUID IS NOT NULL)) t1 LEFT JOIN (SELECT DISTINCT CANONICAL_NAME, UUID FROM VPXV_DS_LUN_INFO) t2 ON t1.DEVICE_BACKING_LUN_UUID = t2.UUID ;fetch 1024 in "SQL_CUR0x7f21f0297c70"

Этот запрос выдаст список всех LUN, а точнее — их vml и canonical_name (naa.####), используемые в качестве RDM.

Следующий запрос покажет все LUN (vml, canonical_name и quality), которые видны ESXi-хостам:

declare "SQL_CUR0x7f21f0297c70" cursor with hold for select distinct SL.UUID, SLD.QUALITY, SL.CANONICAL_NAME FROM VPX_HOST_SCSI_LUN SL, VPX_HOST_SCSI_DISK_PARTITION SDP, VPX_HOST_SCSILUN_DESCRIPTOR SLD WHERE SL.CANONICAL_NAME = SDP.DISK_NAME AND SL.HOST_ID = SDP.HOST_ID AND SL.ID = SLD.ID AND SL.UUID=SLD.DESCRIPTOR_ID_VAL ;fetch 1024 in "SQL_CUR0x7f21f0297c70"

Продублируем этот запрос и посмотрим результаты его обработки:

VCDB=# select distinct SL.UUID, SLD.QUALITY, SL.CANONICAL_NAME FROM VPX_HOST_SCSI_LUN SL, VPX_HOST_SCSI_DISK_PARTITION SDP, VPX_HOST_SCSILUN_DESCRIPTOR SLD WHERE SL.CANONICAL_NAME = SDP.DISK_NAME AND SL.HOST_ID = SDP.HOST_ID AND SL.ID = SLD.ID AND SL.UUID=SLD.DESCRIPTOR_ID_VAL;
uuid | quality | canonical_name
--------------------------------------------------------------------+---------------+-----------------------------------------------------------------------
020000000060060e80100cfdf0053047e700000000444636303046 | mediumQuality | naa.60060e80100cfdf0053047e700000000
0200000000634737943e950000257717bcea7031a058462d534153 | mediumQuality | naa.634737943e950000257717bcea7031a0
020000000066000802593e082f21027383073c8609415641474f20 | mediumQuality | naa.66000802593e082f21027383073c8609
020001000060060e80100cfdf0053047e700000001444636303046 | mediumQuality | naa.60060e80100cfdf0053047e700000001
020002000060060e80100cfdf0053047e70000029a444636303046 | mediumQuality | naa.60060e80100cfdf0053047e70000029a
020003000060060e80100cfdf0053047e700000006444636303046 | mediumQuality | naa.60060e80100cfdf0053047e700000006 <== проблемный LUN
020007000060060e80100cfdf0053047e700000007444636303046 | mediumQuality | naa.60060e80100cfdf0053047e700000007
02000a000060060e80100cfdf0053047e700000032444636303046 | mediumQuality | naa.60060e80100cfdf0053047e700000032
02000b000060060e80100cfdf0053047e700000033444636303046 | mediumQuality | naa.60060e80100cfdf0053047e700000033
02000c000060060e80100cfdf0053047e700000006444636303046 | mediumQuality | naa.60060e80100cfdf0053047e700000006 <== проблемный LUN
05eb25f16c9ede1b9b76480b06cd2bc314cb398a474a27703481c7e440265aaa64 | highQuality | t10.NVMe____Dell_BOSS2DN1____________________________0100000DC5435000
(11 rows)

В выводе мы имеем две записи для LUN с именем naa.60060e80100cfdf0053047e700000006, но с разными vml. Мы поясним этот факт чуть позже. Пока же продолжим разбираться с запросами:

declare "SQL_CUR0x7f21f0297c70" cursor with hold for select DISTINCT UUID FROM VPXV_DS_LUN_INFO WHERE URL = 'ds:///vmfs/volumes/69661695-5a503194-ce6d-f875886e8e6e/' ;fetch 1024 in "SQL_CUR0x7f21f0297c70"

Тут идёт выборка уникальных значений UUID для датастора, который мы расширяем (смотрите рис. 5). В выводе запроса мы получаем два результата:

VCDB=# select DISTINCT UUID FROM VPXV_DS_LUN_INFO WHERE URL = 'ds:///vmfs/volumes/69661695-5a503194-ce6d-f875886e8e6e/';
uuid
--------------------------------------------------------
020003000060060e80100cfdf0053047e700000006444636303046
02000c000060060e80100cfdf0053047e700000006444636303046
(2 rows)

Следующим запросом VC определяет имя (canonical_name) LUN'а, на котором расположен расширяемый датастор:

declare "SQL_CUR0x7f21f0297c70" cursor with hold for select DISTINCT CANONICAL_NAME FROM VPXV_DS_LUN_INFO WHERE URL = 'ds:///vmfs/volumes/69661695-5a503194-ce6d-f875886e8e6e/' ;fetch 1024 in "SQL_CUR0x7f21f0297c70"

Тут получаем единственный результат:

VCDB=# select DISTINCT CANONICAL_NAME FROM VPXV_DS_LUN_INFO WHERE URL = 'ds:///vmfs/volumes/69661695-5a503194-ce6d-f875886e8e6e/';
canonical_name
--------------------------------------
naa.60060e80100cfdf0053047e700000006
(1 row)

Таким образом, vCenter определил:

  • наличие RDM и их идентификаторы;

  • блочные устройства, которые доступны ESXi-хостам (их vml и canonical_name);

  • vml конкретного LUN'а;

  • имя (canonical_name) LUN'а. 

В следующем запросе VC запрашивает информацию по одному конкретному хосту (host-14), что коррелирует с логами VPXD:

declare "SQL_CUR0x7f21f0297c70" cursor with hold for select UUID, CANONICAL_NAME from VPX_HOST_SCSI_LUN where HOST_ID = '14' ;fetch 1024 in "SQL_CUR0x7f21f0297c70"

В устаревших версиях vSphere можно было найти упоминания о Master Browser. Сейчас такого термина в логах нет, но логика, похоже, осталась. По опыту анализа аналогичных сценариев в актуальных версиях это хост с наименьшим идентификатором moref. В данном случае — host-14. В выводе запроса находим информацию о блочных устройствах и их идентификаторах, которые знакомы конкретному хосту:

VCDB=# select UUID, CANONICAL_NAME from VPX_HOST_SCSI_LUN where HOST_ID = '14' ;
uuid | canonical_name
--------------------------------------------------------+--------------------------------------
020000000066000802593e082f21027383073c8609415641474f20 | naa.66000802593e082f21027383073c8609
02000a000060060e80100cfdf0053047e700000032444636303046 | naa.60060e80100cfdf0053047e700000032
02000b000060060e80100cfdf0053047e700000033444636303046 | naa.60060e80100cfdf0053047e700000033
020000000060060e80100cfdf0053047e700000000444636303046 | naa.60060e80100cfdf0053047e700000000
020001000060060e80100cfdf0053047e700000001444636303046 | naa.60060e80100cfdf0053047e700000001
020004000060060e80100cfdf0053047e700000005444636303046 | naa.60060e80100cfdf0053047e700000005
020003000060060e80100cfdf0053047e700000006444636303046 | naa.60060e80100cfdf0053047e700000006 <== проблемный LUN
020007000060060e80100cfdf0053047e700000007444636303046 | naa.60060e80100cfdf0053047e700000007
020002000060060e80100cfdf0053047e70000029a444636303046 | naa.60060e80100cfdf0053047e70000029a
(9 rows)

Следующий запрос разберём более детально:

declare "SQL_CUR0x7f21f0297c70" cursor with hold for SELECT DISTINCT T1.DESCRIPTOR_ID_VAL, T2.CANONICAL_NAME FROM VPX_HOST_SCSILUN_DESCRIPTOR T1, (SELECT UUID, CANONICAL_NAME FROM VPX_HOST_SCSI_LUN WHERE HOST_ID IN (SELECT HOST_ID FROM VPXV_HOST_DATASTORE WHERE DS_ID = '43019' ) GROUP BY UUID, CANONICAL_NAME HAVING COUNT(1) = (SELECT COUNT(1) FROM VPXV_HOST_DATASTORE WHERE DS_ID = '43019' )) T2 WHERE T1.DESCRIPTOR_ID_VAL = T2.UUID AND T1.QUALITY NOT IN ('lowQuality', 'unknownQuality') ;fetch 1024 in "SQL_CUR0x7f21f0297c70"

Здесь мы видим:

  • выборку всех хостов, которые знают о датасторе с moref 43019 (проблемный датастор);

  • все датасторы, которые знают все хосты;

  • подсчёт количества хостов, которые знают о датасторе с moref 43019;

  • определение общих датасторов для хостов по принципу —из результатов второго запроса (все датасторы) находим те, которые повторяются столько раз, сколько у нас имеется хостов (третий запрос – все хосты)

Разбираем запрос:

Скрытый текст
VCDB=# SELECT HOST_ID FROM VPXV_HOST_DATASTORE WHERE DS_ID = '43019';
host_id
---------
14
38004
38014
(3 rows)


VCDB=# SELECT UUID, CANONICAL_NAME FROM VPX_HOST_SCSI_LUN WHERE HOST_ID IN (SELECT HOST_ID FROM VPXV_HOST_DATASTORE WHERE DS_ID = '43019');
uuid | canonical_name
--------------------------------------------------------------------+-----------------------------------------------------------------------
020000000066000802593e082f21027383073c8609415641474f20 | naa.66000802593e082f21027383073c8609
02000a000060060e80100cfdf0053047e700000032444636303046 | naa.60060e80100cfdf0053047e700000032
02000b000060060e80100cfdf0053047e700000033444636303046 | naa.60060e80100cfdf0053047e700000033
020000000060060e80100cfdf0053047e700000000444636303046 | naa.60060e80100cfdf0053047e700000000
020001000060060e80100cfdf0053047e700000001444636303046 | naa.60060e80100cfdf0053047e700000001
020004000060060e80100cfdf0053047e700000005444636303046 | naa.60060e80100cfdf0053047e700000005
020003000060060e80100cfdf0053047e700000006444636303046 | naa.60060e80100cfdf0053047e700000006
020007000060060e80100cfdf0053047e700000007444636303046 | naa.60060e80100cfdf0053047e700000007
020002000060060e80100cfdf0053047e70000029a444636303046 | naa.60060e80100cfdf0053047e70000029a
0200000000634737943e950000257717bcea7031a058462d534153 | naa.634737943e950000257717bcea7031a0
02000a000060060e80100cfdf0053047e700000032444636303046 | naa.60060e80100cfdf0053047e700000032
02000b000060060e80100cfdf0053047e700000033444636303046 | naa.60060e80100cfdf0053047e700000033
020000000060060e80100cfdf0053047e700000000444636303046 | naa.60060e80100cfdf0053047e700000000
020001000060060e80100cfdf0053047e700000001444636303046 | naa.60060e80100cfdf0053047e700000001
020004000060060e80100cfdf0053047e700000005444636303046 | naa.60060e80100cfdf0053047e700000005
02000c000060060e80100cfdf0053047e700000006444636303046 | naa.60060e80100cfdf0053047e700000006
020007000060060e80100cfdf0053047e700000007444636303046 | naa.60060e80100cfdf0053047e700000007
02000a000060060e80100cfdf0053047e700000032444636303046 | naa.60060e80100cfdf0053047e700000032
02000b000060060e80100cfdf0053047e700000033444636303046 | naa.60060e80100cfdf0053047e700000033
020000000060060e80100cfdf0053047e700000000444636303046 | naa.60060e80100cfdf0053047e700000000
020001000060060e80100cfdf0053047e700000001444636303046 | naa.60060e80100cfdf0053047e700000001
020004000060060e80100cfdf0053047e700000005444636303046 | naa.60060e80100cfdf0053047e700000005
020003000060060e80100cfdf0053047e700000006444636303046 | naa.60060e80100cfdf0053047e700000006
020007000060060e80100cfdf0053047e700000007444636303046 | naa.60060e80100cfdf0053047e700000007
05eb25f16c9ede1b9b76480b06cd2bc314cb398a474a27703481c7e440265aaa64 | t10.NVMe____Dell_BOSS2DN1____________________________0100000DC5435000
020002000060060e80100cfdf0053047e70000029a444636303046 | naa.60060e80100cfdf0053047e70000029a
020002000060060e80100cfdf0053047e70000029a444636303046 | naa.60060e80100cfdf0053047e70000029a
020d000000334637943e950000566972747561 | mpx.vmhba2:C1:T6:L0
(28 rows)

VCDB=# SELECT COUNT(1) FROM VPXV_HOST_DATASTORE WHERE DS_ID = '43019';
count
-------
3
(1 row)

VCDB=# SELECT UUID, CANONICAL_NAME FROM VPX_HOST_SCSI_LUN WHERE HOST_ID IN (SELECT HOST_ID FROM VPXV_HOST_DATASTORE WHERE DS_ID = '43019' ) GROUP BY UUID, CANONICAL_NAME HAVING COUNT(1) = (SELECT COUNT(1) FROM VPXV_HOST_DATASTORE WHERE DS_ID = '43019');
uuid | canonical_name
--------------------------------------------------------+--------------------------------------
020000000060060e80100cfdf0053047e700000000444636303046 | naa.60060e80100cfdf0053047e700000000
020001000060060e80100cfdf0053047e700000001444636303046 | naa.60060e80100cfdf0053047e700000001
020002000060060e80100cfdf0053047e70000029a444636303046 | naa.60060e80100cfdf0053047e70000029a
020004000060060e80100cfdf0053047e700000005444636303046 | naa.60060e80100cfdf0053047e700000005
020007000060060e80100cfdf0053047e700000007444636303046 | naa.60060e80100cfdf0053047e700000007
02000a000060060e80100cfdf0053047e700000032444636303046 | naa.60060e80100cfdf0053047e700000032
02000b000060060e80100cfdf0053047e700000033444636303046 | naa.60060e80100cfdf0053047e700000033
(7 rows)

Расширяемый датастор отсутствует в выборке, так как имеет идентичные идентификаторы только на двух хостах из трёх. Именно это и является причиной пустого вывода в UI при попытке его расширения.

VML

Теперь несколько слов о том, почему же vml отличается и что это вообще такое.

vml — дополнительный идентификатор блочных устройств, генерируемый автоматически на стороне VMware при подключении такого устройства к ESXi-хосту. Он имеет определённую структуру, и поэтому даже на разных хостах будет иметь одинаковое значение. На примере проблемного LUN:

vml. 02 00 0300 00 60060e80100cfdf0053047e700000006 444636303046

02 - для блочных устройств формата naa.

00 - определяет тип устройства. Если посмотреть выводы запросов выше, то у устройства mpx.vmhba2:C1:T6:L0 (Local LSI Enclosure Svc Dev (mpx.vmhba2:C1:T6:L0)) этот идентификатор "0d". Известные типы: 0x00 - DISK

0x01 — TAPE

0x02 — PRINTER

0x03 — PROCESSOR /* HP scanners use this */

0x04 — WORM /* Treated as ROM by our system */

0x05 — ROM 0x05

0x06 — SCANNER

0x07 —- MOD /* Magneto-optical disk - - treated as TYPE_DISK /

0x08 — MEDIUM_CHANGER

0x09 — COMM /* Communications device */

0x0c — RAID

0x0d — ENCLOSURE 0x0d /* Enclosure Services Device */

0x0e — RBC 0x0e

0x7f — NO_LUN

0300 — LUN ID, написанный в шестнадцатеричном формате, указанный «наоборот». Из документации:

Now since we utilize 4 hexadecimal locations of the vml for LUN IDs we have store the higher byte after the lower byte, this is for backward compatibility with ESXi releases that only supported LUNs up to 255

The higher byte (>0 for LUNs >= 256) is stored after the lower byte.

LUN ID represented in vml: 0501 = 0105 hexadecimal

We need to convert the hexadecimal value of 0105 to decimal to get the LUN ID, in this example 0105 = Lun 261 

То есть в этом конкретном случае это 0003 и 000с в шестнадцатеричном формате или 3 и 12 в десятичном.

60060e80100cfdf0053047e700000006 — canonical name (символы после naa.)

444636303046 — уникальный хеш дополнительной информации об устройстве. Будет идентичен на всех хостах, даже в рамках разных VC.

Решение

Предположим, мы попали в такую ситуацию по какой-то наследственной причине. Что же делать для устранения проблемы?

  1. Определим список хостов, для которых требуется переделать маппинг на стороне СХД. Самый быстрый и удобный способ — использовать запрос к БД для вывода соотношения. Например:

select canonical_name, uuid, host_id from vpx_host_scsi_lun order by canonical_name;

В выводе легко найти несоответствие uuid для каждого из LUN и определить, на каком из хостов имеется проблема:

Рис. 10. Поиск информации по блочным устройствам в БД.
Рис. 10. Поиск информации по блочным устройствам в БД.

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

Рисунок 11. Вывод ESXi в MM с миграцией выключенных ВМ
Рисунок 11. Вывод ESXi в MM с миграцией выключенных ВМ

3. Удаляем на стороне СХД маппинг проблемных LUN для хоста(ов), выведенных в MM. В зависимости от выбранного подхода к управлению презентацией LUN'ов на стороне СХД это может быть как манипуляция с отдельными хостами, так и удаление хоста(ов) из группы. Так как речь про удаление мапинга на хосте будет зафиксировано штатное событие Permanent Device Lost (PDL), которое не вызовет проблем с зависанием управляющих агентов, как в ситуациях All Path Down (APD).

4. Настраиваем корректный маппинг для хоста(ов), выведенных в ММ. Снова в зависимости от подхода это может означать одно из трёх:

презентовать LUN каждому отдельному хосту;

добавить хост в существующую Host-группу;

создать новую Host-группу, которой потом презентовать LUN или LUN-группу с указанием корректных LUN ID.

5. Выполняем Action -> Storage -> Rescan Storage для каждого из хостов. В отдельных случаях может потребоваться перезагрузка хоста или HBA Reset для перелогина в FC-фабрику, но это исключение и случается редко.

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

Workaround

У тех, кто сталкивался с подобными проблемами расширения датасторов, может возникнуть вопрос: «Зачем так сложно? А как же вариант с расширением датастора напрямую с хоста?».

И действительно, если посмотреть статью вендора, то один из предложенных вариантов — Increase or expand the datastore directly from the ESXi host. Однако прямо перед этим в статье написано: "NOTE: Before starting, verify LUN presentation is the same on all hosts as this is a common, legitimate cause and should not be worked around." То есть этот Workaround не для описанного в статье сценария. В этом случае может возникнуть риск повреждения таблицы разделов или даже данных. Например, при попытке расширить этот датастор с хоста ESXi-03 в одной из пяти попыток мы получили результат:

Рис. 12. Ошибка при расширении датастора.
Рис. 12. Ошибка при расширении датастора.
Рис. 13. Статус датастора из UI хоста.
Рис. 13. Статус датастора из UI хоста.
Рис. 14. Лог hostd.log
Рис. 14. Лог hostd.log
Рис. 15. Лог vmkernel.log
Рис. 15. Лог vmkernel.log

P.S. Опережая возможные вопросы: естественно, это не ошибка при указании целевого размера датастора. Если выбрать размер целевого раздела меньше исходного, то возникнет другая ошибка, и никакого деструктивного воздействия мы не увидим. 

Итого:

Вот 4 простых пункта, которые мы сформулировали для себя:

  • Если неправильно указать LUN ID при презентации LUN хостам, на хостах этот LUN может получить различные VML-идентификаторы.

  • Различные vml и LUN ID для одного LUN в рамках VC влияют на многие механизмы работы с датасторами: расширение датасторов; автоматическое монтирование датасторов новых хостам; работа с RDM и прочее.

  • Внимательно анализируем и выполняем базовые настройки — так можно исправить ситуацию без влияния на продуктивные нагрузки. 

  • Не стоит искать более простой способ решения проблемы, так как он не обязательно будет более простым.

Алексей Радченко

Директор центра компетенций VMware