Skip to content

Commit

Permalink
📝 Extend architectural docs (kairos-io#213)
Browse files Browse the repository at this point in the history
  • Loading branch information
mudler authored Oct 12, 2022
1 parent a1a9bef commit c61717e
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 0 deletions.
74 changes: 74 additions & 0 deletions docs/src/pages/architecture/cloud-init.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
---
layout: "../../layouts/docs/Layout.astro"
title: "Cloud-init based"
index: 2
---

# Cloud-init based

Kairos supports the [standard cloud-init syntax](https://github.com/mudler/yip#compatibility-with-cloud-init-format) and [its own extended syntax](https://github.com/mudler/yip) to allow to configure a system declaratively with a cloud-config centric approach.

If you are not familiar with the concepts of cloud-init, [official cloud-init](https://cloud-init.io/) is a recommended read.

## Configuration persistency

Kairos is an Immutable OS and the only configuration that is persistent across reboots is the cloud-init configuration.
Multiple cloud-init files can be present in the system and Kairos will read them and process them in sequence (lexicographic order) allowing to extend the configuration with additional pieces also after deployment, or to manage logical configuration pieces separately.

In Kairos the `/oem` directory keeps track of all the configuration of the system and stores the configuration files. Multiple files are allowed and they are all executed during the various system stages. `/usr/local/cloud-config` can be optionally used as well to store cloud config files in the persistent partition instead. `/system/oem` is instead reserved to default cloud-init files that are shipped by the base OS image.


By using the standard cloud-config syntax, a subset of the functionalities are available and the settings will be executed in the boot stage.

## Boot stages

During boot the stages are emitted in an event-based pattern until a system completes its boot process

![Kairos-boot-events](https://user-images.githubusercontent.com/2420543/195111193-3167eab8-8058-4676-a1a0-f64aea745646.png)

The events can be used in the cloud-config extended syntax to hook into the various stages, which can allow to hook inside the different stages of a node lifecycle.

For instance, to execute something before reset is sufficient to add the following to the config file used to bootstrap a node:

```yaml
name: "Run something before reset"
stages:
before-reset:
- name: "Setting"
commands:
- |
echo "Run a command before reset the node!"
```
Below there is a detailed list of the stages available that can be used in the cloud-init configuration files:
| **Stage** | **Description** |
|------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| _rootfs_ | This is the earliest stage, running before switching root, just right after the root is mounted in /sysroot and before applying the immutable rootfs configuration. This stage is executed over initrd root, no chroot is applied. |
| _initramfs_ | This is still an early stage, running before switching root. Here you can apply radical changes to the booting setup of Elemental. Despite this is executed before switching root this exection runs chrooted into the target root after the immutable rootfs is set up and ready. |
| _boot_ | This stage is executed after initramfs has switched root, during the systemd bootup process. |
| _fs_ | This stage is executed when fs is mounted and is guaranteed to have access to the state and persistent partitions ( `COS_STATE` and `COS_PERSISTENT` respectively). |
| _network_ | This stage is executed when network is available |
| _reconcile_ | This stage is executed 5m after boot and periodically each 60m. |
| _after-install_ | This stage is executed after installation of the OS has ended |
| _after-install-chroot_ | This stage is executed after installation of the OS has ended. |
| _after-upgrade_ | This stage is executed after upgrade of the OS has ended. |
| _after-upgrade-chroot_ | This stage is executed after upgrade of the OS has ended (chroot call). |
| _after-reset_ | This stage is executed after reset of the OS has ended. |
| _after-reset-chroot_ | This stage is executed after reset of the OS has ended (chroot call). |
| _before-install_ | This stage is executed before installation |
| _before-upgrade_ | This stage is executed before upgrade |
| _before-reset_ | This stage is executed before reset |

Note: Steps executed at the `chroot` stage are running inside the new OS as chroot, allowing to write persisting changes to the image, for example by downloading and installing additional software.


### Sentinels

When a Kairos boots it creates sentinel files in order to allow to execute cloud-init steps programmaticaly.

- /run/cos/recovery_mode is being created when booting from the recovery partition
- /run/cos/live_mode is created when booting from the LiveCD

To execute a block using the sentinel files you can specify: `if: '[ -f "/run/cos/..." ]'`, for instance:
22 changes: 22 additions & 0 deletions docs/src/pages/architecture/immutable.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,25 @@ The benefit of rolling out the same system over a set of machines are obvious:
Tools like Chef, Puppet, and Ansible share the same underlying issues when it comes to configuration management: nodes can have different version matrices of software and OS, which makes your set of nodes dishomogeneous and difficult to maintain and orchestrate from day 1 to day 2.

Kairos tackles the issue from another angle, as can turn _any_ distribution to an "immutable" system, distributed as a standard container image, which gets provisioned to the devices as declared. This allows to treat OSes with the same repeatable portability as containers for apps, removing snowflakes in your cluster. Container registries can be used either internally or externally to the cluster to propagate upgrades with customized versions of the OS (kernel, packages, and so on).

## Design

Kairos after installation will create the following partitions:

- A state partition that stores the container images which are going to be booted (active and passive, stored in `.img` format which are loopback mounted)
- A recovery partition that stores the container images used for recovery (in `.squashfs` format)
- A OEM partition (optional) that stores user configuration and cloud-config files
- A persistent partition to keep the data across reboot

![Kairos-installation-partitioning](https://user-images.githubusercontent.com/2420543/195111190-3bdfb917-312a-40f4-b0bc-4a65a701c06b.png)

The persistent partition is mounted on boot to `/usr/local`, but few mont points are mount-bind to it. The mountpoints are defined in a [cloud-config](https://github.com/kairos-io/kairos/blob/a1a9bef4dff30e0718fa4d2697f075ce37c7ed90/overlay/files/system/oem/11_persistency.yaml#L11) file. It is possible to override such configuration by providing it in the cloud-config provided during installation.

The Recovery system allows to perform emergency tasks in case of failure of the active and passive images, and a fallback mechanism will take place in case of failures such as boots the partitions in this sequence: “A -> B -> Recovery”.

The upgrade happens in a transition image and take place only after all the necessary steps are completed. An upgrade of the ‘A/B’ partitions can be done by [with Kubernetes](/upgrade/kubernetes) or [manually](/upgrade/manual). The upgrade will create a new pristine image that will be selected as active for the next reboot, the old one will be flagged as passive. If we are performing the same from the passive system, only the active is subject to changes.

### Kernel and Initrd

The Kernel and Initrd are loaded from the system images and expected to be present. A typical setup have kernels and initrd in a special boot partition.
In Kairos instead the Kernel and Initrd are being loaded from the images, which are chainloaded from the bootloader (GRUB). This is a design choice to keep the entire OS stack confined as a single layer which gets pulled and swapped atomically during upgrades.

0 comments on commit c61717e

Please sign in to comment.