Skip to content

Commit

Permalink
design-proposal: persist-vmi-firmware-uuid
Browse files Browse the repository at this point in the history
This proposal introduces a mechanism to persist the firmware UUID of a
Virtual Machine Instance (VMI) in KubeVirt. By storing the firmware
UUID, we ensure that it remains consistent across VMI restarts, which is
 crucial for applications and services that rely on the UUID for
 identification or licensing purposes.

Signed-off-by: Daniel Sionov <[email protected]>
  • Loading branch information
dasionov committed Nov 7, 2024
1 parent 3b7cbd4 commit 7201c75
Showing 1 changed file with 181 additions and 0 deletions.
181 changes: 181 additions & 0 deletions design-proposals/persist-vmi-firmware-uuid.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
# Overview
This proposal introduces a mechanism to persist the firmware UUID of a Virtual Machine Instance (VMI) in KubeVirt.
By storing the firmware UUID, we ensure that it remains consistent across VMI restarts.
which is crucial for applications and services that rely on the UUID for identification or licensing purposes.

## Motivation
By definition, UUID must be a universally-unique identifier.
The current implementation for the automatically-computed Firmware UUID is not universally unique:
Two VMs with the same name get the same UUID, even if they reside in different namespaces or different clusters.
This proposal discusses how to fix this, while ensuring that existing VMs keep their current ID.

## Goals
* Generate and persist universally-unique Firmware.UUID for new VMs
* Keep the Firmware.UUID of pre-existing VMs

## Non Goals


## Definition of Users
End Users: Individuals or organizations running VMs and VMIs on KubeVirt who require consistent firmware UUIDs for their applications.

## User Stories
As an end-user, I expect my VMI to maintain its identity across restarts.

## Repos
Kubevirt/kubevirt

# Design

The introduction of a persistent, universally unique firmware UUID will proceed in two phases:

### Phase 1: Preserve Current Generation Method and Persist UUID

In this phase, we aim to minimize workload disruption by persisting the UUID generated with the current method. The goal is to ensure that VMs retain their UUID across restarts without changing the existing generation approach. Below are the potential solutions for this phase:

1. **Persist UUID in the VM’s Spec Field**
**Description:** The UUID would be generated upon the VM’s first boot and stored in the VM’s spec field.

**Pros:**
- Straightforward to implement.
- Avoids adding a new API field, fully backward compatible.

**Cons:**
- This approach "abuses" the spec by storing data that does not represent the user's desired state.
- Could lead to cluttered and harder-to-read VM definitions.


2. **Generate UUID via Webhook and Store in the Spec Field**
**Description:** If no UUID is specified by the user, a webhook generates a random UUID and assigns it to the VM’s spec field.

**Pros:**
- Similar to the first option (no new API field, backward compatible).

**Cons:**
- Adds complexity by involving webhooks, which could slow down performance if numerous VMs start simultaneously.
- May potentially bottleneck `virt-api`.


3. **Add a Firmware UUID Field to VM Status**
**Description:** Store the generated UUID within the VM’s status.

**Pros:**
- Keeps the spec clean.
- Focuses on VM status for generated information.

**Cons:**
- Could introduce a new API field, affecting long-term maintenance and adding to potential API bloat.


4. **Upgrade-Specific Persistence of Firmware.UUID**
**Description:** Just before KubeVirt is upgraded, persist the `Firmware.UUID` of existing VMs in `vm.spec`
After the upgrade, any VM without a `Firmware.UUID` in its spec will be considered new.
If `vm.spec.template.spec.Firmware.UUID` is not defined, the system defaults to using `vm.metadata.uid`.

**Pros:**
- The upgrade-specific code can be removed after two or three releases.
- Simple logic after the upgrade is completed.
- Limited disturbance to git-ops workflows, affecting only pre-existing VMs with the current method.

**Cons:**
- Requires additional code (potentially in `virt-operator`) to handle the upgrade-specific logic.



### Phase 2: Transition to Universally Unique UUID Generation

In the second phase, the approach for generating the firmware UUID will be modified to ensure global uniqueness.
This transition could include changing the UUID generation to consider both the VM name and namespace,
or adopting a pseudo-random hash to guarantee uniqueness across clusters. The solutions for this phase are outlined below:

1. **Use Namespace + Name for UUID Generation**
**Description:** Generate the UUID by combining the VM name and namespace, ensuring uniqueness within the cluster.

**Pros:**
- Simple and straightforward to implement.
- Avoids reliance on an external generator for randomness.

**Cons:**
- Introduces a breaking change, as UUIDs for existing VMs may change unless preserved.


2. **Adopt Pseudo-Random Hashing for UUID Generation**
**Description:** Use a pseudo-random hash to generate a unique UUID that does not rely on specific names or namespaces.

**Pros:**
- Ensures global uniqueness, even across clusters.
- Avoids dependence on VM names and namespaces, providing more flexibility.

**Cons:**
- Introducing randomness could make the UUID less predictable, which may impact certain workloads.
- Requires careful validation to ensure the hash remains consistent for each VM across restarts.


3. **Use `vm.metadata.uid` as the Firmware UUID**
**Description:** Use the `vm.metadata.uid`, a unique identifier assigned to each VM by Kubernetes, as the firmware UUID.

**Pros:**
- Ensures uniqueness within and across clusters, as `metadata.uid` is universally unique for each VM.
- Avoids adding new fields or complex generation logic.
- Simplifies UUID management by leveraging an existing unique identifier.

**Cons:**


By addressing each phase separately, we can balance immediate workload stability with a gradual transition to globally unique UUIDs. This approach allows for flexibility in implementation and can minimize disruption for end-users.


## API Examples
**Example uuid persistence within VM Status**

```yaml
apiVersion: kubevirt.io/v1alpha3
kind: VirtualMachine
metadata:
name: mytestvm
status:
conditions:
- lastProbeTime: "2024-11-06T01:12:29Z"
lastTransitionTime: "2024-11-06T01:12:29Z"
message: Guest VM is not reported as running
reason: GuestNotRunning
status: "False"
type: Ready
created: true
runStrategy: Once
firmwareUUID: "123e4567-e89b-12d3-a456-426614174000"
```
or persist via status condition
```yaml
apiVersion: kubevirt.io/v1alpha3
kind: VirtualMachine
metadata:
name: mytestvm
status:
conditions:
- type: FirmwareUUIDPersisted
status: "123e4567-e89b-12d3-a456-426614174000"
reason: UUIDGenerated
message: "Firmware UUID has been generated and persisted"
lastTransitionTime: "2024-11-06T01:12:29Z"
```
## Scalability
The proposed changes have no anticipated impact on scalability capabilities of the KubeVirt framework
## Update/Rollback Compatibility
should not affect updates / rollbacks.
## Functional Testing Approach
Verify that a newly created VMI has a unique firmware UUID assigned and that this UUID persists across VMI restarts.
Validate that the selected persistence mechanism (spec field, status field, or condition) stores the UUID.
Include unit tests for any logic introduced in controllers to ensure the UUID is generated and persisted correctly.
# Implementation Phases
- Based on the selected design, either introduce a new field or utilize an existing one
(such as in spec, status, or conditions) to store the firmware UUID.
- Update controller logic to check for and persist the UUID, ensuring it is generated only once per VM.
- Testing: add unit and functional tests

0 comments on commit 7201c75

Please sign in to comment.