Skip to main content

vCenter Server のコンテンツライブラリにデータストアから直接 ISO ファイルをインポートする


やりたかったこと

つまり、

  • データストアに直接保存しているたくさんの ISO ファイル
  • どうにかして コンテンツライブラリに簡単にインポートしたい

のです。

でも、コンテンツライブラリは、

  • ローカルファイルのアップロード
  • HTTP でのどこかからのダウンロード

のどちらかでしかインポートできないようで、愚直にやろうとすると、いちどローカルに全部ダウンロードして、それを再度アップロード することになります。

が、もちろん、これは数が多いと相当つらいので、強引でもいいからどうにかしてラクをできないかなあ、という話です。

解決策: データストアから HTTP でダウンロードさせる

PowerCLI スクリプトでの実装

簡単な PowerCLI の関数、Import-ContentLibraryItemFromDatastore を作りました。

こんな感じで、データストア上のファイルのパスと認証情報を渡すと、どうにかしてくれます。

> Import-ContentLibraryItemFromDatastore -Username temporary-user-01@vsphere.local -Password my-password -Item vmstore:\sandbox-dc01\sandbox-ds01\ISO -DestinationLibraryName "ISO Images"

Creating Sample_ISO_File.iso ...
Creating Update Session for Sample_ISO_File.iso ...
Pulling File Sample_ISO_File.iso from Datastore ...
  Waiting for Transfer ...
  Transferring ... 29570480 of 367654912 bytes
  Transferring ... 91598704 of 367654912 bytes
  Transferring ... 154513184 of 367654912 bytes
  Transferring ... 215776424 of 367654912 bytes
  Transferring ... 271944344 of 367654912 bytes
  Transferring ... 322272864 of 367654912 bytes
  Completed.
Completing the Session ...
  Waiting for Complete ...
  Completed.
Deleting the Session ...

トラフィックは、データストアを参照できる ESXi からいちど vCenter Server を経由して、再度 ESXi に流れてコンテンツライブラリのバックエンドのデータストアに書き込まれます。オーバヘッドはそれなりにあるものの、ローカルを経由させるよりは圧倒的に効率的…… なはずです。

-Item では、PowerCLI で接続すると利用できる vmstore:\ 表記で目的のファイルのパスを指定します。ファイルを指定した場合はそのファイル、ディレクトリを指定した場合は配下のファイルすべて、さらに -Recurse スイッチを追加した場合は再帰で取り込み対象が検索されます。ただし、現在では対象になるのは ISO ファイルのみ です。

後述しますが、-Username-Password は、内部でプレーンテキストで利用 されます。この影響で、各種ログなどにプレーンテキストで認証情報が残る 可能性があり、よって、利用する場合は 一時的な専用のユーザを作る ほうがよいでしょう。

詳しい実装は GitHub のリポジトリ を参照してください。

インポート後も、元の ISO ファイルは元のデータストア上に残るので、必要に応じて掃除をします。

PowerCLI スクリプトの利用例

例えば、次の 2 つの ISO ファイルをインポートしたいとします。

PS > Get-ChildItem vmstore:\kuro-dc01\local-ds01\ISO | Select Name, ItemType, Length

Name                      ItemType    Length
----                      --------    ------
Sample_ISO_File_1.iso IsoImageFile 367654912
Sample_ISO_File_2.iso IsoImageFile  88188928

作業前なので、コンテンツライブラリは空っぽです。

PS > Get-ContentLibraryItem -ContentLibrary "ISO Images"
PS >

作った関数でインポートさせます。事前に Connect-VIServerConnect-CisServer(どちらも接続先は vCenter Server)はしておきます。

PS > Import-ContentLibraryItemFromDatastore -Username username@vsphere.local -Password my-secure-password -Item vmstore:\kuro-dc01\local-ds01\ISO -DestinationLibraryName "ISO Images"
Creating Sample_ISO_File_1.iso ...
Creating Update Session for Sample_ISO_File_1.iso ...
Pulling File Sample_ISO_File_1.iso from Datastore ...
  Waiting for Transfer ...
  Waiting for Transfer ...
  Transferring ... 32245264 of 367654912 bytes
  Transferring ... 92454328 of 367654912 bytes
  Transferring ... 154309064 of 367654912 bytes
  Transferring ... 210416392 of 367654912 bytes
  Transferring ... 280139640 of 367654912 bytes
  Transferring ... 336237712 of 367654912 bytes
  Completed.
Completing the Session ...
  Waiting for Complete ...
  Completed.
Deleting the Session ...
Creating Sample_ISO_File_2.iso ...
Creating Update Session for Sample_ISO_File_2.iso ...
Pulling File Sample_ISO_File_2.iso from Datastore ...
  Waiting for Transfer ...
  Transferring ... 26515392 of 88188928 bytes
  Transferring ... 88188928 of 88188928 bytes
  Completed.
Completing the Session ...
  Waiting for Complete ...
  Completed.
Deleting the Session ...

インポートされました。

PS > Get-ContentLibraryItem -ContentLibrary "ISO Images"

Name                           ContentLibrary                 ItemType                       SizeGB
----                           --------------                 --------                       ------
Sample_ISO_File_1              ISO Images                     iso                            0.342
Sample_ISO_File_2              ISO Images                     iso                            0.082

仮想マシンからもマウントできます。

確認できたら、元のファイルを消して完了です。

PS > Remove-Item vmstore:\kuro-dc01\local-ds01\ISO -Recurse

仕組みと手作業で行うときの手順

コンテンツライブラリは、HTTP で公開されているコンテンツならインポートさせられるので、つまり、データストアの中身に vCenter Server が HTTP でアクセスできればよい わけです。

そして、vCenter Server も ESXi も、実は vSphere Web Service API により、ブラウザでデータストアにアクセスできます。vSphere Client の、ログイン画面の手前の右上のアレです。

つまり、データストアの任意のファイルに HTTP でアクセスできる ということです。

実際に掘っていき、目的の ISO ファイルを確認します。

このファイルの URL を確認すると、次のような URL が得られます。これが、ISO ファイルのダウンロード用の URL です。URL の書式の詳細はガイドに記載 があります。

  • https://kuro-vcs01.krkb.lab/folder/ISO/Sample_ISO_File_1.iso?dcPath=kuro-dc01&dsName=local-ds01

ただし、この URL へのアクセスには認証が必要です。実際、例えば vCSA から wget でアクセスしようとすると、401 が返ります。

root@record [ ~ ]# wget 'https://kuro-vcs01.krkb.lab/folder/ISO/Sample_ISO_File_1.iso?dcPath=kuro-dc01&dsName=local-ds01' -O Sample_ISO_File_1.iso
--2020-08-09 00:29:57--  https://kuro-vcs01.krkb.lab/folder/ISO/Sample_ISO_File_1.iso?dcPath=kuro-dc01&dsName=local-ds01
Resolving kuro-vcs01.krkb.lab... 192.168.0.201
Connecting to kuro-vcs01.krkb.lab|192.168.0.201|:443... connected.
HTTP request sent, awaiting response... 401 Unauthorized

Username/Password Authentication Failed.

が、BASIC 認証なので、URL にユーザ名とパスワードを含めて しまえば、実はアクセスできます。

URL に BASIC 認証の情報を含めるには、

  • https://<ユーザ名>:<パスワード>@example.com/

とするだけです。ただし、ユーザ名の @%40 にエンコードします。よって、今回の URL であれば、

  • https://username%40vsphere.local:my-secure-password@kuro-vcs01.krkb.lab/folder/ISO/Sample_ISO_File_1.iso?dcPath=kuro-dc01&dsName=local-ds01

とすればアクセスできます。

root@record [ ~ ]# wget 'https://username%40vsphere.local:my-secure-password@kuro-vcs01.krkb.lab/folder/ISO/Sample_ISO_File_1.iso?dcPath=kuro-dc01&dsName=local-ds01' -O Sample_ISO_File_1.iso
--2020-08-09 00:30:21--  https://username%40vsphere.local:*password*@kuro-vcs01.krkb.lab/folder/ISO/Sample_ISO_File_1.iso?dcPath=kuro-dc01&dsName=local-ds01
Resolving kuro-vcs01.krkb.lab... 192.168.0.201
Connecting to kuro-vcs01.krkb.lab|192.168.0.201|:443... connected.
HTTP request sent, awaiting response... 401 Unauthorized
Authentication selected: Basic realm="VMware HTTP server"
Reusing existing connection to kuro-vcs01.krkb.lab:443.
HTTP request sent, awaiting response... 200 OK
Length: 367654912 (351M) [application/octet-stream]
Saving to: ‘Sample_ISO_File_1.iso’

Sample_ISO_File_1.iso                         100%[=================================================================================================>] 350.62M  69.8MB/s    in 4.8s

2020-08-09 00:30:26 (72.8 MB/s) - ‘Sample_ISO_File_1.iso’ saved [367654912/367654912]

よって、コンテンツライブラリのインポートソースとして、このような認証情報を含めた URL を指定することで、vCenter Server が直接 vCenter Server(や ESXi)からデータストアのコンテンツに HTTP でアクセスでき、結果として、ほぼ直接のインポートが成功します。

先述のスクリプトは、このような URL の組み立てや、HTTP ソースからのインポートを自動で行わせているだけです。

試したけどダメだった例

PowerCLI で vmstore:// 指定

PowerCLI でもコンテンツライブラリはいじれるようになっていて、組み込みのコマンドレットの New-ContentLibraryItem でコンテンツライブラリにファイルを追加できます。

ちまちまとコーディングをせずとも、これが使えるのがどう考えてもいちばん楽なので、安直な発想で Files の指定をこねくり回しました。

が、

  • Filesvmstore:\ のパスを直接書く
    • New-ContentLibraryItem : パラメーター 'Files' の引数変換を処理できません。指定されたパスのフォーマットはサポートされていません。 のエラー
  • New-PSDrive でデータストアにドライブ文字(V:\ など)を割り当ててFiles には V:\ のパスを書く
    • New-PSDrive -Name "V" -PSProvider VimDatastore -Root "\" -Location (Get-Datastore local-ds01) など
    • New-ContentLibraryItem : パラメーター 'Files' の引数変換を処理できません。Supplied path ('V:\ISO\Sample_ISO_File_1.iso') must exist. のエラー

で、いずれもダメでした。

PowerCLI で https://ds:// 指定

続けて、認証情報を埋め込んだ URL や ds://New-ContentLibraryItem に渡してみましたが、いずれもダメでした。

  • Files に認証情報を含んだ URL を指定
    • Unable to transform value 'https://...' into path. のエラー
  • Filesds:// で始まるパスを指定
    • 指定されたパスのフォーマットはサポートされていません。 のエラー

vSphere Automation API で ds:// 指定

ネイティブのコマンドレットが使えないことが分かったので、Get-CisService で Automation API を呼び出して使う作戦に変更しました。

コンテンツライブラリへのインポートは、Automation API では content.item.updatesession.fileadd を使いますが、このときにリクエストに含める FileAddSpec を見ると、source_endpointItemTransferEndpoint)の uri には、データストア内のコンテンツを示す ds:// スキーマが使えるように見えます。

Transfer endpoint URI. The supported URI schemes are: http, https, and ds. An endpoint URI with the ds scheme specifies the location of the file on the datastore. The format of the datastore URI is:
ds:///vmfs/volumes/uuid/path
When the transfer endpoint is a datastore location, the server can import the file directly from the storage backing without the overhead of streaming over HTTP.

ItemTransferEndpoint

URL にパスワードを埋め込むなどというお行儀の悪い方法より、これが使えるならこの方が良いに決まっているので、最初はこれを使うつもりでした。

ds:// 表記で組んでみると、エラーもなく動くし、転送タスクも流れるし、一見インポートできたかのようにはなりました。

PS > Import-ContentLibraryItemFromDatastore -Username username@vsphere.local -Password my-secure-password -Item vmstore:\kuro-dc01\local-ds01\ISO -DestinationLibraryName "ISO Images"
Creating Sample_ISO_File_1.iso ...
Creating Update Session for Sample_ISO_File_1.iso ...
Pulling File Sample_ISO_File_1.iso from Datastore ...
  Waiting for Transfer ...
  Transferring ... 0 of 73728 bytes
  Transferring ... 7372 of 73728 bytes
  Transferring ... 7372 of 73728 bytes
  Transferring ... 7372 of 73728 bytes
  Transferring ... 7372 of 73728 bytes
  Transferring ... 7372 of 73728 bytes
  Transferring ... 7372 of 73728 bytes
  Transferring ... 7372 of 73728 bytes
  Completed.
Completing the Session ...
  Waiting for Complete ...
  Completed.
Deleting the Session ...

が、

  • API が返すファイルサイズが明らかにおかしい(上の例では、300 MB くらいのファイルなのに 70 KB 程度に見える)
  • インポートされたコンテンツライブラリ上のファイルが 4 KB に見える

な状態が抜け出せず、size プロパティを指定しても打破できず、ファイル自体もまともに使えないものにしかならなかったので、ダメでした。

おわりに

いろいろ試して最終的にはどうにかしたものの、そもそも、データストアからの直接のインポートは、もはや普通にできてしかるべきなのではという気がすごくしています。

実際、フォーラムを見ると、ちらほらと『できないの?』な質問はあるようです。

いずれも解決策は書かれていないので、しかたなく今回のような(あまりきれいではない)実装に至ったわけですが、公式の機能追加を待ちたいですね。

とはいえ、ホームユース程度であればこれで充分で、もともとやりたかった目の前の課題(大量のデータストア上の ISO をコンテンツライブラリに突っ込む)にはひとまず対応できそうです。


VCF Lab Constructor(VLC)でネステッドな VMware Cloud Foundation 4.0 環境を気軽に作る


はじめに

VMware Cloud Foundation(VCF)という、SDDC Manager で SDDC 環境全体をイイ感じに管理できる製品があり、これを(ハンズオンラボでなく)自宅で触りたくなりました。ただの趣味というか興味です。

しかし VCF は、お行儀のよい SDDC 環境をしっかりした規模で作るための製品なので、自前で構築しようと思えば、たとえ最小構成でも、256 GB のメモリと 10 TB 超の SSD と 2 つの 10 GbE の NIC を積んだサーバを 4 台用意しないといけません。また、上位ネットワークとは BGP で会話できないといけないですし、DNS サーバや DHCP サーバなど周辺にもいろいろ必要です。さらにはネットワーク構成の詳細やさまざまなオブジェクトの命名など ワークブック の 400 ちかいパラメータを決定する必要もあります。

要するに、自宅で気軽に触れる程度のものでは到底ないわけです。ネステッドで作ればハードウェア面はある程度ごまかせはするものの、周辺サーバの用意やパラメータの決定は、ちょっと触れればいいとほんのり思っているくらいのモチベーションではしんどいものがあります。

とはいえ、海外のさかんな自宅ラボ事情を考えると、自宅で触りたい勢は世界のどこかには存在しているはずで、そう思っていろいろ調べていると、VCF Lab Constructor(VLC)なるものの存在を知りました。このエントリでは、これを使ってネステッドな VCF を構築するまでの流れを紹介します。

VCF Lab Constructor(VLC)

概要

VCF Lab Constructor(VLC)は、VCF をネステッド環境で簡単に構築できるようにいろいろお膳立てをしてくれるツールです。詳しくは VMware のブログで紹介されています。

引用元: Deep dive into VMware Cloud Foundation – Part 1 Building a Nested Lab

具体的には、VLC 経由でデプロイすることで、

  • 値が全部埋まったサンプルのパラメータ(JSON)が提供されていて、ただ動けばよいレベルであればそのまま使える
  • Cloud Builder アプライアンスをパラメータに従って自動でデプロイしてくれる
  • デプロイした Cloud Builder アプライアンスの中に、DNS サーバや BGP ルータなど、必須の周辺サーバの機能を無理やり同居させてくれる
  • パラメータに従って vSAN の構成要件を満たした ESXi を ESXi 上の仮想マシンとしてデプロイしてくれる
  • (指定すれば)Cloud Builder での Bring-Up プロセスも開始してくれる

などのメリットが得られます。これによって、VCF に必要な Cloud Builder と ESXi 環境がサクッと整うため、気軽に VCF を試す環境を得るためのハードルが一気に下がるわけです。

引用元: Deep dive into VMware Cloud Foundation – Part 1 Building a Nested Lab

もちろん公式にサポートはされていませんが、開発は VMware のなかのひとであり、また Slack のコミュニティもあって、それなりにワイワイしています。

準備

VLC のダウンロード URL は、次の URL から登録することで得られます。

ここで得られる URL は最新版のダウンロード用ですが、過去のバージョン用の URL は Slack でピン止めされたメッセージでリストされています。

なお、VCF のバイナリ(Cloud Builder の OVA イメージ)と、VCF を構成する各製品(vCenter Server、ESXi、vSAN、NSX-T)のライセンスキーは別途必要です。ぼくは VMUG Advantage なヒトなのでそれで入手しています。

ハードウェア要件

VLC にはインストールガイドも付属しており、それによると、現在のバージョンでは、

  • 1 台の ESXi(6.7 以降)
    • 128 GB 以上のメモリ
    • 800 GB 以上の SSD

が最低要件とされています。本来の VCF のハードウェア要件からは圧倒的に小さいですが、それでもそこそこのモノは必要ですね。

今回の環境

といいつつ、残念ながら上記の要件を満たせるハードウェアが自宅にないので、以下の環境で踏ん張ることにしました。

  • 1 台の vCenter Server で管理される 2 台の ESXi 7.0
    • 各 32 GB のメモリ(2 台の合計で 64 GB)
    • 各 512 GB の SSD(2 台の合計で 1 TB)
    • 共有ストレージなし

どうにかして処理を 2 台で分散させることにしてディスク容量を確保し、メモリの不足については、パフォーマンスを犠牲にしてオーバコミットをさせまくる前提にします。

手順

細かい手順や注意事項は付属のガイドや Slack のピン止めされたメッセージで案内されているので、ここでは概略だけ紹介します。

環境の準備

VLC に付属のガイドに従って、環境を整えます。

母艦となる物理 ESXi 側では、vDS で MTU を 9,000 にして、トランクモードのポートグループをひとつ作りました。このポートグループに仮想 ESXi と Cloud Buider が接続され、VCF 関連のすべてのパケットが(VLAN のタグ付きで)流れることになります。ポートグループのセキュリティ設定は、プロミスキャスモードなどもすべて承諾しています。

また、今回は二台の ESXi で無理やり分散させるため、vDS のアップリンクもトランクにして、上位にちょっといいスイッチをつなぐことで、ESXi 間で 9,000 バイトのジャンボフレームも VLAN もそのまま流せるようにしています。

作業端末となる Windows 10(ドキュメントや図で触れられている Jump Host)は、仮想マシンではなく、普段使いの Windows 10 をそのまま使うことにしました。積んでいる Intel の物理 NIC が VLAN を喋れたので、サブインタフェイスを作って VLAN ID や IP アドレスをガイドと同等に構成しています。

パラメータの用意

VCF の最新は 4.0.1 ですが、VMUG Advantage でダウンロードできる VCF が 4.0 だったので、VLC も 4.0 をダウンロードしました。

バンドルされている JSON は二つありますが、今回は NO_AVN を使います。AVN(Application Virtual Network)については こちらのエントリで説明 されています。

  • AUTOMATED_AVN_VCF_VLAN_10-13_NOLIC_v4.json
  • AUTOMATED_NO_AVN_VCF_VLAN_10-13_NOLIC_v4.json

この JSON ファイルは、VLC が Cloud Builder や仮想 ESXi をデプロイするときのパラメータになるだけでなく、Cloud Builder がマネジメントドメインをデプロイするときの Bring-Up プロセスのパラメータとしてもそのまま使えます。

この段階で、JSON ファイル中の以下の箇所に、ライセンスキーを埋め込んで上書きしておきます。

{
  ...
  "esxLicense": "<Insert ESXi License>",
  ...
  "vCenterSpecs": [
    {
      ...
      "licenseFile": "<Insert vCenter License>",
      ...
    }
  ],
  "vsanSpecs":[
    {
      ...
      "licenseFile": "<Insert vSAN License>",
      ...
    }
  ],
  "nsxtSpec":
  {
    ...
    "nsxtLicense": "<Insert NSX License>",
    ...
  },
  ...
}

VLC の起動と設定

VLCGui.ps1 を PowerShell で実行すると、進捗表示とログ表示用の PowerShell ウィンドウと、操作用の GUI が起動します。

DNS サーバなど、必要な周辺サービス含めて VLC でデプロイする場合は Automated を、自前で用意しているものを使わせる場合は Manual を選択します。今回は全部オマカセしてしまうので、Automated です。

VCF EMS JSON に先に用意した JSON ファイルを、CB OVA Location に Cloud Builder の OVA ファイルをそれぞれ指定します。右側にはデプロイ先の vCenter Server か ESXi の認証情報を入力して、Connect を押下し、目的の構成を選択状態にします。

Bring-Up プロセスまで続けて実行させてしまう場合は Do Bringup? にチェックを、Cloud Builder と仮想 ESXi のデプロイまでで終える(その先は本来の VCF の構築手順に従って自分でやる)場合はチェックを外します。今回は、小細工もしたいのでチェックを外します。Bring-Up プロセスの詳細を知りたいなどお勉強目的の場合も、チェックを外した方があとあとわかりやすいでしょう。

この後、Validate を押下するとバリデーションが走り、問題なければ Construct! が押下できるようになります。

このバリデーションで、データストアの空き容量もチェックされます。選択したデータストアに 800 GB の空きがないと怒られてしまうので、今回は VLCGui.ps1 のバリデーションの条件文をちょろまかして強引に進めました。

Construct! を押下して走り出してしまえば、あとは待つだけです。Do Bringup? にチェックを入れていた場合は、このまま VCF のマネジメントドメインが完成して SDDC Manager が使える状態になるまで、ひたすら放置すれば勝手に進みます。典型的には 3.5 時間とされていますが、遅い環境だと 9 時間程度かかる例もあるようです(数字だけ見ると長いですが、ほんとうに放置するだけなので、手作業で作るよりは比較にならないほど楽ですね……)。

Do Bringup? にチェックを入れていない場合は、Cloud Builder のデプロイと仮想 ESXi の構成だけなので、数十分程度で終わるでしょう。

Cloud Builder と仮想 ESXi の完成

本来は Cloud Builder のデプロイだけでも手作業 ですが、VLC では OVF Tools を使ってパラメータを流し込んでいるようです。画面を眺めていると、そうして Cloud Builder がデプロイされて構成されたあと、GoBGP や MaraDNS などを使って Cloud Builder に周辺サービス群がねじこまれていく様子が見えます。

Cloud Builder 関係の作業が終わると、4 台の仮想 ESXi の作成が始まり、そして終わります。ESXi も、本来であれば VIA などを使って手作り する必要があった作業です。ラクですね。

今回のように Do Bringup? にチェックを入れなかった場合は、VLC の出番はここで終わりです。

デプロイ先の状態を見ると、Cloud Builder の仮想マシンと、仮想 ESXi が並んでいる様子がわかります。

今回は、VLC でデプロイ先をローカルデータストアにした影響で、Cloud Builder も仮想 ESXi も物理的に同じ ESXi に載ってしまっています。物理リソースが潤沢であればそれで全く問題はありませんが、今回はそうではないので、この段階で 4 台のうち 2 台の仮想 ESXi をもう一方の物理 ESXi に移行して、コンピュートとストレージの負荷分散をはかりました。

VCF の Bring-Up プロセスの実行

VCF の初期構築作業の肝(とぼくが勝手に思っている部分)が、この Bring-Up プロセス です。構成さえ事前に決めれば、vCenter Server も vSAN も NSX-T も SDDC Manager も全自動で仕上げてくれる、VCF によるライフサイクル管理のメリットの一端が垣間見える部分です。

付属の JSON を使った場合は、この段階でホスト名 CB-01a.vcf.sddc.lab で Cloud Builder にアクセスできるようになっているはずです。ログインして、EULA を確認して進めます。

VxRail ではないのでそのまま次へ。

環境要件が表示されます。いろいろありますが、事前準備と VLC によって充足されているか、充足できていなくても無視できる程度にはなっているはずです。

続行するとパラメータを設定するパートに入ります。本来は、ここか VMware の Web サイトからワークブックをダウンロードして、値を埋め、再度ここにアップロードして進めるものですが、VLC の実行時に利用した JSON がここでそのまま使えます。

つまり、今回は、ワークブックを埋めなくてもよく、JSON をアップロードすれば進めます。

バリデーションが開始されます。いくつか警告が出ますが、警告であれば確認の上で Acknowledge で了承して進められます。

続行すると、楽しい構築の始まりです。

あとは、表示されている大量のタスク(スクロールバー参照)が全自動でごりごり進んでいくのを眺めているだけで終わりです。壮観ですね。

VLC で Do Bringup? にチェックを入れていた場合は、VLC が Cloud Builder の API 経由でこの Bring-Up プロセスをキックすることになり、その結果、最初から最後まで VLC だけで透過的に全自動、な見え方になります。

Bring-Up プロセスは、早くて数時間、遅いと半日程度はかかると思います。放置してもよいですが、タスクの中身を見たりデプロイ先の各管理画面に直接入って過程を観察したりするとたいへんおもしろく、かつお勉強になり、これを手でやれといわれたら死んでしまう感じです。

すべてのタスクが Success になって走り切ったら、完成です。

トラブルシュート

Bring-Up プロセスのどこかでエラーが起きたときは、エラーメッセージに加えて、それぞれの管理画面やログファイルを直接のぞくと調べやすくなります。付属の JSON を使った場合は、

  • Cloud Builder: CB-01a.vcf.sddc.lab
  • ESXi: esxi-[1-4].vcf.sddc.lab
  • vCenter Server: vcenter-mgmt.vcf.sddc.lab
  • NSX-T Manager: nsx-mgmt.vcf.sddc.lab
  • SDDC Manager: sddc-manager.vcf.sddc.lab

あたりです。認証情報は JSON に含まれています。

なお、今回のように物理リソースが貧弱な場合は、たまに単なる高負荷で失敗することもあるようです。ネステッド環境内で DRS による vMotion がキックされることもあり、それが負荷に拍車をかけている場合もあります。

このようなとき、単純なリトライで成功する場合もありますが、状況によってはネステッド環境内の DRS のモードを変更したり、リトライ前に手動で vMotion するなどして(物理ホストレイヤでの)負荷の平準化をはかるとよさそうです。VCF 的には DRS はもりもり動かすべきですが、リソースに余裕はないので仕方なしです……。

このほか、VLC のガイド内にもヒントがいろいろありますし、Slack にも情報がたまっています。

VCF の管理と拡張

Bring-Up プロセスが無事に完了したら、SDDC Manager が利用できるようになっているはずです。付属の JSON では、sddc-manager.vcf.sddc.lab です。

ネステッド環境の vCenter Server に入れば、マネジメントドメインの構成も探索できます。

NSX-T の管理画面も触れますね。

現時点でできているのはマネジメントドメインだけなので、本来はここからさらにワークロードドメインを追加構築したり、vRealize Suite をデプロイしたり、VCF 4.0 であれば vSphere with Kubernetes を使ったワークロード管理機能を有効化したり、ネットワークをうにゃうにゃしたり、それっぽいことをいろいろやっていくわけです。

なお、ネステッド環境を拡張したい場合は、VLC の Extension Pack! から、空の ESXi を追加構築できます。追加に必要な JSON も付属しています。

まとめ

VCF Lab Constructor を使って、自宅のラボ環境に、ネステッドな VMware Cloud Foundation 4.0(VCF 4.0)を構築し、その過程を体験・観察しました。

あたかもサクサク成功させたかのように書いていますが、実際は何度かの失敗のあとにたどりついています。

  • 単一の ESXi(32 GB のメモリ、512 GB の SSD)のみを使ってデプロイしようとしたら、データストアがあふれて失敗
  • 単一の ESXi(32 GB のメモリ)と外付けの NFS データストア(2 TB の HDD)を使ってデプロイしようとしたら、処理が遅すぎて NSX-T Manager のデプロイから進めず失敗
  • 二台の ESXi(各 32 GB のメモリ)と外付けの共有 NFS データストア(2 TB の HDD)を使ってデプロイしようとしても、NSX-T Manager のデプロイから進めず失敗

要するに、潤沢なリソースはとにかく正義です。富豪的解決はだいじです。動けばいいや、と割り切るにも限度はあり、こういう無茶をしてもまともに動く環境は得られません。

最終的には本エントリで紹介したように 2 台にうまく分散させることで Bring-Up までは成功しましたが、重すぎてほぼ使い物にならないのが正直な現実でした。

とはいえ、構築プロセス(の一部)を体験できるという意味で、知的好奇心の充足には非常に有効であり、いろいろ見えておもしろかったです。満足しました。

もちろん、構築そのものが高度に自動化されているからといって、設計も同じ程度に楽かといえば当然そんなことはまったくないでしょうし、それどころかむしろ設計、とくに周辺サービス群とのインタラクションとパラメータの具体化、そして長期的な運用プロセスの定義こそがキモな気もするわけで、過度な期待はせずに、できるだけ誠実に向き合っていきたいものですね。


vSphere Lifecycle Manager (vLCM) で ESXi を 6.7 から 7.0 にアップグレードして管理する


はじめに

前回のエントリ で、vSphere 6.7 の環境のうち、vCenter Server を 7.0 にアップグレードして、最新のパッチの適用も行いました。このエントリでは、ESXi を 7.0 にアップグレードし、パッチの適用も行います。

ESXi 6.7 から 7.0 へのアップグレード方法は、ドキュメントでも提示されている とおりにいくつかありますが、今回は、vSphere 7.0 からの新機能である、vSphere Lifecycle Manager(vLCM)を利用します。パッチの適用も vLCM を利用します。

対象の ESXi は、Intel の NUC(NUC8i5BEK)にインストールされています。VMware 的には非サポート(HCL に載っていない)ですが、気にせずできる範囲でやっていきます。

vSphere Lifecycle Manager

これまでも、vSphere 環境のライフサイクル管理の目的で、vSphere Update Manager(VUM)と呼ばれるツールが存在していました。vSphere 7.0 からは、これが vSphere Lifecycle Manager(vLCM)に置き換わっています。

VUM も vLCM も、vSphere 環境のバージョンやパッチの適用状態に任意の基準を決めて、実環境のその基準からの逸脱を確認し、基準に準拠させる修正作業も実行できる、というざっくりした説明の限りでは大きな違いはありませんが、その基準の考え方に、従来どおりの『ベースライン』に加えて、『イメージ』という概念が新しく登場しています。この『イメージ』こそが vLCM の大きな特徴なようです。

考え方

これまでの『ベースライン』による管理では、例えば、ある特定のパッチの適用状態を管理できた一方で、そのパッチ以外のパッケージ構成やバージョンについては、何ら関知しませんでした。つまり、同じベースラインを複数のホストに添付して管理したとしても、その全ホストのパッケージ構成が完全に一致していることは保証できませんでした。

これに対し、vLCM で新しく登場した『イメージ』では、

  • ベースイメージ
    • VMware がバージョンごとにリリースする ESXi そのもので、ブート可能で完全な状態を構成するコンポーネントの集まり
  • ベンダアドオン(任意)
    • OEM ベンダが提供する追加のドライバやパッチ、追加機能など
  • ファームウェアやドライバアドオン(任意)
    • ハードウェアベンダが提供するファームウェアやドライバなど
  • コンポーネント(任意)
    • サードパーティ製の追加ドライバや追加機能など

をまとめて管理するようです。つまり、ESXi を構成する全コンポーネントのあるべき状態(Desired State)を(任意でファームウェアまで含めて)宣言的に『イメージ』として定義できます。イマドキな考え方ですね。詳しくはドキュメントに書いてあります。

vLCM では、従来通りの『ベースライン』による管理と『イメージ』による管理のいずれも利用できますが、

  • 『イメージ』による管理は、ホストクラスタに対してのみ有効化できる
    • クラスタの全台が ESXi 7.0 以降である必要がある
    • クラスタの全台がステートフル(Auto Deploy でなくディスクからブートする)である必要がある
    • クラスタの全体が同一ベンダのハードウェアである必要がある
  • 『ベースライン』管理から『イメージ』管理には切り替えられるが、いちど『イメージ』管理にすると『ベースライン』管理には戻せない
  • 7.0 の時点では、NSX や vSphere with Kubernetes を含むクラスタは『イメージ』での管理は行えない
    • 『イメージ』を利用したホストの修正を行うと、それらのエージェントが削除される
  • ファームウェアの管理まで行う場合、ハードウェアベンダから提供される Hardware Support Manager プラグインの導入が必要
    • 現時点では Dell か HPE のみの模様
    • Dell であれば OpenManage Integration for VMware vCenter (OMIVV)、HPE であれば iLO Amplifier が必要で、それぞれ仮想アプライアンスとして構築する

などなど、種々の注意事項や制約があるようです。ドキュメントをしっかり読まないとハマりそうですね。

なお、従来はパッチやドライバの最小単位は VIB でしたが、7.0 からはコンポーネントなる概念に代わっています。コンポーネントには、一つ以上の VIB を論理的にグループにしたものです。この辺もドキュメントに書いてあるので、作業中の用語に混乱しそうな場合は確認しておくとよさそうです。

今回の作業

今回は、最終的に『ESXi 7.0 を vLCM でイメージ管理できる』状態を目標に、以下を行っていきます。

  • ベースラインを利用して、ESXi 6.7 を 7.0 にアップグレードする
  • イメージでの管理に切り替える
    • その過程で、最新のパッチをベースにしたイメージを作成する
  • イメージを利用して最新のパッチを適用する

ESXi 6.7 の 7.0 へのアップグレード

まずは ESXi を 6.7 から 7.0 にアップグレードします。イメージによる管理は ESXi 7.0 以降でないと行えないため、アップグレードはベースラインを利用して行うことになります。

vLCM のメニュは、vSphere Client に完全に統合されています。というか、もともと VUM だった項目が vLCM になっています。

まずは、アップグレード用のベースラインを作る準備として、[インポートされた ISO] タブから、元になる ISO ファイルをインポートします。

インポートできました。

続いて、ベースラインを作成します。[ベースライン] タブで [新規] > [ベースライン] から、インポートした ISO ファイルを利用したアップグレードベースラインを作ります。

できました。

作成したベースラインをクラスタ(かホスト)に添付します。

デフォルトでは、事前定義された二つのベースライン(重要なホストパッチ、ホストセキュリティパッチ)が最上位の vCenter Server オブジェクトに添付されていて、クラスタやホストにもこれが継承されていますが、今回は事前に分離してから作業しています。

添付すると、アップグレード前なので、非準拠と判定されます。

ここから、ベースラインに合わせる修正作業をしていきます。今回はクラスタに対してまとめて修正を実行しましたが、一台ずつ実施したい場合はホスト単位でももちろん構いません。

修正のための設定をして、続行します。

今回は [今すぐ] にしたので、直ちに適用が始まりました。クラスタ内のホストで 1 台ずつ、

  • 対象ホスト上の稼働中の仮想マシンの移行
  • 対象ホストのメンテナンスモードへの切り替え
  • アップグレード
  • 対象ホストのメンテナンスモードの終了

が行われていきます。サポートされていないハードウェア(NUC8i5BEK)を使っていますが、特に問題なくすんなりとアップグレードされて起動してきました。

仮想マシンが共有ストレージ上にない場合は、Storage vMotion まではしてくれないので、そのホストのアップグレードはスキップされます。その場合、手動で仮想マシンを逃がすなど対処してから再度修正処理を実行します。

最終的に、クラスタ内の全台がベースラインに準拠した状態になったら、アップグレードは完了です。

なお、アップグレードが完了した段階で、ESXi のライセンスが評価モードに切り替わっています。必要に応じて、新しく vSphere 7.0 のライセンスキーを追加し、ホストに適用してください。

ベースラインからイメージへの切り替え

クラスタのホスト全台が ESXi 7.0 以上になったので、ベースライン管理からイメージ管理に切り替えます。

事前準備として、ベースイメージを取り込みます。オフラインバンドルの ZIP を取り込んでもよいですが、今回はインタネットから取得するため、vLCM の設定画面から、以下の URL の利用を有効化します。

  • https://hostupdate.vmware.com/software/VUM/PRODUCTION/main/vmw-depot-index.xml

有効化後、[アクション] > [更新の同期] を実行して、[デポのイメージ] タブにベースイメージのリストが表示されていることを確認します。執筆時点では 7.0.0b7.0.0bs がありますが、違いは VMware のブログ でも説明されています。下部では、ベンダアドオンなども確認できますね。

デポにイメージが表示されたら、クラスタをベースラインからイメージに切り替えていきます。

クラスタの [アップデート] > [イメージ] で、[イメージのセットアップ] からウィザードを開始します。

今回は、アップグレードの残骸(古い fdm の VIB、おそらく今は無効にしている HA をかつて有効にしていた影響)がスタンドアロン VIB として検出されてしまいました。もし今後もこの VIB を導入したままにしたい場合は、この VIB を含むコンポーネントをイメージに含める必要がありますが、今回はただの残骸で不要なので無視します。

ここで ESXi のベースイメージと、任意でベンダアドオンやファームウェアなども選択します。Dell や HPE など、きちんとサポートされるハードウェアを使っている場合は、このあたりから必要な追加コンポーネントを指定することになります。

サポートされているハードウェアを使っていて、かつ、Harware Support Manager が事前に構成されている場合は、あらかじめハードウェアとファームウェアの組み合わせなどを定義しておくことで、ここでファームウェアなどの構成もイメージに含められるようです。

今回はもちろんないので、ミニマムで ESXi のバージョン(執筆時点で最新の 7.0.0b)だけを指定して保存します。

イメージを保存すると、コンプライアンスの確認が走ります。今回は、次の 2 点が検出されていますが、どちらも想定内です。

  • ホストのバージョンがイメージと異なる
  • スタンドアロンの VIB(前述した残骸)がインストールされている

どちらも、このあとの適用作業で修正されます。後者はつまり削除されるわけですが、このように、イメージに含まれない余計なモノが入っていると削除される点は、かつてのベースラインでの管理とは異なる、イメージでの管理の特徴的なところの一つだと思います。

続行すると、イメージ管理への切り替えは完了です。

イメージに準拠するようホストを修正する

クラスタの [アップデート] > [イメージ] の画面で、イメージのコンプライアンスの確認や、事前チェック、修正時の動作に関する設定、実際の修正などが行えます。

修正の実行前には、事前チェックをしておくとよさそうです。修正の失敗の原因になる諸々をチェックして教えてくれます。例えば今回の環境だと、DRS が無効で、かつ vCSA が動作しているホストで問題が検出されました。一台ずつ対応すればよいだけなので、気にしないことにします。

クラスタの全台を修正する場合は [すべて修正] を、ホスト単位で修正する場合はホスト名の左の […] から [修正] を実行します。

確認画面が出て、続行すると修正が開始されます。ホストで何が行われるのか見せてくれるのは、わかりやすくてよいですね。

進捗は元の画面で逐次表示されていきます。これもわかりやすくてよいですね。

途中、停止状態の vCenter Server 6.7(前回のエントリ で作業した残骸で不要なヤツ)が乗っているホストで、vCenter Server が稼働中かつ DRS が無効だから適用できない旨の怒られが発生しました。停止状態でも vCenter Server が居ると(移行できなければ)ダメなようで、不思議な仕様だなあと思いつつ一時的にインベントリから削除して回避しています。

そんなこんなで順次修正が完了し、イメージを遵守できた状態になりました。めでたしめでたし。

まとめ

vSphere 7.0 からの新機能である vLCM を使って、ESXi のアップグレードと、イメージ管理によるパッチ適用を行いました。

NSX や vSphere with Kubernetes を構成するホストでは利用できないなど、制約はまだあるものの、イメージによる管理は VUM よりも素直でわかりやすい印象を受けました。

今回は試しませんでしたが、API を使って JSON ベースでの管理もできるようで、構成管理の負荷を下げる余地はまだまだありそうです。今後の機能追加やサポート範囲の拡大にも期待できそうですね。


vCenter Server を 6.7 から 7.0 にアップグレードする


はじめに

最近 vSphere 7 が出たので、おうちの牧場をアップグレードします。

この牧場は、物理的には Intel の NUC(NUC8i5BEK)にインストールした vSphere 6.7 が 2 台で、その片方に vCSA 6.7 が居る状態です。共有ストレージとして QNAP(iSCSI/NFS)がありますが、諸々の事情で vCSA は ESXi のローカルデータストア(M.2 SSD)に配置しています。外部認証ソースも外部 PSC も使っていない、ミニマムな感じです。

サポートされるアップグレード順序は、KB78221 で説明されています。今回の環境はとてもちまっとしたアレなので、素直に vCenter Server を上げてから ESXi を上げるのみです。

このエントリでは、vCenter Server のアップグレードだけを扱います。

ESXi のアップグレードもこの後でもちろんしますが、これには VUM の後継である vSphere Lifecycle Manager(vLCM)を使ってみたいので、別エントリとして投稿 しています。

vSphere 7.0 の理解と準備

根本的に、vSphere 7.0 になって、

  • ESXi 6.0 以前のサポートが廃止された(6.5 以上が必須)
  • Windows 版の vCenter Server が廃止された
  • 外部 PSC が廃止された(アップグレードの過程で統合される)
  • Flash ベースの vSphere Web Client が廃止された

などなど、アーキテクチャレベルでいろいろ変更があります。

そういう何やかやふくめ、アップグレードにあたっては何はともあれドキュメント読みましょうねという感じなので、KB や製品ドキュメントを一通り見ておきます。

ここからリンクされている KB や関連ドキュメントもざっくり眺めます。マジメなことをいうとそもそも vSphere 7.0 はぼくが使っている NUC への導入をサポートしていませんが、7.0 に限らず昔からそう(アップグレード前の状態でそもそも非サポートな状態)なので気にしないことにします。

OEM のドライバを使っている場合はどうしろとか、現行バージョンが vCSA の 6.7 U2c か U3 なら事前にコレをやれとか、いろいろ書いてあるので、該当する場合はその通りにするとして、凝ったことををしていない今回のようなシンプルな構成であれば、実際の作業はウィザードをぽちぽちするレベルで終わりです。

もちろん、現行が外部データベースを使っていたり、めちゃくちゃ古かったり、外部 PSC が居たり、そもそも Windows 版だったり、外部 VUM を立てていたりすると、いろいろ考慮事項も当然でてくるので、その辺りはドキュメントを読んでください。

vCenter Server のアップグレードプロセス

標準のアップグレード手順に従う場合、処理の流れはだいたいこんな感じです。一連の作業は、ウィザードに従うと自動で順次行われます。

  1. 新しい vCSA インスタンスがデプロイされます。この段階では、IP アドレスは作業用の一時的なもの(作業時に指定)が付与されます
  2. 現行の vCSA から、構成情報がエクスポートされます
  3. 新しい vCSA にエクスポートされたデータを転送します
  4. 現行の vCSA が停止され、現行の vCSA が使っていた IP アドレスや FQDN が新しい vCSA に設定されます
  5. エクスポートされたデータを使って、新しい vCSA に構成が復元されます

この後、状態を確認して、必要な後処理(これもドキュメントがありますが、典型的にはライセンスの投入など)を行えば、vCenter Server のアップグレードは完了です。

新しい vCSA を現行の vCSA と同じインベントリに配置する場合、作業の流れの都合上、仮想マシン名は現行の vCSA のものとは別にする必要があります。この場合、もし仮想マシン名も現行のものを維持したいのであれば、あとから手作業で仮想マシン名の変更(と、ファイル名まで気にする場合は Storage vMotion)が必要です。

vCenter Server のアップグレード

やっていきます。今回は Windows の端末上で GUI インストーラを使って作業しました。

ISO をマウントして、./vcsa-ui-installer/win32/installer.exe を叩くとインストーラが立ち上がるので、[Upgrade] を選択します。

あとは愚直にウィザードに従っていきます。まずは Stage 1 です。

現行の vCSA の情報を入力して、接続を確認します。認証情報と、現行の vCSA それ自体が動作している ESXi の情報も入力します。

新しい vCSA のデプロイ先の ESXi の情報を入力します。

新しい vCSA の仮想マシン名とパスワードを指定します。新しい vCSA が現行の vCSA と同じインベントリに並ぶことになる場合は、現行の vCSA と同じ仮想マシン名だとこの段階で怒られるので、別の名前を入れます。

新しい vCSA のサイズを指定します。

新しい vCSA を配置するデータストアを指定します。シンプロビジョニングにしたい場合はチェックも入れます。

新しい vCSA が利用するポートグループを選択して、バージョンアップ中だけ利用される一時 IP アドレスなどを入力します。

確認画面で [FINISH] を押下すると、デプロイが始まります。

デプロイ先に指定した ESXi を見ると、新しい仮想マシンができて、パワーオンされる様子が観察できます。vCSA 7.0 は、Photon OS 3.0 がベースのようですね、vCSA 6.7 は Photon OS 1.0 でした。

で、終わると、Stage 2 への進め方が案内されます。[CONTINUE] を押下するか、指示された URL にアクセスして続行します。

ここから Stage 2 です。[NEXT] で進むと、アップグレードの事前チェックが開始されます。

このアップグレードの事前チェックでエラーがあると先に進めないので、その場合はどうにかして直します。

今回は、環境固有の構成(6.7 の構築時点で手抜きして DNS サーバを立てずに強引にごまかしていた)の都合上、名前解決関連でエラーになったので、この段階で新しい vCSA に SSH でログインしてごにょごにょして修正しました。この方法は本筋ではないので本エントリの末尾で補足します。

エラーを解消したあとも警告がいくつか残りましたが、エラーでなく警告であれば、確認の上で続行できます。今回は想定内の警告のみだったので、そのまま進めました。

アップグレードするデータの種類を選びます。構成情報だけでなく、過去のタスクやイベント、パフォーマンスの統計情報なども移行できるようですが、その分データ量や作業時間は増えるようです。今回は、せっかくなので全部にしました。

CEIP を構成します。参加すると、表示されている機能が使えるようになります。逆にいえば、参加しないとこれらの機能は使えなくなります。参加状態は後からも変更できます。

現行 vCSA のバックアップを取得済みであることを宣言して続行します。バックアップ、実は取っていませんでしたが、失敗してもまあヨシな環境なのでそのまま進めました。

最後の最後に、現行 vCSA が停止する旨の確認がでて、了承すると実際の処理が開始します。

あとは待ちです。移行のデータは新旧の vCSA 間で直接やりとりされます。作業端末は経由しません。

移行データのエクスポートがひと通り終わると、現行 vCSA がシャットダウンされ、新しい vCSA の構成やサービスの起動、移行データの適用が始まります。この段階から、新しい vCSA が旧 vCSA の IP アドレスなどを持つようになります。

完了しました。

アップグレード後の確認と後処理

完了後、vSphere Client の URL にアクセスすると、確かに HTML5 版のみになっていました。

見た目や操作感は vSphere 6.x の頃とほとんど変わりません。

移行作業中に指定した通り、設定やインベントリ情報だけでなく、過去のタスクやイベント、パフォーマンスの統計情報などもきれいに残っています。

ただ、すぐに目に入るだけでも、

  • vCenter Server のライセンスが評価モードに変わっている
  • 旧 vCSA の仮想マシンが残っている
  • 新 vCSA の仮想マシン名は作業中に指定したもののままだ

あたりは対処が必要そうです。

ライセンスキーは 6.x と 7.x で違うので再適用が必要なのは当然ですが、仮想マシン名は、実体のファイル名まで気にする場合は Storage vMotion でデータストアを移行しないといけないので、ちょっと注意ですね。

vCenter Server の最新パッチ適用

アップグレードが終わったので、アップデートをしようとしました。

vSphere Client からは、Update Planner を利用して、アップデート(パッチ)の有無や適用の事前チェック結果などを確認できます。ただし、この Update Planner は、CEIP に参加していないと使えない(エラーが出る)ようです…… 謎仕様ですね。

既定では、vCSA に接続された ISO ファイルの中身と VMware の公開リポジトリがアップデートの取得先として探索されます。定期的なアップデートの自動チェックも設定できます。

トラブル: アップデートが進まない

で、実際の適用は、VAMI から数クリックで行える…… はずなので、VAMI にログインして、最新のアップデートをいちどステージングして、その後インストールを開始したところ、

  • プログレスバーが『インストールが進行中です』で 0 % からまったく進まない
  • 別セッションで VAMI にログインしようとすると『アップデートの進行中です』が表示されてログインできない
  • パフォーマンスチャートを見ても何も動いていなさそう

な状態になってしまいました。予想ダウンタイムが 254 分というのもにわかには信じがたい数字です。

解決策: VAMI を使わない

調べるとどうも KB があります。

内部でいちどコケていたのか何なのか、進捗がうまく更新されなかったみたいですね。素直に KB の通りにやってみます。

# cat /etc/applmgmt/appliance/software_update_state.conf
{
    "state": "INSTALL_IN_PROGRESS",
    "version": "7.0.0.10400",
    "latest_query_time": "2020-07-18T16:04:05Z",
    "operation_id": "/storage/core/software-update/install_operation"
}

# cp /etc/applmgmt/appliance/software_update_state.conf /tmp/software_update_state.conf.org

# service-control --stop applmgmt
Operation not cancellable. Please wait for it to finish...
Performing stop operation on service applmgmt...
Successfully stopped service applmgmt

# rm /etc/applmgmt/appliance/software_update_state.conf

# service-control --start applmgmt
Operation not cancellable. Please wait for it to finish...
Performing start operation on service applmgmt...
Successfully started service applmgmt

# cat /etc/applmgmt/appliance/software_update_state.conf
{
    "state": "UP_TO_DATE"
}

これで、たしかにログインできるようになりました。GUI で見る限りではインストール前の状態に戻っています。

が、ふたたび GUI からインストールをしようとしたら、再発しました……。

仕方ないので、再度復旧させて、今度は CLI でアップデートを試してみます。見てみると、そもそもステージングが正しくされていない模様。

Command> software-packages list --staged
 [2020-07-19T02:07:58.201] : Packages not staged

GUI の表示がおかしそうなので、GUI からはいちどステージングを解除して、

ステージング自体も今度は CLI から行います。

Command> software-packages stage --url --acceptEulas
 [2020-07-19T02:10:46.201] : Not running on a VMC Gateway appliance.
 ...
 [2020-07-19T02:10:47.201] : Staging process completed successfully

Command> software-packages list --staged
 [2020-07-19T02:11:16.201] :
        category: Bugfix
        ...
        version: 7.0.0.10400
        updateversion: True
        allowedSourceVersions: [7.0.0.0,]
        buildnumber: 16386292
        ...

目的のモノがステージングされてくれたので、インストールします。

Command> software-packages install --staged
 [2020-07-19T02:14:52.201] : Validating software update payload
 [2020-07-19 02:14:52,670] : Running validate script.....
 [2020-07-19T02:14:53.201] : Validation successful
 [2020-07-19 02:14:53,680] : Copying software packages 127/127
 [2020-07-19 02:17:10,915] : Running system-prepare script.....
 [2020-07-19 02:17:12,928] : Running test transaction ....
 [2020-07-19 02:17:14,945] : Running prepatch script.....
 [2020-07-19 02:18:42,103] : Upgrading software packages ....
 [2020-07-19T02:20:09.201] : Setting appliance version to 7.0.0.10400 build 16386292
 [2020-07-19 02:20:09,265] : Running patch script.....
 [2020-07-19 02:26:47,947] : Starting all services ....
 [2020-07-19T02:26:48.201] : Services started.
 [2020-07-19T02:26:48.201] : Installation process completed successfully

10 分くらいで終わりました。254 分とは……?

無事に最新になっています。

Command> com.vmware.appliance.version1.system.version.get
Version:
   Version: 7.0.0.10400
   Product: VMware vCenter Server Appliance
   Build: 16386292
   Type: vCenter Server with an embedded Platform Services Controller
   Summary: Patch for VMware vCenter Server 7.0.0
   Releasedate: June 23, 2020
   Installtime: 2020-07-18T22:37:32.988Z

そんなわけで、もしかすると vCSA のアップデートは VAMI より CLI のほうがトラブルを招きにくいかもしれませんね。そのうち修正されるだろうとは思いますが……。

まとめ

vSphere 6.7 環境のうち、vCenter Server を 7.0 にアップグレードし、パッチの適用も行いました。

アップグレードプロセスや全体的な使用感も 6.7 とは大きく変わっていないので、これまで通り安心して使えそうです。サクサク動いてくれて快適です。

次のエントリ では、vLCM を利用した ESXi のアップグレードとパッチ管理を行っていきます。

補足: vCSA 自身を vCSA 用の DNS サーバにする

アップグレード前、つまり 6.7 の構築時点で手抜きをしていたので、今回の環境内には DNS サーバがありません。このため、アップグレードの Stage 2 の冒頭の事前チェックで、新しい vCSA から現行の vCSA のホスト名が解決できずにエラーになりました。

アップグレード前の vCSA 6.7 は、DNS サーバがなくても FQDN で構成できるようにするため、vCSA 自身を vCSA 用の DNS サーバにしていました。具体的には、

  • vCSA の /etc/hosts にエントリを追加する
  • vCSA で動作している Dnsmasq に /etc/hosts を参照させる

ことをしていました。なお、自宅のラボなので好きにやっていましたが、もちろん非サポートです。

同じことは vCSA 7.0 でも有効なようですし、DNS サーバをわざわざ立てるのもアレなので、今回もこれを行いました。もちろん非サポートです。

Stage 1 のあと、かつ Stage 2 の前であれば、すでに vCSA への SSH ができる状態なので、指定していた一時 IP アドレスに接続して、/etc/hosts に必要なエントリを追記します。

# vi /etc/hosts
# cat /etc/hosts
...
192.168.0.201 kuro-vcs01.krkb.lab kuro-vcs01
192.168.0.200 kuro-qnap01.krkb.lab kuro-qnap01
192.168.0.202 kuro-esxi01.krkb.lab kuro-esxi01
192.168.0.203 kuro-esxi02.krkb.lab kuro-esxi02

この後、Dnsmasq の設定ファイルを修正して、Dnsmasq が /etc/hosts のエントリを DNS クエリへの応答に利用できるようにします。no-hosts をコメントアウトして、オマケで bogus-priv を足すだけです。

# sed -i 's/^no-hosts/#no-hosts\nbogus-priv/' /etc/dnsmasq.conf
# cat /etc/dnsmasq.conf
listen-address=127.0.0.1
bind-interfaces
user=dnsmasq
group=dnsmasq

no-negcache
#no-hosts
bogus-priv
log-queries
log-facility=/var/log/vmware/dnsmasq.log
domain-needed
dns-forward-max=150
cache-size=8192
neg-ttl=3600

この後、Dnsmasq を再起動します。

# systemctl restart dnsmasq

これで、OS がホスト名の名前解決を試みたときに、透過的に /etc/hosts のエントリも応答されるようになりました。dignslookup で確認できます。

# dig kuro-esxi01
...
;; ANSWER SECTION:
kuro-esxi01.            0       IN      A       192.168.0.202

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
...

vCSA(というか Photon OS)は、名前解決時の第一参照先が(/etc/resolv.conf で) 127.0.0.1:53 になっています。vCSA の場合は、このポートで Dnsmasq が待ち受けているため、上記の手順で名前解決に透過的に /etc/hosts が利用できたということです。

なお、DNS サーバがなくても、すべて FQDN でなく IP アドレスを指定してデプロイすれば、上記のような面倒なことをしなくても構築は可能です。


Cluster API で vSphere 上の Kubernetes クラスタを管理する


きっかけ

実験したいことが出てきてしまい、自宅で Kubernetes を触りたくなりました。

これまで Kubernetes を触る場合は Google Kubernetes Engine(GKE)ばかりを使っていたのですが、 今回実験したいのは IoT の世界でいうエッジ側の話なので、できればオンプレミス相当の Kuberentes クラスタが欲しいところです。

そんなわけで、これ幸いと自宅の vSphere 環境で Cluster API を叩いてゲストクラスタを作ることにしました。Cluster API は、2019 年に VMware から発表された VMware Tanzu や Project Pacific の実装でも使われているそうで、そういう意味でも興味のあるところです。

VMware Tanzu や Project Pacific は、エントリの本筋ではないので細かくは書きませんが、めっちゃ雑に書くと、vSphere と Kubernetes がイケてる感じにくっついたヤツです。

Cluster API とは

Cluster API は、Kubernetes っぽいお作法で Kubernetes クラスタそれ自体を管理できる仕組みです。Kubernetes の SIG のプロジェクト として開発が進められています。

最新バージョンは 2019 年 9 月にリリースされた v1alpha2 で、現在は v1alpha3 が開発中です。バージョン名を見てもわかる通り、現段階ではいわゆるアルファ版ですし、ドキュメントでも『プロトタイプだよ』『どんどん変わるからね』と記載されているので、ごりごりに使い込むのはまだちょっと待ったほうがよさそうですね。

Cluster API is still in a prototype stage while we get feedback on the API types themselves. All of the code here is to experiment with the API and demo its abilities, in order to drive more technical feedback to the API design. Because of this, all of the codebase is rapidly changing.

https://github.com/kubernetes-sigs/cluster-api/blob/master/README.md

Kubernetes クラスタを構成するノードは、多くの場合は仮想マシンです。その仮想マシンは、パブリッククラウド上だったりオンプレミスの vSphere 上や OpenStack 上だったりで動いているわけですが、Cluster API では、そうしたプラットフォームごとに Provider なる実装が用意されており、環境差異を抽象化してくれます。これにより、異なる環境でも同一の操作感で Kubernetes クラスタを管理できます。

今回は vSphere 環境上の Kubernetes クラスタの構成が目的なので、vSphere 用の Provider を使って作業します。

構成要素と構成の流れ

最終的には、いわゆる Kubernetes らしく業務や開発で様々なアプリケーションを動作させることになる Kubernetes クラスタと、それらを管理するためだけの Kubernetes クラスタ、の大きく二種類の Kubernetes クラスタができあがります。

前者がゲストクラスタ(ワークロードクラスタ)、後者がマネジメントクラスタなどと呼ばれるようです。Cluster API はこのうちのマネジメントクラスタに組み込まれており、この Cluster API によってゲストクラスタのライフサイクルを簡単に管理できるということです。

ざっくりイメージ

もう少し具体的にいえば、例えば Kubernetes クラスタ自体は cluster リソースとして、あるいはそれを構成するノードの仮想マシンは machine リソースとして扱えるようになり、通常の pod リソースや deployment リソースと同じように、自分以外の Kubernetes クラスタの構成が管理できるということです。

構築の観点では、つまりマネジメントクラスタができさえすれば Cluster API 環境はほぼ完成と言えるわけですが、実際にはマネジメントクラスタ自身もマネジメントクラスタで管理するため、手順はちょっと複雑です。

マネジメントクラスタの作り方はいくつかあるようですが、今回は vSphere 用 Provider の Getting Started の通り、以下のような流れで構成を進めます。

作業の流れのイメージ
  1. 作業用端末(図中 Workstation)に Docker や kuberctl など必要なモノを揃えて、マニフェストファイルを生成する
  2. Docker 上に作業用の Kubernetes クラスタ(ブートストラップクラスタ)を作り、Cluster API を導入する
  3. 導入した Cluster API を使って、マニフェストファイルに従って本当のマネジメントクラスタを作る
  4. マネジメントクラスタに Cluster API 環境を移行(Pivoting)して、ブートストラップクラスタを消す

最終的なマネジメントクラスタを作るためにさらに別の Kubernetes クラスタ(ブートストラップクラスタ)が必要なあたりがわりとややこしいですが、そういうものみたいです。

ここまでできたら、Cluster API の本来の利用方法の通り、マニフェストファイルに従ってゲストクラスタを作ったり消したり拡張したり縮小したりできます。

ここまでの作業はこれをやるためのただのお膳立てです

構築の準備

前述した流れの通り、マネジメントクラスタを構築するには、ブートストラップクラスタが動作できる環境が必要です。また、マネジメントクラスタが動作する vSphere 環境でも、少し準備が必要です。

作業端末の整備

作業前提を整えます。作業用の端末は、ブートストラップクラスタの動作と、それを用いたマネジメントクラスタの構築ができる必要があり、このために、

が必要です。Windows でもおそらく動くとは思いますが、今回は作業用の Ubuntu 端末を別に用意して使っています。

Docker は適当に入れます。今回の端末は Ubuntu 19.10 なので、19.04 用のバイナリを無理やり入れます。

$ sudo apt update
$ sudo apt install apt-transport-https ca-certificates curl software-properties-common
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu disco stable"
$ sudo apt update
$ sudo apt install docker-ce docker-ce-cli containerd.io
$ sudo usermod -aG docker ${USER}

clusterctl と Kind、kubectl はバイナリをダウンロードするだけです。

$ curl -Lo ./clusterctl https://github.com/kubernetes-sigs/cluster-api/releases/download/v0.2.9/clusterctl-darwin-amd64
$ chmod +x ./clusterctl
$ mv ./clusterctl ~/bin
$ curl -Lo ./kind https://github.com/kubernetes-sigs/kind/releases/download/v0.6.1/kind-$(uname)-amd64
$ chmod +x ./kind
$ mv ./kind ~/bin
$ curl -Lo ./kubectl https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl
$ chmod +x ./kubectl
$ mv ./kubectl ~/bin

が、clusterctl は v1alpha2 の時点ですでに DEPRECATED 扱いでした。

しかしながら代替手段がよくわかっていないし、Cluster API のドキュメント 通りではなにやらうまく動かない(kubeconfig 用の secret ができあがらない)ので、v1alpha3 が出て情報が増えてきたらどうにかします。

あと、Kind の最新リリースは現時点で 0.7.0 ですが、それを使うと後続の作業がうまく動かなかったので、ひとつ古い 0.6.1 を指定しています。

vSphere 環境での OVA テンプレートの展開

vSphere 環境用の Provider を使って Kubernetes クラスタを作った場合、最終的にできあがる Kubernetes のノードは vSphere 環境上の仮想マシンです。

この仮想マシンの元になるテンプレートが用意されているので、これをあらかじめデプロイして、テンプレートに変換しておきます。

Ubuntu 版と CentOS 版がありますが、今回は Ubuntu 版の最新の 1.16.3 を使いました。

その他のイメージのリンクは リポジトリに一覧 されています。

vSphere 環境でのフォルダとリソースプールの作成

マネジメントクラスタとゲストクラスタを入れるフォルダ(仮想マシンインベントリのヤツ)とリソースプールを作ります。入れ物としてただあればよいので、設定は適当で大丈夫です。

マネジメントクラスタの構成

では、実際の構築を進めます。ブートストラップクラスタを作り、そこで Cluster API を動作させて、それを通じて最終的なマネジメントクラスタを作ります。

はじめに、構成に必要な環境変数を、envvars.txt にまとめて定義します。内容はそれぞれの環境に依存するので書き換えが必要です。

$ cat envvars.txt
# vCenter config/credentials
export VSPHERE_SERVER='192.168.0.201'                  # (required) The vCenter server IP or FQDN
export VSPHERE_USERNAME='administrator@vsphere.local'  # (required) The username used to access the remote vSphere endpoint
export VSPHERE_PASSWORD='my-secure-password'           # (required) The password used to access the remote vSphere endpoint

# vSphere deployment configs
export VSPHERE_DATACENTER='kuro-dc01'                                 # (required) The vSphere datacenter to deploy the management cluster on
export VSPHERE_DATASTORE='nfs-ds01'                                   # (required) The vSphere datastore to deploy the management cluster on
export VSPHERE_NETWORK='ext-vm'                                       # (required) The VM network to deploy the management cluster on
export VSPHERE_RESOURCE_POOL='k8s'                                    # (required) The vSphere resource pool for your VMs
export VSPHERE_FOLDER='k8s'                                           # (optional) The VM folder for your VMs, defaults to the root vSphere folder if not set.
export VSPHERE_TEMPLATE='template_ubuntu-1804-kube-v1.16.3'           # (required) The VM template to use for your management cluster.
export VSPHERE_DISK_GIB='50'                                          # (optional) The VM Disk size in GB, defaults to 20 if not set
export VSPHERE_NUM_CPUS='2'                                           # (optional) The # of CPUs for control plane nodes in your management cluster, defaults to 2 if not set
export VSPHERE_MEM_MIB='2048'                                         # (optional) The memory (in MiB) for control plane nodes in your management cluster, defaults to 2048 if not set
export SSH_AUTHORIZED_KEY='ssh-rsa AAAAB...6Ix0= kuro@kuro-ubuntu01'  # (optional) The public ssh authorized key on all machines in this cluster

# Kubernetes configs
export KUBERNETES_VERSION='1.16.3'     # (optional) The Kubernetes version to use, defaults to 1.16.2
export SERVICE_CIDR='100.64.0.0/13'    # (optional) The service CIDR of the management cluster, defaults to "100.64.0.0/13"
export CLUSTER_CIDR='100.96.0.0/11'    # (optional) The cluster CIDR of the management cluster, defaults to "100.96.0.0/11"
export SERVICE_DOMAIN='cluster.local'  # (optional) The k8s service domain of the management cluster, defaults to "cluster.local"

続けて、このファイルを使って、マネジメントクラスタの構成を定義したマニフェストファイル群を生成します。この作業のための専用のコンテナイメージが用意されているので、これに食べさせます。

$ docker run --rm \
  -v "$(pwd):/out" \
  -v "$(pwd)/envvars.txt":/envvars.txt:ro \
  gcr.io/cluster-api-provider-vsphere/release/manifests:latest \
  -c management-cluster
Checking 192.168.0.201 for vSphere version
Detected vSphere version 6.7.1
Generated ./out/management-cluster/addons.yaml
Generated ./out/management-cluster/cluster.yaml
Generated ./out/management-cluster/controlplane.yaml
Generated ./out/management-cluster/machinedeployment.yaml
Generated /build/examples/pre-67u3/provider-components/provider-components-cluster-api.yaml
Generated /build/examples/pre-67u3/provider-components/provider-components-kubeadm.yaml
Generated /build/examples/pre-67u3/provider-components/provider-components-vsphere.yaml
Generated ./out/management-cluster/provider-components.yaml
WARNING: ./out/management-cluster/provider-components.yaml includes vSphere credentials

これで、./out/management-cluster 配下にマニフェストファイル群が出力されました。

$ ls -l ./out/management-cluster/
total 268
-rw-r--r-- 1 kuro kuro  19656 Feb 11 08:54 addons.yaml
-rw-r--r-- 1 kuro kuro    933 Feb 11 08:54 cluster.yaml
-rw-r--r-- 1 kuro kuro   3649 Feb 11 08:54 controlplane.yaml
-rw-r--r-- 1 kuro kuro   2576 Feb 11 08:54 machinedeployment.yaml
-rw-r--r-- 1 kuro kuro 240747 Feb 11 08:54 provider-components.yaml

で、あとはこれらを clusterctl に食べさせるだけです。

$ clusterctl create cluster \
  --bootstrap-type kind \
  --bootstrap-flags name=management-cluster \
  --cluster ./out/management-cluster/cluster.yaml \
  --machines ./out/management-cluster/controlplane.yaml \
  --provider-components ./out/management-cluster/provider-components.yaml \
  --addon-components ./out/management-cluster/addons.yaml \
  --kubeconfig-out ./out/management-cluster/kubeconfig
NOTICE: clusterctl has been deprecated in v1alpha2 and will be removed in a future version.
I0211 08:55:09.414116    2332 createbootstrapcluster.go:27] Preparing bootstrap cluster
I0211 08:55:59.745617    2332 clusterdeployer.go:82] Applying Cluster API stack to bootstrap cluster
...
I0211 08:56:02.302440    2332 clusterdeployer.go:87] Provisioning target cluster via bootstrap cluster
...
I0211 08:56:02.454960    2332 applymachines.go:46] Creating machines in namespace "default"
I0211 08:59:12.512879    2332 clusterdeployer.go:105] Creating target cluster
...
I0211 08:59:13.394821    2332 clusterdeployer.go:123] Pivoting Cluster API stack to target cluster
...
I0211 08:59:56.665878    2332 clusterdeployer.go:164] Done provisioning cluster. You can now access your cluster with kubectl --kubeconfig ./out/management-cluster/kubeconfig
I0211 08:59:56.666586    2332 createbootstrapcluster.go:36] Cleaning up bootstrap cluster.

主要なログだけ抜粋していますが、これだけで、

  1. Kind を使って、作業端末の Docker 上にブートストラップクラスタを構築する
  2. ブートストラップクラスタに Cluster API を導入する
  3. その Cluster API を使って、マニフェスト通りに vSphere 環境上にマネジメントクラスタをデプロイする
    • 仮想マシンをテンプレートからデプロイする
    • 仮想マシンをクラスタのコントロールプレーンとして構成する
  4. ブートストラップクラスタ上に構成していた Cluster API の環境をマネジメントクラスタに移行する(Pivoting)

が実行され、最終的な形でマネジメントクラスタができあがります。

完成したマネジメントクラスタへの接続に必要な情報は、./out/management-cluster/kubeconfig に保存されています。kubectl の設定ファイルをこれに切り替えてコマンドを実行すると、マネジメントクラスタ自体の情報や、machine リソースとしての自分自身の存在が確認できます。

$ export KUBECONFIG="$(pwd)/out/management-cluster/kubeconfig"

$ kubectl cluster-info
Kubernetes master is running at https://192.168.0.27:6443
KubeDNS is running at https://192.168.0.27:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

$ kubectl get machines
NAME                                       PROVIDERID                                       PHASE
management-cluster-controlplane-0          vsphere://42069f1f-21ac-45be-69b9-e94702d3062b   running

vSphere 環境では、仮想マシン management-cluster-controlplane-0 の存在が確認できるはずです。

ここまででマネジメントクラスタができたので、Cluster API 環境は完成です。あとは好きなように Cluster API を使ってゲストクラスタを作ったり消したり拡張したり縮小したりできます。

ゲストクラスタの構成

実際に、Cluster API を使って、新しくゲストクラスタを構成します。

Cluster API は、Kubernetes のお作法で Kubernetes クラスタ自体が管理できるので、つまり、クラスタの構成情報も、Pod や Deployment などほかの Kubernetes リソースと同じように、マニフェストファイルで定義されます。よって、ゲストクラスタを作るには、その構成を定義したマニフェストファイルが必要です。

本来はきちんと中身を書くべきっぽいですが、マネジメントクラスタ用のマニフェストファイルを作ったのと同じ方法でゲストクラスタ用のマニフェストファイル群も作れるので、ここではそれを利用します。

$ docker run --rm \
  -v "$(pwd):/out" \
  -v "$(pwd)/envvars.txt":/envvars.txt:ro \
  gcr.io/cluster-api-provider-vsphere/release/manifests:latest \
  -c workload-cluster-1
Checking 192.168.0.201 for vSphere version
Detected vSphere version 6.7.1
Generated ./out/workload-cluster-1/addons.yaml
Generated ./out/workload-cluster-1/cluster.yaml
Generated ./out/workload-cluster-1/controlplane.yaml
Generated ./out/workload-cluster-1/machinedeployment.yaml
Generated /build/examples/pre-67u3/provider-components/provider-components-cluster-api.yaml
Generated /build/examples/pre-67u3/provider-components/provider-components-kubeadm.yaml
Generated /build/examples/pre-67u3/provider-components/provider-components-vsphere.yaml
Generated ./out/workload-cluster-1/provider-components.yaml
WARNING: ./out/workload-cluster-1/provider-components.yaml includes vSphere credentials

ゲストクラスタの定義と、コントロールプレーンの定義が、

  • ./out/workload-cluster-1/cluster.yaml
  • ./out/workload-cluster-1/controlplane.yaml

に含まれます。また、ワーカノードの定義は、

  • ./out/workload-cluster-1/machinedeployment.yaml

です。自分でマニフェストをいじる場合は、この辺をどうにかする必要があるということですね。

実際にデプロイするには、kubectl の接続先をマネジメントクラスタに切り替えてから、先の 3 つのファイルをマネジメントクラスタに突っ込みます。

$ export KUBECONFIG="$(pwd)/out/management-cluster/kubeconfig"

$ kubectl apply -f ./out/workload-cluster-1/cluster.yaml
cluster.cluster.x-k8s.io/workload-cluster-1 created
vspherecluster.infrastructure.cluster.x-k8s.io/workload-cluster-1 created

$ kubectl apply -f ./out/workload-cluster-1/controlplane.yaml
kubeadmconfig.bootstrap.cluster.x-k8s.io/workload-cluster-1-controlplane-0 created
machine.cluster.x-k8s.io/workload-cluster-1-controlplane-0 created
vspheremachine.infrastructure.cluster.x-k8s.io/workload-cluster-1-controlplane-0 created

$ kubectl apply -f ./out/workload-cluster-1/machinedeployment.yaml
kubeadmconfigtemplate.bootstrap.cluster.x-k8s.io/workload-cluster-1-md-0 created
machinedeployment.cluster.x-k8s.io/workload-cluster-1-md-0 created
vspheremachinetemplate.infrastructure.cluster.x-k8s.io/workload-cluster-1-md-0 created

この作業によって、まずコントロールプレーンがデプロイされ、続けてワーカノードがデプロイされます。vSphere 環境でも順次仮想マシンがデプロイされパワーオンされていく様子が観察できるでしょう。

デプロイが完了すると、以下のように、マネジメントクラスタが Kubernetes クラスタ自体を cluster リソースや machine リソースとして管理できている状態になります。

$ kubectl get clusters
NAME                 PHASE
management-cluster   provisioned
workload-cluster-1   provisioned

$ kubectl get machines
NAME                                       PROVIDERID                                       PHASE
management-cluster-controlplane-0          vsphere://42069f1f-21ac-45be-69b9-e94702d3062b   running
workload-cluster-1-controlplane-0          vsphere://4206f835-1e8d-3473-943f-0e2cc4b04319   running
workload-cluster-1-md-0-78469c8cf9-fr22j   vsphere://4206661b-9be8-cede-eeee-68ddbbdeb872   running
workload-cluster-1-md-0-78469c8cf9-jnqnw   vsphere://4206861f-e133-4a53-2008-3346c81ed8e3   running

ゲストクラスタへの接続情報は、secret リソースとして保持されています。これを kubeconfig として保存することで、kubectl でゲストクラスタに接続できるようになります。

$ kubectl get secrets
NAME                            TYPE                                  DATA   AGE
...
workload-cluster-1-kubeconfig   Opaque                                1      
...

$ kubectl get secret workload-cluster-1-kubeconfig -o=jsonpath='{.data.value}' | \
  { base64 -d 2>/dev/null || base64 -D; } >./out/workload-cluster-1/kubeconfig

実際に接続すれば、当たり前ですがゲストクラスタやノードの情報が確認できます。

$ export KUBECONFIG="$(pwd)/out/workload-cluster-1/kubeconfig"

$ kubectl cluster-info
Kubernetes master is running at https://192.168.0.28:6443
KubeDNS is running at https://192.168.0.28:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

$ kubectl get nodes
NAME                                       STATUS     ROLES    AGE     VERSION
workload-cluster-1-controlplane-0          NotReady   master   3m14s   v1.16.3
workload-cluster-1-md-0-78469c8cf9-fr22j   NotReady   <none>   90s     v1.16.3

表示されている通り、この段階ではノードは NotReady です。これは CNI プラグインが構成されていないからで、雑にいえば、この Kubernetes クラスタ内のコンテナネットワークに使う実装を明示する必要があるということです。

コンテナネットワークの実装には Flannel とか Calico とかいろいろありますが、ゲストクラスタ用マニフェスト群の中にある ./out/workload-cluster-1/addons.yaml で Calico を構成できるので、今回はこれを使います。

適用してしばらく待つと、ノードが Ready になり、ゲストクラスタの完成です。

$ kubectl apply -f ./out/workload-cluster-1/addons.yaml 
configmap/calico-config created
...
serviceaccount/calico-kube-controllers created

$ kubectl get nodes
NAME                                       STATUS   ROLES    AGE     VERSION
workload-cluster-1-controlplane-0          Ready    master   4m22s   v1.16.3
workload-cluster-1-md-0-78469c8cf9-fr22j   Ready    <none>   2m38s   v1.16.3

ゲストクラスタの拡張

Kubernetes って、アプリケーションのスケールアウトが kubectl scale だけでできてめっちゃラクですよね。

というのと同じノリで、ゲストクラスタもめっちゃラクにスケールアウトできるので、やってみましょう。

ノードの管理はマネジメントクラスタから行うので、接続先を切り替えて、machinedeployment をスケールさせます。

$ export KUBECONFIG="$(pwd)/out/management-cluster/kubeconfig"

$ kubectl scale md workload-cluster-1-md-0 --replicas=3
machinedeployment.cluster.x-k8s.io/workload-cluster-1-md-0 scaled

$ kubectl get machines
NAME                                       PROVIDERID                                       PHASE
management-cluster-controlplane-0          vsphere://42069f1f-21ac-45be-69b9-e94702d3062b   running
workload-cluster-1-controlplane-0          vsphere://4206f835-1e8d-3473-943f-0e2cc4b04319   running
workload-cluster-1-md-0-78469c8cf9-fr22j   vsphere://4206661b-9be8-cede-eeee-68ddbbdeb872   running
workload-cluster-1-md-0-78469c8cf9-jnqnw   vsphere://4206861f-e133-4a53-2008-3346c81ed8e3   running
workload-cluster-1-md-0-78469c8cf9-nxvht   vsphere://4206ec88-6607-1699-8051-e1447a448983   running

これだけでノードが 3 台になりました。仮想マシンも増えています。

ノードが増えた様子

簡単ですね。

ゲストクラスタのロードバランサの構成

おまけです。

vSphere が組み込みでロードバランサを持っていないから仕方ないですが、 現状、Cluster API でゲストクラスタを構成するときには、ロードバランサは構成できません。

このままだと、ゲストクラスタで kubectl expose--type=LoadBalancer しても EXTERNAL-IP が永遠に pending のままで、外部に公開できません。

GitHub でも issue があります し、めっちゃがんばると多分オンプレミス環境でも NSX-T とかでどうにかできるとは思いますが、その域に達していないので、とりあえず MetalLB を突っ込んで解決します。

MetalLB とは

ロードバランサが使えずにサービスを外部に公開できない、というのは、ベアメタル環境で Kubernetes を使うときによく遭遇する話題のようで、そういうヒト向けの仮想ロードバランサの実装です。

実際には正しい負荷分散にはならないみたいですが、ものすごく気軽に使えますし、アクセス経路の提供という意味では充分機能するので便利です。

MetalLB の構成と初期設定

公式のドキュメント に従います。インストール用のマニフェストファイルを突っ込んだあと、

$ kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.8.3/manifests/metallb.yaml
namespace/metallb-system created
...
deployment.apps/controller created

ドキュメントの Layer 2 Configuration の通りに設定用マニフェストファイルを作って突っ込みます。IP アドレスのレンジは任意で修正します。

$ cat metallb.yaml 
apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    address-pools:
    - name: default
      protocol: layer2
      addresses:
      - 192.168.0.50-192.168.0.99

$ kubectl apply -f metallb.yaml 
configmap/config created

これだけです。

動作確認

Kubernetes のチュートリアルのヤツ を作って、

$ kubectl apply -f https://k8s.io/examples/service/load-balancer-example.yaml
deployment.apps/hello-world created

$ kubectl get pods
NAME                          READY   STATUS    RESTARTS   AGE
hello-world-f9b447754-6rrt9   1/1     Running   0          68s
hello-world-f9b447754-b6psq   1/1     Running   0          68s
hello-world-f9b447754-ml5w8   1/1     Running   0          68s
hello-world-f9b447754-nprbn   1/1     Running   0          68s
hello-world-f9b447754-wpgv5   1/1     Running   0          68s

expose します。

$ kubectl expose deployment hello-world --type=LoadBalancer
service/hello-world exposed

$ kubectl get services
NAME          TYPE           CLUSTER-IP       EXTERNAL-IP    PORT(S)          AGE
hello-world   LoadBalancer   100.69.189.221   192.168.0.50   8080:32015/TCP   6s
kubernetes    ClusterIP      100.64.0.1       <none>         443/TCP          4h55m

$ kubectl describe services hello-world
...
Endpoints:                100.113.190.67:8080,100.113.190.68:8080,100.97.109.3:8080 + 2 more...
...

EXTERNAL-IP に MetalLB で設定したレンジの IP アドレスが振られていますし、エンドポイントも 5 つです。

実際にこの IP アドレスにアクセスすると、正しく表示が返ってきます。無事に動いているようです。

$ curl http://192.168.0.50:8080/
Hello Kubernetes!

まとめ

vSphere 環境で Cluster API を使って Kubernetes クラスタを管理できる状態を整えました。

最初の作業はちょっとだけ手間ですが、いちどできてしまうとスケールも相当楽なので使いやすそうです。ロードバランサ周りが NSX-T などふくめいい感じにできるようになってくると、活用の幅も広がりそうですね。

VMware Tanzu や Project Pacific でも Kubernetes クラスタのライフサイクル管理は謳われているので、この手の作業が導入作業も含めて GUI や API 経由でポチポチ簡単にできるようになるのだろうと勝手に思っています。GA になったら触ってみます。