Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

design-proposal: Generating disk serial numbers #305

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
202 changes: 202 additions & 0 deletions design-proposals/generated-disk-serial.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
# Overview
This proposal introduces a new feature in KubeVirt to automatically
generate serial numbers for each disk attached to a virtual machine.
akrejcir marked this conversation as resolved.
Show resolved Hide resolved

## Motivation
- Windows guest OS in the VM requires that disk serial numbers are defined and persistent across reboots.
- Generating the serial reduces manual configuration.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reference (doc or implemention) how this is addressed in other virtualization management system, especially oVirt and OpenStack?

Copy link
Author

@akrejcir akrejcir Jul 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will check oVirt code.

@lyarwood , do you know how this is done in OpenStack? Or can you point me to docs or source, where I could find it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@akrejcir we talked about introducing persistent serials for the longest time but could never implement it due to a mountain of tech debt we had in the codebase. The following design was as far as we got:

https://specs.openstack.org/openstack/nova-specs/specs/stein/approved/local-disk-serial-numbers.html

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

oVirt uses the disk GUID as a serial number. It would be similar if we used the UID of a PVC.

## Goals
- Add an option to the VM's `.spec` that will enable automatic serial number generation for disks that
don't have a serial number specified.

- Generate unique serial numbers for each disk. The number has to be unique compared to all other disks attached
to all VMs with this disk.

- Don't store the serial number in the VM's `.spec`. It would confuse gitops operators.

- The serial number should remain the same across storage migration.

akrejcir marked this conversation as resolved.
Show resolved Hide resolved
## Non Goals

- No customization options for serial number format.

## Definition of Users

- VM owners

## User Stories

- As a VM owner, I want to use the automated disk serial number assignment to reduce manual configuration.
- As a VM owner, I want each disk to have a unique serial number.
- As a VM owner, I want newly created Windows VMs to have serial numbers set on disks by default.

## Repos
- [kubevirt](https://github.com/kubevirt/kubevirt)

# Design

A new boolean option `generateDiskSerials` will be added to the VMI `.spec`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need an option for it? What's the default right now? Is it 123456789, which means nobody cares about it anyway? Can't we just enable it if the ID was not set manually?

Copy link
Author

@akrejcir akrejcir Jul 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default right now is no serial number. The <serial> tag in the libvirt domain XML is not specified.

We could enable it by default for all disks. That is one of the open questions in this design.
I'm unsure if it may confuse guests on existing VMs, if the disk will have a serial that it didn't have before.

When it is set to `true`, kubevirt will generate a serial number for each disk, that does not have one specified.
These serial numbers will then be set in the libvirt domain xml.

akrejcir marked this conversation as resolved.
Show resolved Hide resolved
This option can also be added to `VirtualMachinePreference`, so it can be set on new VMs and
the user does not need to be aware of it.

## Persistence of generated serial numbers

The serial number has to be the same across VM restarts and storage migration,
so it has to be stored somewhere, or generated deterministically.

This section lists several options how to store serial numbers.
Then the rest of the document describes details of option: **Annotation on the PVC object**.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally speaking the ID can be scoped in two ways:

  • VM/I Internal - serial is only defined/kept within the VM/I bject
  • VM/I external - serial is sourced from an external object - this is the case with the PVC annotation approach

If it's internal, then usually the requirements of a persistent serial number are met, however, it could lead to trouble if a volume is changed on a VMI, or if a volume is used on multiple VMIs.

If it is external, then we also meet the requirement of a persistent serial number, the same volume will get the same serial whenever attached to a VM that's good for vols attached to multi VMs, however, we need to think about cloning, and restore, and what it means for disk serial numbers. Something also requires permissionsto write the PVC.

Just to name a few things.


### Annotation on the PVC object
The serial number will be stored as an annotation on the PVC object. It would be created when the VMI is created.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will require some component to have PVC write permissions.

Then it will be read by `virt-handler` when creating libvirt domain XML.
akrejcir marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't we just persist all serial numbers in the Status of the VirtualMachine?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the status may be emptied by a GitOps controller, when it creates a new version of the VM. I will check.

I will add this possibility to the document for discussion.

Copy link
Member

@lyarwood lyarwood Jul 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should be ignoring any updates of Status outside of the /Status subresource IIRC so I don't think a GitOps workflow would overwrite it here. That's why we are looking to move instance type metadata out of the Spec etc.

https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status

The PUT and POST verbs on objects MUST ignore the status values, to avoid accidentally overwriting the status in read-modify-write scenarios. A /status subresource MUST be provided to enable system components to update statuses of resources they manage.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. It could work. I will add it to the design document.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question as for instancetypes. What if the status needs to be recreated? Where is the ID derived from? Can we recreate the same ID if the status needs to be recreated from scratch?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is the main issue with this approach.

If we could deterministically generate the serial number, then we don't need to store it in .status.
In this case, the serial number is randomly generated, so it needs to be stored somewhere. If .status is recreated, then a new number is generated.


#### Advantages:
- Serial is associated with PVC.
- Serial is clearly visible to anyone who can read PVC.

#### Disadvantages:
- Does not store serials for other volume types except PVC.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requires additional permissions to write PVCs



### Storing it in the `status` of the VM
Serial numbers will be stored in the `.status` of the VM.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How to restore / transfer a VM with the serial number? IIUC you are not allowed to write to the status of a K8S object.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will look into it.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've checked the code, and the .status of a VM is not stored into the snapshot.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think @0xFelix 's point was that we then need a way of persisting the serial in the core spec of a VirtualMachine during a snapshot so that we can then restore the status (and the state of the VM) later.

GitOps does not use the `/status` subresource to update the objects it creates, so it should not overwrite the serials.
More information about `.status` is [here](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status).

#### Advantages:
- We can store serial numbers for all volume types.
- Serial is clearly visible to anyone who can read VM.

#### Disadvantages:
- Harder to make sure that a disk has the same serial if it is mounted to multiple VMs.
- It may be an unexpected place to store persistent information that cannot be regenerated if `.status` is wiped.


### Deterministic generation
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this approach the most. Basically a stateless approach without configurables.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be the best choice, if it can be compatible with storage migration.

We can use name and namespace, or UID fields of the PVC to deterministically generate the serial number.
For non-PVC volumes, we can use other metadata to generate a serial number.

#### Advantages:
- We don't need to store anything.

#### Disadvantages:
- If the storage is migrated to a PVC with different metadata, it would change the serial number.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usually we do not "migrate" PVCs (aka modify them in-place).
Instead new PVCs are created. @alicefr @awels what does storage class migration do?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Storage class migration requires one to create new PVCs as the target of the migration. So there will be new PVCs. PVCs themselves are mostly immutable, in particular the name is immutable.



### Storing the serial in a ConfigMap
We can create a ConfigMap that would store all disk serials for a VM.

#### Advantages:
- We can store serial numbers for all volume types.

#### Disadvantages:
- Keeping the ConfigMap in sync with the VM is more complicated.
- Harder to make sure that a disk has the same serial if it is mounted to multiple VMs.


## API Examples

### Existing API to set serial number manually

The serial number can be specified manually in VM spec here:
```yaml
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: example-vm
spec:
template:
spec:
domain:
devices:
disks:
- name: disk
serial: 1234567890 # <-- serial number
disk:
bus: virtio
volumes:
- name: disk
persistentVolumeClaim:
claimName: example-pvc
```

### New API

To enable the serial generation, new filed `generateDiskSerials` will be added to the VMI `.spec`:
```yaml
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: example-vm
spec:
template:
spec:
domain:
devices:
generateDiskSerials: true # <-- new field
disks:
- name: disk
disk:
bus: virtio
volumes:
- name: disk
persistentVolumeClaim:
claimName: example-pvc
```

The generated serial will be stored as an annotation in the PVC:
```yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: example-pvc
annotations:
kubevirt.io/disk-serial: 123456789 # <-- new annotation
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use vm.kubevirt.io/disk-serial

cc @EdDev @alaypatel07 can we have api conventions? Possibly worth to standardize how we prefix annotations accross kubevirt.

spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Gi
```

## Scalability
Serials are generated during VMI creation, if the annotation does not exist.

## Update/Rollback Compatibility
The feature is backward compatible. Existing VMs remain unaffected unless the new field is set.
Rollback ignores the new field.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should check todays state:

If a serial is not specified, between VM start, stop, start, does the serial of the disk inside the VM change?

If it is the same serial, then we might need a migraiton plan.


## Testing Approach

### Unit tests
We can add new unit tests to check if the generated libvirt XML contains the `<serial>` tag.

### Functional Tests
Unit tests will probably be enough. They will check that correct libvirt XML is created.

If we want to add a functional test, we can copy [this test](https://github.com/kubevirt/kubevirt/blob/a37a2b317c335bc1a662d57bd9137d715f52e202/tests/storage/storage.go#L375),
and modify it to enable `generateDiskSerials` field instead of specifying the serial manually.

## Design questions

- Do we want the serials to be generated by default on all VMs,
akrejcir marked this conversation as resolved.
Show resolved Hide resolved
or do we want a configuration option to enable it?
- We would not need any API for generating them.
- The downside is that existing disks that previously did not have a serial configured,
will have it. This could confuse the guest OS that expects the disk serial to not change.

- Where is a good place for the `generateDiskSerials` field?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spec.template.spec.domain.devices.generateDiskSerials of the VirtualMachine IMHO

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree.

- Is it a good idea to store the serial in an annotation, or a different approach is better?

## Implementation considerations
The length of the serial number is limited. The [libvirt documentation](https://libvirt.org/formatdomain.html#hard-drives-floppy-disks-cdroms) says:

> Note that depending on hypervisor and device type the serial number may be truncated silently. IDE/SATA devices are commonly limited to 20 characters. SCSI devices depending on hypervisor version are limited to 20, 36 or 247 characters.
>
> Hypervisors may also start rejecting overly long serials instead of truncating them in the future so it's advised to avoid the implicit truncation by testing the desired serial length range with the desired device and hypervisor combination.