Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions modules/cloud-init/simple-setup-init.tftpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#cloud-config
users:
%{ for user in users}
- name: ${user.user_name}
groups: sudo
shell: /bin/bash
sudo: 'ALL=(ALL) NOPASSWD:ALL'
ssh-authorized-keys:
- ${user.ssh_public_key}
%{ endfor}


runcmd:
- apt-get update
- apt-get upgrade


# mount disk if provided
%{ if extra_disk_id != "" }
# Prepare partition on secondary disk
- mkdir -p ${extra_path}
- echo "mkdir" >> /home/tux/log.txt
- parted -s /dev/disk/by-id/virtio-${extra_disk_id} mklabel gpt >> /home/tux/log.txt
- parted -s /dev/disk/by-id/virtio-${extra_disk_id} mkpart primary ext4 0% 100% >> /home/tux/log.txt
- sync
- echo "sync" >> /home/tux/log.txt
- mkfs.ext4 /dev/disk/by-id/virtio-${extra_disk_id}-part1 >> /home/tux/log.txt
- sync
- mount -o rw /dev/disk/by-id/virtio-${extra_disk_id}-part1 ${extra_path} >> /home/tux/log.txt
- echo "/dev/disk/by-id/virtio-${extra_disk_id}-part1 ${extra_path} ext4 defaults 0 2" >> /etc/fstab
- chown nobody:nogroup ${extra_path}
- chmod 777 ${extra_path}
%{ endif }

# mount shared filesystem if provided
%{if shared_filesystem_id != "" }
- mkdir -p ${shared_filesystem_mount}
- mount -t virtiofs filesystem-0 ${shared_filesystem_mount}
- chmod a+w ${shared_filesystem_mount}
- echo "filesystem-0 ${shared_filesystem_mount} virtiofs rw 0 0" >> /etc/fstab
%{endif}

# install s3 access
%{if aws_access_key_id != ""}
- snap install aws-cli --classic

%{ for user in users}
- mkdir -p /home/${user.user_name}/.aws
- echo "[default]" > /home/${user.user_name}/.aws/credentials
- echo "aws_access_key_id=${aws_access_key_id}" >> /home/${user.user_name}/.aws/credentials
- echo "aws_secret_access_key=${aws_secret_access_key}" >> /home/${user.user_name}/.aws/credentials
- echo "[default]" > /home/${user.user_name}/.aws/config
- echo "endpoint_url = https://storage.eu-north1.nebius.cloud:443" >> /home/${user.user_name}/.aws/config
- echo "region = eu-north1" >> /home/${user.user_name}/.aws/config
- chown -R ${user.user_name}:${user.user_name} /home/${user.user_name}/.aws
- chmod 600 /home/${user.user_name}/.aws/credentials
%{ endfor }

- mkdir -p /root/.aws
- echo "[default]" > /root/.aws/credentials
- echo "aws_access_key_id=${aws_access_key_id}" >> /root/.aws/credentials
- echo "aws_secret_access_key=${aws_secret_access_key}" >> /root/.aws/credentials
- echo "[default]" > /root/.aws/config
- echo "endpoint_url = https://storage.eu-north1.nebius.cloud:443" >> /root/.aws/config
- echo "region = eu-north1" >> /root/.aws/config


# install s3 mount

%{if mount_bucket != "" }
- wget https://s3.amazonaws.com/mountpoint-s3-release/1.14.0/x86_64/mount-s3-1.14.0-x86_64.deb
- dpkg -i mount-s3-1.14.0-x86_64.deb
- mkdir -p ${s3_mount_path}
- mount-s3 --upload-checksums=off --maximum-throughput-gbps=200 --allow-delete --allow-overwrite --allow-other --endpoint-url=https://storage.eu-north1.nebius.cloud:443 ${mount_bucket} ${s3_mount_path}
%{endif}
%{endif}
48 changes: 48 additions & 0 deletions modules/instance/locals.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
locals {

users = [
for user in var.users: {
user_name = user.user_name
ssh_public_key = user.ssh_public_key != null ? user.ssh_public_key : (
fileexists(user.ssh_key_path) ? file(user.ssh_key_path) : null)
}
]

regions_default = {
eu-west1 = {
cpu_nodes_platform = "cpu-d3"
cpu_nodes_preset = "16vcpu-64gb"
gpu_nodes_platform = "gpu-h200-sxm"
gpu_nodes_preset = "1gpu-16vcpu-200gb"
}
eu-north1 = {
cpu_nodes_platform = "cpu-e2"
cpu_nodes_preset = "16vcpu-64gb"
gpu_nodes_platform = "gpu-h100-sxm"
gpu_nodes_preset = "1gpu-16vcpu-200gb"
}
}

current_region_defaults = local.regions_default[var.region]

# cpu_nodes_preset = coalesce(var.cpu_nodes_preset, local.current_region_defaults.cpu_nodes_preset)
# cpu_nodes_platform = coalesce(var.cpu_nodes_platform, local.current_region_defaults.cpu_nodes_platform)
# gpu_nodes_platform = coalesce(var.gpu_nodes_platform, local.current_region_defaults.gpu_nodes_platform)
# gpu_nodes_preset = coalesce(var.gpu_nodes_preset, local.current_region_defaults.gpu_nodes_preset)

extra_path = var.extra_path
extra_disk_id = var.add_extra_storage ? substr(nebius_compute_v1_disk.extra-storage-disk[0].id, 0, 20) : ""


cloud_init_log = jsonencode({
extra_path = local.extra_path
extra_disk_id = local.extra_disk_id
state = terraform.workspace
users = local.users

})
# current_region_defaults = local.regions_default[var.region]
#
# cpu_nodes_preset = coalesce(var.cpu_nodes_preset, local.current_region_defaults.cpu_nodes_preset)
# cpu_nodes_platform = coalesce(var.cpu_nodes_platform, local.current_region_defaults.cpu_nodes_platform)
}
81 changes: 81 additions & 0 deletions modules/instance/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
resource "nebius_compute_v1_disk" "boot-disk" {
parent_id = var.parent_id
name = join("-", ["instance-boot-disk", var.instance_name])
block_size_bytes = 4096
size_bytes = 1024 * 1024 * 1024 * var.boot_disk_size_gb
type = "NETWORK_SSD"
source_image_family = { image_family = "ubuntu22.04-cuda12" }
}

resource "nebius_compute_v1_disk" "extra-storage-disk" {
count = var.add_extra_storage ? 1 : 0
parent_id = var.parent_id
name = join("-", ["extra-storage-disk", var.instance_name])
block_size_bytes = 4096
size_bytes = 1024 * 1024 * 1024 * var.extra_storage_size_gb
type = var.extra_storage_class
}


resource "nebius_compute_v1_instance" "instance" {
parent_id = var.parent_id
name = var.instance_name

network_interfaces = [
{
name = "eth0"
subnet_id = var.subnet_id
ip_address = {}
public_ip_address = var.public_ip ? {} : null
}
]

resources = {
platform = var.platform
preset = var.preset
}

boot_disk = {
attach_mode = "READ_WRITE"
existing_disk = nebius_compute_v1_disk.boot-disk
}

secondary_disks = var.add_extra_storage ? [
{
attach_mode = "READ_WRITE"
existing_disk = {
id = nebius_compute_v1_disk.extra-storage-disk[0].id
}
}
] : []

filesystems = var.shared_filesystem_id != "" ? [
{
attach_mode = "READ_WRITE"
existing_filesystem = {
id = var.shared_filesystem_id
}
mount_tag = "filesystem-0"
}
] : []


cloud_init_user_data = templatefile("../modules/cloud-init/simple-setup-init.tftpl", {
users = local.users,
extra_path = local.extra_path,
extra_disk_id = local.extra_disk_id,
shared_filesystem_id = var.shared_filesystem_id,
shared_filesystem_mount = var.shared_filesystem_mount,
aws_access_key_id = var.aws_access_key_id,
aws_secret_access_key = var.aws_secret_access_key,
mount_bucket = var.mount_bucket,
s3_mount_path = var.s3_mount_path
})
}

resource "local_file" "cloud_init_variables_log" {
content = local.cloud_init_log
filename = "${path.module}/cloud-init-variables.log"


}
8 changes: 8 additions & 0 deletions modules/instance/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
output "internal_ip" {
description = "The internal IP address"
value = trimsuffix(nebius_compute_v1_instance.instance.status.network_interfaces[0].ip_address.address, "/32")
}
output "public_ip" {
description = "The public IP address"
value = trimsuffix(nebius_compute_v1_instance.instance.status.network_interfaces[0].public_ip_address.address, "/32")
}
8 changes: 8 additions & 0 deletions modules/instance/provider.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
terraform {
required_providers {
nebius = {
source = "terraform-provider.storage.eu-north1.nebius.cloud/nebius/nebius"
version= ">= 0.4.24"
}
}
}
128 changes: 128 additions & 0 deletions modules/instance/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
variable "parent_id" {
type = string
description = "Id of the folder where the resources going to be created."
default = null
}

variable "subnet_id" {
type = string
description = "ID of the subnet."
default = null
}

variable "region" {
type = string
description = "region"
default = "eu-north1"
}

variable "instance_name" {
type = string
description = "name of the instance"
default = "instance"
}

variable "platform" {
description = "VM platform."
type = string
default = "cpu-e2"
}

variable "preset" {
description = "VM resources preset."
type = string
default = "16vcpu-64gb"
}

variable "cpu_nodes_preset" {
description = "CPU and RAM configuration for instances."
type = string
default = null
}

variable "shared_filesystem_id" {
description = "Id of an existing shared file system"
type = string
default = ""
}

variable "shared_filesystem_mount" {
description = "mounting point of the shared file system"
type = string
default = "/mnt/share"
}

variable "users" {
description = "List of users with their SSH keys"
type = list(object({
user_name = string
ssh_public_key = optional(string) # Inline SSH key
ssh_key_path = optional(string, "~/.ssh/id_rsa.pub") # Path to SSH key file
}))
default = []
validation {
condition = alltrue([
for user in var.users : user.ssh_public_key != null || fileexists(user.ssh_key_path)
])
error_message = "Each user must have at least one SSH key defined as 'ssh_public_key' or 'ssh_key_path'."
}
}

variable "add_extra_storage" {
type = bool
default = false
description = "if true, a new disk will be created and mounted at <extra_path>"
}

variable "extra_path" {
type = string
default = "/mnt/storage"
description = "Folder where the network storage will be mounted on"
}

variable "boot_disk_size_gb" {
type = number
default = 50
description = "size of the boot disk"
}

variable "extra_storage_size_gb" {
type = number
default = 50
description = "size of the newly created nfs storage"
}

variable "extra_storage_class" {
type = string
default = "NETWORK_SSD"
description = "Network type of additional disk being added"
}


variable "public_ip" {
type = bool
default = true
description = "attach a public ip to the vm if true"
}
variable "mount_bucket" {
type = string
description = "name of a bucket that should be mounted into fs"
default = ""
}

variable "s3_mount_path" {
type = string
description = "mountpoint for s3 mount"
default = "/mnt/s3"
}
variable "aws_access_key_id" {
type = string
description = "S3 access key"
default = ""
}

variable "aws_secret_access_key" {
type = string
description = "S3 access key"
default = ""
}
Loading