mirror of
https://github.com/ChainSafe/lodestar.git
synced 2026-01-10 08:08:16 -05:00
chore: add script to launch up local kurtosis testnet (#8070)
**Motivation** Adds a bash script that allows one to launch up a local kurtosis testnet based off of the changes made locally. Might be useful to others -- if so, I can clean it up <!-- Why is this PR exists? What are the goals of the pull request? --> **Description** ``` # start a testnet with local changes ./scripts/kurtosis/run.sh start # stop the testnet and cleanup ./scripts/kurtosis/run.sh stop ``` --------- Co-authored-by: Nico Flaig <nflaig@protonmail.com>
This commit is contained in:
203
docs/pages/contribution/testing/kurtosis.md
Normal file
203
docs/pages/contribution/testing/kurtosis.md
Normal file
@@ -0,0 +1,203 @@
|
||||
# Kurtosis Scripts for Lodestar
|
||||
|
||||
This directory contains scripts and configurations for running Lodestar testnets using [Kurtosis](https://www.kurtosis.com/).
|
||||
|
||||
## Prerequisites
|
||||
|
||||
1. Install Kurtosis: https://docs.kurtosis.com/install
|
||||
2. Install Docker: https://docs.docker.com/get-docker/
|
||||
|
||||
## Quick Start
|
||||
|
||||
From the Lodestar root directory:
|
||||
|
||||
```bash
|
||||
# Start a testnet (automatically builds local Docker image)
|
||||
./scripts/kurtosis/run.sh start
|
||||
|
||||
# View running services and find service names
|
||||
kurtosis enclave inspect lodestar-testnet
|
||||
|
||||
# List just the service names
|
||||
kurtosis enclave inspect lodestar-testnet | grep -E "cl-|el-|vc-" | grep RUNNING
|
||||
|
||||
# Check logs of a specific service (use actual service name from above)
|
||||
# Note: Service names follow pattern: cl-<number>-<client>-<execution-client>
|
||||
# For Lodestar nodes, this will be cl-3-lodestar-geth, cl-4-lodestar-geth, etc.
|
||||
./scripts/kurtosis/run.sh logs cl-3-lodestar-geth
|
||||
|
||||
# Follow logs in real-time
|
||||
./scripts/kurtosis/run.sh logs cl-3-lodestar-geth --follow
|
||||
|
||||
# Stop and clean up the testnet
|
||||
./scripts/kurtosis/run.sh stop
|
||||
|
||||
# Force clean up (if stop fails)
|
||||
./scripts/kurtosis/run.sh clean
|
||||
```
|
||||
|
||||
Or change to the kurtosis directory first:
|
||||
|
||||
```bash
|
||||
cd scripts/kurtosis/
|
||||
|
||||
# Start a testnet
|
||||
./run.sh start
|
||||
|
||||
# Find service names
|
||||
kurtosis enclave inspect lodestar-testnet | grep RUNNING
|
||||
|
||||
# Check logs (replace with actual service name)
|
||||
./run.sh logs cl-3-lodestar-geth
|
||||
|
||||
# Stop
|
||||
./run.sh stop
|
||||
```
|
||||
|
||||
**Note:** The `start` command automatically builds a fresh Docker image from your local Lodestar code before starting the testnet.
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
### Custom Configuration
|
||||
|
||||
```bash
|
||||
# Create a custom config
|
||||
cp lodestar.yaml my-custom-config.yaml
|
||||
# Edit my-custom-config.yaml
|
||||
|
||||
# Run with custom config
|
||||
./run.sh start my-custom-config.yaml
|
||||
```
|
||||
|
||||
### Port Forwarding
|
||||
|
||||
Access services running inside Kurtosis:
|
||||
|
||||
```bash
|
||||
# Forward Grafana dashboard
|
||||
./run.sh port-forward grafana 3000
|
||||
|
||||
# Forward Lodestar REST API
|
||||
./run.sh port-forward cl-1-lodestar 9596
|
||||
```
|
||||
|
||||
### Custom Enclave Name
|
||||
|
||||
Run multiple testnets simultaneously:
|
||||
|
||||
```bash
|
||||
./run.sh -e testnet-1 start
|
||||
./run.sh -e testnet-2 start config-2.yaml
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Finding Service Names
|
||||
|
||||
The testnet runs multiple services. To find the correct service name for logs:
|
||||
|
||||
```bash
|
||||
# Show all services with their names
|
||||
kurtosis enclave inspect lodestar-testnet | grep -A 1 "User Services" | grep -E "cl-|el-|vc-"
|
||||
|
||||
# Example output:
|
||||
# cl-1-lighthouse-geth (Lighthouse consensus client)
|
||||
# cl-2-lighthouse-geth (Lighthouse consensus client)
|
||||
# cl-3-lodestar-geth (Lodestar consensus client)
|
||||
# cl-4-lodestar-geth (Lodestar consensus client)
|
||||
# el-1-geth-lighthouse (Geth execution client)
|
||||
# el-2-geth-lighthouse (Geth execution client)
|
||||
```
|
||||
|
||||
Service naming pattern:
|
||||
|
||||
- `cl-` = Consensus Layer
|
||||
- `el-` = Execution Layer
|
||||
- `vc-` = Validator Client
|
||||
- Format: `<layer>-<number>-<client>-<paired-client>`
|
||||
|
||||
### Check Service Status
|
||||
|
||||
```bash
|
||||
kurtosis service inspect lodestar-testnet <service-name>
|
||||
```
|
||||
|
||||
### Debug Failed Services
|
||||
|
||||
```bash
|
||||
# Check logs of a failed service
|
||||
kurtosis service logs lodestar-testnet <service-name>
|
||||
|
||||
# Get a shell inside a service container
|
||||
kurtosis service shell lodestar-testnet <service-name>
|
||||
```
|
||||
|
||||
### Clean Up Stuck Enclaves
|
||||
|
||||
```bash
|
||||
# Force remove an enclave
|
||||
kurtosis enclave rm -f lodestar-testnet
|
||||
|
||||
# Remove all enclaves
|
||||
kurtosis clean -a
|
||||
```
|
||||
|
||||
## Configuration Options
|
||||
|
||||
The configuration files use the [ethereum-package](https://github.com/ethpandaops/ethereum-package) format. Key options include:
|
||||
|
||||
- `participants`: Define execution and consensus layer nodes
|
||||
- `network_params`: Network configuration (preset, fork epochs, etc.)
|
||||
- `additional_services`: Enable monitoring, transaction spammers, etc.
|
||||
|
||||
See the [ethereum-package documentation](https://github.com/ethpandaops/ethereum-package) for all available options.
|
||||
|
||||
## Examples
|
||||
|
||||
### Minimal Testnet
|
||||
|
||||
```yaml
|
||||
participants:
|
||||
- el_type: geth
|
||||
count: 1
|
||||
- cl_type: lodestar
|
||||
count: 1
|
||||
validator_count: 32
|
||||
|
||||
network_params:
|
||||
preset: minimal
|
||||
```
|
||||
|
||||
### Multi-Client Testnet
|
||||
|
||||
```yaml
|
||||
participants:
|
||||
- el_type: geth
|
||||
count: 2
|
||||
- el_type: besu
|
||||
count: 1
|
||||
- cl_type: lodestar
|
||||
count: 2
|
||||
- cl_type: lighthouse
|
||||
count: 1
|
||||
validator_count: 32
|
||||
|
||||
network_params:
|
||||
preset: mainnet
|
||||
```
|
||||
|
||||
### Testnet with Custom Lodestar Flags
|
||||
|
||||
```yaml
|
||||
participants:
|
||||
- el_type: geth
|
||||
count: 2
|
||||
- cl_type: lodestar
|
||||
cl_image: chainsafe/lodestar:latest
|
||||
count: 2
|
||||
cl_extra_params:
|
||||
- "--metrics"
|
||||
- "--metrics.port=8008"
|
||||
- "--network.subscribeAllSubnets"
|
||||
validator_count: 32
|
||||
```
|
||||
@@ -114,6 +114,7 @@ const sidebars: SidebarsConfig = {
|
||||
"contribution/testing/index",
|
||||
"contribution/testing/end-to-end-tests",
|
||||
"contribution/testing/integration-tests",
|
||||
"contribution/testing/kurtosis",
|
||||
"contribution/testing/performance-tests",
|
||||
"contribution/testing/simulation-tests",
|
||||
"contribution/testing/spec-tests",
|
||||
|
||||
18
scripts/kurtosis/lodestar.yaml
Normal file
18
scripts/kurtosis/lodestar.yaml
Normal file
@@ -0,0 +1,18 @@
|
||||
participants:
|
||||
# Execution layer
|
||||
- el_type: geth
|
||||
el_image: ethereum/client-go:latest
|
||||
count: 2
|
||||
|
||||
# Consensus layer - Lodestar nodes using local build
|
||||
- cl_type: lodestar
|
||||
cl_image: lodestar:local # Uses locally built image
|
||||
count: 4
|
||||
validator_count: 8 # 32 validators total (8 per node)
|
||||
|
||||
network_params:
|
||||
# Use minimal preset for faster testing
|
||||
preset: minimal
|
||||
|
||||
additional_services:
|
||||
- prometheus_grafana
|
||||
224
scripts/kurtosis/run.sh
Executable file
224
scripts/kurtosis/run.sh
Executable file
@@ -0,0 +1,224 @@
|
||||
#!/bin/bash
|
||||
# Script to run Lodestar testnet using Kurtosis
|
||||
|
||||
set -e
|
||||
|
||||
# Colors for output
|
||||
GREEN='\033[0;32m'
|
||||
RED='\033[0;31m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Default values
|
||||
ENCLAVE_NAME="lodestar-testnet"
|
||||
CONFIG_FILE="lodestar.yaml"
|
||||
KURTOSIS_PACKAGE="github.com/ethpandaops/ethereum-package"
|
||||
|
||||
# Function to print colored output
|
||||
print_info() {
|
||||
echo -e "${GREEN}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
print_warn() {
|
||||
echo -e "${YELLOW}[WARN]${NC} $1"
|
||||
}
|
||||
|
||||
# Function to check if command exists
|
||||
command_exists() {
|
||||
command -v "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# Function to check dependencies
|
||||
check_dependencies() {
|
||||
print_info "Checking dependencies..."
|
||||
|
||||
if ! command_exists kurtosis; then
|
||||
print_error "Kurtosis is not installed. Please install it from https://docs.kurtosis.com/install"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command_exists docker; then
|
||||
print_error "Docker is not installed. Please install Docker."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to start the testnet
|
||||
start_testnet() {
|
||||
local config_path="$1"
|
||||
|
||||
print_info "Starting testnet with enclave name: $ENCLAVE_NAME"
|
||||
|
||||
# Check if enclave already exists
|
||||
if kurtosis enclave inspect "$ENCLAVE_NAME" >/dev/null 2>&1; then
|
||||
print_warn "Enclave $ENCLAVE_NAME already exists. Cleaning it up..."
|
||||
kurtosis enclave rm -f "$ENCLAVE_NAME"
|
||||
fi
|
||||
|
||||
# Run Kurtosis with the configuration
|
||||
print_info "Starting Kurtosis with configuration: $config_path"
|
||||
kurtosis run --enclave "$ENCLAVE_NAME" "$KURTOSIS_PACKAGE" --args-file "$config_path"
|
||||
|
||||
print_info "Testnet started successfully!"
|
||||
print_info "View services: kurtosis enclave inspect $ENCLAVE_NAME"
|
||||
}
|
||||
|
||||
# Function to stop the testnet
|
||||
stop_testnet() {
|
||||
print_info "Stopping testnet: $ENCLAVE_NAME"
|
||||
kurtosis enclave stop "$ENCLAVE_NAME"
|
||||
|
||||
print_info "Cleaning up testnet resources..."
|
||||
kurtosis enclave rm -f "$ENCLAVE_NAME"
|
||||
|
||||
print_info "Testnet stopped and cleaned up successfully"
|
||||
}
|
||||
|
||||
# Function to clean up the testnet
|
||||
clean_testnet() {
|
||||
print_info "Cleaning up testnet: $ENCLAVE_NAME"
|
||||
kurtosis enclave rm -f "$ENCLAVE_NAME"
|
||||
}
|
||||
|
||||
# Function to show logs
|
||||
show_logs() {
|
||||
local service="$1"
|
||||
if [ -z "$service" ]; then
|
||||
print_info "Available services:"
|
||||
kurtosis service ls "$ENCLAVE_NAME"
|
||||
else
|
||||
print_info "Showing logs for service: $service"
|
||||
kurtosis service logs "$ENCLAVE_NAME" "$service" --follow
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to port-forward a service
|
||||
port_forward() {
|
||||
local service="$1"
|
||||
local port="$2"
|
||||
|
||||
if [ -z "$service" ] || [ -z "$port" ]; then
|
||||
print_error "Usage: $0 port-forward <service-name> <port>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
print_info "Port-forwarding $service:$port"
|
||||
kurtosis port-forward "$ENCLAVE_NAME" "$service" "$port"
|
||||
}
|
||||
|
||||
# Function to build local Docker image
|
||||
build_local() {
|
||||
print_info "Building local Lodestar Docker image..."
|
||||
|
||||
# Get the root directory (two levels up from scripts/kurtosis)
|
||||
# TODO: There might be a better way to get the root
|
||||
LODESTAR_ROOT="$SCRIPT_DIR/../.."
|
||||
|
||||
# Build the Docker image
|
||||
if docker build -f Dockerfile.dev -t lodestar:local "$LODESTAR_ROOT"; then
|
||||
print_info "Successfully built lodestar:local"
|
||||
print_info "You can now use this image in your config files with: cl_image: lodestar:local"
|
||||
else
|
||||
print_error "Failed to build Docker image"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to show usage
|
||||
usage() {
|
||||
echo "Usage: $0 [command] [options]"
|
||||
echo ""
|
||||
echo "Commands:"
|
||||
echo " start [config-file] Start the testnet (builds local image, default: lodestar.yaml)"
|
||||
echo " stop Stop and clean up the testnet"
|
||||
echo " clean Force clean up the testnet (if stop fails)"
|
||||
echo " logs [service] Show logs for a service (or list services)"
|
||||
echo " port-forward <service> <port> Forward a port from a service"
|
||||
echo " build Build local Docker image only (without starting)"
|
||||
echo " help Show this help message"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " -e, --enclave <name> Set enclave name (default: lodestar-testnet)"
|
||||
echo ""
|
||||
echo "Examples:"
|
||||
echo " $0 start"
|
||||
echo " $0 start custom-config.yaml"
|
||||
echo " $0 logs cl-1-lodestar"
|
||||
echo " $0 port-forward grafana 3000"
|
||||
}
|
||||
|
||||
# Parse command line arguments
|
||||
COMMAND=""
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
-e|--enclave)
|
||||
ENCLAVE_NAME="$2"
|
||||
shift 2
|
||||
;;
|
||||
build|start|stop|clean|logs|port-forward|help)
|
||||
COMMAND="$1"
|
||||
shift
|
||||
break
|
||||
;;
|
||||
*)
|
||||
print_error "Unknown option: $1"
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Check dependencies
|
||||
check_dependencies
|
||||
|
||||
# Get the directory of this script
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
|
||||
# Execute command
|
||||
case $COMMAND in
|
||||
build)
|
||||
build_local
|
||||
;;
|
||||
start)
|
||||
CONFIG_PATH="${1:-$CONFIG_FILE}"
|
||||
# Make path absolute if relative
|
||||
if [[ ! "$CONFIG_PATH" = /* ]]; then
|
||||
CONFIG_PATH="$SCRIPT_DIR/$CONFIG_PATH"
|
||||
fi
|
||||
|
||||
if [ ! -f "$CONFIG_PATH" ]; then
|
||||
print_error "Configuration file not found: $CONFIG_PATH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Always build local image before starting
|
||||
print_info "Building local Lodestar Docker image before starting testnet..."
|
||||
build_local
|
||||
|
||||
start_testnet "$CONFIG_PATH"
|
||||
;;
|
||||
stop)
|
||||
stop_testnet
|
||||
;;
|
||||
clean)
|
||||
clean_testnet
|
||||
;;
|
||||
logs)
|
||||
show_logs "$1"
|
||||
;;
|
||||
port-forward)
|
||||
port_forward "$1" "$2"
|
||||
;;
|
||||
help)
|
||||
usage
|
||||
;;
|
||||
*)
|
||||
print_error "No command specified"
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
Reference in New Issue
Block a user