iSCSIストレージ上のvSphere仮想マシンのSANバックアップを仮想マシン上で実験する


vSphere仮想環境でFC-SANやiSCSI-SANの共有ディスク上に作ったVMFSデータストアがあり、そこにあるvSphere仮想マシンのバックアップを行う場合の手法はいくつかある。

・SAN
・HotAdd
・NBD/NBDSSL

ここらを解説してる資料があるかなーと探してみると

vSphere 5時代の「Virtual Disk Transport Methods」だと絵付きで解説されてるんですが、現状のVMware公式記述はVMware Virtual Disk Development Kit Programming Guide 8.0の「Virtual Disk Transport Methods」で一覧としてのページには絵はないが個別ページ(SAN Transport)には絵がある。

じゃあ、とバックアップソフト側を探すといろいろでてくる

その中でも、Veritas NetBackup「VMware のトランスポートモード: ベストプラクティスとトラブルシューティング」が分かりやすいかなぁ、と感じた。

SAN Transport

SAN Transportについて、何の変哲もないiSCSIストレージを、ESXiサーバとWindowsサーバの両方につなげただけでも使えるのかな、と検証してみようとした。

(上記画像はVMwareから転載)

まあ、実機の環境がなかったので、vSphere仮想マシンのWindowsサーバからiSCSI接続して構築してみたところ、commvaultの場合は「SAN access is only supported for physical machines.」というメッセージでバックアップさせてくれなかった。

Event Code: 91:248
Severity: Minor
Program: vsbkp
Description:
Unable to open the disks for virtual machine [仮想マシン名] for SAN access. SAN access is only supported for physical machines.

なにを設定すればごまかせるかな?と試行錯誤・・・とりあえず以下の設定で仮想マシンを作ってみたものの駄目だった。

CPU:ハードウェア仮想化 ハードウェアアシストによる仮想化をゲストOSに公開
IOMMU:IOMMUをゲストOSに公開
パフォーマンスカウント:仮想CPUパフォーマンスカウンタの有効化
SCSIコントローラ:LSI Logic SAS
ネットワークアダプタ:E1000e
ゲストOS:その他 その他(64ビット)
VMware-toolsインストールなし

結局のところ、普通に作ってから、[構成パラメータ]で「smbios.reflecthost」を「TRUE」とするだけで成功した。以下は実際に使った設定。

SCSIコントローラ:LSI Logic SAS
ネットワークアダプタ:E1000e
ゲストOS:Windows Windows Server 2016以降
VMware-toolsインストールあり
構成パラメータ: smbios.reflecthost 「TRUE」

どうやらBIOS stringにVMwareの文字列が入っているかどうかで判定していた模様。

今回はCommvaultバックアップでの事例だったけど、NetBackupなど他のバックアップソフトウェアでもvSphere環境へのアクセスはVDDK経由で行っているので、おそらく同じような制限がかかっているのではないかと想定している。

2023/11/22追記: NetBackup 8.1.1環境があったので試してみたら、こちらは偽装しなくてもそのまま動いた

検証用にCentOS5を新規インストールしたら面倒だった 2024/01/09版


2024/01/09追記: 2024/01/09にCentOS 5.11のインストールを試み、この記事の内容が引き続き使えることを確認した。(記事自体への修正はない)


検証のため古いOSを2022年にインストールしてみるシリーズ、今回はCentOS5をインストールする必要がありインストールした。(これまで「Windows Server 2008R2編」「Windows 7編」)

久しぶりすぎて忘れていたこととか、2022年の現状だと発生することとか、いろいろあったのでメモ書きとして残す。

vSphere環境上にインストールしたのだが、まず設定でいくつか問題が・・・

NICが認識できない

vSphere仮想マシンを新規作成する際のゲストOSを「CentOS 4/5以降 (64ビット)」で作成すると

ネットワークアダプタが「VMXNET3」として作成される。

しかし、VMXNET3のドライバはCentOS5.11のインストールISOには含まれていないため、ネットワーク接続が行えない

インストール直後からネットワーク接続を行いたい場合はアダプタタイプを「E1000」あたりで設定して作成する。

VMware Toolsが用意されていない

最近のESXiに含まれているVMware Toolsのlinux.iso にはRHEL5/CentOS5で使えるVMware Toolsが入っていない。

RHEL5/CentOS5に対応するのはVMware Tools 10.3.22までで、10.3.23以降は対応していない。

以前と同じように https://packages.vmware.com/tools/releases/10.3.22/ にあるレポジトリRPM をインストールしてyumコマンドでvmware-toolsをインストールしようとしたのですが、packages.vmware.com がTLS1.2のみ許可するWebサーバ設定となっているため、CentOS5からではファイルがダウンロードできない状態となっています。

このため https://www.vmware.com/go/tools から VMware Tools 10.3.22のダウンロードリンク から VMware Tools packages for Linuxをダウンロードして使うこととなる。

CentOS5の更新がダウンロードできない

CentOS5.11をインストールした直後の状態で yum check-update を実行すると下記のエラーとなる。

# yum check-update
Loaded plugins: fastestmirror, security
Loading mirror speeds from cached hostfile
YumRepo Error: All mirror URLs are not using ftp, http[s] or file.
 Eg. Invalid release/repo/arch combination/
removing mirrorlist with no valid mirrors: /var/cache/yum/base/mirrorlist.txt
Error: Cannot find a valid baseurl for repo: base
#

これはmirrorlistでCentOS5用のファイルが提供されなくなったためのエラーとなる。

これに対してはmirrorlistではなくbaseurlに変更し、URLを「http://mirror.centos.org/centos/$releasever/~」から「http://vault.centos.org/centos/5.11/~」に書き換える、という手法が知られている。

しかし、2022年8月時点ではこの手法で書き換えた場合、「M2Crypto.SSL.SSLError: unknown protocol」というエラーで失敗する

# yum check-update
Loaded plugins: fastestmirror, security
Loading mirror speeds from cached hostfile
Traceback (most recent call last):
  File "/usr/bin/yum", line 29, in ?
    yummain.user_main(sys.argv[1:], exit_code=True)
  File "/usr/share/yum-cli/yummain.py", line 309, in user_main
    errcode = main(args)
  File "/usr/share/yum-cli/yummain.py", line 178, in main
    result, resultmsgs = base.doCommands()
  File "/usr/share/yum-cli/cli.py", line 345, in doCommands
    self._getTs(needTsRemove)
  File "/usr/lib/python2.4/site-packages/yum/depsolve.py", line 101, in _getTs
    self._getTsInfo(remove_only)
  File "/usr/lib/python2.4/site-packages/yum/depsolve.py", line 112, in _getTsInfo
    pkgSack = self.pkgSack
  File "/usr/lib/python2.4/site-packages/yum/__init__.py", line 662, in <lambda>
    pkgSack = property(fget=lambda self: self._getSacks(),
  File "/usr/lib/python2.4/site-packages/yum/__init__.py", line 502, in _getSacks
    self.repos.populateSack(which=repos)
  File "/usr/lib/python2.4/site-packages/yum/repos.py", line 260, in populateSack
    sack.populate(repo, mdtype, callback, cacheonly)
  File "/usr/lib/python2.4/site-packages/yum/yumRepo.py", line 168, in populate
    if self._check_db_version(repo, mydbtype):
  File "/usr/lib/python2.4/site-packages/yum/yumRepo.py", line 226, in _check_db_version
    return repo._check_db_version(mdtype)
  File "/usr/lib/python2.4/site-packages/yum/yumRepo.py", line 1226, in _check_db_version
    repoXML = self.repoXML
  File "/usr/lib/python2.4/site-packages/yum/yumRepo.py", line 1399, in <lambda>
    repoXML = property(fget=lambda self: self._getRepoXML(),
  File "/usr/lib/python2.4/site-packages/yum/yumRepo.py", line 1391, in _getRepoXML
    self._loadRepoXML(text=self)
  File "/usr/lib/python2.4/site-packages/yum/yumRepo.py", line 1381, in _loadRepoXML
    return self._groupLoadRepoXML(text, ["primary"])
  File "/usr/lib/python2.4/site-packages/yum/yumRepo.py", line 1365, in _groupLoadRepoXML
    if self._commonLoadRepoXML(text):
  File "/usr/lib/python2.4/site-packages/yum/yumRepo.py", line 1201, in _commonLoadRepoXML
    result = self._getFileRepoXML(local, text)
  File "/usr/lib/python2.4/site-packages/yum/yumRepo.py", line 974, in _getFileRepoXML
    cache=self.http_caching == 'all')
  File "/usr/lib/python2.4/site-packages/yum/yumRepo.py", line 811, in _getFile
    http_headers=headers,
  File "/usr/lib/python2.4/site-packages/urlgrabber/mirror.py", line 412, in urlgrab
    return self._mirror_try(func, url, kw)
  File "/usr/lib/python2.4/site-packages/urlgrabber/mirror.py", line 398, in _mirror_try
    return func_ref( *(fullurl,), **kwargs )
  File "/usr/lib/python2.4/site-packages/urlgrabber/grabber.py", line 936, in urlgrab
    return self._retry(opts, retryfunc, url, filename)
  File "/usr/lib/python2.4/site-packages/urlgrabber/grabber.py", line 854, in _retry
    r = apply(func, (opts,) + args, {})
  File "/usr/lib/python2.4/site-packages/urlgrabber/grabber.py", line 922, in retryfunc
    fo = URLGrabberFileObject(url, filename, opts)
  File "/usr/lib/python2.4/site-packages/urlgrabber/grabber.py", line 1010, in __init__
    self._do_open()
  File "/usr/lib/python2.4/site-packages/urlgrabber/grabber.py", line 1093, in _do_open
    fo, hdr = self._make_request(req, opener)
  File "/usr/lib/python2.4/site-packages/urlgrabber/grabber.py", line 1202, in _make_request
    fo = opener.open(req)
  File "/usr/lib64/python2.4/urllib2.py", line 364, in open
    response = meth(req, response)
  File "/usr/lib64/python2.4/urllib2.py", line 471, in http_response
    response = self.parent.error(
  File "/usr/lib64/python2.4/urllib2.py", line 396, in error
    result = self._call_chain(*args)
  File "/usr/lib64/python2.4/urllib2.py", line 337, in _call_chain
    result = func(*args)
  File "/usr/lib64/python2.4/urllib2.py", line 565, in http_error_302
    return self.parent.open(new)
  File "/usr/lib64/python2.4/urllib2.py", line 358, in open
    response = self._open(req, data)
  File "/usr/lib64/python2.4/urllib2.py", line 376, in _open
    '_open', req)
  File "/usr/lib64/python2.4/urllib2.py", line 337, in _call_chain
    result = func(*args)
  File "/usr/lib64/python2.4/site-packages/M2Crypto/m2urllib2.py", line 82, in https_open
    h.request(req.get_method(), req.get_selector(), req.data, headers)
  File "/usr/lib64/python2.4/httplib.py", line 810, in request
    self._send_request(method, url, body, headers)
  File "/usr/lib64/python2.4/httplib.py", line 833, in _send_request
    self.endheaders()
  File "/usr/lib64/python2.4/httplib.py", line 804, in endheaders
    self._send_output()
  File "/usr/lib64/python2.4/httplib.py", line 685, in _send_output
    self.send(msg)
  File "/usr/lib64/python2.4/httplib.py", line 652, in send
    self.connect()
  File "/usr/lib64/python2.4/site-packages/M2Crypto/httpslib.py", line 55, in connect
    sock.connect((self.host, self.port))
  File "/usr/lib64/python2.4/site-packages/M2Crypto/SSL/Connection.py", line 174, in connect
    ret = self.connect_ssl()
  File "/usr/lib64/python2.4/site-packages/M2Crypto/SSL/Connection.py", line 167, in connect_ssl
    return m2.ssl_connect(self.ssl, self._timeout)
M2Crypto.SSL.SSLError: unknown protocol
#

これは、 vault.centos.org が TLS 1.2を使用したhttpsアクセスしか受け付けなくなったが、CentOS5側ではTLS 1.2に非対応であるため、TLS 1.2が理解できず「unknown protocol」となっている、という状態である。

2022年8月時点では archive.kernel.org は http アクセスを許可してくれているため、URLを「http://archive.kernel.org/centos-vault/5.11/」に書き換えることで、CentOS5のアップデートが行えるようになる。

# CentOS-Base.repo
#
# The mirror system uses the connecting IP address of the client and the
# update status of each mirror to pick mirrors that are updated to and
# geographically close to the client.  You should use this for CentOS updates
# unless you are manually picking other mirrors.
#
# If the mirrorlist= does not work for you, as a fall back you can try the
# remarked out baseurl= line instead.
#
#

[base]
name=CentOS-$releasever - Base
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os
#baseurl=http://vault.centos.org/centos/$releasever/os/$basearch/
baseurl=http://archive.kernel.org/centos-vault/5.11/os/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5

#released updates
[updates]
name=CentOS-$releasever - Updates
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=updates
#baseurl=http://vault.centos.org/centos/$releasever/updates/$basearch/
baseurl=http://archive.kernel.org/centos-vault/5.11/updates/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5

#additional packages that may be useful
[extras]
name=CentOS-$releasever - Extras
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=extras
#baseurl=http://vault.centos.org/centos/$releasever/extras/$basearch/
baseurl=http://archive.kernel.org/centos-vault/5.11/extras/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5

#additional packages that extend functionality of existing packages
[centosplus]
name=CentOS-$releasever - Plus
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=centosplus
#baseurl=http://vault.centos.org/centos/$releasever/centosplus/$basearch/
baseurl=http://archive.kernel.org/centos-vault/5.11/centosplus/$basearch/
gpgcheck=1
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5

#contrib - packages by Centos Users
[contrib]
name=CentOS-$releasever - Contrib
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=contrib
#baseurl=http://vault.centos.org/centos/$releasever/contrib/$basearch/
baseurl=http://archive.kernel.org/centos-vault/5.11/contrib/$basearch/
gpgcheck=1
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5

コピーしてきた仮想マシンがThe specified feature is not supported by this versionで起動できない


なんか生き残っていたvSphere 5.5上で動いていたvSphere仮想マシンを新vSphere環境に移行したいけど、費用かけないいい方法は無い?という相談があった。

ある程度作業ができる人なので「仮想マシン止めてからsshでESXiにログインして、仮想マシンが入ったディレクトリをまるごとscpでコピーすればいいんじゃないですか?」と提案した。

で・・・やってみたけど、仮想マシンのパワーオンに失敗したけど、なんだろ?という質問が・・・

すべてのディスクを列挙できません。指定された機能はこのバージョンではサポートされていません

というエラーとのこと。

こういうのは英語で探さないと情報がでてこないけど、正しいのがわからないので、とりあえず「not support this version」あたりの単語から https://kb.vmware.com/ で検索して情報捜索。

Failed to power on virtual machine (82542)
 仮想マシンのパワーオンに失敗する場合のまとめ

“The specified feature is not supported by this version” error creating a snapshot in a vSAN environment (83381)
 vSANとVMFS6とでサポートしている機能に差があることで、特定のデータストアで起動できない、という事例

Migrating a VM to a VSAN datastore fails (82801)
 VSANに移行しようとして失敗する際にvmfssparseのエラーなどがでている

どうやらデータストアのファイルシステムと、仮想マシンのスナップショット周りでなにかがある、というのが見えてきた。

その観点で調査継続

VMFS でのスナップショットのフォーマット

VMFS5で2TB未満の仮想ディスクのスナップショットはVMFSsparseフォーマット
VMFS5で2TB以上の仮想ディスクのスナップショットは SEsparseフォーマット
VMFS6の仮想ディスクスナップショットは全てSEsparseフォーマット

Virtual Machines running on an SEsparse snapshot may report guest data inconsistencies (59216)

VMFS5データストアとNFSデータストアでは、2TB以上の仮想ディスクはSEsparse形式

ということが判明した。

このことから、起動しなかった仮想マシンではスナップショットが使われいたのではないか?という仮説となった。

確認してもらうと確かにスナップショットが使われていたとのこと。

対処方法としては、「新環境にNFSデータストアがあるのであればそこに移動させた後であれば起動できる」一度起動したあとであればstorage vmotionを使ってVMFS6データストアに移動できる。

もしくは、スナップショットを消してから移行を行う、ということとなった。

Windows Server 2008をいまさらセットアップした(作業メモ版)


2022/07/08追記

何回か実行してみたところ、いろんな問題があったため、新しい記事「Windows Server 2008 SP2のWindows Updateがうまくいかない件への対処策 2022/07/07版」としてまとめ直しました。


とあるバックアップソフトの対象機種からWindows Server 2008が外れた。

これは「ホントにインストールできない」という意味なのか、それとも「インストールできるけどサポート対象と認定しない」という意味なのか、どちらなんだろ?と確認するため、Windows Server 2008環境を新規でセットアップした。

Windows Server 2008 SP2 のISOイメージを使ってvSphere環境でインストールを実施。

まず、VMware Toolsをインストールしようとしたら対応していないOSと言われてしまう。

調べると最後のWindows Server 2008 SP2対応はVMware Tools 11.0.6だったらしい。

このバージョンのVMware toolsダウンロードを https://packages.vmware.com/tools/releases/11.0.6/ から行ってインストールを実施。

続いて、Windows OSのアップデートは WSUS Offline Updateを使ってオフライン状態でアップデートできないかな、と確認してみると、ESR versionの 11.9.1 であればWindows Server 2008に対応していたので、ISOイメージを作成した。

が・・・ ListMissingUpdateIds.vbs で、「信頼プロバイダが信頼していないルート証明書で強制終了しました」というエラーで失敗して、パッチ適用の本編に進まない。

certmgr.mscを起動して確認してみると「証明書失効リスト」にいろいろある・・・

ListMissingUpdateIds.vbs の処理を修正しないとダメっぽいんだけど、うまくデバグできなかったので対処を諦めて普通にWindows Updateを実施。

しかし、最後10個ぐらいのところで、それ以上進まなくなる、という現象が発生。

2回実施中2回とも発生なので、特定の何かで問題が発生している模様。

この状態になると強制電源OFF/ONして、Windows Updateのロールバック処理を行うぐらいしか対処方法が無かった。

ロールバック完了後に再度Windows Updateを実行してみると半分以上がまだ未適用でした・・・面倒くさい

この後のWindows Updateはハングアップすることはなく普通に進み、とはいえ、何回か再起動とWindows Updateの再実行が必要でした。


で・・・

今回、Windows Server 2008環境を構築するきっかけとなった非対応問題ですが、「インストールできない」という状況でした。

なぜインストールできないのか、というのは前提条件である.NET Framework 4.6.2がWindows Server 2008に非対応だったから、ということでした。

なお、Windows Server 2008については古いバージョンをインストールしておけばサーバ側が新しいバージョンであってもバックアップ/リストアが問題無く動作していました。


WSUS Offline Updateを使わないでいきなりWindows Updateしてみると、Microsoftサイトにアクセスできずに終わります。

なぜかこのような状態になっているかと言えば、といえばhttpsアクセス時に使用する証明書が全て有効期限切れとなっているためですね。

これはcertmgr.mscを起動して確認出来る信頼されたルート証明書機関の有効期限を見ればわかります。

WSUS Offline Updateはルート証明書の更新はやってくれて下記の様な感じになっています。これによりhttpsによるアクセスが成功するようになっている感じですね。

ESXi をprofileベースでアップデートする


hpeやDELLなどのメーカ製サーバにESXiをインストールする際はそれぞれのメーカが提供するOEMイメージを使用する。

で、あとでパッチを適用する場合、メーカから出ているBundle zipファイルを適用するが、「esxcli software update -d ~」で適用すると「構成:イメージ プロファイル」の記述がアップデートされない。

プロファイルとしてきちんとアップデートを適用するには、それなりの操作を行う必要がある。

(1) Bundle zipファイル内のプロファイル名確認

まず、提供されているBundle zipファイルに含まれるプロファイル名を確認するために「esxcli software sources profile list」を実行

[root@ホスト名] esxcli software sources profile list -d /vmfs/volumes/~/VMware-VMvisor-Installer-6.7.0.update03-18828794.x86_64-DellEMC_Customized-A16.zip
Name                             Vendor  Acceptance Level  Creation Time        Modification Time
-------------------------------  ------  ----------------  -------------------  -------------------
DellEMC-ESXi-6.7U3-18828794-A16  Dell    PartnerSupported  2021-10-26T03:23:17  2022-01-11T12:21:23
[root@ホスト名]

(2) 現状適用されているプロファイル名確認

次に現状のプロファイル名を確認するために「esxcli software profile get」を実行

[root@ホスト名] esxcli software profile get
(Updated) DellEMC-ESXi-6.7U3-15160138-A03
   Name: (Updated) DellEMC-ESXi-6.7U3-15160138-A03
   Vendor: Dell
   Creation Time: 2021-12-28T08:45:43
   Modification Time: 2022-04-22T07:27:05
   Stateless Ready: False
   Description:

      2021-12-28T08:45:43.600204+00:00: The following VIBs are
      installed:
        net-ixgbe     3.7.13.7.14iov-20vmw.670.0.0.8169922
        ata-pata-amd  0.3.10-3vmw.670.0.0.8169922
<略>
[root@ホスト名] 

(3) プロファイルによるアップデートの適用

プロファイルとしてアップデートを適用するため「esxcli software profile update」でコマンドを実行。

[root@ホスト名]  esxcli software profile update -d /vmfs/volumes/~VMware-VMvisor-Installer-6.7.0.update03-18828794.x86_64-DellEMC_Customized-A16.zip -p DellEMC-ESXi-6.7U3-18828794-A16
<略>

(4) 再起動

適用を反映させるため、再起動を実施