RFC-0210:虛擬化功能轉送

RFC-0210:虛擬化能力轉送
狀態已接受
領域
  • 虛擬化
說明

定義虛擬化功能如何在平台和產品之間轉送方式。

問題
  • 115651
毛皮變化
作者
審查人員
提交日期 (年-月-日)2022-11-07
審查日期 (年-月-日)2023-02-23

摘要

本文件說明我們會如何轉送建立虛擬機器的能力 實際演練過程中的畫面建立關聯後,本文件也會說明 Fuchsia 平台內含的虛擬化功能和 API 以及產品有哪些元件

提振精神

所有虛擬化元件目前均由 Fuchsia 核心提供 平台,包括:

  • 用於模擬虛擬機器和虛擬裝置的元件
  • 提供特定訪客作業系統二進位檔的套件
  • 整合訪客專屬功能與產品的元件

這項做法有一些顯著的缺點。將所有訪客專用元件 讓產品無法整合 以產品專屬方式進行虛擬化此外,許多邀請對象會保留 保留使用者資料,而我們必須確保這類使用者資料已加密 與所有其他使用者資料一併保護本文件將說明 這點適用於各產品的差異 但許多設計都考量到 建立工作站產品做為示範

本提案的明確目標是,以虛擬化形式提供 Fuchsia 平台功能換句話說,我們會公開一系列功能 產品工作階段,能讓產品善用 不必轉送所有低層級權限 虛擬化功能必須融入工作階段本身也就是 部分,根據 RFC-0092 指南 - 工作階段RFC-0194 - 附加條款:工作階段數。 詳情請參閱「安全性 注意事項

相關人員

誰會負責確認 RFC 是否已獲接受?(這個部分為選填,但 encouraged.)

講師:

FEC 任命的人員,透過 RFC 程序處理此 RFC。

審查者:

  • 阿布杜拉
  • Alerad
  • 達哈辛
  • 吉桑基
  • Aaronwood
  • Ypomortsev

諮詢:

列出應審查 RFC,但不需經過核准的人員。

社交功能:

這份計畫的草稿是由虛擬化、相關人士和相關人員交流 元件架構和安全性

詞彙解釋

  • Virtual Machine Manager (vmm):負責模擬的元件 以及推動虛擬機器
  • 虛擬裝置:模擬單一裝置的元件 (例如 區塊、聯播網等) 即可
  • vsock:允許 0 個設定通訊端的半虛擬化通訊端裝置 連線。通常會做為 共乘者。

背景

Fuchsia 上的虛擬機器是由 Vmm (虛擬機器管理員) 驅動 元件。vmm 元件本身會管理多個子元件, 實作虛擬裝置 (例如 virtio_block.cmvirtio_net.cm 等),不過 本文件會將整組元件視為 vmmvmm 會為虛擬機器提供基本資源 (記憶體、 vcpus) 和虛擬裝置。vmm 元件適用於各訪客通用,且不支援 任何訪客 OS 專屬邏輯。每個 vmm 元件執行個體都是由 訪客 OS 專用的 GuestManager 元件,例如 TerminaGuestManagerGuestManager。包含較高層級的邏輯 和任何訪客專屬服務或功能 GuestManager 負責提供所有啟動資源 (核心、 ramdisk、區塊裝置等),以及訪客設定,例如 虛擬 CPU 數量或記憶體容量

Fuchsia 支援的每個訪客作業系統目前都是完全模擬 使用靜態元件路徑例如 TerminaGuestManager 元件 (在工作站上執行 Linux 終端機的訪客) 有一個靜態子項 由核心資料分割提供的 vmm 元件。有些路徑允許 Linux 要在工作階段中連線至 TerminaGuestManager 的終端機元件 核心領域,以及可讓訪客透過圖形 殼層 (使用 virtio-wayland)。

顯示目前能力轉送的圖表

儲存空間

GuestManager 元件會負責開啟所有檔案,並 所需裝置,以遵守 vmm 規範;vmm 本身只會收到帳號代碼 檔案、封鎖裝置或其他有狀態功能TerminaGuestManager 會在目錄中建立檔案來初始化有狀態分區 CFv2 data 儲存空間能力提供的 3D 儲存空間另一個唯讀 (有狀態) 系統會針對內含映像檔的 blobfs 檔案,提供磁碟分割 TerminaGuestManager 套件本身。

由於 TerminaGuestManager 是核心領域中的元件,因此 data 提供給 Kubernetes 的 領域。這代表工作站等有 區分為不同帳戶訂閱量 (依使用者驗證因素加密), 這個磁碟區不會放置訪客資料儲存空間, 含有使用者的機密資料。另外,如果還想 多使用者系統 如果核心領域中只有單一元件,則單一 vmm 執行個體 且資料會與所有帳戶共用,而這並非無法啟用的解決方案。

設計

希望將 vmm 元件保持在核心內是理想狀態,因為這需要多個元件 特殊權限的能力此外,因為 vmm 提供 因此,在啟動虛擬機器時,目前沒有任何產品專屬的政策或行為 vmm。從核心擷取 GuestManager 元件是理想的做法 因為這些是產品專屬的套件,可將邏輯和訪客元素 僅適用於特定產品的作業系統藉由移動 則可讓產品自由自訂core 虛擬化功能是以產品專屬的方式整合,無須處理 並能掌握低階虛擬機器模擬作業的細節

我們會推出新的核心資料分割,讓工作階段能建立「vmm」 CFv2 集合中的元件執行個體,但必須提供任何狀態 由用戶端管理。屆時,我們會以虛擬方式 機器使用能力轉送,而非使用 vmm.cm 做為靜態子項 每個 GuestManager 元件這樣我們就能移動 GuestManager 將元件插入工作階段,而不必移動 Vmm 本身 嵌入工作階段也就是說,我們保留 vmm,也就是產品和訪客。 在core中跨平台也能使用產品,並將特定產品的GuestManagers移至 會很有幫助

為此,我們將推出新的 VmmLauncher 元件來處理 vmm 元件。這個元件會公開相同的 GuestLifecycle 通訊協定 所有由 vmm 公開的資訊差別在於 GuestLifecycleVmmLauncher 會建立新的 vmm 執行個體 每個 GuestLifecycle 連線,並轉送 FIDL 管道的伺服器端 新增至新元件GuestLifecycle 通訊協定用於初始化 VM 再開始執行作業

顯示建議能力轉送圖表

/// The guest control plane allows for creating, starting, and stopping the guest.
protocol GuestLifecycle {
    /// Create a VMM configured with the provided config. This instantiates all
    /// devices and loads the kernel without starting the VCPU or device dispatch
    /// loops.
    ///
    /// `Create` must not be called after a call to `Run` until `Stop` is called.
    /// Once a guest has been stopped with a call to `Stop`, then `Create` may be
    /// called again to re-initialize the guest.
    Create(resource struct {
        guest_config GuestConfig;
    }) -> (struct {}) error GuestError;

    /// Binds to the Guest protocol for an initialized guest.
    ///
    /// This operation must be called between `Create` and `Stop`, otherwise
    /// the provided channel will be immediately closed.
    Bind(resource struct {
        guest server_end:Guest;
    }) -> (struct {}) error GuestError;

    /// Start the VCPU and device dispatch loops. This will not return until the
    /// dispatch loops exit. On a clean shutdown (either guest or client initiated)
    /// this will return success.
    ///
    /// If forced to stop by the guest manager calling stop, a SHUTDOWN_FORCED
    /// error will be returned. This will also return any runtime error that forces
    /// the guest to stop.
    ///
    /// `Run` must only be called after a call to `Create`. Once a guest is stopped with
    /// a call to `Stop`, then `Run` may not be called again until `Create` is called
    /// to re-initialize the guest. Notably, we do not support calling `Stop`
    /// and then `Run` directly; the call to `Create` after `Stop` is a requirement.
    Run() -> (struct {}) error GuestError;

    /// Stop a running VMM. Returns once the dispatch loops have stopped. After
    /// Stop returns, `Create` and then `Run` can be called again.
    Stop() -> ();
};

type GuestError = strict enum {
    /// Catch all VMM error.
    INTERNAL_ERROR = 1;

    /// A device endpoint was requested via the guest client API, but the device isn't enabled.
    DEVICE_NOT_PRESENT = 2;

    /// The config failed VMM validation for reasons such as a missing required field.
    BAD_CONFIG = 3;

    /// The VMM failed to initialize the guest object, usually due to capability routing issues
    /// or memory layout problems.
    GUEST_INITIALIZATION_FAILURE = 4;

    /// The VMM failed to initialize a device.
    DEVICE_INITIALIZATION_FAILURE = 5;

    /// The VMM failed to start a device, usually because the device component returned a failure.
    DEVICE_START_FAILURE = 6;

    /// Two or more devices have attempted to register overlapping memory ranges.
    DEVICE_MEMORY_OVERLAP = 7;

    /// Failed to connect to a required service. Check the routing in the manifest.
    FAILED_SERVICE_CONNECT = 8;

    /// Failed to add a public service.
    DUPLICATE_PUBLIC_SERVICES = 9;

    /// General error when loading the guest kernel.
    KERNEL_LOAD_FAILURE = 10;

    /// Error when starting a VCPU.
    VCPU_START_FAILURE = 11;

    /// A VCPU encountered a fatal error while running.
    VCPU_RUNTIME_FAILURE = 12;

    /// The VMM was asked to run before it was created.
    NOT_CREATED = 13;

    /// A VMM is already running. The VMM must be stopped and a new VMM must be created before it
    /// can be run again.
    ALREADY_RUNNING = 14;

    /// A running VMM was forced to stop by the VMM controller.
    CONTROLLER_FORCED_HALT = 15;
};

公開提供給用戶端設定的參數集包括 GuestConfig FIDL 資料表。這樣就能設定機器類型 (vcpu 和記憶體) 以及可用的虛擬裝置。

type GuestConfig = resource table {
    /// Type of kernel to load.
    1: kernel_type KernelType;
    /// File to load the kernel from.
    2: kernel client_end:fuchsia.io.File;
    /// File to load the initial RAM disk from.
    3: ramdisk client_end:fuchsia.io.File;
    /// File to load the dtb overlay for a Linux kernel from.
    4: dtb_overlay client_end:fuchsia.io.File;
    /// Kernel command-line to use.
    5: cmdline string:MAX;
    /// Additional kernel command-lines to append to the main command-line.
    6: cmdline_add vector<string:MAX>:MAX;
    /// The number of CPUs to provide to a guest.
    7: cpus uint8;
    /// Amount of guest memory required, in bytes. This value may be rounded up
    /// depending on the system configuration.
    8: guest_memory uint64;
    /// A list of block devices to give a guest. Cannot be changed from the
    /// command-line.
    9: block_devices vector<BlockSpec>:MAX_BLOCK_DEVICES;
    /// A list of specifications for network devices.
   10: net_devices vector<NetSpec>:MAX_NET_DEVICES;
    /// Optional virtio-wl device.
   11: wayland_device WaylandDevice;
    /// Optional virtio-magma device.
   12: magma_device MagmaDevice;
    /// Whether to add a default network device.
   13: default_net bool;
    /// Enable virtio-balloon.
   14: virtio_balloon bool;
    /// Enable virtio-console.
   15: virtio_console bool;
    /// Enable virtio-gpu.
   16: virtio_gpu bool;
    /// Enable virtio-rng.
   17: virtio_rng bool;
    /// Enable virtio-vsock.
   18: virtio_vsock bool;
    /// Enable virtio-sound.
   19: virtio_sound bool;
    /// Enable input streams (capture) for virtio-sound.
   20: virtio_sound_input bool;
    /// Host ports to listen for guest initiated vsock connections on. This can be
    /// used for simplicity if a Listener is known at config creation time, or if a
    /// Listener must be available at the moment of guest creation for timing
    /// reasons.
    /// To add a Listener after a guest starts, see HostVsockEndpoint::Listen.
   21: vsock_listeners vector<Listener>:MAX;
};

Guest 通訊協定可讓您從 VM 存取執行階段服務。

/// A `Guest` provides access to services of a guest instance.
protocol Guest {
    /// Get a guest console.
    ///
    /// The details regarding what output is produced and what input is accepted
    /// are determined by each guest, but will typically be a read/write socket
    /// with a shell.
    ///
    /// Returns ZX_ERR_UNAVAILABLE if the guest has no configured console.
    GetConsole() -> (resource struct {
        socket zx.handle:SOCKET;
    }) error zx.status;

    /// Get the socket for low-level guest debug logs.
    ///
    /// The details regarding what output is produced and what input is accepted
    /// are determined by each guest, but will typically be a read-only socket
    /// with the guest kernel's serial logs.
    GetSerial() -> (resource struct {
        socket zx.handle:SOCKET;
    }) error zx.status;

    /// Get the vsock endpoint for the guest.
    ///
    /// This endpoint can be used to register listeners for guest initiated
    /// connections, and to initiate connections from a client. If listeners need
    /// to be registered before the guest starts so that they are immediately
    /// available, set them via the `GuestConfig` instead of using this protocol.
    ///
    /// Returns error VSOCK_NOT_PRESENT if the guest was started without a vsock
    /// device.
    GetHostVsockEndpoint(resource struct {
        endpoint server_end:HostVsockEndpoint;
    }) -> (struct {}) error GuestError;

    /// Get the balloon controller endpoint for the guest.
    ///
    /// Returns error BALLOON_NOT_PRESENT if the guest was started without a
    /// balloon device.
    GetBalloonController(resource struct {
        controller server_end:BalloonController;
    }) -> (struct {}) error GuestError;
};

實作

我們會透過核心中的元件實作 VmmLauncher vmm_launcher.cm。此元件會管理 CFv2 集合 發布 vmm 元件。之後,GuestManager 元件會更新 從其 "parent" 存取 GuestLifecycle 能力,而不是 靜態的子項。系統會使用核心資料分割來提供 vmm_launcher.cm /core/virtualization。我們選擇公開 做為 virtualization 的資料分割,因為任何 支援虛擬化功能

然後,我們會在產品工作階段公開 GuestLifecycle 通訊協定,並 請更新工作站產品工作階段,加入 TerminaGuestManager

工具、診斷和開發人員人體工學

我們必須確保, 產品。都是使用手動新增的額外核心資料分割來完成 對建構中的元件 套用 GN 引數每個核心資料分割都支援 。這個提案沒有任何項目需要調整運作方式,但 從 vmm 及其相關聯的裝置 負責將大多數能力路徑導向訪客管理員 資料分割。

以日後的工作來說,我們可以變更發布 GuestManager 元件的方式 開發用途簡單的房客 (例如 debianzircon) 不需要任何 除了 GuestLifecycle 以外,我們也支援啟動這類功能 以減少 需要核心領域資料分割,才能支援虛擬化工作流程。

安全性考量

vmm 需要一些特殊權限才能正確運作 (例如: HypervisorResource/dev 目錄)。這種設計可避免 這些特殊權限功能給這個工作階段。

這項設計的其中一項能力差異在於,我們之前提供的通訊協定 一個 VM 執行個體 (例如 fuchsia.virtualization.TerminaGuestManager),現在我們將提供 來建立任意數量的 VM 執行個體 fuchsia.virtualization.GuestManager 通訊協定。這項能力已經公開 只會透過 vmm 元件啟動工作階段,我們將不允許啟動工作階段 新增至包含 vmm 例項的集合中。

由工作階段建立的所有邀請對像都會在GuestLifecycle時停止 管道已關閉,以確保在使用者工作階段結束後,沒有任何訪客繼續放送 已停止。

為避免 vmm 執行個體之間外洩狀態,可變動目錄功能 會從對應的vmm 與每個執行個體相關聯的 GuestManager 元件,而非 靜態轉送共用目錄能力這也適用於工作階段 以一致的方式管理及保護有狀態 VM 資料

說明文件

產品使用虛擬化的方式,會詳細記錄在新的 部分。這包括 並詳細說明產品工作階段可使用的 FIDL 通訊協定組合,以及 和最佳做法

測試

為了配合這項異動,所有現有的整合測試將轉換為 請使用 vmm_launcher 來展示正確功能。我們也會 探索可能的方法對 vmm_launcher 進行模糊測試,以確認 vmm 執行個體不會轉送有狀態的共用功能。

考慮的替代品

移除使用 VmmLauncher 元件的需求

本文件中建議的 vmm_launcher.cm 沒有任何作用 只會將元件建立成集合 傳入連線要求。這個屬性可由 元件架構,方便我們移除此元件。適用對象 舉例來說,為了支援這個元件架構 同質的元件集合您不需要在 接著,每次連結元件時,系統就會自動啟動 。

新增自訂元件來執行此作業並非耗費大量工作 是常見的模式,請考慮將此項目加入元件 直接建構架構

新增明確的 VmmLauncher 通訊協定

請勿間接建立新的 vmm 元件以回應連線 加入現有的 GuestLifecycle 通訊協定,我們可以建立新的已命名通訊協定 用於 VmmLauncher。如果我們發現 必須擴大 API 範圍才能納入更多功能

library fuchsia.virtualization;

@discoverable
protocol VmmLauncher {
    /// Launches a new, uninitialized virtual machine. The bound
    /// `GuestLifecycle` can be used to initialize the VM and start or stop it.
    ///
    /// The VM will be stopped and the component destroyed when the
    ///`GuestLifecycle` channel is closed.
    Launch(resource struct {
        lifecycle server_end:GuestLifecycle;
    });

    /// ... other functionality ...
};

由於我們尚未要求任何其他功能,因此建議優先採用 改用現有的通訊協定組合