Skip to content

Commit a8e354d

Browse files
authored
Merge pull request bottlerocket-os#632 from ginglis13/ephemeral-storage-bind
apiclient: add implicit default behavior for ephemeral-storage bind
2 parents d8a0c51 + cde42a0 commit a8e354d

File tree

4 files changed

+128
-3
lines changed

4 files changed

+128
-3
lines changed

sources/api/apiclient/README.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,45 @@ If you want to group sets of changes yourself, pick a transaction name and appen
193193
For example, if you want the name "FOO", you can `PATCH` to `/settings?tx=FOO` and `POST` to `/tx/commit_and_apply?tx=FOO`.
194194
(Transactions are created automatically when used, and are cleaned up on reboot.)
195195

196+
### Ephemeral storage
197+
198+
This lets you manage ephemeral storage on instances that have local instance storage (like NVMe SSDs).
199+
200+
#### Initialize ephemeral storage
201+
202+
Before binding directories, you need to initialize the ephemeral storage:
203+
204+
```shell
205+
apiclient ephemeral-storage init
206+
```
207+
208+
This sets up the storage devices as a RAID array and formats them.
209+
210+
#### Bind directories to ephemeral storage
211+
212+
You can bind directories to the ephemeral storage so they persist across container restarts:
213+
214+
```shell
215+
apiclient ephemeral-storage bind
216+
```
217+
218+
This automatically binds the appropriate directories for your platform (Kubernetes vs ECS). For Kubernetes variants, this includes directories like `/var/lib/kubelet`, `/var/lib/containerd`, `/var/log/pods`, and `/var/lib/soci-snapshotter`. For ECS variants, it includes `/var/lib/docker`, `/var/lib/containerd`, and `/var/log/ecs`.
219+
220+
You can also specify custom directories:
221+
222+
```shell
223+
apiclient ephemeral-storage bind --dirs /var/lib/containerd /custom/path
224+
```
225+
226+
#### List ephemeral storage information
227+
228+
You can list available disks and currently bound directories:
229+
230+
```shell
231+
apiclient ephemeral-storage list-disks
232+
apiclient ephemeral-storage list-dirs
233+
```
234+
196235
### Report mode
197236

198237
This allows you to generate certain reports based on the current state of the system.

sources/api/apiclient/README.tpl

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,45 @@ If you want to group sets of changes yourself, pick a transaction name and appen
193193
For example, if you want the name "FOO", you can `PATCH` to `/settings?tx=FOO` and `POST` to `/tx/commit_and_apply?tx=FOO`.
194194
(Transactions are created automatically when used, and are cleaned up on reboot.)
195195

196+
### Ephemeral storage
197+
198+
This lets you manage ephemeral storage on instances that have local instance storage (like NVMe SSDs).
199+
200+
#### Initialize ephemeral storage
201+
202+
Before binding directories, you need to initialize the ephemeral storage:
203+
204+
```shell
205+
apiclient ephemeral-storage init
206+
```
207+
208+
This sets up the storage devices as a RAID array and formats them.
209+
210+
#### Bind directories to ephemeral storage
211+
212+
You can bind directories to the ephemeral storage so they persist across container restarts:
213+
214+
```shell
215+
apiclient ephemeral-storage bind
216+
```
217+
218+
This automatically binds the appropriate directories for your platform (Kubernetes vs ECS). For Kubernetes variants, this includes directories like `/var/lib/kubelet`, `/var/lib/containerd`, `/var/log/pods`, and `/var/lib/soci-snapshotter`. For ECS variants, it includes `/var/lib/docker`, `/var/lib/containerd`, and `/var/log/ecs`.
219+
220+
You can also specify custom directories:
221+
222+
```shell
223+
apiclient ephemeral-storage bind --dirs /var/lib/containerd /custom/path
224+
```
225+
226+
#### List ephemeral storage information
227+
228+
You can list available disks and currently bound directories:
229+
230+
```shell
231+
apiclient ephemeral-storage list-disks
232+
apiclient ephemeral-storage list-dirs
233+
```
234+
196235
### Report mode
197236

198237
This allows you to generate certain reports based on the current state of the system.

sources/api/apiclient/src/main.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -272,8 +272,9 @@ fn usage() -> ! {
272272
273273
ephemeral-storage bind options:
274274
--dirs DIR [DIR ...] Directories to bind to configured ephemeral storage
275-
(e.g. /var/lib/containerd). If no ephemeral disks are found
276-
this operation does nothing.
275+
(e.g. /var/lib/containerd). If not specified, uses platform (k8s vs. ECS)
276+
defaults. If no ephemeral disks are found this operation does nothing.
277+
277278
278279
ephemeral-storage list-disks options:
279280
-f, --format Format of the disk listing (text or json). Default format is text.
@@ -794,9 +795,13 @@ fn parse_ephemeral_storage_init_args(args: Vec<String>) -> EphemeralStorageSubco
794795

795796
/// Parses arguments for the 'bind' ephemeral-storage subcommand.
796797
fn parse_ephemeral_storage_bind_args(args: Vec<String>) -> EphemeralStorageSubcommand {
798+
// If no arguments, use default directories
797799
if args.is_empty() {
798-
usage_msg("Did not give arguments to bind")
800+
return EphemeralStorageSubcommand::Bind(EphemeralStorageBindArgs {
801+
targets: Vec::new(),
802+
});
799803
}
804+
800805
let mut targets = Vec::new();
801806
let mut iter = args.into_iter().peekable();
802807
while let Some(arg) = iter.next() {
@@ -810,6 +815,7 @@ fn parse_ephemeral_storage_bind_args(args: Vec<String>) -> EphemeralStorageSubco
810815
x => usage_msg(format!("Unknown argument '{x}'")),
811816
}
812817
}
818+
813819
EphemeralStorageSubcommand::Bind(EphemeralStorageBindArgs { targets })
814820
}
815821

sources/api/apiserver/src/server/ephemeral_storage.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,17 @@ pub fn bind(variant: &str, dirs: Vec<String>) -> Result<()> {
118118
_ => format!("{RAID_DEVICE_DIR}{RAID_DEVICE_NAME}"),
119119
};
120120

121+
let dirs = if dirs.is_empty() {
122+
let allowed_dirs = allowed_bind_dirs(variant);
123+
allowed_dirs
124+
.allowed_exact
125+
.into_iter()
126+
.map(|s| s.to_string())
127+
.collect()
128+
} else {
129+
dirs
130+
};
131+
121132
// Normalize input by trimming trailing "/"
122133
let dirs: Vec<String> = dirs
123134
.into_iter()
@@ -431,3 +442,33 @@ pub mod error {
431442
}
432443

433444
pub type Result<T> = std::result::Result<T, error::Error>;
445+
446+
#[cfg(test)]
447+
mod tests {
448+
use super::*;
449+
450+
#[test]
451+
fn test_bind_with_default_dirs_k8s() {
452+
let variant = "aws-k8s-1.33";
453+
let allowed_dirs = allowed_bind_dirs(variant);
454+
455+
for dir in [
456+
"/var/lib/kubelet",
457+
"/var/lib/containerd",
458+
"/var/lib/soci-snapshotter",
459+
"/var/log/pods",
460+
] {
461+
assert!(allowed_dirs.allowed_exact.contains(dir));
462+
}
463+
}
464+
465+
#[test]
466+
fn test_bind_with_default_dirs_ecs() {
467+
let variant = "aws-ecs-2";
468+
let allowed_dirs = allowed_bind_dirs(variant);
469+
470+
for dir in ["/var/lib/docker", "/var/lib/containerd", "/var/log/ecs"] {
471+
assert!(allowed_dirs.allowed_exact.contains(dir));
472+
}
473+
}
474+
}

0 commit comments

Comments
 (0)