Kubernetes
Kubernetes installations support Wave Lite, a configuration mode for Wave that supports container augmentation and inspection on AWS, Azure, and GCP deployments, and enables the use of Fusion file system in Nextflow pipelines.
This page describes how to run Wave Lite on Kubernetes. It includes:
- Database configuration
- Namespace creation
- Wave configuration
- Wave deployment
- Service creation
- Advanced configuration
- Next steps
Wave's full build capabilities require specific integrations on Kubernetes and AWS EFS Storage, making EKS and AWS a hard dependency for fully-featured deployments. After you configure a base Wave Lite installation on AWS with this guide, see Configure Wave Build to optionally extend your installation to support build capabilities.
You will need the following to get started:
- A Kubernetes cluster (version 1.31 or higher)
- An externally managed PostgreSQL instance (version 12 or higher)
- An externally managed Redis instance (version 6.0 or higher)
- A Kubernetes cluster with at least:
- Memory: 4 GB RAM per Wave pod
- CPU: 1 CPU core per pod
- Network: Connectivity to your external PostgreSQL and Redis instances
- Storage: Sufficient storage for your container images and temporary files
This guide assumes:
- You have already deployed Seqera Platform Enterprise
- You will deploy Wave into the
wavenamespace - You have appropriate cluster permissions to create namespaces, deployments, and services
- Your PostgreSQL and Redis instances are accessible from the Kubernetes cluster
Database configuration
To create your wave PostgreSQL database and user account with appropriate privileges:
-
Connect to PostgreSQL.
-
Create a dedicated user for Wave:
CREATE ROLE wave_user LOGIN PASSWORD '<SECURE_PASSWORD>';Replace
<SECURE_PASSWORD>with a secure password for the database user. -
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;
Namespace creation
To create a Kubernetes wave namespace:
-
Create
namespace.yamlwith the following configuration:---
apiVersion: v1
kind: Namespace
metadata:
name: "wave"
labels:
app: wave-app -
Deploy the
wavenamespace:kubectl apply -f namespace.yaml
Wave configuration
To configure database connections, Redis caching, and server settings:
-
Create
wave-config.yamlwith the following configuration:---
apiVersion: v1
kind: ConfigMap
metadata:
name: wave-cfg
namespace: "wave"
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://<POSTGRES_HOST>:5432/wave"
user: "wave_user"
password: "<SECURE_PASSWORD>"
# Redis configuration for caching and session management
redis:
uri: "rediss://<REDIS_HOST>:6379"
# Platform integration (optional)
tower:
endpoint:
url: "<PLATFORM_SERVER>"
# 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: falseReplace the following:
<POSTGRES_HOST>: your Postgres service endpoint<REDIS_HOST>: your Redis service endpoint<SECURE_PASSWORD>: your secure password for the database user<PLATFORM_SERVER>: your Platform endpoint URL (optional)
tipIt is recommended to use Kubernetes Secrets for sensitive data instead of embedding them in the ConfigMap. For example, by adding environment variables with secrets to your Wave deployment manifest:
---
env:
- name: WAVE_DB_PASSWORD
valueFrom:
secretKeyRef:
name: wave-secrets
key: db-passwordSee the Kubernetes Secrets for more details.
- Deploy the ConfigMap to the
wavenamespace:
kubectl apply -f wave-config.yaml
Wave deployment
To deploy Wave using the deployment manifest:
-
Create
wave-deployment.yamlwith the following configuration:---
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: <AWS_ACCOUNT>.dkr.ecr.us-east-1.amazonaws.com/nf-tower-enterprise/wave:<WAVE_IMAGE_TAG>
name: wave-app
ports:
- containerPort: 9090
env:
- name: MICRONAUT_ENVIRONMENTS
value: "postgres,redis,lite"
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: AlwaysReplace the following:
<AWS_ACCOUNT>: your AWS account ID<WAVE_IMAGE_TAG>: your Wave image tag version
-
Deploy Wave to the
wavenamespace:kubectl apply -f wave-deployment.yaml
Service creation
To expose Wave within the cluster using a Service:
-
Create
wave-service.yamlwith the following configuration:---
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 -
Deploy the service to the
wavenamespace:kubectl apply -f wave-service.yaml
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": [
"<RESOURCE_NAME>/wave/*"
]
}
]
Replace <RESOURCE_NAME> with your ECR repository Amazon Resource Name (ARN).
Advanced configuration
See Configuring Wave for advanced Wave features, scaling guidance, and integration options.