Skip to content

Commit

Permalink
(docs): Clean Up
Browse files Browse the repository at this point in the history
  • Loading branch information
Lasith Koswatta Gamage committed Jan 8, 2024
1 parent 0f423d6 commit 0797111
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 71 deletions.
129 changes: 66 additions & 63 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@

* **Format** a file system
* **Label** a file system
* **Resize** a file system (when a threshold is reached)
* **Resize** a file system
* **Mount** a block device
* **Ownership** and **Permissions** management of the mount point
* Manage **ownership** and **permissions** of the mount point

Currently, the following file systems are supported for querying and modification...

Expand Down Expand Up @@ -45,13 +45,11 @@ curl -L \
sudo install -m755 /tmp/ebs-bootstrap /usr/local/sbin/ebs-bootstrap
```

## Modes
## Documentation

// TODO

## Configuration

// TODO
<a href="https://github.com/reecetech/ebs-bootstrap/wiki" target="_blank">
<img src="https://img.shields.io/badge/github-%23121011.svg?style=for-the-badge&logo=github&logoColor=white">
</a>

## Use Cases

Expand Down Expand Up @@ -79,17 +77,9 @@ ExecStopPost=-/etc/ebs-bootstrap/post-hook.sh
WantedBy=multi-user.target
```

```
cat /etc/ebs-bootstrap/post-hook.sh
#!/bin/sh
if [ "${EXIT_STATUS}" = "0" ]; then
echo "🟢 Post Stop Hook: Success"
else
echo "🔴 Post Stop Hook: Failure"
fi
```
It is then possible to configure another `systemd` service to only start if the `ebs-bootstrap` service is successful. Certain databases support the ability to spread database chunks across multiple devices that need to be mounted to pre-defined directories with the correct ownership and permissions.

It is then possible to configure another `systemd` service to only start if the `ebs-bootstrap` service is successful. Certain databases support the ability to spread database chunks across multiple devices that need to be mounted to pre-defined directories with the correct ownership and permissions. In this particular use-case, the database could be configured as a `systemd` service that relies on the `ebs-bootstrap.service` to succeed before attempting to start. This can be achieved by specifiying `ebs-boostrap.service` as a dependency in the `Requires=` and `After=` parameters.
In this particular use-case, the database could be configured as a `systemd` service that relies on the `ebs-bootstrap.service` to succeed before attempting to start. This can be achieved by specifiying `ebs-boostrap.service` as a dependency in the `Requires=` and `After=` parameters.

```ini
[Unit]
Expand All @@ -111,59 +101,71 @@ WantedBy=multi-user.target

### `cloud-init`

By default, `ebs-bootstrap` consumes a configuration file located at `/etc/ebs-boostrap/config.yml`. `cloud-init` can be configured to write a config to this location, using the `write_files` module. Ensure that `ebs-bootstrap` is installed on your Instance via the process of baking it into your Golden AMI or downloading it early in the boot process, using the `runcmd` module.
By default, `ebs-bootstrap` consumes a configuration file located at `/etc/ebs-boostrap/config.yml`. `cloud-init` can be configured to write a config to this location, using the `write_files` module. Ensure that `ebs-bootstrap` is installed on your Instance via the process of baking it into your Golden AMI or downloading it early in the boot process, using the `bootcmd` module.

<<<<<<< HEAD
The advent of Instance Store provided Nitro-enabled EC2 instances the ability to harness the power of high speed NVMe. For a stateful workload like a database, you might want a fast and ephemeral space for temporary tables, alongside a stateful EBS volume declared in a different CloudFormation Stack. However, these Instance Store devices were ephemeral and had to be formatted and mounted on each startup cycle.
=======
The advent of Instance Store provided Nitro-enabled EC2 instances the ability to harness the power of high speed NVMe. However, these Instance Store devices were ephemeral and had to be formatted and mounted on each startup cycle. For a stateful workload like a database, you might want a fast and ephemeral space for temporary tables, alongside a stateful EBS volume declared in a different CloudFormation Stack.
>>>>>>> dd8a7cb... (docs): Clean Up
From the perspective of a **sceptical** Platforms Engineer, you do not mind a tool like `ebs-bootstrap` automating the task of formatting and mounting an ephemeral device. However, you personally draw the line on automation executing modifications to a stateful device, **without** the prior consent of a human. `ebs-bootstrap` empowers this Platform Engineer by allowing them to specify the execution mode, on a **device-by-device** basis: Instance Store (`force`) and EBS Volume (`healthcheck`)

```yaml
Parameters:
LatestUbuntuAmi:
Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
Default: /aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id

Resources:
Instance:
Type: AWS::EC2::Instance
...
InstanceType: m5ad.large # Nitro Instance Type
Volumes:
- Device: /dev/sdb # EBS Volume (Stateful)
VolumeId: !ImportValue EbsVolumeId
BlockDeviceMappings:
- DeviceName: /dev/sdh # Instance Store (Ephemeral)
VirtualName: ephemeral0
UserData:
Fn::Base64: !Sub
- |+
#cloud-config
write_files:
- content: |
devices:
/dev/sdb:
fs: ${FileSystem}
mountPoint: /mnt/ebs
mountOptions: ${MountOptions}
user: ec2-user
group: ec2-user
permissions: 755
label: stateful
mode: healthcheck
/dev/sdh:
fs: ${FileSystem}
mountPoint: /mnt/instance-store
mountOptions: ${MountOptions}
user: ec2-user
group: ec2-user
permissions: 755
label: ephemeral
mode: force
path: /etc/ebs-bootstrap/config.yml
runcmd:
- curl -L -o /tmp/ebs-bootstrap "${EbsBootstrapUrlPrefix}-$(uname -m)"
- install -m755 /tmp/ebs-bootstrap /usr/local/sbin/ebs-bootstrap
bootcmd:
- /usr/local/sbin/ebs-bootstrap
- FileSystem: ext4
MountOptions: defaults,nofail,x-systemd.device-timeout=5
EbsBootstrapUrlPrefix: >
https://github.com/reecetech/ebs-bootstrap/releases/download/latest/ebs-bootstrap-linux
Properties:
...
ImageId: !Ref LatestUbuntuAmi
InstanceType: m5ad.large # Nitro Instance Type
Volumes:
- Device: /dev/sdb # EBS Volume
VolumeId: !ImportValue StatefulVolumeId
BlockDeviceMappings:
- DeviceName: /dev/sdh # Instance Store
VirtualName: ephemeral0
UserData:
Fn::Base64: !Sub
- |+
#cloud-config
write_files:
- content: |
devices:
/dev/sdb:
fs: ${FileSystem}
mountPoint: /mnt/ebs
mountOptions: ${MountOptions}
user: ubuntu
group: ubuntu
permissions: 755
label: stateful
mode: healthcheck
/dev/sdh:
fs: ${FileSystem}
mountPoint: /mnt/instance-store
mountOptions: ${MountOptions}
user: ubuntu
group: ubuntu
permissions: 755
label: ephemeral
mode: force
path: /etc/ebs-bootstrap/config.yml
bootcmd:
- curl -L -o /tmp/ebs-bootstrap "${EbsBootstrapUrlPrefix}-$(uname -m)"
- install -m755 /tmp/ebs-bootstrap /usr/local/sbin/ebs-bootstrap
runcmd:
- /usr/local/sbin/ebs-bootstrap
mounts:
- [ "LABEL=stateful", /mnt/ebs, ${FileSystem}, "${MountOptions}", "0", "2"]
- FileSystem: ext4
MountOptions: defaults,nofail,x-systemd.device-timeout=5
EbsBootstrapUrlPrefix: https://github.com/reecetech/ebs-bootstrap/releases/latest/download/ebs-bootstrap-linux
```
Assuming this is the very first launch, `ebs-bootstrap` would refuse to perform any modifications associated to the EBS device as it was assigned the `healthcheck` mode. However, we can temporarily override this behaviour with the `-mode=prompt` option. This allows the Platform Engineer to approve any suggested changes by `ebs-bootstrap`.
Expand All @@ -184,7 +186,8 @@ Assuming this is the very first launch, `ebs-bootstrap` would refuse to perform
🟢 Passed all validation checks
```
By inspecting the output of `lsblk`, we can verify that `ebs-bootstrap` was able to recover the CloudFormation assigned block device mappings (`/dev/sdb` and `/dev/sdh`) from both EBS and Instance Store NVMe devices (`/dev/nvme1n1` and `/dev/nvme2n1`) and format/label/mount the respective devices
By inspecting the output of `lsblk`, we can verify that `ebs-bootstrap` was able to recover the CloudFormation assigned block device mappings (`/dev/sdb` and `/dev/sdh`) from both EBS and Instance Store NVMe devices (`/dev/nvme1n1` and `/dev/nvme2n1`) and format/label/mount the respective devices.
```
[~] lsblk -o NAME,FSTYPE,MOUNTPOINT,LABEL,SIZE
NAME FSTYPE MOUNTPOINT LABEL SIZE
Expand Down
Binary file modified assets/ebs-bootstrap.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions internal/action/format.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ func (a *FormatDeviceAction) Prompt() string {
}

func (a *FormatDeviceAction) Refuse() string {
return fmt.Sprintf("Refused to format to %s", a.fileSystemService.GetFileSystem())
return fmt.Sprintf("Refused to format %s to %s", a.device, a.fileSystemService.GetFileSystem())
}

func (a *FormatDeviceAction) Success() string {
return fmt.Sprintf("Successfully formatted to %s", a.fileSystemService.GetFileSystem().String())
return fmt.Sprintf("Successfully formatted %s to %s", a.device, a.fileSystemService.GetFileSystem().String())
}
4 changes: 2 additions & 2 deletions internal/action/format_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ func TestFormatDeviceActionMessages(t *testing.T) {
{
Name: "Refuse",
Message: fda.Refuse(),
ExpectedOutput: "Refused to format to ext4",
ExpectedOutput: "Refused to format /dev/xvdf to ext4",
},
{
Name: "Success",
Message: fda.Success(),
ExpectedOutput: "Successfully formatted to ext4",
ExpectedOutput: "Successfully formatted /dev/xvdf to ext4",
},
}
for _, subtest := range subtests {
Expand Down
4 changes: 2 additions & 2 deletions internal/action/label.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ func (a *LabelDeviceAction) Prompt() string {
}

func (a *LabelDeviceAction) Refuse() string {
return fmt.Sprintf("Refused to label to '%s'", a.label)
return fmt.Sprintf("Refused to label %s to '%s'", a.device, a.label)
}

func (a *LabelDeviceAction) Success() string {
return fmt.Sprintf("Successfully labelled to '%s'", a.label)
return fmt.Sprintf("Successfully labelled %s to '%s'", a.device, a.label)
}
4 changes: 2 additions & 2 deletions internal/action/label_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ func TestLabelDeviceActionMessages(t *testing.T) {
{
Name: "Refuse",
Message: lda.Refuse(),
ExpectedOutput: "Refused to label to 'example'",
ExpectedOutput: "Refused to label /dev/xvdf to 'example'",
},
{
Name: "Success",
Message: lda.Success(),
ExpectedOutput: "Successfully labelled to 'example'",
ExpectedOutput: "Successfully labelled /dev/xvdf to 'example'",
},
}
for _, subtest := range subtests {
Expand Down

0 comments on commit 0797111

Please sign in to comment.