# Kubernetes Storage Node Server Template # Extracted from wuji infrastructure patterns (real production config) # Provides storage node server configuration for Ceph/Rook import providers.upcloud.kcl.defaults_upcloud as upcloud_prov import workspace_templates.lib.compose as comp # Storage configuration for storage nodes schema StorageNodeStorage { name: str = "root" size: int = 35 total: int = 80 parts: [any] = [ {name = "root", size = 35, type = "ext4", mount = True, mount_path = "/"} {name = "ceph_0", size = 25, type = "raw", mount = True, mount_path = ""} {name = "ceph_1", size = 20, type = "raw", mount = True, mount_path = ""} ] } # Base storage node server configuration from wuji production schema StorageNodeServer { # Basic server configuration hostname: str # Must be provided (e.g., "{infra}-strg-0") title: str # Must be provided (e.g., "{Infra} Storage 0") plan: str = "2xCPU-4GB" # Production-tested plan from wuji # Storage configuration (optimized for Ceph from wuji) storages: [StorageNodeStorage] = [ StorageNodeStorage {} ] # Network configuration network_private_ip: str # Must be provided (e.g., "10.11.1.30") liveness_ip: str = "{{network_public_ip}}" liveness_port: int = 22 extra_hostnames: [str] = [] # Will include hostname by default # Labels (production patterns from wuji) labels: str = "use=k8s-storage" # Taskservs for storage nodes (from wuji production) default_taskservs: [any] = [ {name = "os", profile = "worker"} {name = "resolv"} {name = "runc"} {name = "crun"} {name = "youki"} {name = "containerd"} {name = "kubernetes"} {name = "kubernetes", profile = "k8s-nodejoin"} {name = "external-nfs"} ] # Additional taskservs additional_taskservs: [any] = [] # Enable/disable the server not_use: bool = False # Custom configuration custom_config: {str: any} = {} } # Template function to create storage node server def create_storage_node_server [ infra_name: str, node_index: int, private_ip: str, ceph_devices: [str] = ["vda3", "vda4"], overrides: {str: any} = {} ] -> any { let base_config = StorageNodeServer { hostname: $"($infra_name)-strg-($node_index)" title: $"($infra_name | str title-case) Storage ($node_index)" network_private_ip: $private_ip extra_hostnames: [$"($infra_name)-strg-($node_index)"] labels: $"use=k8s-($infra_name), use=k8s-storage" } # Apply overrides let final_config = comp.deep_merge $base_config $overrides # Combine taskservs let all_taskservs = $final_config.default_taskservs | append $final_config.additional_taskservs # Create UpCloud server configuration upcloud_prov.Server_upcloud { hostname: $final_config.hostname title: $final_config.title plan: $final_config.plan not_use: $final_config.not_use storages: $final_config.storages | each {|storage| upcloud_prov.Storage_upcloud { name: $storage.name size: $storage.size total: $storage.total parts: $storage.parts } } labels: $final_config.labels network_private_ip: $final_config.network_private_ip liveness_ip: $final_config.liveness_ip liveness_port: $final_config.liveness_port extra_hostnames: $final_config.extra_hostnames taskservs: $all_taskservs } | comp.deep_merge $final_config.custom_config } # Common storage configurations storage_configs = { small: { plan: "2xCPU-4GB" storages: [{ name: "root" size: 25 total: 60 parts: [ {name = "root", size = 25, type = "ext4", mount = True, mount_path = "/"} {name = "ceph_0", size = 35, type = "raw", mount = True, mount_path = ""} ] }] } standard: { plan: "2xCPU-4GB" # Default from wuji } large: { plan: "4xCPU-8GB" storages: [{ name: "root" size: 50 total: 200 parts: [ {name = "root", size = 50, type = "ext4", mount = True, mount_path = "/"} {name = "ceph_0", size = 75, type = "raw", mount = True, mount_path = ""} {name = "ceph_1", size = 75, type = "raw", mount = True, mount_path = ""} ] }] } } # Export the template for use in infrastructure _server = upcloud_prov.Server_upcloud { hostname = "storage-0" title = "Storage Node 0" plan = "2xCPU-4GB" storages = [ { name = "root" size = 35 total = 80 parts = [ {name = "root", size = 35, type = "ext4", mount = True, mount_path = "/"} {name = "ceph_0", size = 25, type = "raw", mount = True, mount_path = ""} {name = "ceph_1", size = 20, type = "raw", mount = True, mount_path = ""} ] } ] labels = "use=k8s-storage" network_private_ip = "10.11.1.30" liveness_ip = "{{network_public_ip}}" liveness_port = 22 extra_hostnames = ["storage-0"] taskservs = [ {name = "os", profile = "worker"} {name = "resolv"} {name = "runc"} {name = "crun"} {name = "youki"} {name = "containerd"} {name = "kubernetes"} {name = "kubernetes", profile = "k8s-nodejoin"} {name = "external-nfs"} ] } _server