provisioning/schemas/infrastructure/examples-multi-provider.ncl
Jesús Pérez 44648e3206
chore: complete nickel migration and consolidate legacy configs
- Remove KCL ecosystem (~220 files deleted)
- Migrate all infrastructure to Nickel schema system
- Consolidate documentation: legacy docs → provisioning/docs/src/
- Add CI/CD workflows (.github/) and Rust build config (.cargo/)
- Update core system for Nickel schema parsing
- Update README.md and CHANGES.md for v5.0.0 release
- Fix pre-commit hooks: end-of-file, trailing-whitespace
- Breaking changes: KCL workspaces require migration
- Migration bridge available in docs/src/development/
2026-01-08 09:55:37 +00:00

544 lines
15 KiB
Plaintext

# Multi-Provider Infrastructure Examples
# Nickel examples demonstrating multi-provider deployment patterns
# References: multi-provider-deployment.md guide
let hetzner = import "../../extensions/providers/hetzner/nickel/main.ncl" in
let upcloud = import "../../extensions/providers/upcloud/nickel/main.ncl" in
let aws = import "../../extensions/providers/aws/nickel/main.ncl" in
let digitalocean = import "../../extensions/providers/digitalocean/nickel/main.ncl" in
{
# =============================================================================
# Example 1: Three-Provider Web Application
# =============================================================================
# Architecture:
# - DigitalOcean: Web servers (cost-effective compute) - NYC region
# - AWS: Managed PostgreSQL database (high availability) - US-East region
# - Hetzner: Backup storage volumes (low-cost data retention) - Germany
#
# Total Monthly Cost: ~$77 (vs $150+ for single provider)
# Key Benefits: Cost optimization, compute specialization, managed database
three_provider_web_app = {
workspace_name = "three-provider-webapp",
description = "Web application leveraging provider strengths",
# Provider routing and configuration
providers = {
primary_compute = "digitalocean",
database = "aws",
backup = "hetzner"
},
# ==========================================================================
# Private Networks and VPN Tunnels
# ==========================================================================
networks = {
# DigitalOcean VPC (10.0.0.0/16)
do_vpc = digitalocean.VPC & {
name = "webapp-vpc",
region = "nyc3",
ip_range = "10.0.0.0/16"
},
# AWS VPC (10.1.0.0/16)
aws_vpc = aws.VPC & {
cidr_block = "10.1.0.0/16",
enable_dns_hostnames = true,
enable_dns_support = true
},
# AWS DB Subnet
aws_db_subnet = aws.Subnet & {
vpc_id = "{{ networks.aws_vpc.id }}",
cidr_block = "10.1.1.0/24",
availability_zone = "us-east-1a"
},
# Hetzner Private Network (10.2.0.0/16)
hetzner_network = hetzner.Network & {
name = "backup-network",
ip_range = "10.2.0.0/16"
}
},
# VPN Tunnels for secure communication
vpn_configuration = {
do_to_aws_tunnel = {
protocol = "ipsec",
encryption = "aes-256",
source_networks = ["10.0.0.0/16"],
destination_networks = ["10.1.0.0/16"],
description = "DO web tier to AWS database"
},
aws_to_hetzner_tunnel = {
protocol = "ipsec",
encryption = "aes-256",
source_networks = ["10.1.0.0/16"],
destination_networks = ["10.2.0.0/16"],
description = "AWS database to Hetzner backup"
}
},
# ==========================================================================
# DigitalOcean: Web Tier (3 droplets with load balancer)
# ==========================================================================
web_tier = {
# Application servers
droplets = digitalocean.Droplet & {
name = "web-server",
region = "nyc3",
size = "s-2vcpu-4gb",
image = "ubuntu-22-04-x64",
count = 3,
vpc_uuid = "{{ networks.do_vpc.id }}",
firewall = {
inbound_rules = [
# SSH from management
{
protocol = "tcp",
ports = "22",
sources = {
addresses = ["0.0.0.0/0"]
}
},
# HTTP from load balancer
{
protocol = "tcp",
ports = "80",
sources = {
addresses = ["0.0.0.0/0"]
}
},
# HTTPS from load balancer
{
protocol = "tcp",
ports = "443",
sources = {
addresses = ["0.0.0.0/0"]
}
},
# Database access to AWS RDS
{
protocol = "tcp",
ports = "5432",
sources = {
addresses = ["10.0.0.0/8"] # AWS VPC CIDR
}
}
],
outbound_rules = [
{
protocol = "tcp",
destinations = {
addresses = ["0.0.0.0/0"]
}
},
{
protocol = "udp",
ports = "53",
destinations = {
addresses = ["8.8.8.8/32", "8.8.4.4/32"]
}
}
]
},
tags = ["web", "production"]
},
# Load balancer for web tier
load_balancer = digitalocean.LoadBalancer & {
name = "web-lb",
algorithm = "round_robin",
region = "nyc3",
forwarding_rules = [
{
entry_protocol = "http",
entry_port = 80,
target_protocol = "http",
target_port = 80,
certificate_id = null
},
{
entry_protocol = "https",
entry_port = 443,
target_protocol = "http",
target_port = 80,
certificate_id = "cert-id"
}
],
sticky_sessions = {
type = "cookies",
cookie_name = "LB_SESSION",
cookie_ttl_seconds = 300
}
}
},
# ==========================================================================
# AWS: Database Tier (Managed RDS PostgreSQL)
# ==========================================================================
# Create security group for RDS
database_sg = aws.SecurityGroup & {
name = "webapp-db-sg",
description = "Security group for RDS database",
vpc_id = "{{ networks.aws_vpc.id }}",
ingress_rules = [
{
protocol = "tcp",
from_port = 5432,
to_port = 5432,
cidr_blocks = ["10.0.0.0/16"] # Allow from DO web tier via VPN
}
]
},
database_tier = aws.RDS & {
identifier = "webapp-db",
engine = "postgres",
engine_version = "14.6",
instance_class = "db.t3.medium",
allocated_storage = 100,
storage_type = "gp3",
multi_az = true,
publicly_accessible = false,
db_subnet_group_name = "default",
vpc_security_group_ids = ["{{ database_sg.id }}"],
backup_retention_days = 30,
skip_final_snapshot = false,
tags = [
{ key = "Environment", value = "production" },
{ key = "Application", value = "webapp" },
{ key = "Network", value = "private-vpc" }
]
},
# ==========================================================================
# Hetzner: Backup Storage (Volumes for periodic backups)
# ==========================================================================
backup_storage = hetzner.Volume & {
name = "webapp-backups",
size = 500,
location = "nbg1",
automount = false,
format = "ext4",
labels = { "purpose" = "backup" }
}
},
# =============================================================================
# Example 2: Multi-Region High Availability
# =============================================================================
# Architecture:
# - Region 1 (US): DigitalOcean NYC with primary database
# - Region 2 (EU): Hetzner Germany with read replicas
# - Region 3 (APAC): AWS Singapore with read replicas
#
# Features:
# - Global load balancing with DNS failover
# - Async database replication (300s lag)
# - Geographic distribution for low latency
# - Automatic failover to secondary regions
multi_region_ha = {
workspace_name = "multi-region-ha",
description = "High availability across three geographic regions",
global_config = {
dns_provider = "route53",
ttl = 60,
health_check_interval = 30,
failover_strategy = "geographic"
},
# Primary Region: US East (DigitalOcean)
region_us_east = {
provider = "digitalocean",
region_name = "us-east",
location = "nyc3",
servers = digitalocean.Droplet & {
name = "us-app",
region = "nyc3",
size = "s-2vcpu-4gb",
image = "ubuntu-22-04-x64",
count = 3,
tags = ["primary", "us-east"]
},
database = digitalocean.Database & {
name = "us-db",
engine = "pg",
version = "14",
size = "db-s-2vcpu-4gb",
region = "nyc3",
num_nodes = 3, # 3-node cluster for HA
multi_az = true
}
},
# Secondary Region: EU Central (Hetzner)
region_eu_central = {
provider = "hetzner",
region_name = "eu-central",
location = "nbg1",
servers = hetzner.Server & {
name = "eu-app",
server_type = "cx31",
image = "ubuntu-22.04",
location = "nbg1",
count = 3,
labels = { "region" = "eu-central" }
},
# Read-only replica database
database_replica = {
replication_lag_seconds = 300,
read_only = true,
replica_of = "region_us_east.database"
}
},
# Tertiary Region: APAC (AWS)
region_asia_southeast = {
provider = "aws",
region_name = "asia-southeast",
location = "ap-southeast-1",
servers = aws.EC2 & {
name = "asia-app",
instance_type = "t3.medium",
image_id = "ami-xxxxxxxxx",
count = 3,
region = "ap-southeast-1",
tags = [
{ key = "Region", value = "asia-southeast" }
]
},
# Read-only replica database
database_replica = {
replication_lag_seconds = 300,
read_only = true,
replica_of = "region_us_east.database"
}
},
# Global DNS configuration
global_load_balancing = {
dns_zones = ["example.com"],
records = [
{
name = "us.example.com",
type = "A",
ttl = 60,
failover_primary = true,
health_check = {
protocol = "HTTPS",
path = "/health",
interval = 30
}
},
{
name = "eu.example.com",
type = "A",
ttl = 60,
failover_secondary = true,
health_check = {
protocol = "HTTPS",
path = "/health",
interval = 30
}
},
{
name = "asia.example.com",
type = "A",
ttl = 60,
failover_tertiary = true,
health_check = {
protocol = "HTTPS",
path = "/health",
interval = 30
}
}
],
geolocation_routing = {
north_america = "us.example.com",
europe = "eu.example.com",
asia_pacific = "asia.example.com"
}
}
},
# =============================================================================
# Example 3: Cost-Optimized Deployment
# =============================================================================
# Architecture:
# - Hetzner: Application compute (best price/performance)
# - AWS: Managed services (RDS, ElastiCache, SQS)
# - DigitalOcean: CDN and edge locations (cost-effective distribution)
#
# Cost Optimization:
# - Compute on Hetzner (€50/month vs $300 on AWS)
# - Managed services on AWS (reliability + managed ops)
# - CDN on DigitalOcean (cheaper than CloudFront)
#
# Monthly Cost Breakdown:
# - Hetzner: €50 for 5 CPX21 servers
# - AWS: $150 for RDS + ElastiCache + SQS
# - DigitalOcean: $50 for CDN and edge nodes
# Total: ~$250/month (vs $600+ for all-AWS)
cost_optimized_deployment = {
workspace_name = "cost-optimized",
description = "Optimized deployment using provider strengths",
# ==========================================================================
# Hetzner: Application Tier (Best compute pricing)
# ==========================================================================
compute_tier = {
# Main application servers
primary_servers = hetzner.Server & {
name = "app",
server_type = "cpx21", # 4 vCPU, 8GB RAM, 10Gbps - €20.90/month
image = "ubuntu-22.04",
location = "nbg1",
count = 3,
labels = {
"tier" = "application",
"cost_center" = "compute"
}
},
# Storage node for shared data
storage_node = hetzner.Server & {
name = "storage",
server_type = "cx41", # 4 vCPU, 16GB RAM
image = "ubuntu-22.04",
location = "nbg1",
volumes = [
{
size = 1000,
format = "ext4",
automount = true
}
],
labels = {
"tier" = "storage",
"cost_center" = "storage"
}
}
},
# ==========================================================================
# AWS: Managed Services Tier
# ==========================================================================
managed_services = {
# Database
database = aws.RDS & {
identifier = "app-db",
engine = "postgres",
engine_version = "14.6",
instance_class = "db.t3.small",
allocated_storage = 100,
multi_az = true
},
# Cache
cache = aws.ElastiCache & {
cluster_id = "app-cache",
engine = "redis",
engine_version = "7.0",
node_type = "cache.t3.small",
num_cache_nodes = 2,
automatic_failover_enabled = true
},
# Message Queue
queue = aws.SQS & {
queue_name = "app-queue",
visibility_timeout_seconds = 300,
message_retention_seconds = 1209600
}
},
# ==========================================================================
# DigitalOcean: CDN and Edge Tier
# ==========================================================================
cdn_tier = {
# CDN distribution
cdn = {
provider = "digitalocean",
endpoints = [
{
name = "app-cdn",
origin = "content.example.com",
regions = ["nyc1", "sfo1", "lon1", "sgp1", "blr1"],
cache_control = {
browser_cache_ttl = 3600,
cdn_cache_ttl = 86400
}
}
]
},
# Edge nodes for regional content delivery
edge_nodes = digitalocean.Droplet & {
name = "edge-node",
regions = ["nyc3", "sfo3", "lon1", "sgp1"],
size = "s-1vcpu-1gb",
image = "ubuntu-22-04-x64",
count = 1, # 1 per region
tags = ["edge", "cdn"]
},
# Spaces for object storage
object_storage = {
provider = "digitalocean",
space_name = "app-content",
region = "nyc3",
versioning = true,
lifecycle_rules = [
{
id = "delete-old-files",
days = 90,
action = "delete"
}
]
}
},
# Cost model
cost_model = {
monthly_estimate = {
hetzner = {
primary_servers = "€62.70", # 3x CPX21 @ €20.90
storage_node = "€27.60", # 1x CX41
subtotal = "€90.30"
},
aws = {
database = "$60",
cache = "$25",
queue = "$15",
subtotal = "$100"
},
digitalocean = {
cdn = "$25",
edge_nodes = "$24", # 4x $6 droplets
object_storage = "$15",
subtotal = "$64"
},
total = "€90.30 + $100 + $64 ≈ $280/month"
}
}
}
}