Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated UpCloud terraform script to use private network and dynamic additional disks #7779

Merged
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
48 changes: 27 additions & 21 deletions contrib/terraform/upcloud/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,29 @@ The setup looks like following

```text
Kubernetes cluster
+-----------------------+
| +--------------+ |
| | +--------------+ |
| | | | |
| | | Master/etcd | |
| | | node(s) | |
| +-+ | |
| +--------------+ |
| ^ |
| | |
| v |
| +--------------+ |
| | +--------------+ |
| | | | |
| | | Worker | |
| | | node(s) | |
| +-+ | |
| +--------------+ |
+-----------------------+
+--------------------------+
| +--------------+ |
| | +--------------+ |
| --> | | | |
| | | Master/etcd | |
| | | node(s) | |
| +-+ | |
| +--------------+ |
| ^ |
| | |
| v |
| +--------------+ |
| | +--------------+ |
| --> | | | |
| | | Worker | |
| | | node(s) | |
| +-+ | |
| +--------------+ |
+--------------------------+
```

The nodes uses a private network for node to node communication and a public interface for all external communication.

## Requirements

* Terraform 0.13.0 or newer
Expand Down Expand Up @@ -94,13 +96,17 @@ terraform destroy --var-file cluster-settings.tfvars \

## Variables

* `hostname`: A valid domain name, e.g. example.com. The maximum length is 128 characters.
* `prefix`: Prefix to add to all resources, if set to "" don't set any prefix
* `template_name`: The name or UUID of a base image
* `username`: a user to access the nodes
* `username`: a user to access the nodes, defaults to "ubuntu"
* `private_network_cidr`: CIDR to use for the private network, defaults to "172.16.0.0/24"
* `ssh_public_keys`: List of public SSH keys to install on all machines
* `zone`: The zone where to run the cluster
* `machines`: Machines to provision. Key of this object will be used as the name of the machine
* `node_type`: The role of this node *(master|worker)*
* `cpu`: number of cpu cores
* `mem`: memory size in MB
* `disk_size`: The size of the storage in GB
* `additional_disks`: Additional disks to attach to the node.
* `size`: The size of the additional disk in GB
* `tier`: The tier of disk to use (`maxiops` is the only one you can choose atm)
40 changes: 35 additions & 5 deletions contrib/terraform/upcloud/cluster-settings.tfvars
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@

# See: https://developers.upcloud.com/1.3/5-zones/
zone = "fi-hel1"
username = "ubuntu"

inventory_file = "inventory.ini"
# Prefix to use for all resources to separate them from other resources
prefix = "kubespray"

# A valid domain name, e.g. host.example.com. The maximum length is 128 characters.
hostname = "example.com"
inventory_file = "inventory.ini"

# Set the operating system using UUID or exact name
template_name = "Ubuntu Server 20.04 LTS (Focal Fossa)"
Expand All @@ -17,7 +16,7 @@ ssh_public_keys = [
"ssh-rsa public key 2",
]

#check list of available plan https://developers.upcloud.com/1.3/7-plans/
# check list of available plan https://developers.upcloud.com/1.3/7-plans/
machines = {
"master-0" : {
"node_type" : "master",
Expand All @@ -27,6 +26,7 @@ machines = {
"mem" : "4096"
# The size of the storage in GB
"disk_size" : 250
"additional_disks" : {}
},
"worker-0" : {
"node_type" : "worker",
Expand All @@ -36,6 +36,16 @@ machines = {
"mem" : "4096"
# The size of the storage in GB
"disk_size" : 250
"additional_disks" : {
# "some-disk-name-1": {
# "size": 100,
# "tier": "maxiops",
# },
# "some-disk-name-2": {
# "size": 100,
# "tier": "maxiops",
# }
}
},
"worker-1" : {
"node_type" : "worker",
Expand All @@ -45,6 +55,16 @@ machines = {
"mem" : "4096"
# The size of the storage in GB
"disk_size" : 250
"additional_disks" : {
# "some-disk-name-1": {
# "size": 100,
# "tier": "maxiops",
# },
# "some-disk-name-2": {
# "size": 100,
# "tier": "maxiops",
# }
}
},
"worker-2" : {
"node_type" : "worker",
Expand All @@ -54,5 +74,15 @@ machines = {
"mem" : "4096"
# The size of the storage in GB
"disk_size" : 250
"additional_disks" : {
# "some-disk-name-1": {
# "size": 100,
# "tier": "maxiops",
# },
# "some-disk-name-2": {
# "size": 100,
# "tier": "maxiops",
# }
}
}
}
16 changes: 10 additions & 6 deletions contrib/terraform/upcloud/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ provider "upcloud" {
module "kubernetes" {
source = "./modules/kubernetes-cluster"

zone = var.zone
hostname = var.hostname
prefix = var.prefix
zone = var.zone

template_name = var.template_name
username = var.username

private_network_cidr = var.private_network_cidr

machines = var.machines

ssh_public_keys = var.ssh_public_keys
Expand All @@ -30,13 +32,15 @@ data "template_file" "inventory" {
template = file("${path.module}/templates/inventory.tpl")

vars = {
connection_strings_master = join("\n", formatlist("%s ansible_user=ubuntu ansible_host=%s etcd_member_name=etcd%d",
connection_strings_master = join("\n", formatlist("%s ansible_user=ubuntu ansible_host=%s ip=%s etcd_member_name=etcd%d",
keys(module.kubernetes.master_ip),
values(module.kubernetes.master_ip),
values(module.kubernetes.master_ip).*.public_ip,
values(module.kubernetes.master_ip).*.private_ip,
range(1, length(module.kubernetes.master_ip) + 1)))
connection_strings_worker = join("\n", formatlist("%s ansible_user=ubuntu ansible_host=%s",
connection_strings_worker = join("\n", formatlist("%s ansible_user=ubuntu ansible_host=%s ip=%s",
keys(module.kubernetes.worker_ip),
values(module.kubernetes.worker_ip)))
values(module.kubernetes.worker_ip).*.public_ip,
values(module.kubernetes.worker_ip).*.private_ip))
list_master = join("\n", formatlist("%s",
keys(module.kubernetes.master_ip)))
list_worker = join("\n", formatlist("%s",
Expand Down
142 changes: 106 additions & 36 deletions contrib/terraform/upcloud/modules/kubernetes-cluster/main.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,41 @@
locals {
# Create a list of all disks to create
disks = flatten([
for node_name, machine in var.machines : [
for disk_name, disk in machine.additional_disks : {
disk = disk
disk_name = disk_name
node_name = node_name
}
]
])

# If prefix is set, all resources will be prefixed with "${var.prefix}-"
# Else don't prefix with anything
resource-prefix = "%{ if var.prefix != ""}${var.prefix}-%{ endif }"
}

resource "upcloud_network" "private" {
name = "${local.resource-prefix}k8s-network"
zone = var.zone

ip_network {
address = var.private_network_cidr
dhcp = true
family = "IPv4"
}
}

resource "upcloud_storage" "additional_disks" {
for_each = {
for disk in local.disks: "${disk.node_name}_${disk.disk_name}" => disk.disk
}

size = each.value.size
tier = each.value.tier
title = "${local.resource-prefix}${each.key}"
zone = var.zone
}

resource "upcloud_server" "master" {
for_each = {
Expand All @@ -6,61 +44,93 @@ resource "upcloud_server" "master" {
if machine.node_type == "master"
}

hostname = "${each.key}.${var.hostname}"
cpu = each.value.cpu
mem = each.value.mem
zone = var.zone
hostname = "${local.resource-prefix}${each.key}"
cpu = each.value.cpu
mem = each.value.mem
zone = var.zone

template {
storage = var.template_name
size = each.value.disk_size
size = each.value.disk_size
}

# Public network interface
network_interface {
type = "public"
}

# Network interfaces
network_interface {
type = "public"
}
# Private network interface
network_interface {
type = "private"
network = upcloud_network.private.id
}

network_interface {
type = "utility"
}
# Include at least one public SSH key
login {
user = var.username
keys = var.ssh_public_keys
create_password = false
dynamic "storage_devices" {
for_each = {
for disk_key_name, disk in upcloud_storage.additional_disks :
disk_key_name => disk
# Only add the disk if it matches the node name in the start of its name
if length(regexall("^${each.key}_.+", disk_key_name)) > 0
}

}
content {
storage = storage_devices.value.id
}
}

# Include at least one public SSH key
login {
user = var.username
keys = var.ssh_public_keys
create_password = false
}
}


resource "upcloud_server" "worker" {
for_each = {
for name, machine in var.machines :
name => machine
if machine.node_type == "worker"
}

hostname = "${each.key}.${var.hostname}"
cpu = each.value.cpu
mem = each.value.mem
zone = var.zone
hostname = "${local.resource-prefix}${each.key}"
cpu = each.value.cpu
mem = each.value.mem
zone = var.zone

template {
storage = var.template_name
size = each.value.disk_size
storage = var.template_name
size = each.value.disk_size
}

# Public network interface
network_interface {
type = "public"
}

# Network interfaces
network_interface {
type = "public"
}

# Include at least one public SSH key
login {
user = var.username
keys = var.ssh_public_keys
create_password = false
}
# Private network interface
network_interface {
type = "private"
network = upcloud_network.private.id
}

dynamic "storage_devices" {
for_each = {
for disk_key_name, disk in upcloud_storage.additional_disks :
disk_key_name => disk
# Only add the disk if it matches the node name in the start of its name
if length(regexall("^${each.key}_.+", disk_key_name)) > 0
}

content {
storage = storage_devices.value.id
}
}

# Include at least one public SSH key
login {
user = var.username
keys = var.ssh_public_keys
create_password = false
}
}
10 changes: 8 additions & 2 deletions contrib/terraform/upcloud/modules/kubernetes-cluster/output.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,19 @@
output "master_ip" {
value = {
for instance in upcloud_server.master :
instance.hostname => instance.network_interface[0].ip_address
instance.hostname => {
"public_ip": instance.network_interface[0].ip_address
"private_ip": instance.network_interface[1].ip_address
}
}
}

output "worker_ip" {
value = {
for instance in upcloud_server.worker :
instance.hostname => instance.network_interface[0].ip_address
instance.hostname => {
"public_ip": instance.network_interface[0].ip_address
"private_ip": instance.network_interface[1].ip_address
}
}
}
Loading