Skip to content

Commit e7f38c3

Browse files
committed
docs: add boot process documentation
Add documentation of Bottlerocket's boot sequence, including systemd target progression, service dependencies, and synchronization mechanisms. Include keywords for semantic search discoverability. Signed-off-by: Sean P. Kelly <[email protected]>
1 parent 9b7adf3 commit e7f38c3

File tree

1 file changed

+349
-0
lines changed

1 file changed

+349
-0
lines changed

docs/boot-process.md

Lines changed: 349 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,349 @@
1+
# Bottlerocket Boot Process
2+
3+
This document describes how Bottlerocket boots, focusing on the systemd target progression and service dependencies.
4+
5+
**Keywords:** boot, systemd, targets, preconfigured, configured, multi-user, fipscheck, sysinit, services, dependencies, ordering, API system, bootstrap containers, settings, startup, initialization
6+
7+
## Overview
8+
9+
Bottlerocket's boot sequence progresses through five main stages, each represented by a systemd target:
10+
11+
```
12+
sysinit.target
13+
14+
fipscheck.target (FIPS mode only)
15+
16+
preconfigured.target (API system initialization)
17+
18+
configured.target (bootstrap containers)
19+
20+
multi-user.target (workload services)
21+
```
22+
23+
Each stage must complete before the next begins. Services use systemd dependencies (`After=`, `Requires=`, `Wants=`) to coordinate within and between stages.
24+
25+
## Boot Stages
26+
27+
### Stage 0: sysinit.target
28+
29+
Standard systemd initialization. Most services implicitly depend on this through `DefaultDependencies=yes` (the default).
30+
31+
Early services that need to run before normal dependency chains use `DefaultDependencies=no`:
32+
33+
- Filesystem preparation (`prepare-var.service`, `prepare-boot.service`, etc.)
34+
- Data store migration (`migrator.service`)
35+
36+
### Stage 1: fipscheck.target
37+
38+
**Purpose:** Verify cryptographic module integrity when FIPS mode is enabled.
39+
40+
**When it runs:** Only when the kernel command line includes `fips=1`.
41+
42+
**Key services:**
43+
44+
- `check-kernel-integrity.service` - Verifies kernel integrity
45+
- `check-fips-modules.service` - Loads and tests the `tcrypt` module
46+
- Creates `/etc/.fips-module-check-passed` sentinel file on success
47+
- Blocks boot if FIPS checks fail
48+
49+
**Transition:** `activate-preconfigured.service` runs after `fipscheck.target` completes.
50+
51+
### Stage 2: preconfigured.target
52+
53+
**Purpose:** Initialize the API system and apply all boot-time configuration.
54+
55+
**What "preconfigured" means:** The system has:
56+
57+
- A populated data store with default and user-provided settings
58+
- A running API server
59+
- All configuration files generated from settings
60+
61+
This is the most complex boot stage. Services run in a specific order to build up the system configuration:
62+
63+
#### 2.1 Data Store Setup
64+
65+
**migrator** (`migrator.service`)
66+
67+
- **When:** Runs with `DefaultDependencies=no`, before everything else
68+
- **What:** Updates data store schema if the OS version changed
69+
- **Dependencies:** Required by `apiserver.service`, `storewolf.service`, and `preconfigured.target`
70+
71+
**storewolf** (`storewolf.service`)
72+
73+
- **When:** After `migrator.service`
74+
- **What:** Creates data store directories and populates default settings
75+
- **Details:**
76+
- Reads defaults from variant-specific `defaults.d` directories
77+
- Writes settings to _pending_ state in "bottlerocket-launch" transaction
78+
- Settings not available to other services until committed
79+
- **Dependencies:** Required by `preconfigured.target`
80+
81+
#### 2.2 API Server
82+
83+
**apiserver** (`apiserver.service`)
84+
85+
- **When:** After `storewolf.service`
86+
- **What:** Starts the API server on Unix socket `/run/api.sock`
87+
- **Details:** Allows reading/writing settings via API
88+
- **Dependencies:** Wanted by `preconfigured.target`
89+
90+
#### 2.3 Settings Population
91+
92+
**early-boot-config** (`early-boot-config.service`)
93+
94+
- **When:** After `network-online.target`, `apiserver.service`, `storewolf.service`
95+
- **What:** Applies user data settings (cloud-init equivalent)
96+
- **Details:**
97+
- Only runs on first boot (checks for `/var/lib/bottlerocket/early-boot-config.ran`)
98+
- Fetches user data from platform metadata service (e.g., EC2 IMDS)
99+
- PATCHes settings to API in _pending_ state (not committed)
100+
- **Dependencies:** Required by `preconfigured.target`
101+
102+
**sundog** (`sundog.service`)
103+
104+
- **When:** After `network-online.target`, `apiserver.service`, `early-boot-config.service`
105+
- **What:** Generates dynamic settings that can't be determined until runtime
106+
- **Details:**
107+
- Examples: primary IP address, cluster DNS settings
108+
- Runs `settings-committer` first to access user data settings
109+
- PATCHes generated settings to API in _pending_ state
110+
- **Dependencies:** Required by `preconfigured.target`
111+
- **Subcomponent:** `pluto.service` generates Kubernetes-specific settings
112+
113+
#### 2.4 Configuration Application
114+
115+
**settings-applier** (`settings-applier.service`)
116+
117+
- **When:** After `storewolf.service`, `sundog.service`, `early-boot-config.service`, `apiserver.service`
118+
- **What:** Writes all configuration files based on settings
119+
- **Details:**
120+
- Runs `settings-committer` to commit the "bottlerocket-launch" transaction
121+
- Runs `thar-be-settings --all` to generate all config files
122+
- This is when pending settings become live
123+
- **Dependencies:** Required by `preconfigured.target`
124+
125+
#### 2.5 Stage Transition
126+
127+
**activate-configured** (`activate-configured.service`)
128+
129+
- **When:** After `preconfigured.target` completes
130+
- **What:** Transitions to `configured.target`
131+
- **Details:**
132+
- Sets systemd default target to `configured.target`
133+
- Starts `configured.target` asynchronously
134+
- **Dependencies:** Wanted by `preconfigured.target`
135+
136+
### Stage 3: configured.target
137+
138+
**Purpose:** Run bootstrap containers that perform additional system configuration.
139+
140+
**What "configured" means:** The system has:
141+
142+
- Completed all API-based configuration
143+
- Run any user-defined bootstrap containers
144+
- Applied any additional configuration from bootstrap containers
145+
146+
**Key services:**
147+
148+
**bootstrap-containers@** (`[email protected]`)
149+
150+
- **When:** After `host-containerd.service`, before `configured.target`
151+
- **What:** Runs bootstrap containers defined in settings
152+
- **Details:**
153+
- Template unit instantiated for each configured bootstrap container
154+
- Only runs once per container (checks for `/run/bootstrap-containers/%i.ran`)
155+
- Containers have access to host filesystem at `/.bottlerocket/rootfs`
156+
- Boot blocks until all bootstrap containers complete
157+
- Useful for: installing software, modifying files, running setup scripts
158+
- **Dependencies:** Runs before `configured.target`
159+
160+
**activate-multi-user** (`activate-multi-user.service`)
161+
162+
- **When:** After `configured.target` and `reboot-if-required.service`
163+
- **What:** Transitions to `multi-user.target`
164+
- **Details:**
165+
- Sets systemd default target to `multi-user.target`
166+
- Starts `multi-user.target` asynchronously
167+
- **Dependencies:** Wanted by `configured.target`
168+
169+
### Stage 4: multi-user.target
170+
171+
**Purpose:** Start workload services (kubelet, ECS agent, etc.).
172+
173+
**What "multi-user" means:** The system is fully configured and ready to run workloads.
174+
175+
**Key services:**
176+
177+
- `kubelet.service` (Kubernetes variants)
178+
- `ecs.service` (ECS variants)
179+
- `[email protected]` (admin container)
180+
- `[email protected]` (control container)
181+
182+
**Dependencies:**
183+
184+
- Requires `basic.target` and `configured.target`
185+
- This ensures all configuration is complete before workloads start
186+
187+
## Service Dependency Patterns
188+
189+
### Ordering Dependencies
190+
191+
- `After=` - This service starts after the specified units
192+
- `Before=` - This service starts before the specified units
193+
194+
### Requirement Dependencies
195+
196+
- `Requires=` - This service requires the specified units (hard dependency)
197+
- `Wants=` - This service wants the specified units (soft dependency)
198+
- `RequiredBy=` - Reverse of `Requires=` (specified in `[Install]` section)
199+
- `WantedBy=` - Reverse of `Wants=` (specified in `[Install]` section)
200+
201+
### Early Boot Services
202+
203+
Services that need to run very early use `DefaultDependencies=no` to avoid the standard dependency chain:
204+
205+
- `migrator.service`
206+
- `prepare-*.service` (filesystem preparation)
207+
- `activate-preconfigured.service`
208+
209+
## Synchronization Mechanisms
210+
211+
### Systemd Targets
212+
213+
Targets serve as synchronization points. A target is "reached" when all services required by or wanted by that target have completed.
214+
215+
Target relationships:
216+
217+
```
218+
preconfigured.target:
219+
Requires: basic.target
220+
RequiredBy: configured.target, multi-user.target
221+
222+
configured.target:
223+
Requires: preconfigured.target
224+
RequiredBy: multi-user.target
225+
226+
multi-user.target:
227+
Requires: basic.target, configured.target
228+
```
229+
230+
### Sentinel Files
231+
232+
Services use sentinel files to track state across reboots:
233+
234+
- `/var/lib/bottlerocket/early-boot-config.ran` - Prevents `early-boot-config.service` from running after first boot
235+
- `/run/bootstrap-containers/<name>.ran` - Prevents bootstrap containers from re-running
236+
- `/etc/.fips-module-check-passed` - Marks FIPS check completion
237+
238+
Services use `ConditionPathExists=` or `ConditionPathExists=!` to check for these files.
239+
240+
### Transaction Commits
241+
242+
The API system uses transactions to ensure atomic updates:
243+
244+
1. Services write settings to _pending_ state during boot
245+
2. Settings are grouped in the "bottlerocket-launch" transaction
246+
3. `settings-committer` commits the transaction, making settings live
247+
4. `settings-applier` then generates configuration files from live settings
248+
249+
This ensures all boot-time settings are applied together, preventing partial configuration.
250+
251+
## Boot Flow Diagram
252+
253+
```
254+
┌─────────────────────────────────────────────────────────────────┐
255+
│ sysinit.target │
256+
│ - Standard systemd initialization │
257+
│ - prepare-var.service, prepare-boot.service (early filesystem) │
258+
└────────────────────────────┬────────────────────────────────────┘
259+
260+
┌─────────────────────────────────────────────────────────────────┐
261+
│ fipscheck.target (FIPS mode only) │
262+
│ - check-kernel-integrity.service │
263+
│ - check-fips-modules.service │
264+
└────────────────────────────┬────────────────────────────────────┘
265+
266+
activate-preconfigured.service
267+
268+
┌─────────────────────────────────────────────────────────────────┐
269+
│ preconfigured.target │
270+
│ │
271+
│ 1. migrator.service (data store migration) │
272+
│ 2. storewolf.service (data store creation) │
273+
│ 3. apiserver.service (API server) │
274+
│ 4. early-boot-config.service (user data, first boot only) │
275+
│ 5. sundog.service (dynamic settings) │
276+
│ 6. settings-applier.service (commit & apply settings) │
277+
│ │
278+
│ Result: API system running, all settings applied │
279+
└────────────────────────────┬────────────────────────────────────┘
280+
281+
activate-configured.service
282+
283+
┌─────────────────────────────────────────────────────────────────┐
284+
│ configured.target │
285+
│ │
286+
│ - bootstrap-containers@*.service (user-defined setup) │
287+
│ │
288+
│ Result: Additional configuration complete │
289+
└────────────────────────────┬────────────────────────────────────┘
290+
291+
activate-multi-user.service
292+
293+
┌─────────────────────────────────────────────────────────────────┐
294+
│ multi-user.target │
295+
│ │
296+
│ - kubelet.service / ecs.service (workload orchestrator) │
297+
│ - [email protected] (admin container) │
298+
│ - [email protected] (control container) │
299+
│ │
300+
│ Result: System ready for workloads │
301+
└─────────────────────────────────────────────────────────────────┘
302+
```
303+
304+
## Debugging Boot Issues
305+
306+
### Check Target Status
307+
308+
```bash
309+
# Check if a target has been reached
310+
systemctl is-active preconfigured.target
311+
systemctl is-active configured.target
312+
systemctl is-active multi-user.target
313+
314+
# See what's blocking a target
315+
systemctl list-dependencies preconfigured.target
316+
systemctl list-dependencies --reverse preconfigured.target
317+
```
318+
319+
### Check Service Status
320+
321+
```bash
322+
# See all failed services
323+
systemctl --failed
324+
325+
# Check specific service
326+
systemctl status migrator.service
327+
systemctl status apiserver.service
328+
329+
# View service logs
330+
journalctl -u migrator.service
331+
journalctl -u apiserver.service
332+
```
333+
334+
### Boot Timeline
335+
336+
To see the boot timeline:
337+
338+
```bash
339+
systemd-analyze
340+
systemd-analyze blame
341+
systemd-analyze critical-chain
342+
```
343+
344+
## Related Documentation
345+
346+
- [API System](../sources/api/README.md) - Detailed API component documentation
347+
- [Bootstrap Containers](../sources/api/bootstrap-containers/README.md) - Bootstrap container usage
348+
- [Early Boot Config](../sources/early-boot-config/README.md) - User data configuration
349+
- [Settings System](../sources/api/thar-be-settings/README.md) - Configuration file generation

0 commit comments

Comments
 (0)