Kubernetes installation
Wave enables you to provision container images on-demand, removing the need to build and upload them manually to a container registry. Wave can can provision both disposable containers that are only accessible for a short period, and regular registry-persisted container images.
This installation guide covers Wave in augmentation-only mode (referred to here as wave-lite
), which provides:
- inspect - Container inspection and metadata retrieval
- augment - Container image augmentation with additional layers
Wave's full build capabilities require specific integrations with Kubernetes and AWS EFS Storage, making EKS & AWS a hard dependency for fully-featured deployments. The following Wave features are not available in this configuration:
- Container Freeze
- Container Build service
- Container Mirror service
- Container Security scanning
- Container blobs caching
After you have configured a base Wave installation with this guide, see Configuring Wave Build to extend your installation to support build capabilities.
Prerequisites
Required infrastructure:
- Kubernetes cluster - Version 1.31 or higher (any distribution)
- PostgreSQL instance - Version 12 or higher (managed externally)
- Redis instance - Version 6.0 or higher (managed externally)
System requirements
The minimum system requirements for a Wave Kubernetes installation are:
- Memory: Minimum 4GB RAM per Wave pod
- CPU: Minimum 1 CPU core per pod
- Network: Connectivity to your external PostgreSQL and Redis instances
- Storage: Sufficient storage for your container images and temporary files
See Configuring Wave for detailed scaling and performance tuning guidance.
Assumptions
This guide assumes:
- You have already deployed Seqera Platform Enterprise
- You will deploy Wave into the
wave
namespace - You have appropriate cluster permissions to create namespaces, deployments, and services
- Your PostgreSQL and Redis instances are accessible from the Kubernetes cluster
Database configuration
Wave requires a PostgreSQL database to operate.
Create a dedicated wave
database and user account with the appropriate privileges:
-- Create a dedicated user for Wave
CREATE ROLE wave_user LOGIN PASSWORD 'your_secure_password';
-- Create the Wave database
CREATE DATABASE wave;
-- Connect to the wave database
\c wave;
-- Grant basic schema access
GRANT USAGE, CREATE ON SCHEMA public TO wave_user;
-- Grant privileges on existing tables and sequences
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO wave_user;
GRANT USAGE, SELECT, UPDATE ON ALL SEQUENCES IN SCHEMA public TO wave_user;
-- Grant privileges on future tables and sequences
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO wave_user;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT USAGE, SELECT, UPDATE ON SEQUENCES TO wave_user;
Create namespace
---
apiVersion: v1
kind: Namespace
metadata:
name: "wave"
labels:
app: wave-app
Configure Wave
Create a ConfigMap containing Wave's configuration. Update the following values to match your environment:
- Database connection details (
uri
,user
,password
) - Redis connection string
- Seqera Platform API endpoint
This configuration contains sensitive values. It is recommended to use Kubernetes Secrets for sensitive data, instead of embedding them directly in the ConfigMap. See the Kubernetes Secrets documentation for more details.
Example using environment variables with secrets:
env:
- name: WAVE_DB_PASSWORD
valueFrom:
secretKeyRef:
name: wave-secrets
key: db-password
kind: ConfigMap
apiVersion: v1
metadata:
name: wave-cfg
namespace: "wave"
labels:
app: wave-cfg
data:
config.yml: |
wave:
# Build service configuration - disabled for Wave base installation
build:
enabled: false
# Mirror service configuration - disabled for Wave base installation
mirror:
enabled: false
# Security scanning configuration - disabled for Wave base installation
scan:
enabled: false
# Blob caching configuration - disabled for Wave base installation
blobCache:
enabled: false
# Database connection settings
db:
uri: "jdbc:postgresql://your-postgres-host:5432/wave"
user: "wave_user"
password: "your_secure_password"
# Redis configuration for caching and session management
redis:
uri: "rediss://your-redis-host:6379"
# Platform integration (optional)
tower:
endpoint:
url: "https://your-platform-server.com"
# Micronaut framework configuration
micronaut:
# Executor configuration for handling concurrent requests
executors:
stream-executor:
type: FIXED
number-of-threads: 16
# Netty HTTP server configuration
netty:
event-loops:
default:
num-threads: 64
stream-pool:
executor: stream-executor
# HTTP client configuration
http:
services:
stream-client:
read-timeout: 30s
read-idle-timeout: 5m
event-loop-group: stream-pool
# Management endpoints configuration
loggers:
# Enable metrics for monitoring
metrics:
enabled: true
# Enable health checks
health:
enabled: true
disk-space:
enabled: false
jdbc:
enabled: false
Create deployment
Deploy Wave using the following Deployment manifest:
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: wave
namespace: "wave"
labels:
app: wave-app
spec:
replicas: 1
selector:
matchLabels:
app: wave-app
template:
metadata:
labels:
app: wave-app
spec:
containers:
- image: REPLACE_ME_AWS_ACCOUNT.dkr.ecr.us-east-1.amazonaws.com/nf-tower-enterprise/wave:REPLACE_ME_WAVE_IMAGE_TAG
name: wave-app
ports:
- containerPort: 9090
env:
- name: MICRONAUT_ENVIRONMENTS
value: "postgres,redis,lite"
- name: WAVE_JVM_OPTS
value: '-XX:+UseG1GC -Xms512m -Xmx850m -XX:MaxDirectMemorySize=100m -Dio.netty.maxDirectMemory=0 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/efs/wave/dump/java-$(POD_NAME).hprof -Djdk.httpclient.keepalive.timeout=10 -Djdk.tracePinnedThreads=short -Djdk.traceVirtualThreadInThreadDump=full'
resources:
requests:
memory: "4000Mi"
limits:
memory: "4000Mi"
workingDir: "/work"
volumeMounts:
- name: wave-cfg
mountPath: /work/config.yml
subPath: "config.yml"
readinessProbe:
httpGet:
path: /health
port: 9090
initialDelaySeconds: 5
timeoutSeconds: 3
livenessProbe:
httpGet:
path: /health
port: 9090
initialDelaySeconds: 5
timeoutSeconds: 3
failureThreshold: 10
volumes:
- name: wave-cfg
configMap:
name: wave-cfg
restartPolicy: Always
Create Service
Expose Wave within the cluster using a Service:
---
apiVersion: v1
kind: Service
metadata:
name: wave-service
namespace: "wave"
labels:
app: wave-app
spec:
selector:
app: wave-app
ports:
- name: http
port: 9090
targetPort: 9090
protocol: TCP
type: ClusterIP
Next steps
Configure Seqera Platform to integrate with Wave
Configure your Seqera Platform Enterprise deployment to integrate with Wave by setting the Wave server endpoint in your tower.yml
configuration.
Networking
Wave must be accessible from:
- Seqera Platform services
- Compute environments (for container image access)
Configure external access using a Kubernetes ingress.
Update the following example ingress with your provider-specific annotations:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: wave-ingress
namespace: wave
spec:
rules:
- host: wave.your-domain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: wave-service
port:
number: 9090
TLS
Wave does not handle TLS termination directly. Configure TLS at your ingress controller or load balancer level. Most ingress controllers support automatic certificate provisioning through provider integrations.
Production environments
Consider implementing the following for production deployments:
Reliability:
- Pod Disruption Budgets, for availability during cluster maintenance
- Horizontal Pod Autoscaler, for automatic scaling based on load
- Multiple replicas with anti-affinity rules, for high availability
Resource management:
- Node selectors or affinity rules for optimal pod placement
- Resource quotas and limit ranges for the Wave namespace
AWS credentials to access ECR
Wave requires access to AWS ECR for container image management. Create an IAM role with the following permissions:
"Statement": [
{
"Action": [
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:GetRepositoryPolicy",
"ecr:DescribeRepositories",
"ecr:ListImages",
"ecr:DescribeImages",
"ecr:BatchGetImage",
"ecr:GetLifecyclePolicy",
"ecr:GetLifecyclePolicyPreview",
"ecr:ListTagsForResource",
"ecr:DescribeImageScanFindings",
"ecr:CompleteLayerUpload",
"ecr:UploadLayerPart",
"ecr:InitiateLayerUpload",
"ecr:PutImage"
],
"Effect": "Allow",
"Resource": [
"<REPO>/wave/*"
]
}
Advanced configuration
See Configuring Wave for advanced Wave features, scaling guidance, and integration options.