ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
macOSやLinuxの仮想マシンの作成
Virtualizationフレームワークを使用して、Mac上に仮想マシンをすばやく作成する方法をご覧ください。仮想Macを作成し、分離された環境でAppの変更をすばやくテストする方法を紹介します。また、Appleシリコンに完全なLinuxディストリビューションをインストールして実行する方法をはじめ、Rosetta 2を活用して、x86-64 Linuxバイナリを実行する方法についても解説します。
リソース
関連ビデオ
WWDC23
-
ダウンロード
(軽快な音楽)
Benjamin Poulain: 仮想化のセッションへようこそ 本日の内容を説明します Appleシリコン上の仮想マシンでの macOSやLinuxの実行方法を見ていきます セッション後にはご自身の Macで 同様の事ができるはずです 少し大変そうに思えますが諦めずに 一緒にやって行きましょう 本日の進行内容です まずは仮想化テクノロジーの概要から始め Virtualizationフレームワークの使い方を見ていきます そして macOSにおいて掘り下げていきます 仮想の Macを作成し macOS をインストールします その後は Linuxで掘り下げていきます 完全な Linuxディストーションや 新機能の実行方法を見ます まずは概要からです 最初は仮想化を有効化する スタックを見ましょう 全てはハードウェアから始まります AppleシリコンにはCPUや メモリの仮想化を有効化する 特別なハードウェアがあります つまり単一SoCに加えて 複数のOSを実行できるのです このハードウェアを活用する ソフトウェアが必要で macOSカーネルに直接搭載されています もうカーネルエクステンション つまりKEXTを書く必要はありません 全て搭載済みです Appからこれらの機能を使うには Hypervisorフレームワークを使います CPUやメモリの仮想化を 可能にする低レベルAPIです しかし低レベルのフレームワークなので 仮想環境の詳細を逐一書かなければなりません フル機能のOSを実行したい場合が多いため 高レベルAPIのVirtualizationフレームワークがあり Appleシリコン上でmacOSを動かしたり AppleシリコンとIntelの両方でLinuxを動作させる 仮想マシンを作成することができます 本日のセッションの焦点は Virtualizationフレームワークです その使用時には2種類のオブジェクトを扱います まずはコンフィグレーション・オブジェクトで 仮想マシンの全プロパティを定義します 2つ目は仮想マシンオブジェクトで 仮想マシンやインタラクション方法を 抽象化します コンフィグレーションから見ていきましょう これはハードウェアを定義するもので その作成は Apple Storeで購入する Macをカスタムするのに似ています CPUの数やメモリの大きさ デバイスの種類を定義します 単純なコンフィグレーションから始めましょう コンテンツを表示するディスプレイを加えます タイプができるようキーボードを追加します UIを使うトラックパッドを加えます 仮想マシンのコンフィグレーションは これで完了です しかし相手は仮想マシンなので 全てコードで行います Swiftでどのように書けるか見てみましょう ハードウェアの定義は非常に単純です VZVirtualMachineConfiguration オブジェクトから始めます 全コンフィグレーションの ルートオブジェクトです 次にマシンが持つ CPUの数を決めましょう ここでは 4 CPUです 次はメモリの大きさです ここでは4GBのメモリを与えています 最後に マシンの持つデバイスの定義です この例では単一のストレージデバイスと マウスなどのポインティング デバイスを設定します 多くのデバイスが用意されていて 解決したい問題に応じて選ぶことになります ではコンフィグレーションです VZVirtualMachineConfigurationで始まります そこに CPUやメモリデバイスを追加します 次に仮想マシンオブジェクトを見ていきます
Macのコンフィグレーションが終わると 郵送で届きます 中身を開けて始めましょう ですが相手は仮想マシンなので コードを使って行います Swiftでどのようにできるか見てみましょう まずは VZVirtualMachineのインスタンスを コンフィグレーションから作ります これで仮想ハードウェアの インスタンスを抽象化します さあ 実際に動かせる仮想マシンができました このケースでは start() と呼び出して起動します 仮想マシンとインタラクトしたい場合 便利な他のオブジェクトが用意されています 例えば仮想ディスプレイを表示したいなら VZVirtualMachineViewが使えます ビューの作成から始めます ビューで仮想マシンを “virtualMachine”と設定すれば 準備完了です これで一般の NSViewと同様に使えるわけです Appに組み込めば 仮想マシンのコンテンツが見られます
コンフィグレーションのまとめです VZVirtualMachineConfigurationから始まり そこから CPUやメモリやデバイスを定義します コンフィグレーションから仮想マシンを作り 仮想マシンオブジェクトを使います VZVirtualMachineが仮想マシン自体を抽象化し VZVirtualMachineViewがコンテンツを表示し 仮想マシンの使用に役立つ その他のオブジェクトもあります コンフィグレーションは仮想マシンの定義を かなり柔軟に行えます 残念ながら1セッションでは 全てをカバーできません このセッションではいくつかの コアとなる機能について見ていきます その他に関してはドキュメントがありますので どうぞご覧になってください 概要では仮想マシンの作り方を見ただけです 次はフルOSの実行方法を見ていきましょう まずは macOSです Virtualizationフレームワークは AppleシリコンでmacOSをサポートします Appleシリコンで仮想化フレームワークを 作った時 macOSとVirtualizationフレームワークを 同時に開発しました そのため仮想マシン内でmacOSを実行すると 信じられないほどの効率になっています それでは内容です まずは仮想マシンを 仮想Macに変えるために必要なものについて 次に仮想Macに macOSを インストールする手順です そして macOS用の特別なデバイスについて 最後は非常に重要なユースケースで ホストと仮想Mac間のファイル共有です
ではコンフィグレーションです 一般的な仮想マシンの作り方を見てきましたね それを Macにするための 特別なプロパティを追加します ではどのように仮想Macが作れるのでしょうか? まず特別なプラットフォームを定義します プラットフォームとは 特定の仮想マシンの全プロパティを 保持するオブジェクトです 仮想Macのハードウェアには 特有の3つのプロパティがあります まずはハードウェアモデルで 作りたい仮想Macのバージョンを 特定するものです 次に補助記憶装置で システムが使用する 不揮発性メモリのフォームです 3つ目はマシン識別子で マシンを示す特有の数字であり 実際の Macに 特有のシリアル番号があるのと同様です プラットフォームができれば ほぼ準備完了ですが macOSをブートする方法が必要です そのために使う特殊なブートローダがー macOSブートローダです Swiftでこの全てをどのように行うのでしょうか 前と同じベースで始めます コードは概要で見たものと同じです VZMacPlatformConfigurationを作ります これは仮想Mac用の プラットフォームオブジェクトです この Mac用のハードウェアモデルが必要です 前に保存したものを使います 仮想マシンでは補助記憶装置はローカルの ファイルシステム内のファイルに 支えられています ここではファイルの URLから 補助記憶装置を初期化します 前に保存したものから VZMacMachineIdentifierを 初期化しています 新規にインストールする場合は 新しい識別子を作成することもできます 3種のプロパティを設定し プラットフォームは準備完了です あとはコンフィグレーション オブジェクトに設定するだけです これでハードウェアは完了で 次はブートする方法です VZMacBootLoaderでブートローダを設定します これでブートの準備完了です 仮想Macの定義とその起動方法を見てきました ですがソフトウェアが必要で そのインストレーションを見ていきます macOSのインストールには3段階あります まずはインストールしたいmacOSバージョンの リストアイメージをダウンロードします このバージョンと互換性のある コンフィグレーションを 作成する必要があります 最後に互換性のある仮想マシンに リストアイメージをインストールします まずはリストアイメージのダウンロードです リストアイメージはDeveloper Webから ダウンロードできますが Virtualizationでも対応可能です VZMacOSRestoreImage.latestSupportedを 呼び出して 最新の安定版の restoreImage オブジェクトが入手できます その中の URL ロパティで ファイルがダウンロードできます ダウンロードした macOSと互換性のある 仮想マシンを作っていきます ここでも仮想化を使えます リストアイメージオブジェクトに 構成要件を問い合わせます リストアイメージが現状のシステムで 実行可能であれば 要件を列挙したオブジェクトが出てきます 要件から このmacOSを実行するのに必要な ハードウェアモデルが分かります ハードウェアモデルの復元方法は 前に見ましたね 新規で取得する方法をお見せします
要件の中に2つの有効なプロパティがあります この macOSの実行に必要な CPUの数とメモリのサイズを オブジェクトが教えてくれます ようやくインストレーションを 始める準備ができました コンフィグレーションから 新たしい仮想マシンを作ります 次にインストーラを作ります インストーラには2つの引数が必要で 作成した互換性のある仮想マシンと ダウンロードしたリストアイメージへのパスです install() を呼び出せば もう macOSの実行準備完了です これで仮想macを設定し macOSをインストールできますが Mac用の特別デバイスをいくつか見てみましょう まずは GPUアクセラレーションです GPU機能を仮想macに公開する グラフィック装置を 作成しました これで仮想マシンでMetalの実行が可能になり macOSで素晴らしい グラフィックス性能が実現します ではやってみましょう
まずはグラフィック装置の コンフィグレーション作成です ここで使うのは VZMacGraphicsDeviceConfiguration 次はディスプレイの設置です サイズとピクセル密度を決めて ディスプレイを設定します これでデバイスの コンフィグレーションは準備完了です ここでもメイン構成オブジェクトに設置します 仮想マシンのグラフィック装置として 設置します
次は Macとインタラクトする新デバイスです macOS Venturaでは トラックパッドのサポートを 仮想macに加えています これによりローテーション ピンチやズームなど ジェスチャーの使用が可能になりました この新らしいデバイスには 新しいドライバを使います それを使うためにはホストシステムと 仮想マシンの両方でmacOS 13が必要です 設定方法を見ましょう とても簡単です VZMacTrackpadConfigurationで 新しいオブジェクトを作ります それを仮想マシンのポインティング デバイスに設定します これで仮想macのビューで ジェスチャーが使えます 最後に頻繁に使われる ホストシステムと仮想マシン間の ファイル共有です macOS 12にはLinuxとファイル共有する Virtioが導入されています macOS Venturaでは macOSのサポートを追加しています 仮想マシンと共有したいフォルダを 選べるようになったのです ホストシステムでの変更は 瞬時に仮想マシンに反映され その逆も然りです 設定してみましょう 先ずは共有したいディレクトリで VZShareDirectoryを作ります 次に共有オブジェクトを作ります ここでは単一ディレクトリの共有に VZSingleDirectoryShareを使います VZMultipleDirectoryShareなら 複数ディレクトリの共有も可能です 共有ができたので今度はデバイスの作成です 特別なものから始めますよ ファイルシステムデバイスは タグで識別されます macOS Venturaには特別なタグがあり 仮想マシンにこのデバイスの 自動マウントを指示します ここで使う特別なタグは macOSGuestAutomountTagです そしてデバイスを作り特別なタグを使います 構成した単一ディレクトリから共有を設定します 最後にデバイスを コンフィグレーションに追加します 最後にデモですべてを一緒に見てみましょう まず最初は基本のコンフィグレーションです VZVirtualMachineConfigurationにあるのは CPUとメモリとキーボードとディスクのみです 仮想macを作りたいので プラットフォームの設定から始めていきます そのための createMacPlatformは 上に定義してあります 仮想mac作成に次に必要なのはブートローダです macOSのブート方法が分かる ブートローダが必要です そのためにプラットフォームのブートローダを VZMacOSBootLoader() に設定します 次はデバイスの設定です 高速グラフィック処理のために VZMacGraphicsConfigurationを設定します オブジェクトを作成し ディスプレイのサイズとピクセル密度を定義し コンフィグレーションに追加します 次は新しいトラックパッドです ポインティングデバイスを VZMacTrackpadConfigurationに 設定するだけで終わりです できました これで仮想マシンを起動できますが もう少し続きます ディレクトリの共有方法を見てきましたね ここでやりましょう まずファイルシステムデバイスの コンフィグレーション作成です その自動マウントを macOSに指示する 特別タグを使いますよ そして共有の定義です ファイルシステムのパスから 単一ディレクトリを使います 今 編集中のプロジェクトを共有しましょう
デバイスをコンフィグレーションに 追加して終わりです 全て準備完了です Appを立ち上げます MacGraphicsデバイスを 構成したので VZVirtualMachineViewで コンテンツが見えます ウィンドウにはこのように表示されます これで macOSを1から作成しました 共有ディレクトリも 編集中のプロジェクトも見えます 最後に Linuxに移ります Virtualizationフレームワークは macOS Big Surの当初から Linuxをサポートしてきました macOS Venturaでは いくつかの 便利な新機能も追加され それを皆さんにお見せします
まず Linuxディストリビューションを 一切変更なしで 仮想マシンに完全に イントールする方法を見ます 次に LinuxのUIを示すために追加する 新しいデバイスについて見ます 最後に Rosetta 2を利用してLinuxバイナリを 仮想マシンで実行する方法を見ていきます まずはインストールについてです 実際のマシンの場合は インストーラ付きのISOファイルを ダウンロードします そしてISOファイルを フラッシュドライブに復元 ドライブをコンピュータに差し込み そこからブートします 仮想マシンの場合も同様のフローで行います ですがこの場合で使うのは 仮想の USBドライブです やってみましょう ダウンロードした ISOファイルの パスから URLを作ります ファイルからディスクイメージの アタッチメントを作ります これはデバイスに添付できる ストレージの一部を表しています 次に仮想ストレージデバイスを構成します ここでは USBストレージが欲しいので VZUSBMassStorageDeviceConfiguration を使います そして最後はいつものように メインのコンフィグレーションに デバイスを追加します USBデバイスの隣に出てきた もう1つのストレージデバイスの メインディスクが Linuxのインストール先です これで USBドライブができましたが そこからのブートが必要です macOS Venturaには EFIへの サポートが追加されています EFIは ARMとIntel両ハードウェアを ブートする業界標準です 仮想マシンにも同様のサポートを導入しました EFIにはブートディスカバリーの 仕組みがあります これによって USBドライブの インストーラが発見できます EFIは個々のドライブを見て ブート可能なものを見つけます インストーラが見つかれば次に進みます インストーラ自体が EFIに 次に使うドライブを教えます インストール後は EFIが Linux ディストリビューションを起動します コードを使った EFIの 設定方法を見てみましょう まず VZEFIBootLoaderで ブートローダを作ります EFIはシャットダウンとブートの間の 情報保存に不揮発性メモリが必要です EFI変数ストアと呼ばれています 仮想マシンではファイルシステムの ファイルによって このようなストレージを支えられます 新しい変数ストアを1から作っていきます これで EFIができました あとはコンフィグレーションの ブートローダとしての設定です 次は Linux仮想マシンの新機能 グラフィックスです macOS Venturaでは Virtio GPU 2Dのサポートを追加しました Virtio GPU 2Dは準仮想化デバイスで これにより Linuxが ホストの macOSに サーフェスを提供できるのです Linuxがコンテンツを描画し 描画されたフレームを Virtualizationフレームワークに渡し Virtio フレームワークがそれを表示します macOSと同様にVZVirtualMachineViewで このコンテンツをAppに表示できます やってみましょう
デバイスの設定方法はmacOSの時と似ています VZVirtioGraphicsDeviceConfiguration を作りましょう 仮想ディスプレイのサイズを定義していきます Virtio用語では 仮想ディスプレイは スキャンアウトと言います ディスプレイのサイズで スキャンアウトを作ります 最後に新しいデバイスを コンフィグレーションの グラフィックスデバイスに設定します 仮想マシンのコンテンツ表示の 準備ができました デモで全てを通して見てみましょう 中断した所から始めましょう Mac専用のコードを消去していきます そしてブート元のディスクを変更しましょう パスを Macドライブから Linuxドライブに取り替えます 次に必要なのはブートローダです VZEFIBootLoaderでEFIを設定します まず EFIブートローダオブジェクトを 作成します 次にそのファイルから 変数ストアをロードします 最後に EFIをブートローダとして コンフィグレーションに設定します これでブート可能ですが UIを表示したほうがいいですね コンフィグレーションに Virtio GPUを追加しましょう VZVirtioGraphicsDeviceConfigurationで グラフィックスデバイスを作成します 仮想ディスプレイのサイズで スキャンアウトを定義します Virtio GPUをグラフィックスデバイスとして コンフィグレーションに設定します 最後はマウスの作成です 仮想USBのスクリーンコーディネート ポインタデバイスを使って Linuxのマウスができました 完了ですプロジェクトを実行できます EFIがディスクを見て ブート可能か判断します Linuxは Virtio GPUデバイスで UIのコンテンツを表示します マウスを使って Linuxとインタラクト可能です 最後になりましたがLinuxでの Rosetta 2の利用方法を見てみましょう 我々の多くは Mac上でのサービスの 開発に熱心ですが 一旦完成すると 作成したバイナリは 恐らく x86サーバーで実行する必要があります x86エミュレーションがこれに適していますが もっと良い方法があります macOS VenturaではRosetta 2のパワーを Linuxバイナリに導入しました
Rosetta 2は 仮想マシン内の Linux x86-64バイナリを 翻訳してくれます つまり好きな ARM Linux ディストリビューション上で x86-64 AppをRosettaで実行可能です しかも高速です Macで使用してきたのと同じテクノロジーで 信じられないほどの性能をみせてくれます 使い方を見てみましょう まず Linuxに Rosettaへのアクセスを与えます 使うのは macOSの時と同じ ファイル共有テクノロジーです フォルダ共有の代わりに VZLinuxRosettaDirectoryShareという 特別なオブジェクトを使います そして共有デバイスを作り Rosettaディレクトリ共有を設定し 最後にまたデバイスを コンフィグレーションに設定します これで仮想マシンはRosetta使用ができます 次に Linuxがいかにそれを利用できるかです
まずファイルシステムに 共有ディレクトリをマウントします Linuxから Appを翻訳する Rosettaバイナリが見えます update-binfmtsを使って x86-64バイナリはRosettaで処理するように システムに指示します このコマンドを覚える必要はありません 全てドキュメントされています Linuxは準備完了です 起動したx86-64バイナリを Rosettaが翻訳します
Linuxセクション終了の前に 全て合わせて見てみましょう スクラッチからインストールした完全な Linuxディストリビューションがあります Virtio GPU 2Dで UIが表示できます 仮想マシン内では Rosettaで PHPサーバーを実行しています macOSホストから接続することができます
仮想マシンの作成がかつてないほど シンプルになりました Virtualizationフレームワークなら ほんの数行のコードで 仮想マシンが実行できます また仮想マシンは macOSで 驚くほどの速さをみせます 仮想化についての詳細は コードサンプルと ドキュメンテーションをご覧ください 是非 このテクノロジーで 可能性を広げてください (軽快な音楽)
-
-
4:11 - Running the virtual machine
let virtualMachine = VZVirtualMachine(configuration: configuration) try await virtualMachine.start()
-
4:33 - Showing the virtual machine’s display
let virtualMachineView = VZVirtualMachineView() virtualMachineView.virtualMachine = virtualMachine
-
7:43 - Start from the base
var configuration = VZVirtualMachineConfiguration() configuration.cpuCount = 4 configuration.memorySize = (4 * 1024 * 1024 * 1024) as UInt64 configuration.storageDevices = [newBlockDevice()] configuration.pointingDevices = [newPointingDevice()]
-
7:47 - Set up the platform
let platform = VZMacPlatformConfiguration() let hardwareModel = VZMacHardwareModel(dataRepresentation: savedHardwareModel) platform.hardwareModel = hardwareModel! let auxiliaryStorage = VZMacAuxiliaryStorage(contentsOf: auxiliaryStorageURL) platform.auxiliaryStorage = auxiliaryStorage let machineIdentifier = VZMacMachineIdentifier(dataRepresentation: savedIdentifier) platform.machineIdentifier = machineIdentifier! configuration.platform = platform
-
8:31 - Boot loader
configuration.bootLoader = VZMacOSBootLoader()
-
9:16 - 1. Getting an image
let restoreImage = try await VZMacOSRestoreImage.latestSupported try await download(restoreImage.url)
-
9:29 - 2. Create a compatible configuration
let requirements = restoreImage.mostFeaturefulSupportedConfiguration guard let requirements = requirements else { // No compatible configuration. return } platform.hardwareModel = requirements.hardwareModel configuration.cpuCount = requirements.minimumSupportedCPUCount configuration.memorySize = requirements.minimumSupportedMemorySize
-
10:10 - 3. Install macOS
let virtualMachine = VZVirtualMachine(configuration: configuration) let installer = VZMacOSInstaller(virtualMachine: virtualMachine, restoringFromImageAt: imageURL) try await installer.install()
-
10:58 - Setting up GPU acceleration
let graphicsConfiguration = VZMacGraphicsDeviceConfiguration() graphicsConfiguration.displays = [ VZMacGraphicsDisplayConfiguration(widthInPixels: 1920, heightInPixels: 1200, pixelsPerInch: 80) ] configuration.graphicsDevices = [graphicsConfiguration]
-
11:48 - Setting up the Mac trackpad
let trackpad = VZMacTrackpadConfiguration() configuration.pointingDevices = [trackpad]
-
12:33 - Share a folder
let sharedDirectory = VZSharedDirectory(url: directoryURL, readOnly: false) let share = VZSingleDirectoryShare(directory: sharedDirectory) let tag = VZVirtioFileSystemDeviceConfiguration.macOSGuestAutomountTag let sharingDevice = VZVirtioFileSystemDeviceConfiguration(tag: tag) sharingDevice.share = share configuration.directorySharingDevices = [sharingDevice]
-
16:10 - Setting up USB Mass Storage device configuration
let diskImageURL = URL(fileURLWithPath: "linux.iso") let attachment = try! VZDiskImageStorageDeviceAttachment(url: diskImageURL, readOnly: true) let usbDeviceConfiguration = VZUSBMassStorageDeviceConfiguration(attachment: attachment) configuration.storageDevices = [usbDeviceConfiguration, createBlockDevice()]
-
17:27 - Booting Linux
let efi = VZEFIBootLoader() efi.variableStore = VZEFIVariableStore(creatingVariableStoreAt: storeURL, options: []) configuration.bootLoader = efi
-
18:24 - Setting up Virtio graphics
let virtioGPU = VZVirtioGraphicsDeviceConfiguration() virtioGPU.scanouts = [ VZVirtioGraphicsScanoutConfiguration(widthInPixels: 1280, heightInPixels: 720) ] configuration.graphicsDevices = [virtioGPU]
-
21:02 - Setting up Rosetta
let rosettaDirectoryShare = try! VZLinuxRosettaDirectoryShare() let directorySharingDevice = VZVirtioFileSystemDeviceConfiguration(tag: "RosettaShare") directorySharingDevice.share = rosettaDirectoryShare configuration.directorySharingDevices = [directorySharingDevice]
-
21:37 - Setting up Linux
mount -t virtiofs RosettaShare /mnt/Rosetta sudo /usr/sbin/update-binfmts --install rosetta /mnt/Rosetta/rosetta \ --magic "\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x3e\x00" \ --mask "\xff\xff\xff\xff\xff\xfe\xfe\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff" \ --credentials yes --preserve no --fix-binary yes
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。