Skip to content

Commit 5452348

Browse files
committed
doc: adapt snapshot versioning docs and CHANGELOG
Adapt documentation around snapshot versions format and compatibility to remove mentions of Versionize and the effects its usage had to snapshot compatibility. Also, add a CHANGELOG entry regarding the new strategy for snapshot versioning. Signed-off-by: Babis Chalios <[email protected]>
1 parent a1f6a6e commit 5452348

File tree

5 files changed

+53
-148
lines changed

5 files changed

+53
-148
lines changed

CHANGELOG.md

+13
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1515
`VcpuExit::IoOut`. The average for these VM exits is not emitted since
1616
it can be deduced from the available emitted metrics.
1717

18+
### Changed
19+
20+
- [#4230](https://github.com./firecracker-microvm/firecracker/pull/4230):
21+
Changed microVM snapshot format version strategy. Firecracker snapshot format
22+
now has a version that is independent of Firecracker version. The current
23+
version of the snapshot format is v1.0.0. From now on, the Firecracker binary
24+
will define the snapshot format version it supports and it will only be able
25+
to load snapshots with format that is backwards compatible with that version.
26+
Users can pass the `--snapshot-version` flag to the Firecracker binary to see
27+
its supported snapshot version format. This change renders all previous
28+
Firecracker snapshots (up to Firecracker version v1.6.0) incompatible with
29+
the current Firecracker version.
30+
1831
## [v1.6.0]
1932

2033
### Added

docs/images/version_graph.png

-24.3 KB
Binary file not shown.

docs/images/versionize.png

-47.1 KB
Binary file not shown.

docs/snapshotting/snapshot-support.md

+7-48
Original file line numberDiff line numberDiff line change
@@ -175,41 +175,13 @@ The snapshot functionality is still in developer preview due to the following:
175175

176176
## Snapshot versioning
177177

178-
The Firecracker snapshotting implementation offers support for snapshot versioning
179-
(`cross-version snapshots`) in the following contexts:
180-
181-
- Saving snapshots at older versions
182-
183-
**DEPRECATED**: This feature is deprecated starting with version 1.5.0. It
184-
will be removed in a subsequent release. After dropping support, Firecracker
185-
will be able to create snapshots only for the version supported by the
186-
Firecracker binary that launched the microVM and not for older versions.
187-
188-
This refers to being able to create a snapshot with any version in the
189-
`[N, N + o]` interval, while running Firecracker version `N+o`.
190-
191-
The possibility to save snapshots at older versions might not be offered by
192-
all Firecracker releases. Depending on the features that it introduces, a new
193-
Firecracker release `v` might drop the possibility to save snapshots at any
194-
versions older than `v`.
195-
196-
For example Firecracker v1.0 and v1.1 adds support for some additional virtio
197-
features (e.g. notification suppression). These features lead the guest
198-
drivers to behave in a very specific way and as a consequence the Firecracker
199-
devices have to respond accordingly. As a result, the snapshots that are
200-
created while these features are in use will not be backwards compatible with
201-
previous versions of Firecracker since the devices that come with these older
202-
versions do not behave in a way that’s compatible with the snapshotted guest
203-
drivers.
204-
205-
The list of versions that break snapshot backwards compatibility: `1.0`, `1.1`
206-
- Loading snapshots from older versions (being able to load a snapshot created
207-
by any Firecracker version in the `[N, N + o]` interval, in a Firecracker
208-
version `N+o`).
209-
210-
The design supports an unlimited number of versions, the value of `o` (maximum number
211-
of older versions that we can restore from / save a snapshot to, from the current
212-
version) will be defined later.
178+
The microVM state snapshot file uses a data format that has a version in the
179+
form of `MAJOR.MINOR.PATCH`. Each Firecracker binary supports a fixed version
180+
of the snapshot data format. When creating a snapshot, Firecracker will use the
181+
supported data format version. When loading snapshots, Firecracker will check
182+
that the snapshot version is compatible with the version it supports. More
183+
information about the snapshot data format and details about snapshot data
184+
format versions can be found at [versioning](./versioning.md).
213185

214186
## Snapshot API
215187

@@ -294,7 +266,6 @@ curl --unix-socket /tmp/firecracker.socket -i \
294266
"snapshot_type": "Full",
295267
"snapshot_path": "./snapshot_file",
296268
"mem_file_path": "./mem_file",
297-
"version": "1.0.0"
298269
}'
299270
```
300271

@@ -323,24 +294,13 @@ the snapshot. If they exist, the files will be truncated and overwritten.
323294
- If diff snapshots were enabled, the snapshot creation resets then the
324295
dirtied page bitmap and marks all pages clean (from a diff snapshot point
325296
of view).
326-
- If a `version` is specified, the new snapshot is saved at that version,
327-
otherwise it will be saved at the latest snapshot version of the running
328-
Firecracker. The version is only used for the microVM state file as it
329-
contains internal state structures for device emulation, vCPUs and others
330-
that can change their format from a Firecracker version to another.
331-
Versioning is not required for the block and memory files.
332297

333298
- _on failure_: no side-effects.
334299

335300
**Notes**:
336301

337302
- The separate block device file components of the snapshot have to be handled
338303
by the user.
339-
- If specified, `version` must match the firecracker version that introduced a
340-
snapshot version, which may differ from the running Firecracker version. For
341-
example, if you are running on `1.1.2` and want to target version `1.0.4`, you
342-
should specify `1.0.0`. Not specifying `version` uses the latest snapshot
343-
version available to that version.
344304

345305
#### Creating diff snapshots
346306

@@ -358,7 +318,6 @@ curl --unix-socket /tmp/firecracker.socket -i \
358318
"snapshot_type": "Diff",
359319
"snapshot_path": "./snapshot_file",
360320
"mem_file_path": "./mem_file",
361-
"version": "1.0.0"
362321
}'
363322
```
364323

docs/snapshotting/versioning.md

+33-100
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,18 @@
11
# Firecracker snapshot versioning
22

3-
This document describes how Firecracker persists its state across multiple
4-
versions, diving deep into the snapshot format, encoding, compatibility and
3+
This document describes how Firecracker persists microVM state into Firecracker
4+
snapshots. It describes the snapshot format, encoding, compatibility and
55
limitations.
66

77
## Introduction
88

9-
The design behind the snapshot implementation enables version tolerant save
10-
and restore across multiple Firecracker versions which we call a version space.
11-
For example, one can pause a microVM, save it to disk with Firecracker version
12-
**0.23.0** and later load it in Firecracker version **0.24.0**. It also works
13-
in reverse: Firecracker version **0.23.0** loads what **0.24.0** saves.
14-
15-
Below is an example graph showing backward and forward snapshot compatibility.
16-
This is the general picture, but keep in mind that when adding new features
17-
some version translations would not be possible.
18-
19-
![Version graph](
20-
../images/version_graph.png?raw=true
21-
"Version graph")
22-
23-
A non-exhaustive list of how cross-version snapshot support can be used:
24-
25-
Example scenario #1 - load snapshot from older version:
26-
27-
* Start Firecracker v0.23 → Boot microVM → *Workload starts* → Pause →
28-
CreateSnapshot(snap) → kill microVM
29-
* Start Firecracker v0.24 → LoadSnapshot → Resume → *Workload continues*
30-
31-
Example scenario #2 - load snapshot in older version:
32-
33-
* Start Firecracker v0.24 → Boot microVM → *Workload starts* → Pause →
34-
CreateSnapshot(snap, “0.23”) → kill microVM
35-
* Start Firecracker v0.23 → LoadSnapshot(snap) → Resume → *Workload continues*
36-
37-
Example scenario #3 - load snapshot in older version:
38-
39-
* Start Firecracker v0.24 → LoadSnapshot(older_snap) → Resume →
40-
*Workload continues* → Pause → CreateSnapshot(snap, “0.23”) → kill microVM
41-
* Start Firecracker v0.23 → LoadSnapshot(snap) → Resume → *Workload continues*
9+
Firecracker uses the serde crate [1] along with the bincode [2] format to
10+
serialize its state into Firecracker snapshots. Firecracker snapshots have
11+
versions that are independent of Firecracker versions. Each Firecracker version
12+
declares support for a specific snapshot data format version. When creating a
13+
snapshot, Firecracker will use the supported snapshot format version. When
14+
loading a snapshot, Firecracker will check that format of the snapshot file is
15+
compatible with the snapshot version Firecracker supports.
4216

4317
## Overview
4418

@@ -61,59 +35,32 @@ emulation, KVM and vCPUs) with 2 exceptions - serial emulation and vsock backend
6135

6236
While we continuously improve and extend Firecracker's features by adding new
6337
capabilities, devices or enhancements, the microVM state file may change both
64-
structurally and semantically with each new release. The state file includes
65-
versioning information and each Firecracker release implements distinct
66-
save/restore logic for the supported version space.
38+
structurally and semantically with each new release.
6739

6840
## MicroVM state file format
6941

70-
A microVM state file is further split into four different fields:
42+
A Firecracker snapshot has the following format:
7143

72-
| Field | Bits| Description |
73-
|----|----|----|
74-
| magic_id | 64 | Firecracker snapshot, architecture (x86_64/aarch64) and storage version. |
75-
| version | 16 | The snapshot version number internally mapped 1:1 to a specific Firecracker version. |
44+
| Field | Bits | Description |
45+
|-------|------|-------------|
46+
| magic_id | 64 | Firecracker snapshot and architecture (x86_64/aarch64). |
47+
| version | M | The snapshot data format version (`MAJOR.MINOR.PATCH`) |
7648
| state | N | Bincode blob containing the microVM state. |
77-
| crc| 64 | Optional CRC64 sum of magic_id, version and state fields. |
78-
79-
**Note**: the last 16 bits of `magic_id` encode the storage version which specifies
80-
the encoding used for the `version` and `state` fields. The current
81-
implementation sets this field to 1, which identifies it as a [Serde bincode](https://github.com./servo/bincode)
82-
compatible encoder/decoder.
83-
84-
### Version tolerant ser/de
85-
86-
Firecracker reads and writes the `state` blob of the snapshot by using per
87-
version, separate serialization and deserialization logic. This logic is mostly
88-
autogenerated by a Rust procedural macro based on `struct` and `enum`
89-
annotations. Basically, one can say that these structures support versioning.
90-
The versioning logic is generated by parsing a structure's history log (encoded
91-
using Rust annotations) and emitting Rust code.
92-
93-
Versioned serialization and deserialization is divided into two translation layers:
94-
95-
* field translator,
96-
* semantic translator.
97-
98-
The _field translator_ implements the logic to convert between different
99-
versions of the same Rust POD structure: it can deserialize or serialize from
100-
source version to target.
101-
The translation is done field by field - the common fields are copied from
102-
source to target, and the fields that are unique to the target are
103-
(de)serialized with their default values.
104-
105-
The _semantic translator_ is only concerned with translating the semantics of
106-
the serialized/deserialized fields.
107-
108-
The _field translator_ is generated automatically through a procedural macro,
109-
and the _semantic translation methods_ have to be annotated in the structure
110-
by the user.
111-
112-
This block diagram illustrates the concept:
113-
114-
![Versionize](
115-
../images/versionize.png?raw=true
116-
"Versionize layers")
49+
| crc | 64 | Optional CRC64 sum of magic_id, version and state fields. |
50+
51+
The snapshot format has its own version encoded in the snapshot file itself
52+
after the snapshot's `magic_id`. The snapshot format version is independent of
53+
the Firecracker version and it is of the form `MAJOR.MINOR.PATCH`.
54+
55+
Currently, Firecracker uses the [Serde bincode
56+
encoder](https://github.com./servo/bincode) for serializing the microVM state.
57+
The encoding format that bincode uses does not allow backwards compatible
58+
changes in the state, so essentially every change in the microVM state
59+
description will result in bump of the format's `MAJOR` version. If the needs
60+
arises, we will look into alternative formats that allow more flexibility with
61+
regards to backwards compatibility. If/when this happens, we will define how
62+
changes in the snapshot format reflect to changes in its `MAJOR.MINOR.PATCH`
63+
version.
11764

11865
## VM state encoding
11966

@@ -132,10 +79,6 @@ Key benefits of using *bincode*:
13279

13380
The current implementation relies on the [Serde bincode encoder](https://github.com./servo/bincode).
13481

135-
Versionize is compatible to Serde with bincode backend: structures serialized
136-
with versionize at a specific version can be deserialized with Serde. Also
137-
structures serialized with serde can be deserialized with versionize.
138-
13982
## Snapshot compatibility
14083

14184
### Host kernel
@@ -195,18 +138,8 @@ specifically, the MSRs corresponding to the guest exposed features.
195138

196139
## Implementation
197140

198-
To enable Firecracker cross version snapshots we have designed and built two
199-
crates:
200-
201-
* [versionize](https://crates.io/crates/versionize) - defines the `Versionize`
202-
trait, implements serialization of primitive types and provides a helper
203-
class to map Firecracker versions to individual structure versions.
204-
* [versionize_derive](https://crates.io/crates/versionize_derive) - exports
205-
a procedural macro that consumes structures and enums and their annotations
206-
to produce an implementation of the `Versionize` trait.
207-
208-
The microVM state file format is implemented in the [snapshot crate](../../src/snapshot/src/lib.rs)
209-
in the Firecracker repository.
210-
All Firecracker devices implement the [Persist](../../src/snapshot/src/persist.rs)
141+
The microVM state file format is implemented in the [snapshot
142+
crate](../../src/snapshot/src/lib.rs) in the Firecracker repository. All
143+
Firecracker devices implement the [Persist](../../src/snapshot/src/persist.rs)
211144
trait which exposes an interface that enables creating from and saving to the
212145
microVM state.

0 commit comments

Comments
 (0)