Use shared rootfs with per-VM home
This commit is contained in:
parent
dee329cf39
commit
092700b241
3 changed files with 43 additions and 47 deletions
|
|
@ -19,12 +19,17 @@ Minimal Firecracker launcher.
|
||||||
|
|
||||||
## Run Options
|
## Run Options
|
||||||
```
|
```
|
||||||
./run.sh --name calm_otter --vcpu 4 --ram 2048 --disk-size 6G
|
./run.sh --name calm_otter --vcpu 4 --ram 2048 --home-size 6G
|
||||||
```
|
```
|
||||||
- `--name`: must be unique and match `[a-z0-9][a-z0-9_-]{0,63}`.
|
- `--name`: must be unique and match `[a-z0-9][a-z0-9_-]{0,63}`.
|
||||||
- `--vcpu`: defaults to 2, max 16.
|
- `--vcpu`: defaults to 2, max 16.
|
||||||
- `--ram`: MiB, defaults to 1024, max 32768.
|
- `--ram`: MiB, defaults to 1024, max 32768.
|
||||||
- `--disk-size`: M/G suffixes supported; must be >= base `rootfs.ext4` size. Requires `resize2fs`.
|
- `--home-size`: M/G suffixes supported (default: 2G).
|
||||||
|
|
||||||
|
## Storage Layout
|
||||||
|
- `rootfs.ext4` is mounted read-only as `/` and shared across VMs.
|
||||||
|
- Each VM gets a writable ext4 disk mounted at `/home`.
|
||||||
|
- The base image must include an `/etc/fstab` entry for `/dev/vdb` → `/home`.
|
||||||
|
|
||||||
## SSH
|
## SSH
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -231,6 +231,10 @@ ssh -i "$SSH_KEY" -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
|
||||||
printf 'nameserver %s\n' \"$DNS_SERVER\" > /etc/resolv.conf
|
printf 'nameserver %s\n' \"$DNS_SERVER\" > /etc/resolv.conf
|
||||||
echo \"$VM_NAME\" > /etc/hostname
|
echo \"$VM_NAME\" > /etc/hostname
|
||||||
printf '127.0.0.1 localhost\n127.0.1.1 %s\n' \"$VM_NAME\" > /etc/hosts
|
printf '127.0.0.1 localhost\n127.0.1.1 %s\n' \"$VM_NAME\" > /etc/hosts
|
||||||
|
mkdir -p /home
|
||||||
|
if ! grep -q '^/dev/vdb ' /etc/fstab; then
|
||||||
|
echo '/dev/vdb /home ext4 defaults 0 2' >> /etc/fstab
|
||||||
|
fi
|
||||||
apt-get update
|
apt-get update
|
||||||
DEBIAN_FRONTEND=noninteractive apt-get -y upgrade
|
DEBIAN_FRONTEND=noninteractive apt-get -y upgrade
|
||||||
DEBIAN_FRONTEND=noninteractive apt-get -y install git less tree ca-certificates curl
|
DEBIAN_FRONTEND=noninteractive apt-get -y install git less tree ca-certificates curl
|
||||||
|
|
|
||||||
77
run.sh
77
run.sh
|
|
@ -13,7 +13,7 @@ Options:
|
||||||
--name <name> VM name (lowercase letters, digits, -, _)
|
--name <name> VM name (lowercase letters, digits, -, _)
|
||||||
--vcpu <count> vCPU count (default: 2)
|
--vcpu <count> vCPU count (default: 2)
|
||||||
--ram <mib> RAM in MiB (default: 1024)
|
--ram <mib> RAM in MiB (default: 1024)
|
||||||
--disk-size <size> Root disk size (e.g. 4G, 10240M); must be >= base image
|
--home-size <size> Home disk size (e.g. 4G, 10240M)
|
||||||
-h, --help Show this help
|
-h, --help Show this help
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
@ -37,6 +37,7 @@ CIDR="24"
|
||||||
|
|
||||||
DEFAULT_VCPU=2
|
DEFAULT_VCPU=2
|
||||||
DEFAULT_RAM=1024
|
DEFAULT_RAM=1024
|
||||||
|
DEFAULT_HOME_SIZE="2G"
|
||||||
MIN_VCPU=1
|
MIN_VCPU=1
|
||||||
MAX_VCPU=16
|
MAX_VCPU=16
|
||||||
MIN_RAM=256
|
MIN_RAM=256
|
||||||
|
|
@ -46,7 +47,7 @@ DNS_SERVER="1.1.1.1"
|
||||||
|
|
||||||
VCPU_COUNT="$DEFAULT_VCPU"
|
VCPU_COUNT="$DEFAULT_VCPU"
|
||||||
RAM_MIB="$DEFAULT_RAM"
|
RAM_MIB="$DEFAULT_RAM"
|
||||||
DISK_SIZE=""
|
HOME_SIZE="$DEFAULT_HOME_SIZE"
|
||||||
VM_NAME=""
|
VM_NAME=""
|
||||||
|
|
||||||
shopt -s nullglob
|
shopt -s nullglob
|
||||||
|
|
@ -92,8 +93,8 @@ while [[ $# -gt 0 ]]; do
|
||||||
RAM_MIB="${2:-}"
|
RAM_MIB="${2:-}"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
--disk-size)
|
--home-size)
|
||||||
DISK_SIZE="${2:-}"
|
HOME_SIZE="${2:-}"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
-h|--help)
|
-h|--help)
|
||||||
|
|
@ -113,7 +114,7 @@ if ! [[ "$VCPU_COUNT" =~ ^[0-9]+$ ]]; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
if (( VCPU_COUNT < MIN_VCPU || VCPU_COUNT > MAX_VCPU )); then
|
if (( VCPU_COUNT < MIN_VCPU || VCPU_COUNT > MAX_VCPU )); then
|
||||||
log "vcpu must be between 1 and $MAX_VCPU"
|
log "vcpu must be between $MIN_VCPU and $MAX_VCPU"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
@ -122,20 +123,18 @@ if ! [[ "$RAM_MIB" =~ ^[0-9]+$ ]]; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
if (( RAM_MIB < MIN_RAM || RAM_MIB > MAX_RAM )); then
|
if (( RAM_MIB < MIN_RAM || RAM_MIB > MAX_RAM )); then
|
||||||
log "ram must be between 256 and $MAX_RAM MiB"
|
log "ram must be between $MIN_RAM and $MAX_RAM MiB"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
DISK_BYTES=""
|
HOME_BYTES=""
|
||||||
if [[ -n "$DISK_SIZE" ]]; then
|
if ! HOME_BYTES="$(parse_disk_size "$HOME_SIZE")"; then
|
||||||
if ! DISK_BYTES="$(parse_disk_size "$DISK_SIZE")"; then
|
log "invalid --home-size value: $HOME_SIZE"
|
||||||
log "invalid --disk-size value: $DISK_SIZE"
|
exit 1
|
||||||
exit 1
|
fi
|
||||||
fi
|
if (( HOME_BYTES > MAX_DISK_BYTES )); then
|
||||||
if (( DISK_BYTES > MAX_DISK_BYTES )); then
|
log "home-size exceeds max of $((MAX_DISK_BYTES / 1024 / 1024 / 1024))G"
|
||||||
log "disk-size exceeds max of $((MAX_DISK_BYTES / 1024 / 1024 / 1024))G"
|
exit 1
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -z "$VM_NAME" ]]; then
|
if [[ -z "$VM_NAME" ]]; then
|
||||||
|
|
@ -193,7 +192,7 @@ sudo -v
|
||||||
VM_STARTED=0
|
VM_STARTED=0
|
||||||
CLEANUP_ON_EXIT=0
|
CLEANUP_ON_EXIT=0
|
||||||
KEEP_VM_DIR_ON_FAIL=1
|
KEEP_VM_DIR_ON_FAIL=1
|
||||||
DISK_PATH="$VM_DIR/rootfs.ext4"
|
HOME_PATH="$VM_DIR/home.ext4"
|
||||||
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
local exit_code=$?
|
local exit_code=$?
|
||||||
|
|
@ -242,35 +241,12 @@ else
|
||||||
log "setcap not available; firecracker may need root to open TAP"
|
log "setcap not available; firecracker may need root to open TAP"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cp --reflink=auto "$ROOTFS" "$DISK_PATH"
|
if ! command -v mkfs.ext4 >/dev/null 2>&1; then
|
||||||
|
log "mkfs.ext4 required to create home disk"
|
||||||
if [[ -n "$DISK_BYTES" ]]; then
|
|
||||||
if ! command -v resize2fs >/dev/null 2>&1; then
|
|
||||||
log "resize2fs required for --disk-size"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
BASE_BYTES="$(stat -c%s "$ROOTFS")"
|
|
||||||
if (( DISK_BYTES < BASE_BYTES )); then
|
|
||||||
log "disk-size must be >= base image size"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
if (( DISK_BYTES > BASE_BYTES )); then
|
|
||||||
log "resizing rootfs to $DISK_SIZE"
|
|
||||||
truncate -s "$DISK_BYTES" "$DISK_PATH"
|
|
||||||
resize2fs "$DISK_PATH" >/dev/null
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! command -v debugfs >/dev/null 2>&1; then
|
|
||||||
log "debugfs required to set resolv.conf"
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
RESOLV_TMP="$VM_DIR/resolv.conf"
|
truncate -s "$HOME_BYTES" "$HOME_PATH"
|
||||||
printf 'nameserver %s\n' "$DNS_SERVER" >"$RESOLV_TMP"
|
mkfs.ext4 -F "$HOME_PATH" >/dev/null
|
||||||
debugfs -w -R "write $RESOLV_TMP /etc/resolv.conf" "$DISK_PATH" >/dev/null 2>&1 || {
|
|
||||||
log "failed to write /etc/resolv.conf into rootfs"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# Host bridge
|
# Host bridge
|
||||||
if ! ip link show "$BR_DEV" >/dev/null 2>&1; then
|
if ! ip link show "$BR_DEV" >/dev/null 2>&1; then
|
||||||
|
|
@ -352,8 +328,19 @@ log "attaching root filesystem"
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d "{
|
-d "{
|
||||||
\"drive_id\": \"rootfs\",
|
\"drive_id\": \"rootfs\",
|
||||||
\"path_on_host\": \"$DISK_PATH\",
|
\"path_on_host\": \"$ROOTFS\",
|
||||||
\"is_root_device\": true,
|
\"is_root_device\": true,
|
||||||
|
\"is_read_only\": true
|
||||||
|
}" >/dev/null
|
||||||
|
|
||||||
|
# Home filesystem
|
||||||
|
log "attaching home filesystem"
|
||||||
|
"${CURL_CMD[@]}" --unix-socket "$API_SOCK" -X PUT http://localhost/drives/home \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "{
|
||||||
|
\"drive_id\": \"home\",
|
||||||
|
\"path_on_host\": \"$HOME_PATH\",
|
||||||
|
\"is_root_device\": false,
|
||||||
\"is_read_only\": false
|
\"is_read_only\": false
|
||||||
}" >/dev/null
|
}" >/dev/null
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue