Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
37 changes: 37 additions & 0 deletions build/golden-image/Containerfile
Original file line number Diff line number Diff line change
@@ -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
141 changes: 141 additions & 0 deletions build/golden-image/README.md
Original file line number Diff line number Diff line change
@@ -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).
55 changes: 55 additions & 0 deletions build/golden-image/build.sh
Original file line number Diff line number Diff line change
@@ -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"
Loading