目次
- はじめに
- 1. 概要
- 2. VMware Provider の作成
- 3. Cold 移行プランの作成と実行
- 4. Warm 移行プランの作成と実行
- A. トラブルシュート (Tips 集)
- おわりに (予告)
はじめに
#1 準備編では、Migration Toolkit for Virtualization (MTV) を 「実行できる状態」 に整えることを目的に、MTV Operator の導入、VMware 側の CBT (Changed Block Tracking) 有効化、VDDK イメージの用意 (ICR への push)、vCenter / ESXi の FQDN を引くための DNS フォワーディング設定などを整理しました。
本記事(#2 実行編)では、その準備ができている前提で、いよいよ MTV の VMware Provider を使って vSphere → OpenShift Virtualization on IBM ROKS の VM 移行を実行します。
導入のポイントは「いきなり Warm migration を狙わない」ことです。Warm 移行は停止時間を短縮できる一方、前提条件 (CBT / vSphere 側の状態 / 転送経路 / 変換 Pod など) が増えます。そこで本記事では、まず 最小構成の Cold migration を確実に成功 させ、成功パターン (Provider → Mapping → Plan → 実行 → 検証) を作ってから、Warm migration (増分同期 → Cutover) に進みます。
1. 概要
本記事は、Migration Toolkit for Virtualization (MTV) の VMware Provider を利用し、VMware vSphere 上の仮想マシンを OpenShift Virtualization (= KubeVirt) へ移行する 実行手順 をまとめたものです。扱う移行方式は次の2つです。
- Cold migration (停止移行)
- VM を停止してから一括コピー → 変換 → 移行先で起動
- まずはこの方式で、移行経路と変換処理が成立することを確認します
- Warm migration (増分同期 + Cutover)
- 初回同期 (フル) → 増分同期 (CBT) → 最終 Cutover (停止 → 最終同期 → 切替)
- 停止時間を短くする狙いで、実行手順と確認ポイントを整理します
1-1. 前提
以下が満たされている前提で進めます。
- vSphere 側 ← 移行元
- 移行対象 VM の停止/起動ができる権限がある (少なくとも read-only ではない)
- Warm 用に CBT を有効化する予定の VM は、スナップショット無し・要件を満たすことを確認済み
- OpenShift Virtualization (OCPv) 側 ← 移行先
- OCPv on ROKS 側に MTV がインストール済み (
openshift-mtvで Pod が Ready) - Warm をやる場合、移行元 VM で CBT が有効 (スナップショット無し、設定反映済み)
- クラスタからアクセス可能、かつセキュアなレジストリ (例: IBM Container Registry; ICR) に VDDK init イメージを push 済み
- OpenShift から vCenter / ESXi の FQDN が名前解決できる (DNS forwarding 済み)
- ネットワーク的に OpenShift → vCenter / ESXi への疎通が取れる (必要ポートが遮断されていない)
- OCPv on ROKS 側に MTV がインストール済み (
[参考] Qiita > MTV VMware Provider による vSphere から OpenShift Virtualization on IBM ROKS への "Cold/Warm" VM 移行 #1 − 準備編
1-2. 実行の流れ (全体像)
本記事は次の順で進めます。
- VMware Provider を作成 (vCenter 接続確認)
- Network / Storage Mapping を作成
- Migration Plan を作成 (まず Cold)
- Cold 移行を実行 → 移行後 VM を起動して基本動作確認
- 同様の対象で Warm 移行 (初回同期 → 増分同期 → Cutover)
- 失敗しやすいポイントを整理
2. VMware Provider の作成
VMware Provider は、MTV (Migration Toolkit for Virtualization) に「この vSphere 環境を移行元として使う」ことを伝えるための 接続定義 (Source 側のプロバイダー設定) です。
VMware Provider を作ることで MTV は次をできるようになります。
- vCenter に接続してインベントリを取得します。
- クラスタ / ESXi / データストア / ネットワーク / VM 一覧などを MTV が参照できるようになります。
- 移行対象 VM を選べるようになります。
- Plan 作成時に「どの VM を移行するか」を MTV の UI で選択できるのは、 Provider で vSphere を参照しているため。
- 移行実行時のデータ転送の入口になります。
- 実際のディスクコピーや変換の段階では、MTV の内部コンポーネントが vCenter/ESXi へ接続してデータを取り出します。この接続の前提を Provider が持ちます。
2-1. 手順
- OpenShift web console > Migration for Virtualization > Providers に移動し、[Create provider] ボタンをクリックします。
- Providers 一覧に
host(Type:KubeVirt) が 自動作成されていることを確認します。
これは「移行先 (この OpenShift Virtualization クラスタ)」を表す Provider です。
- Providers 一覧に
- [Project] プルダウンから、Provider を作成するプロジェクト (= 名前空間)を選択します。
ここではopenshift-mtvを選択しました (MTV が推奨する既定の名前空間)。 - [Provider details] では、登録可能な Provider の一覧が表示されます。この中から「VMware」を選択します。
- デフォルトの名前空間 (
openshift-*など) を一覧に表示するために、必要に応じて [Show default projects] を ON にします。
- デフォルトの名前空間 (
- 選択した VMware Provider の詳細設定の入力画面に遷移します。ここで MTV から VSphere への接続などに必要な情報を入力します。
- Provider details
- Provider resource name:
<任意の名前> - Endpoint type:
vCenter - URL:
https://vcsosv-vc.corp.example.local/sdk(例) - VDDK init image:
us.icr.io/hmishima-ns/vddk:9.0.1-amd64(例)- MTV が移行実行時 (conversion pod の init コンテナ) に pull して利用する VDDK イメージを指定します。IBM Container Registry (ICR) を使う場合は
us.icr.io/<namespace>/vddk:<tag>のようになります。 -
Use VMware Virtual Disk Development Kit (VDDK) async IO Optimization.オプションは有効にしておくと無難です。筆者の環境では有効にした方が Warm migration にかかる時間が少し短縮されました。どの程度短縮されるかは環境によると考えられますが、少なくとも当該オプションを有効化してパフォーマンスが劣化するなどのネガティブな効果は確認できませんでした。
- MTV が移行実行時 (conversion pod の init コンテナ) に pull して利用する VDDK イメージを指定します。IBM Container Registry (ICR) を使う場合は
- Provider resource name:
- Provider credentials
- Username:
<vCenter Admin のユーザー名> - Password:
<vCenter Admin のパスワード> - Skip certificate validation:
True- 本番環境ではセキュリティポリシーに従って
Falseにするか否かを判断してください
- 本番環境ではセキュリティポリシーに従って
- Username:
- Provider details
- Provider の健全性を確認します。
- Provider のステータスが Ready になっていること
- 作成された VMware Provider の [Virtual machines] タブから、接続先の vSphere に存在する仮想マシンが見えていること (vSphere のインベントリ取得ができていること)
補足:ESXi ホストの shortname と DNS 解決
MTV の VMware → OpenShift Virtualization の移行では、Provider 登録自体は vCenter に接続できれば成立することがあります。しかし、移行実行中の v2v プロセス (virt-v2v / nbdkit + vddk など) が ESXi ホストへ接続する段階で、ESXi のホスト名が DNS で解決できずに失敗するケースがあります。エラー例として、Host address lookup ... failed: Name or service not known (Network File Copy (NFC) 接続確立時の解決失敗) があります。
[参考] Red Hat Customer Portal > Unable to migrate VM from VMware to Openshift Virtualization due to DNS issue
もし Provider の [Hosts] タブで、ESXi が 短いホスト名 (esxi のような shortname) のみで表示されていたり、FQDN になっていない場合は、ESXi 側で FQDN を設定し、DNS で解決できる状態にすることを検討してください。
このため、Provider 登録後に Providers > Provider Details > Hosts を確認し、ESXi が FQDN で認識されているか、少なくとも MTV 実行環境 (Pod) からそのホスト名が名前解決できる状態になっているかを事前に確認することを推奨します。もし shortname しか表示されない場合は、ESXi 側で FQDN を設定する、または DNS/hosts で shortname の解決を補うなどの対処を検討してください。
[参考] How to change the hostname of an ESXi host via DCUI or CLI
-
ESXi 8.x で CLI を利用した設定例
# 現在の FQDN 確認 hostname -f # FQDN を設定(例) esxcli system hostname set --fqdn=<ESXI_FQDN> # 反映確認 hostname -f設定後、MTV の Provider 画面 (Providers > Provider Details > Hosts) を再表示し、ESXi ホストが FQDN で認識されていることを確認します。
3. Cold 移行プランの作成と実行
ここからは Cold migration の具体手順に入ります。
3-1. Plan を作成 (Cold)
- OpenShift web console > Migration for Virtualization > MIgration plans から、[Create plan] を選択します。
- Create migration plan ページに遷移します。Basic setup > General から基本設定を入力します。
- Plan name:移行プランに任意の名前を付けます。
- Plan project:この移行プランを作成する名前空間を指定します。
- Source provider:先ほど作成した VMware Providerを指定します。
- Target provider:OpenShift Virtualization を意味する
hostcluster (Provider) を指定します。 - Target project:vSphere から移行してきた仮想マシンを OpenShift Virtualization のどの名前空間に配置するかを指定します。
- 移行対象の仮想マシンを選択します。
- 移行元である vSphere 側の仮想マシンが起動中の場合、Cold migration 実行時に MTV の forklift-controller によって停止されます。
- [Use new network map] からNetwork mapping を作成します。
- Source network:vSphere 上の仮想マシンに紐づいている Network アダプターを指定します。
- Target network:Default network を指定します。
- Network map name:任意の名前を付けます。大文字やアンダースコア
_などの文字は使えません。
Migration Plan 作成時の Network mapping で選ぶ “Default network” は、基本的に移行先 (OpenShift Virtualization 側) の 既定ネットワーク (primary network) です。“Default network” は、基本的に Pod network (CNI/クラスタ既定ネットワーク) を指します。
OpenShift Virtualization では、「仮想マシンは既定で単一の内部 Pod network に接続される」と Red Hat のドキュメントにも明記されています。
- [Use new storage map] から Storage mapping を作成します。
- Migration type として
Coldを選択します。
- Other settings (optional) で [Preserved Static IPs] を無効にします。
- 2026年2月現在の ROKS の制約で本機能は期待通りに動作しません。移行後に OS側 で IP アドレスを調整する必要があります。近い将来、この制約は解消される予定ですが、現時点で公開可能な公式情報はありません。
- [Preserved Static IPs] を有効にして移行プランを作成すると下記の警告が表示されます。
Warning alert: The plan migration might not work as expected
Your migration plan preserves the static IPs of VMs and uses Pod Networking target network mapping. This combination isn't supported, because VM IPs aren't preserved in Pod Networking migrations.
- Hooks は作りませんでした。
- 移行プランの設定内容を確認して、[Create plan] ボタンをクリックします。
- 移行プランが作成され、ステータスが "Ready to migtation" になったことを確認します。
以上で、Cold Plan の作成は完了です。
3-2. Plan を実行 (Cold)
- 先ほど作成した Cold Plan の画面から [Start] ボタンをクリックします。
- Cold migration が開始されます。
- 移行が成功し、Plan のステータスが "Complete" になっていることを確認します。
- 筆者の環境では3台同時に移行する Plan を作成していますが、3台すべての移行が完了するまでに6分程度かかりました。
- 例えば下記の観点で、実際に移行ができているか確認します。
- 移行先の名前空間に仮想マシンが作られていること
- VM が起動できること (ログインは後回しでもOK)
- ディスクが正しくアタッチされている
- NIC が期待するネットワークに接続されている
- 期待する StorageClass/PVC になっている
以上で、Cold migration は完了です。
4. Warm 移行プランの作成と実行
作成方法は Cold の場合とほとんど同じですが、いくつかの留意事項があります。
-
VDDK の利用準備を確認します。詳細は #1 準備編 の記事を参照ください。
-
spec.vddkInitImageに ICR の VDDK イメージを設定済み# hiroaki.mishima @ HiroakinoMacBook-Pro in ~ [17:30:02] $ PROVIDER=vcsosv-vc-test; oc get provider -n openshift-mtv "$PROVIDER" -o jsonpath='{.spec.settings.vddkInitImage}{"\n"}' us.icr.io/hmishima-ns/vddk:8.0.3-amd64-v3 - ROKS から ICR を pull できる状態
-
-
移行対象 (vSphere 側) の仮想マシンの CBT が正しく有効化されていることを確認します。詳細は #1 準備編 の記事を参照ください。
- スナップショット無し
ctkEnabled=TRUEscsiX:Y.ctkEnabled=TRUE
-
移行対象 (vSphere 側) の仮想マシンに VMware Tools がインストールされているか確認します。インストールされていない場合、移行プロセスの Initialize フェーズで下記のエラーが発生し、移行に失敗します。
Initialize migration.
Danger alert: Error details
ServerFaultCode: Cannot complete operation because VMware Tools is not running in this virtual machine.
4-1. Plan を作成 (Warm)
- OpenShift web console > Migration for Virtualization > MIgration plans から、[Create plan] を選択します。
- Create migration plan ページに遷移します。Basic setup > General から基本設定を入力します。
- Plan name:移行プランに任意の名前を付けます。
- Plan project:この移行プランを作成する名前空間を指定します。
- Source provider:VDDK init image が有効な Provider を選択する必要があります。
- Target provider:Cold と同様に
hostを指定します。 - Target project:vSphere から移行してきた仮想マシンを OpenShift Virtualization のどの名前空間に配置するかを指定します。
- 移行対象の仮想マシンを選択します。
- Network/Storage map:Cold と同様です。
- Migration type:
Warmを選択します。
- Other settings (optional) の [Preserved Static IPs] は、Cold と同様に無効にします。
- Hooks:Cold と同様に、今回は作りませんでした。
- 移行プランの設定内容を確認して、[Create plan] ボタンをクリックします。

- 移行プランが作成され、ステータスが "Ready to migtation" になったことを確認します。
以上で、Warm Plan の作成は完了です。
4-2. Plan を実行 (Warm)
- 先ほど作成した Warm Plan の画面から [Start] ボタンをクリックします。
- Warm migration が開始されます。
- Initialize → PreflightInspection → DiskTransfer フェーズまで完了した後も、仮想マシンは vSphere 側で稼働を続けており、OCPv on ROKS 側ではまだインスタンス化されていません。この時点で、プランの状態は "Paused" と表示されます。
- プランの [Virtual machines] タブから、プラン内の仮想マシンの状態を確認します。DiskTransfer フェーズまですべて完了していることが確認できます
- Plan の画面から [Schedule cutover] ボタンをクリックして、Cutover をスケジュールします。すぐに実行することも、将来の日時にスケジュールすることもできます。
- Cutover を実行すると、vSphere 側の移行対象の仮想マシンはシャットダウンされ、スナップショットも削除されました。
- 続けて、もう1つスナップショットが作成され、その後削除されることがあります。これは、おそらく CBT によってシグナルされた残りのデータがレプリケートされる処理を表しているのだろうと推測されます。
Warm plan を "Paused" のまま Cutover 待ちにすると、vSphere 側に CBT の増分同期によってスナップショットが作成され続けます。筆者の経験則ですが、vSphere 側のスナップショットが多くなると、移行の動作が不安定になり、Cutover フェーズで失敗することがありました。
また、vSphere の観点でも、スナップショットを大量に抱え続けることは推奨されないため、Cutover 待ちで長期間放置することは避けた方が無難です。
- Cutover が開始され、Plan が進み始めたことを確認します。
- Cutover が完了し、Plan の状態が "Complete" になったことを確認します。
- Plan の [Virtual machines] タブから、Plan 内の仮想マシンの状態を確認します。すべて "Succeeded" になっておりことを確認します。
- OpenShift Virtualization 側で移行された仮想マシンを確認します。今回の Warm plan で移行した仮想マシンが3台すべて
ocpv-lab名前空間に存在することが確認できました。
以上で Warm migration は完了です。
A. トラブルシュート (Tips 集)
筆者が検証中に遭遇した事象や、エラー解消のために試行錯誤した内容の一部をご紹介します。
A-1. まず見るべき全体像
MTV の VMware Provider 移行は、だいたいこの流れで障害点が分かれます。
- Plan/Migration (forklift-controller):Plan が進んでいるか / どのフェーズで止まったか
- DiskTransfer (CDI importer / nbdkit + VDDK):importer pod のエラーが本体のことが多い
- DV/PVC/prime (CDI / Populator):PVC/DV/Secret 不整合で詰まりやすい
- vSphere 側 (Snapshot/CBT/VDDK互換):Warm で遭遇しやすい
A-1-1. 用語の意味
- forklift-controller
- MTV の中核となる “コントローラ (制御) コンポーネント” です。
- OpenShift 上で動く Kubernetes コントローラとして、MTV が使う各種 CR (Provider / Plan / Migration / NetworkMap / StorageMap など) を監視・更新し、移行ワークフロー全体 (検査 → ディスク転送 → Warm のスナップショット制御 → Cutover など) をオーケストレーションします。
- CDI importer
- KubeVirt / OpenShift Virtualization でディスクイメージを PVC に取り込む (Import/Clone/Upload する) ための “実行役 Pod (importer pod)” です。
- MTV (Forklift)で VMware Provider を使うと、最終的に DataVolume (DV) が作られ、DV の spec.source (今回の検証では
vddk) に従って CDI が importer pod を起動し、実データ転送を行います。 - [参考] GitHub > KubeVirt CDI (Containerized Data Importer) 公式リポジトリ
- DataVolume (DV)
- PVC に関連付く import/clone/upload をオーケストレーションする、CDI が提供するカスタムリソース (CR) です。
- DV は KubeVirt と統合されており、PVC 側の準備ができる前に VM が起動してしまうことを防ぎます。
- 筆者の検証にて Warm plan (例: warm-test) を実行したところ、Plan 内の仮想マシン毎にDataVolume (例:
warm-test-vm-1433-xxxx)が生成されました。これはMTV/Forklift が移行の DiskTransfer (CopyDisks) フェーズのために作る “ディスク取り込み用の DV” と考えられます。 - [参考] Red Hat Documentation > Chapter 11. Migrating virtual machine storage
- nbdkit
- NBD (Network Block Device) サーバを実装するためのツールで、プラグイン方式で「いろいろなバックエンド (ファイル、クラウド、ストレージ、VMware など)」を “ブロックデバイス” として提供します。
- MTV の VMware 移行 (特に VDDK を使う系) では、CDI importer (importer Pod) が vSphere/ESXi からディスクを読む際に、内部で nbdkit を起動して「vSphere 上の VMDK (スナップショット含む) を NBD 経由で読める形にする」という構成になっています:
- importer コンテナが nbdkit を起動
- nbdkit は vddk プラグイン (nbdkit-vddk-plugin) を使い、VMware VDDVMware の VDDK (VixDiskLib / libvixDiskLib) 経由で VMDK を開く
- importer (またはその内部処理) が、その NBD ソケットからディスク内容を読み取り、PVC へ書き込む
- [参考] nbdkit - network block device (NBD) server
- prime
-
prime-<UUID>は、CDI (Containerized Data Importer) が Populator (Volume Populator / dataSourceRef )方式でインポートやクローンを実行する際に内部的に作る 中間 (作業用) PVC です。 -
Populator 方式 (
cdi.kubevirt.io/storage.usePopulator: "true"が付く DV など) では、最終的に欲しい PVC (例:warm-test-vm-1433-xxxx) に直接書き込むのではなく、- prime PVC (
prime-...) を先に作る (実データの受け皿/importer pod が掴むブロックデバイス) - importer pod (
importer-prime-...) が prime PVC にデータを書き込む - 状態が整ったら、最終 PVC (DV の
status.claimName側) へ反映する
という “中継地点” を作って処理を進めます。
- prime PVC (
-
正常系では、移行が進めば prime PVC は勝手に消える (または後処理で片付く) 想定ですが、異常系では DV/PVC を消しても prime PVC が残ることがあります。筆者の検証では、Warm plan を削除しても残骸として残ったケースが確認されました。
-
[参考] GitHub > Only create target PVC in other namespaces using upload populator #3462
-
A-2. まず取るべき ID
A-2-1. Plan の UID
移行 Plan の UID を取得します。
PLAN=warm-test # Planの名前
oc get plan -n openshift-mtv "$PLAN" -o jsonpath='{.metadata.uid}{"\n"}'
# 出力例
28f506da-aabd-44fd-9096-b0c15290711a
A-2-2. Migration の UID
- Migration Resource (
kind: Migration) の名前 (.metadata.name) を取得します。
# hiroaki.mishima @ HiroakinoMacBook-Pro in ~ [10:28:13]
$ PLAN=warm-test
{ oc get migration -n openshift-mtv | head -n 1; oc get migration -n openshift-mtv | grep -E "^${PLAN}-"; }
NAME READY RUNNING SUCCEEDED FAILED AGE
warm-test-5pgnx True True 21h
warm-test-8856q True True 19h
warm-test-qc6fd True True 22h
warm-test-t88t9 True True 20h
- Migration Resource (例:
warm-test-t88t9) の UID を取得します。
MIG=warm-test-t88t9 # Migration Resourceの名前
oc get migration -n openshift-mtv "$MIG" -o jsonpath='{.metadata.uid}{"\n"}'
# 出力例
d4e9333b-2c6f-4d9e-a60c-d8bffc37efd9
A-2-3. CDI Pod
- 移行先の名前空間 (例:
ocpv-lab) で CDI (containerized-data-importer) の Pod を引きます。
NS=ocpv-lab
oc get pod -n "$NS" -l app=containerized-data-importer -o wide
# 出力例
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
importer-prime-3fe07917-4237-4c99-b813-b80830ffb7f8-checkpoint-snapshot-1507 0/1 CrashLoopBackOff 1 (15s ago) 25s 172.■■.■■.■■ kube-d4okn6ad02tla11413g0-acsosvclust-workerp-0000033f <none> <none>
importer-prime-995eb110-d646-433b-908c-2de254cb9b3a-checkpoint-snapshot-1509 0/1 CrashLoopBackOff 1 (15s ago) 26s 172.■■.■■.■■ kube-d4okn6ad02tla11413g0-acsosvclust-workerp-0000033f <none> <none>
importer-prime-ef2ed60b-a691-4d70-a7f6-eeaef05ea71d-checkpoint-snapshot-1508 1/1 Running 2 (14s ago) 26s 172.■■.■■.■■ kube-d4okn6ad02tla11413g0-acsosvclust-workerp-0000033f <none> <none>
- どの DV/PVC に紐づく importer なのか確認する場合は下記のコマンドを利用します。
# importer pod -> Controlled By (PVC prime-xxxx) を見る
POD=<importer-pod>
oc describe pod -n "$NS" "$POD" | egrep -n 'Name:|Controlled By:|IMPORTER_UUID|IMPORTER_CURRENT_CHECKPOINT|IMPORTER_BACKING_FILE|IMPORTER_ACCESS_KEY_ID|IMPORTER_SECRET_KEY'
# 出力例 (抜粋)
Name: importer-prime-3fe07917-4237-4c99-b813-b80830ffb7f8-checkpoint-snapshot-1507
Controlled By: PersistentVolumeClaim/prime-3fe07917-4237-4c99-b813-b80830ffb7f8
IMPORTER_UUID: 421dc7ff-dc30-7cdd-fef5-ca40c11bd2c3
IMPORTER_BACKING_FILE: [datastore-km000] win2022-acs/win2022-acs.vmdk
IMPORTER_CURRENT_CHECKPOINT: snapshot-1507
IMPORTER_ACCESS_KEY_ID: <set to the key 'accessKeyId' in secret 'warm-test-vm-1433-8wx8s'> Optional: false
IMPORTER_SECRET_KEY: <set to the key 'secretKey' in secret 'warm-test-vm-1433-8wx8s'> Optional: false
A-3. Plan / Migration の状態確認
A-3-1. Plan の準備状況と履歴
- Plan が
READY = Trueであることを確認します。
oc get plan -n openshift-mtv warm-test -o wide
# 出力例
NAME READY EXECUTING SUCCEEDED FAILED AGE
warm-test True True 22h
- 直近の Migration 履歴を確認します。
oc get plan -n openshift-mtv warm-test -o yaml | egrep -n 'status:|conditions:|Ready|migration:|phase:|error:|message:' -n
# 出力例 (異常系)
56:status:
57: conditions:
59: lastTransitionTime: "2026-02-25T03:11:24Z"
60: message: The migration plan is ready.
61: status: "True"
62: type: Ready
69: migration:
72: - conditions:
75: lastTransitionTime: "2026-02-25T03:17:44Z"
77: status: "True"
92: migration:
94: name: warm-test-qc6fd
96: uid: 5740a869-1d0f-4037-9f6c-e41edb18b3e2
111: - conditions:
114: lastTransitionTime: "2026-02-25T04:00:53Z"
116: status: "True"
129: migration:
131: name: warm-test-5pgnx
133: uid: 1cd65046-a6fc-46b1-9df8-00f95264298c
153: conditions:
156: lastTransitionTime: "2026-02-25T03:59:55Z"
157: message: The VM migration has FAILED.
160: error:
161: phase: CopyDisks
# 出力例 (正常系)
56:status:
57: conditions:
60: message: The migration plan is ready.
61: status: "True"
62: type: Ready
66: message: The plan execution has SUCCEEDED.
67: status: "True"
69: migration:
...
189: - conditions:
193: message: The plan execution has SUCCEEDED.
194: status: "True"
207: migration:
...
457: conditions:
461: message: The VM migration has SUCCEEDED.
462: status: "True"
468: phase: Completed
473: phase: Completed
483: phase: Completed
494: phase: Completed
504: phase: Completed
516: phase: Completed
527: phase: Completed
536: phase: Completed
544: phase: Completed
A-3-2. Migration のフェーズ
どこでプランが止まっているのか確認します。
MIG=warm-test-t88t9
oc get migration -n openshift-mtv "$MIG" -o yaml | egrep -n 'phase:|Paused|paused|reason:|message:|conditions:' | head -n 260
# 出力例 (抜粋)
23: conditions:
26: message: The migration is ready.
32: message: The migration has FAILED.
...
247: conditions:
251: message: The VM migration has FAILED.
255: phase: CopyDisks
262: phase: Completed
267: phase: Completed
277: phase: Completed
287: phase: Running
292: phase: Running
301: phase: Running
306: phase: Running
310: reason: 'Pod is running; '
328: phase: Pending
334: phase: Pending
- ポイント
- phase: CopyDisks で止まる場合、DV/PVC/importer (CDI) が問題になっていることがあります。
- Warmの Paused は migration YAML 全体を
grepした断片だけだと見落とすことがあるため、UI と併せて確認 (またはoc get migration -o json | jq ...) すると良いです。
A-4. ログを見る場所
A-4-1. forklift-controller
Plan/Migration の司令塔であり、トラブル時にまず確認します。
oc logs -n openshift-mtv deploy/forklift-controller --since=2h | tail -n 200
# 出力例 (抜粋)
{"level":"info","ts":"2026-02-25 05:01:26.911","logger":"plan|k5mwl","msg":"Reconcile started.","plan":{"name":"warm-test","namespace":"openshift-mtv"}}
{"level":"info","ts":"2026-02-25 05:01:27.664","logger":"plan|k5mwl","msg":"validate VDDK job completed","plan":{"name":"warm-test","namespace":"openshift-mtv"},"image":"us.icr.io/hmishima-ns/vddk:9.0.1-amd64"}
{"level":"info","ts":"2026-02-25 05:01:27.715","logger":"plan|k5mwl","msg":"Migration ignored.","plan":{"name":"warm-test","namespace":"openshift-mtv"},"migration":"openshift-mtv/warm-test-qc6fd"}
{"level":"info","ts":"2026-02-25 05:01:27.715","logger":"plan|k5mwl","msg":"Migration ignored.","plan":{"name":"warm-test","namespace":"openshift-mtv"},"migration":"openshift-mtv/warm-test-5pgnx"}
{"level":"info","ts":"2026-02-25 05:01:27.715","logger":"plan|k5mwl","msg":"No pending migrations found.","plan":{"name":"warm-test","namespace":"openshift-mtv"}}
{"level":"info","ts":"2026-02-25 05:01:27.772","logger":"plan|k5mwl","msg":"Reconcile ended.","plan":{"name":"warm-test","namespace":"openshift-mtv"},"reQ":3}
# grep 例 (必要に応じて)
oc logs -n openshift-mtv deploy/forklift-controller --since=2h | \
grep -iE 'warm-test|snapshot|checkpoint|delete|cleanup|secret|importFailed|nbdkit|vddk|paused|cutover' | tail -n 200
- ポイント
- “snapshot / active snapshot deleted / validate VDDK job” などを追うことができます。
- ただし DV/importer の詳細エラーは DV 側に出ることが多いです。
A-4-2. DV (DataVolume) のイベントと Status メッセージ
- 移行先の名前空間 (例:
ocpv-lab) の DV のイベントを探索します。
NS=ocpv-lab
oc get dv -n "$NS"
# 出力例 (抜粋)
NAME PHASE PROGRESS RESTARTS AGE
warm-test-vm-1433-7pnbm ImportInProgress ■■.■% 19h
DV=warm-test-vm-1433-7pnbm
oc describe dv -n "$NS" "$DV" | sed -n '1,260p'
# 出力例 (抜粋; secret not found)
Status:
Conditions:
...
Last Heartbeat Time: 2026-02-25T04:01:54Z
Last Transition Time: 2026-02-25T03:56:32Z
Message: secret "warm-test-vm-1433-7pnbm" not found
Reason: CreateContainerConfigError
Status: False
Type: Running
Phase: ImportInProgress
Restart Count: 12
Events:
...
Warning CreateContainerConfigError 38m datavolume-import-controller secret "warm-test-vm-1433-7pnbm" not found
# 出力例 (抜粋; timed out waiting for nbdkit to be ready)
Status:
Conditions:
...
Message: Unable to connect to vddk data source: timed out waiting for nbdkit to be ready
Reason: Error
Status: False
Type: Running
Phase: ImportInProgress
Restart Count: 4
Events:
Normal ImportScheduled 3m22s datavolume-import-controller Import into warm-test-vm-1433-7zff5 scheduled
Normal ImportInProgress 3m13s datavolume-import-controller Import into warm-test-vm-1433-7zff5 in progress
Warning Error 27s datavolume-import-controller Unable to connect to vddk data source: timed out waiting for nbdkit to be ready
- 上記の出力例では、
status.conditions[].messageに核心(secret not found/timed out waiting for nbdkit/no snapshots)が出ています。
A-4-3. importer pod (CDI importer / nbdkit / VDDK)
- importer pod を探索します。
NS=ocpv-lab
oc get pod -n "$NS" -l app=containerized-data-importer
# 出力例
NAME READY STATUS RESTARTS AGE
importer-prime-941b9435-c3ab-4ace-8378-ba8f84037c04-checkpoint-snapshot-1512 1/1 Running 0 22s
importer-prime-c20bfdac-836c-4a32-b62c-18d967ab49bc-checkpoint-snapshot-1511 1/1 Running 1 33s
- importer pod のログを確認します。
$ POD=<importer-pod> # importer pod の名前 (NAME)
oc logs -n "$NS" "$POD" -c importer --tail=300
# 出力例 (抜粋; no snapshots for this VM)
I0225 04:59:13.606351 1 vddk-datasource_amd64.go:831] Creating VDDK data source: backingFile [[datastore-km000] win2022-acs/win2022-acs.vmdk], currentCheckpoint [snapshot-1507], previousCheckpoint [], finalCheckpoint [false]
I0225 04:59:13.672864 1 vddk-datasource_amd64.go:298] Current VM power state: poweredOff
E0225 04:59:13.680970 1 vddk-datasource_amd64.go:858] Could not find current snapshot snapshot-1507: no snapshots for this VM
E0225 04:59:13.681063 1 importer.go:347] no snapshots for this VM
$ oc logs -n "$NS" "$POD" -c importer --previous --tail=300
# 出力例 (抜粋; libvixDiskLib.so.8 not found → nbdkit ready timeout)
... nbdkit: debug: vddk: get_ready
... nbdkit: error: /opt/vmware-vix-disklib-distrib/lib64/libvixDiskLib.so.8: cannot open shared object file: No such file or directory
...
E0225 05:15:36.807195 1 nbdkit.go:336] Failed waiting for nbdkit to start up: timed out waiting for nbdkit to be ready
E0225 05:15:36.807448 1 importer.go:347] timed out waiting for nbdkit to be ready
$ oc describe pod -n "$NS" "$POD" | sed -n '1,260p'
# 出力例 (重要箇所の抜粋)
State: Terminated
Reason: Error
Message: Unable to connect to vddk data source: timed out waiting for nbdkit to be ready
...
Environment:
IMPORTER_UUID: 421dc7ff-dc30-7cdd-fef5-ca40c11bd2c3
IMPORTER_BACKING_FILE: [datastore-km000] win2022-acs/win2022-acs.vmdk
IMPORTER_CURRENT_CHECKPOINT: snapshot-1512
- ポイント
-
--previousは CrashLoop 解析で有効です。 - libvixDiskLib.so.X 系は VDDK のメジャーバージョン不整合で典型的に起きることがあります。筆者の検証では 9.0.1 → 8.0.3 で解消しました。
-
A-4-4. 直近イベント
Secret/PVC/DV 系のイベントを時系列で確認します。
oc get events -n "$NS" --sort-by=.lastTimestamp | tail -n 120
# 出力例 (抜粋; secret not found)
LAST SEEN TYPE REASON OBJECT MESSAGE
...
34m Warning CreateContainerConfigError datavolume/warm-test-vm-1435-2rjjs secret "warm-test-vm-1435-gx9r4" not found
...
- DV/Pod/PVC 周りの直近イベントを確認します。下記の例では
secret not foundを狙い撃ちしています。
oc get events -n "$NS" --sort-by=.lastTimestamp | grep -iE 'secret "warm-test-vm-' | tail -n 80
# 出力例
42s Normal CreatedPVCPrimeSuccessfully persistentvolumeclaim/warm-test-vm-1433-7zff5 PVC Prime created successfully
29s Normal ImportScheduled datavolume/warm-test-vm-1433-7zff5 Import into warm-test-vm-1433-7zff5 scheduled
20s Normal ImportInProgress datavolume/warm-test-vm-1433-7zff5 Import into warm-test-vm-1433-7zff5 in progress
5s Warning Error datavolume/warm-test-vm-1433-7zff5 Unable to connect to vddk data source: timed out waiting for nbdkit to be ready
- ポイント
- DV/PVC/importer の“時系列”が一番見えるのが events
-
Prime created successfullyが出たら Populator 経由 (prime-xxxx) が生成された合図
A-5. よくある症状別 Tips
筆者が遭遇した事象をベースに記載します。
A-5-1. secret "xxx" not found
DV の secretRef が欠落していると発生します。
見る場所
-
oc describe dvのSecret Ref:とstatus.message -
eventsのCreateContainerConfigError
原因パターン
- 過去の失敗 migration の DV が残り続け、参照する Secret が既に消えている
- “現行の Migration 以外” の残骸が混ざっている
- 特に移行プラン (例:
warm-test) を何回も Restart したり、同名の Plan の再作成した場合
- 特に移行プラン (例:
確認
NS=ocpv-lab
# DV -> secretRef 一覧
oc get dv -n "$NS" -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.source.vddk.secretRef}{"\t"}{.metadata.labels.migration}{"\n"}{end}' | sort
# secretRef 実在チェック (MISSING を出す)
for s in $(oc get dv -n "$NS" -o jsonpath='{range .items[*]}{.spec.source.vddk.secretRef}{"\n"}{end}' | sort -u); do
oc get secret -n "$NS" "$s" -o name >/dev/null 2>&1 || echo "MISSING: $s"
done
対処
- “現行の Migration UID (
MIG_UID) 以外” の DV/PVC/prime を掃除した後、再施行します。(後述の"掃除"手順)
A-5-2. no snapshots for this VM
Warm 実行時に vSphere 側で適切なスナップショットが見つからない場合に発生します。
見る場所
- importer log:
Could not find current snapshot snapshot-XXXX: no snapshots for this VM - Migration YAML:DiskTransfer の reason/message
原因候補
- Warm のスナップショット作成が vSphere 側で失敗/作成されていない
- CBT 周りの前提不備 (スナップショット残骸、CBT反映不完全など)
- 参照している snapshot ID が古い/不整合 (過去残骸 DV 参照)
対処の考え方
- まずは残骸 (旧 DV/PVC/prime) を掃除 → 再実行
- vSphere 側で対象 VM の snapshot 状態と CBT を再確認
- 可能なら “Paused を長時間放置しない” (snapshot が増えやすい)
A-5-3. timed out waiting for nbdkit to be ready
見る場所
- DV status.message
- importer log 末尾の stack trace (
waitForNbd)
原因候補
- nbdkit が起動しているが、VDDK ライブラリ不整合で ready にならない
- 典型例:
libvixDiskLib.so.8: cannot open shared object file
→ VDDK バージョンとプラグインの期待がズレている
対処
- Provider の
spec.settings.vddkInitImageを適切な VDDK イメージに変更- VDDK と vSphere のメジャーバージョンを一致させる
- importer log に
libvixDiskLib.so.Xのエラーが出ていないか確認
A-6. “掃除”手順
DV/PVC/prime をすべて削除します。Plan の再実行前に一度クリーンにする方法が、最も再現性が高いトラブルシュートです。
A-6-1. 対象の Migration UID を環境変数で指定
MIG=warm-test-t88t9
MIG_UID=$(oc get migration -n openshift-mtv "$MIG" -o jsonpath='{.metadata.uid}')
echo "$MIG_UID"
A-6-2. importer pod を停止
再生成されますが、“掃除前” の混乱を減らす目的で実施します。
NS=ocpv-lab
oc delete pod -n "$NS" -l app=containerized-data-importer --ignore-not-found
A-6-3. 対象 MIG_UID に紐づく DV/PVC を削除
NS=ocpv-lab
# DV削除
oc get dv -n "$NS" -o json | jq -r --arg m "$MIG_UID" '
.items[] | select((.metadata.name|startswith("warm-test-vm-")) and (.metadata.labels.migration==$m)) | .metadata.name
' | xargs -r -n1 oc delete dv -n "$NS" --ignore-not-found
# PVC削除
oc get pvc -n "$NS" -o json | jq -r --arg m "$MIG_UID" '
.items[] | select((.metadata.name|startswith("warm-test-vm-")) and (.metadata.labels.migration==$m)) | .metadata.name
' | xargs -r -n1 oc delete pvc -n "$NS" --ignore-not-found
A-6-4. prime-* PVC を削除
ラベルが無かったり、追えないケースがあるので prefix で掃除します。
oc get pvc -n "$NS" -o name | grep '^persistentvolumeclaim/prime-' | \
xargs -r -n1 oc delete -n "$NS" --ignore-not-found
A-6-5. 残骸確認
oc get dv,pvc,pod -n "$NS" | egrep 'warm-test-vm-|importer-prime-|prime-' || true
A-7. Provider 側の “VDDK init image 設定確認” Tips
Provider CR は spec.settings.vddkInitImage に入っています (spec.vddkInitImage ではない点がハマりどころ)。
PROVIDER=vcsosv-vc-test # 利用した VMware Provider の名前
oc get provider -n openshift-mtv "$PROVIDER" -o jsonpath='{.spec.settings.vddkInitImage}{"\n"}'
oc get provider -n openshift-mtv "$PROVIDER" -o yaml | sed -n '1,120p'
A-8. MTV から ICR を pull できるか確認
一番確実なのは 実際に Pod を起動して pull させる方法です。
A-8-1. SA (ServiceAccount) / pull secret を確認
oc get sa -n openshift-mtv default -o yaml | egrep -n 'imagePullSecrets|pullSecrets' -n
oc get secret -n openshift-mtv | egrep -i 'dockercfg|dockerconfigjson|pull'
A-8-2. ICR の VDDK イメージを「その場で pull」
一時的な Pod を起動し、確認後に削除します。
NS=openshift-mtv
IMAGE=us.icr.io/hmishima-ns/vddk:8.0.3-amd64-v3
oc run icr-pull-test -n "$NS" --restart=Never --image="$IMAGE" --command -- /bin/sh -c 'echo OK; sleep 5'
oc get pod -n "$NS" icr-pull-test -o wide
oc describe pod -n "$NS" icr-pull-test | sed -n '1,160p'
oc logs -n "$NS" icr-pull-test || true
# 掃除
oc delete pod -n "$NS" icr-pull-test --ignore-not-found
- 失敗する場合は
describe podの Events にBack-off pulling image/Unauthorized/x509等が出るので、それで切り分けします。
おわりに (予告)
本記事では、MTV の VMware Provider を使って、vSphere から OpenShift Virtualization on IBM ROKS へ VM を移行する 実行手順 を、Cold → Warm の順に整理しました。特に Warm では、初回同期後に Paused (Cutover 待ち) になる挙動や、Cutover 実行時に vSphere 側でスナップショットが作成・削除される流れなど、「実際に動かして初めて腹落ちするポイント」を確認できたと思います。
一方で、Cold migration は VMware Provider ではなく OVA Provider を使う パターンもあります。VMware Provider が vCenter / ESXi に直接接続してインベントリを扱うのに対し、OVA Provider は OVF/OVA をいったん受けてから取り込む 形になります。そのため、事前に準備すべきもの(配置場所や取り込み経路など)や、運用上のハマりどころが少し変わってきます。
次回の記事『MTV OVA Provider による vSphere から OpenShift Virtualization on IBM ROKS への "Cold" VM 移行 #3 − 準備&実行編』では、VMware Provider は動いたけど、OVA Provider は別の地雷が多い…」という状態にならないように、準備から実行までを一気通貫で再現できる構成になるように意識して書いています。


