How do I deploy a Linode using custom disk configurations?
I would like to know a good way to deploy a Linode using the API that allows me to have a Linode that:
- Has no swap
- Has a disk that contains one of Linode's stock images but has a custom size
- Has an extra disk with a custom size
3 Replies
This is certainly possible. I'll propose two options that will basically go over the following workflow:
- Add an empty Linode
- Create the boot disk with the desired size
- Create the secondary disk with the desired size
- Create a Configuration Profile that contains both disks and the preferred kernel option
Using our Linode CLI(which is basically a wrapper of our API), I went through the workflow to create a test Linode. Here's how that looked like:
# Add empty Linode
linode-cli linodes create --region "ca-central" --label "API-Custom-Disk-Example" --type "g6-nanode-1" --private_ip true --group "API"
# Create the boot disk with the desired size
linode-cli linodes disk-create --label "boot" --size 6000 --image "linode/ubuntu18.04" --root_pass "2HKH$^*llsa..." 19869124
# Create the secondary disk with the desired size
linodes disk-create --label "secondary" --size 3000 19869124
# Create a Configuration Profile that contains both disks and the preferred kernel option
linode-cli linodes config-create --label "boot_config" --kernel "linode/grub2" --devices.sda.disk_id 40616257 --devices.sdb.disk_id 40616264 --root_device "/dev/sda" 19869124
Just in case you need a quick reference, here are the API docs for each endpoint you are going to use when following the workflow above:
The second alternative is using Terraform. Terraform is a cool Infrastructure as Code (IaC) tool that allows you to deploy your infrastructure in a wide number of providers, including us. You simply define the specs needed for a Linode in a file and let Terraform handle the rest. We actually have a quick intro to Terraform in our Docs site that can give you a quick start on Terraform + Linode:
Use Terraform to Provision Linode Environments
Terraform also has a very good documentation on their Linode Provider. More specifically, I think the "linode_instance" resource is where you'll find most of the parameters needed to accomplish your use case:
So you can have a reference, I created the following Terraform file to create a Linode that fulfills the aforementioned requirements:
provider "linode" {
token = "my_APIv4_token"
}
resource "linode_instance" "terraform-custom-disk" {
label = "Terraform-Custom-Disk-Example"
tags = ["Terraform"]
region = "ca-central"
type = "g6-nanode-1"
private_ip = true
disk {
label = "boot"
size = 6000
image = "linode/ubuntu18.04"
root_pass = "terr4form-test"
}
disk {
label = "secondary"
size = 3000
}
config {
label = "boot_config"
kernel = "linode/grub2"
devices {
sda {
disk_label = "boot"
}
sdb {
disk_label = "secondary"
}
}
root_device = "/dev/sda"
}
boot_config_label = "boot_config"
}
I wanted to add an example using the Linode API. Ive used the Linode CLI to obtain the needed Linode and Disk ID numbers, and some sleep
statements to wait for each step to complete before moving on. You can replace these parts with API calls and to remove the dependency of the Linode CLI, and to have your code actually check for completion at each stage, instead of just sleeping for 60 seconds, but that's outside the scope of this discussion.
#!/usr/bin/env bash
# This is optional. I find it useful for debugging
set -xo pipefail
# Put your Linode API Token here
TOKEN="YOUR_LINODE_API_TOKEN_GOES_HERE"
# Create a Linode with no image
curl -H "Content-Type: application/json" \
-H "Authorization: Bearer ${TOKEN}" \
-X POST -d '{
"swap_size": 512,
"label": "API-Custom-Disk-Example",
"type": "g6-standard-2",
"region": "ca-central",
"group": "API"
}' \
https://api.linode.com/v4/linode/instances
# Obtain the Linode's ID
LINODE_ID=$(linode-cli linodes list --text | awk '/API-Custom-Disk-Example/{print $1}')
# Wait while the new Linode is provisioned
printf "Waiting for the Linode to finish provisioning..."
sleep 60
printf "\n"
# Create boot disk
curl -H "Content-Type: application/json" \
-H "Authorization: Bearer ${TOKEN}" \
-X POST -d '{
"label": "boot",
"image": "private/5877828",
"size": 24000,
"root_pass": "aComplexP@ssword"
}' \
https://api.linode.com/v4/linode/instances/"${LINODE_ID}"/disks
# Obtain the Boot Disk's ID
DISK_ID=$(linode-cli linodes disks-list $LINODE_ID --text | awk '/boot/{print $1}' | tail -1)
echo $DISK_ID
# Wait to give the disk a chance to finish being created
sleep 60
# Create swap disk
curl -H "Content-Type: application/json" \
-H "Authorization: Bearer ${TOKEN}" \
-X POST -d '{
"label": "swap",
"size": 512,
"filesystem": "swap"
}' \
https://api.linode.com/v4/linode/instances/"${LINODE_ID}"/disks
# Obtain the Swap Disk's ID
SWAP_DISK_ID=$(linode-cli linodes disks-list $LINODE_ID --text | awk '/swap/{print $1}' | tail -1)
echo $SWAP_DISK_ID
# Create the Linode's Configuration Profile
curl -H "Content-Type: application/json" \
-H "Authorization: Bearer ${TOKEN}" \
-X POST -d '{
"kernel": "linode/grub2",
"comments": "This is my main Config",
"memory_limit": 2048,
"run_level": "default",
"virt_mode": "paravirt",
"helpers": {
"updatedb_disabled": true,
"distro": true,
"modules_dep": true,
"network": true,
"devtmpfs_automount": false
},
"label": "boot-config",
"devices": {
"sda": {
"disk_id": $DISK_ID,
"volume_id": null
},
"sdb": {
"disk_id": $SWAP_DISK_ID,
"volume_id": null
}
}
}' \
https://api.linode.com/v4/linode/instances/"${LINODE_ID}"/configs
Is there a way of doing this from the cloud manager? Currently, I can't deploy a linode without using some type of image. For custom configurations, it would be ideal to create a Linode with no disk configurations, no operating systems, and no configuration profiles. This would be a more advanced use case, but it would allow for something such as the copying of a disk image with a custom configuration and partition layout.