diff --git a/README.md b/README.md index 78d080c..8212049 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,39 @@ Or run directly: go run ./cmd/virtwork --help ``` +## Golden Container Disk Image (Optional) + +For faster VM boot times, virtwork provides a golden container disk image with all workload tools pre-installed: + +- **stress-ng** (CPU/memory workloads) +- **fio** (disk I/O workloads) +- **iperf3** (network workloads) +- **postgresql-server** (database workloads) +- **tc, iptables** (chaos engineering tools) + +Using this image reduces VM boot time by 2-5 minutes by eliminating package installation. + +### Using the Golden Image + +```bash +# Use via CLI flag +virtwork run --container-disk-image quay.io/opdev/virtwork-disk:latest + +# Or via environment variable +export VIRTWORK_CONTAINER_DISK_IMAGE=quay.io/opdev/virtwork-disk:latest +virtwork run + +# Or via config file +echo "container_disk_image: quay.io/opdev/virtwork-disk:latest" > config.yaml +virtwork run --config config.yaml +``` + +### Building the Golden Image + +See [build/golden-image/README.md](build/golden-image/README.md) for build instructions. + +**Note**: The golden image is optional. If you use the default Fedora image, packages will be installed at VM boot time via cloud-init as usual. + ## Quick Start ```bash diff --git a/build/golden-image/Containerfile b/build/golden-image/Containerfile new file mode 100644 index 0000000..f0b7376 --- /dev/null +++ b/build/golden-image/Containerfile @@ -0,0 +1,37 @@ +# Golden Container Disk Image for virtwork +# Copyright 2026 Red Hat +# SPDX-License-Identifier: Apache-2.0 + +FROM quay.io/containerdisks/fedora:41 + +LABEL io.k8s.display-name="virtwork-disk" \ + io.k8s.description="Fedora 41 container disk with virtwork workload tools pre-installed" \ + summary="Container disk for virtwork with CPU, memory, database, network, and disk tools" \ + description="Pre-built Fedora 41 container disk with stress-ng, fio, iperf3, postgresql-server, and chaos engineering tools for faster VM boot times" \ + name="virtwork-disk" \ + version="1.0" \ + maintainer="OpenDev Community" + +# Install all workload tools in a single layer to minimize image size +# Clean DNF cache to reduce final image size +RUN dnf install -y \ + stress-ng \ + fio \ + iperf3 \ + postgresql-server \ + iproute-tc \ + iptables-nft \ + && dnf clean all \ + && rm -rf /var/cache/dnf + +# Verify all critical binaries are present +RUN which stress-ng && \ + which fio && \ + which iperf3 && \ + which pgbench && \ + which tc && \ + which iptables-nft + +# Expose metadata for KubeVirt compatibility +# The containerdisk format expects the disk image to be at /disk/ +# This is already handled by the base fedora:41 image diff --git a/build/golden-image/README.md b/build/golden-image/README.md new file mode 100644 index 0000000..7161bea --- /dev/null +++ b/build/golden-image/README.md @@ -0,0 +1,141 @@ +# Golden Container Disk Image + +This directory contains the Containerfile and build scripts for the virtwork golden container disk image. + +## Overview + +The golden image is based on `quay.io/containerdisks/fedora:41` and includes all tools needed for virtwork workloads pre-installed. This eliminates package installation at VM boot time, reducing startup time by 2-5 minutes. + +### Pre-installed Tools + +- **stress-ng** — CPU and memory stress testing (cpu, memory workloads) +- **fio** — Flexible I/O tester for disk benchmarking (disk workload) +- **iperf3** — Network performance testing (network workload) +- **postgresql-server** — PostgreSQL database with pgbench (database workload) +- **iproute-tc** — Traffic control for network chaos engineering (future chaos workloads) +- **iptables-nft** — Firewall rules for network partition simulation (future chaos workloads) + +Additional tools like `fallocate`, `dd`, `kill`, and `pkill` are already present in the base Fedora image. + +## Building + +### Prerequisites + +- Podman or Docker installed +- Network access to pull `quay.io/containerdisks/fedora:41` + +### Build Locally + +```bash +./build.sh +``` + +This builds the image as `quay.io/opdev/virtwork-disk:latest` (local copy, not pushed to registry). + +### Build and Push + +```bash +PUSH=true ./build.sh +``` + +This builds and pushes to `quay.io/opdev/virtwork-disk:latest`. Requires authentication to the registry. + +### Build with Custom Registry + +```bash +REGISTRY=my.registry.io ./build.sh +``` + +### Build with Custom Tag + +```bash +TAG=1.0.0 ./build.sh +``` + +### Environment Variables + +| Variable | Description | Default | +|----------|-------------|---------| +| `REGISTRY` | Container registry hostname | `quay.io/opdev` | +| `IMAGE_NAME` | Image name | `virtwork-disk` | +| `TAG` | Image tag | `latest` | +| `PUSH` | Push to registry after building | `false` | + +## Testing + +After building, verify tools are present: + +```bash +podman run --rm quay.io/opdev/virtwork-disk:latest /bin/bash -c "stress-ng --version" +podman run --rm quay.io/opdev/virtwork-disk:latest /bin/bash -c "fio --version" +podman run --rm quay.io/opdev/virtwork-disk:latest /bin/bash -c "iperf3 --version" +podman run --rm quay.io/opdev/virtwork-disk:latest /bin/bash -c "psql --version" +``` + +## Using the Golden Image + +The golden image is **optional**. To use it with virtwork: + +### CLI Flag + +```bash +virtwork run --container-disk-image quay.io/opdev/virtwork-disk:latest +``` + +### Environment Variable + +```bash +export VIRTWORK_CONTAINER_DISK_IMAGE=quay.io/opdev/virtwork-disk:latest +virtwork run +``` + +### Config File + +```yaml +# config.yaml +container_disk_image: quay.io/opdev/virtwork-disk:latest +``` + +```bash +virtwork run --config config.yaml +``` + +## Image Size + +The golden image adds approximately **34MB** to the base Fedora 41 container disk image: + +- Base Fedora 41 container disk: ~600MB +- Golden image: ~634MB + +## Design Decisions + +### Why Keep Package Installation in Cloud-Init? + +DNF is **idempotent** — when it tries to install a package that's already present, it completes instantly with "Package X is already installed" messages. + +This means: +- **Golden image users**: Get instant package "installation" (already there) — saves 2-5 minutes +- **Default Fedora users**: Get normal package installation at boot +- **Same workload code**: Works for both images without conditional logic + +### Why Not Remove Packages from Cloud-Init? + +Removing package installation from workload code would require: +- Changes to all 5 workload implementations +- Changes to all workload tests +- Conditional logic to detect which image is in use +- Maintaining two code paths + +The current approach is simpler and maintains backward compatibility. + +## Future Enhancements + +1. **Multi-architecture support**: Build for arm64 in addition to amd64 +2. **Automated builds**: GitHub Actions workflow on schedule +3. **Image scanning**: Add Trivy security scanning +4. **Semantic versioning**: Pin specific package versions for reproducibility +5. **Image variants**: Create minimal/full variants for different use cases + +## License + +Apache License 2.0. See [LICENSE](../../LICENSE). diff --git a/build/golden-image/build.sh b/build/golden-image/build.sh new file mode 100755 index 0000000..5b72ddf --- /dev/null +++ b/build/golden-image/build.sh @@ -0,0 +1,55 @@ +#!/bin/bash +# Build script for virtwork golden container disk image +# Copyright 2026 Red Hat +# SPDX-License-Identifier: Apache-2.0 + +set -euo pipefail + +REGISTRY="${REGISTRY:-quay.io/opdev}" +IMAGE_NAME="${IMAGE_NAME:-virtwork-disk}" +TAG="${TAG:-latest}" +FULL_IMAGE="${REGISTRY}/${IMAGE_NAME}:${TAG}" + +echo "Building golden container disk image: ${FULL_IMAGE}" +echo "======================================================" + +# Build the image +podman build \ + --tag "${FULL_IMAGE}" \ + --file Containerfile \ + . + +echo "" +echo "Image built successfully: ${FULL_IMAGE}" +echo "" + +# Optional: push to registry +if [[ "${PUSH:-false}" == "true" ]]; then + echo "Pushing image to registry..." + podman push "${FULL_IMAGE}" + echo "Image pushed successfully" + echo "" +fi + +# Verify the image contains expected tools +echo "Verifying installed tools..." +echo "==============================" +podman run --rm "${FULL_IMAGE}" /bin/bash -c " + which stress-ng && echo '✓ stress-ng found' || echo '✗ stress-ng MISSING' && + which fio && echo '✓ fio found' || echo '✗ fio MISSING' && + which iperf3 && echo '✓ iperf3 found' || echo '✗ iperf3 MISSING' && + which pgbench && echo '✓ pgbench found' || echo '✗ pgbench MISSING' && + which tc && echo '✓ tc found' || echo '✗ tc MISSING' && + which iptables-nft && echo '✓ iptables-nft found' || echo '✗ iptables-nft MISSING' +" + +echo "" +echo "======================================================" +echo "Build complete!" +echo "Image: ${FULL_IMAGE}" +echo "" +echo "To push this image to the registry, run:" +echo " PUSH=true ./build.sh" +echo "" +echo "To use a custom registry, run:" +echo " REGISTRY=my.registry.io ./build.sh"