summaryrefslogtreecommitdiff
path: root/docs/atomic-upgrades.md
diff options
context:
space:
mode:
authorTimothée Ravier <travier@redhat.com>2020-10-02 14:34:33 +0200
committerTimothée Ravier <travier@redhat.com>2020-10-02 14:34:48 +0200
commit68ac9e9c50d0e190a5a82bef5fdea29bd46fdd0a (patch)
tree57e51adcd58f966a09beae6dd437c3e14a9d2273 /docs/atomic-upgrades.md
parent6ca312a92399c92b60d83eae161a8b8ea148989b (diff)
downloadostree-68ac9e9c50d0e190a5a82bef5fdea29bd46fdd0a.tar.gz
docs: Move and update pages from the manual
Diffstat (limited to 'docs/atomic-upgrades.md')
-rw-r--r--docs/atomic-upgrades.md129
1 files changed, 129 insertions, 0 deletions
diff --git a/docs/atomic-upgrades.md b/docs/atomic-upgrades.md
new file mode 100644
index 00000000..3ddd8b40
--- /dev/null
+++ b/docs/atomic-upgrades.md
@@ -0,0 +1,129 @@
+---
+nav_order: 5
+---
+
+# Atomic Upgrades
+{: .no_toc }
+
+1. TOC
+{:toc}
+
+## You can turn off the power anytime you want...
+
+OSTree is designed to implement fully atomic and safe upgrades;
+more generally, atomic transitions between lists of bootable
+deployments. If the system crashes or you pull the power, you
+will have either the old system, or the new one.
+
+## Simple upgrades via HTTP
+
+First, the most basic model OSTree supports is one where it replicates
+pre-generated filesystem trees from a server over HTTP, tracking
+exactly one ref, which is stored in the `.origin` file for the
+deployment. The command `ostree admin upgrade`
+implements this.
+
+To begin a simple upgrade, OSTree fetches the contents of the ref from
+the remote server. Suppose we're tracking a ref named
+`exampleos/buildmaster/x86_64-runtime`. OSTree fetches the URL
+`http://example.com/repo/refs/heads/exampleos/buildmaster/x86_64-runtime`,
+which contains a SHA256 checksum. This determines the tree to deploy,
+and `/etc` will be merged from currently booted tree.
+
+If we do not have this commit, then, then we perform a pull process.
+At present (without static deltas), this involves quite simply just
+fetching each individual object that we do not have, asynchronously.
+Put in other words, we only download changed files (zlib-compressed).
+Each object has its checksum validated and is stored in `/ostree/repo/objects/`.
+
+Once the pull is complete, we have all the objects locally
+we need to perform a deployment.
+
+## Upgrades via external tools (e.g. package managers)
+
+As mentioned in the introduction, OSTree is also designed to allow a
+model where filesystem trees are computed on the client. It is
+completely agnostic as to how those trees are generated; they could be
+computed with traditional packages, packages with post-deployment
+scripts on top, or built by developers directly from revision control
+locally, etc.
+
+At a practical level, most package managers today (`dpkg` and `rpm`)
+operate "live" on the currently booted filesystem. The way they could
+work with OSTree is instead to take the list of installed packages in
+the currently booted tree, and compute a new filesystem from that. A
+later chapter describes in more details how this could work:
+[Adapting Existing Systems](adapting-existing.md).
+
+For the purposes of this section, let's assume that we have a
+newly generated filesystem tree stored in the repo (which shares
+storage with the existing booted tree). We can then move on to
+checking it back out of the repo into a deployment.
+
+## Assembling a new deployment directory
+
+Given a commit to deploy, OSTree first allocates a directory for
+it. This is of the form `/boot/loader/entries/ostree-$stateroot-$checksum.$serial.conf`.
+The `$serial` is normally `0`, but if a
+given commit is deployed more than once, it will be incremented.
+This is supported because the previous deployment may have
+configuration in `/etc` that we do not want to use or overwrite.
+
+Now that we have a deployment directory, a 3-way merge is
+performed between the (by default) currently booted deployment's
+`/etc`, its default
+configuration, and the new deployment (based on its `/usr/etc`).
+
+## Atomically swapping boot configuration
+
+At this point, a new deployment directory has been created as a
+hardlink farm; the running system is untouched, and the bootloader
+configuration is untouched. We want to add this deployment to the
+"deployment list".
+
+To support a more general case, OSTree supports atomic transitioning
+between arbitrary sets of deployments, with the restriction that the
+currently booted deployment must always be in the new set. In the
+normal case, we have exactly one deployment, which is the booted one,
+and we want to add the new deployment to the list. A more complex
+command might allow creating 100 deployments as part of one atomic
+transaction, so that one can set up an automated system to bisect
+across them.
+
+## The bootversion
+
+OSTree allows swapping between boot configurations by implementing the
+"swapped directory pattern" in `/boot`. This means it is a symbolic
+link to one of two directories `/ostree/boot.[0|1]`. To swap the
+contents atomically, if the current version is `0`, we create
+`/ostree/boot.1`, populate it with the new contents, then atomically
+swap the symbolic link. Finally, the old contents can be garbage
+collected at any point.
+
+## The /ostree/boot directory
+
+However, we want to optimize for the case where the set of
+kernel/initramfs/devicetree sets is the same between both the old and new
+deployment lists. This happens when doing an upgrade that does not
+include the kernel; think of a simple translation update. OSTree
+optimizes for this case because on some systems `/boot` may be on a
+separate medium such as flash storage not optimized for significant
+amounts of write traffic. Related to this, modern OSTree has support
+for having `/boot` be a read-only mount by default - it will
+automatically remount read-write just for the portion of time
+necessary to update the bootloader configuration.
+
+To implement this, OSTree also maintains the directory
+`/ostree/boot.$bootversion`, which is a set
+of symbolic links to the deployment directories. The
+`$bootversion` here must match the version of
+`/boot`. However, in order to allow atomic transitions of
+*this* directory, this is also a swapped directory,
+so just like `/boot`, it has a version of `0` or `1` appended.
+
+Each bootloader entry has a special `ostree=` argument which refers to
+one of these symbolic links. This is parsed at runtime in the
+initramfs.
+
+###### Licensing for this document:
+`SPDX-License-Identifier: (CC-BY-SA-3.0 OR GFDL-1.3-or-later)`