Terraform support for UpCloud (#7360)
* terraform support for UpCloud * terraform support for UpCloud * terraform support for UpCloud * terraform support for UpCloud * terraform support for UpCloud * terraform support for UpCloud * terraform support for UpCloud * Updates to README.md and main.tf files * formatting and updating readme * added a .terraform_validate CI job * fixed format issue * added sample inventory * added symbolic link to group_vars * added missing tf variables and minor fixes * added text formatting * minor formatting fixespull/7376/head
parent
5dba53a223
commit
5c5bf41afe
|
@ -108,6 +108,13 @@ tf-0.13.x-validate-vsphere:
|
||||||
PROVIDER: vsphere
|
PROVIDER: vsphere
|
||||||
CLUSTER: $CI_COMMIT_REF_NAME
|
CLUSTER: $CI_COMMIT_REF_NAME
|
||||||
|
|
||||||
|
tf-0.13.x-validate-upcloud:
|
||||||
|
extends: .terraform_validate
|
||||||
|
variables:
|
||||||
|
TF_VERSION: 0.13.5
|
||||||
|
PROVIDER: upcloud
|
||||||
|
CLUSTER: $CI_COMMIT_REF_NAME
|
||||||
|
|
||||||
tf-0.14.x-validate-openstack:
|
tf-0.14.x-validate-openstack:
|
||||||
extends: .terraform_validate
|
extends: .terraform_validate
|
||||||
variables:
|
variables:
|
||||||
|
@ -142,6 +149,13 @@ tf-0.14.x-validate-vsphere:
|
||||||
PROVIDER: vsphere
|
PROVIDER: vsphere
|
||||||
CLUSTER: $CI_COMMIT_REF_NAME
|
CLUSTER: $CI_COMMIT_REF_NAME
|
||||||
|
|
||||||
|
tf-0.14.x-validate-upcloud:
|
||||||
|
extends: .terraform_validate
|
||||||
|
variables:
|
||||||
|
TF_VERSION: 0.14.3
|
||||||
|
PROVIDER: upcloud
|
||||||
|
CLUSTER: $CI_COMMIT_REF_NAME
|
||||||
|
|
||||||
# tf-packet-ubuntu16-default:
|
# tf-packet-ubuntu16-default:
|
||||||
# extends: .terraform_apply
|
# extends: .terraform_apply
|
||||||
# variables:
|
# variables:
|
||||||
|
|
|
@ -0,0 +1,106 @@
|
||||||
|
# Kubernetes on UpCloud with Terraform
|
||||||
|
|
||||||
|
Provision a Kubernetes cluster on [UpCloud](https://upcloud.com/) using Terraform and Kubespray
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The setup looks like following
|
||||||
|
|
||||||
|
```text
|
||||||
|
Kubernetes cluster
|
||||||
|
+-----------------------+
|
||||||
|
| +--------------+ |
|
||||||
|
| | +--------------+ |
|
||||||
|
| | | | |
|
||||||
|
| | | Master/etcd | |
|
||||||
|
| | | node(s) | |
|
||||||
|
| +-+ | |
|
||||||
|
| +--------------+ |
|
||||||
|
| ^ |
|
||||||
|
| | |
|
||||||
|
| v |
|
||||||
|
| +--------------+ |
|
||||||
|
| | +--------------+ |
|
||||||
|
| | | | |
|
||||||
|
| | | Worker | |
|
||||||
|
| | | node(s) | |
|
||||||
|
| +-+ | |
|
||||||
|
| +--------------+ |
|
||||||
|
+-----------------------+
|
||||||
|
```
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
* Terraform 0.13.0 or newer
|
||||||
|
|
||||||
|
## Quickstart
|
||||||
|
|
||||||
|
NOTE: Assumes you are at the root of the kubespray repo.
|
||||||
|
|
||||||
|
For authentication in your cluster you can use the environment variables.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export TF_VAR_UPCLOUD_USERNAME=username
|
||||||
|
export TF_VAR_UPCLOUD_PASSWORD=password
|
||||||
|
```
|
||||||
|
|
||||||
|
To allow API access to your UpCloud account, you need to allow API connections by visiting [Account-page](https://hub.upcloud.com/account) in your UpCloud Hub.
|
||||||
|
|
||||||
|
Copy the cluster configuration file.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
CLUSTER=my-upcloud-cluster
|
||||||
|
cp -r inventory/sample inventory/$CLUSTER
|
||||||
|
cp contrib/terraform/upcloud/cluster-settings.tfvars inventory/$CLUSTER/
|
||||||
|
export ANSIBLE_CONFIG=ansible.cfg
|
||||||
|
cd inventory/$CLUSTER
|
||||||
|
```
|
||||||
|
|
||||||
|
Edit `cluster-settings.tfvars` to match your requirement.
|
||||||
|
|
||||||
|
Run Terraform to create the infrastructure.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
terraform init ../../contrib/terraform/upcloud
|
||||||
|
terraform apply --var-file cluster-settings.tfvars \
|
||||||
|
-state=tfstate-$CLUSTER.tfstate \
|
||||||
|
../../contrib/terraform/upcloud/
|
||||||
|
```
|
||||||
|
|
||||||
|
You should now have a inventory file named `inventory.ini` that you can use with kubespray.
|
||||||
|
You can use the inventory file with kubespray to set up a cluster.
|
||||||
|
|
||||||
|
It is a good idea to check that you have basic SSH connectivity to the nodes. You can do that by:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ansible -i inventory.ini -m ping all
|
||||||
|
```
|
||||||
|
|
||||||
|
You can setup Kubernetes with kubespray using the generated inventory:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ansible-playbook -i inventory.ini ../../cluster.yml -b -v
|
||||||
|
```
|
||||||
|
|
||||||
|
## Teardown
|
||||||
|
|
||||||
|
You can teardown your infrastructure using the following Terraform command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
terraform destroy --var-file cluster-settings.tfvars \
|
||||||
|
-state=tfstate-$CLUSTER.tfstate \
|
||||||
|
../../contrib/terraform/upcloud/
|
||||||
|
```
|
||||||
|
|
||||||
|
## Variables
|
||||||
|
|
||||||
|
* `hostname`: A valid domain name, e.g. example.com. The maximum length is 128 characters.
|
||||||
|
* `template_name`: The name or UUID of a base image
|
||||||
|
* `username`: a user to access the nodes
|
||||||
|
* `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
|
|
@ -0,0 +1,58 @@
|
||||||
|
|
||||||
|
# See: https://developers.upcloud.com/1.3/5-zones/
|
||||||
|
zone = "fi-hel1"
|
||||||
|
username = "ubuntu"
|
||||||
|
|
||||||
|
inventory_file = "inventory.ini"
|
||||||
|
|
||||||
|
# A valid domain name, e.g. host.example.com. The maximum length is 128 characters.
|
||||||
|
hostname = "example.com"
|
||||||
|
|
||||||
|
# Set the operating system using UUID or exact name
|
||||||
|
template_name = "Ubuntu Server 20.04 LTS (Focal Fossa)"
|
||||||
|
|
||||||
|
ssh_public_keys = [
|
||||||
|
# Put your public SSH key here
|
||||||
|
"ssh-rsa public key 1",
|
||||||
|
"ssh-rsa public key 2",
|
||||||
|
]
|
||||||
|
|
||||||
|
#check list of available plan https://developers.upcloud.com/1.3/7-plans/
|
||||||
|
machines = {
|
||||||
|
"master-0" : {
|
||||||
|
"node_type" : "master",
|
||||||
|
#number of cpu cores
|
||||||
|
"cpu" : "2",
|
||||||
|
#memory size in MB
|
||||||
|
"mem" : "4096"
|
||||||
|
# The size of the storage in GB
|
||||||
|
"disk_size" : 250
|
||||||
|
},
|
||||||
|
"worker-0" : {
|
||||||
|
"node_type" : "worker",
|
||||||
|
#number of cpu cores
|
||||||
|
"cpu" : "2",
|
||||||
|
#memory size in MB
|
||||||
|
"mem" : "4096"
|
||||||
|
# The size of the storage in GB
|
||||||
|
"disk_size" : 250
|
||||||
|
},
|
||||||
|
"worker-1" : {
|
||||||
|
"node_type" : "worker",
|
||||||
|
#number of cpu cores
|
||||||
|
"cpu" : "2",
|
||||||
|
#memory size in MB
|
||||||
|
"mem" : "4096"
|
||||||
|
# The size of the storage in GB
|
||||||
|
"disk_size" : 250
|
||||||
|
},
|
||||||
|
"worker-2" : {
|
||||||
|
"node_type" : "worker",
|
||||||
|
#number of cpu cores
|
||||||
|
"cpu" : "2",
|
||||||
|
#memory size in MB
|
||||||
|
"mem" : "4096"
|
||||||
|
# The size of the storage in GB
|
||||||
|
"disk_size" : 250
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
|
||||||
|
terraform {
|
||||||
|
required_version = ">= 0.13.0"
|
||||||
|
}
|
||||||
|
provider "upcloud" {
|
||||||
|
# Your UpCloud credentials are read from environment variables:
|
||||||
|
username = var.UPCLOUD_USERNAME
|
||||||
|
password = var.UPCLOUD_PASSWORD
|
||||||
|
}
|
||||||
|
|
||||||
|
module "kubernetes" {
|
||||||
|
source = "./modules/kubernetes-cluster"
|
||||||
|
|
||||||
|
zone = var.zone
|
||||||
|
hostname = var.hostname
|
||||||
|
|
||||||
|
template_name = var.template_name
|
||||||
|
username = var.username
|
||||||
|
|
||||||
|
machines = var.machines
|
||||||
|
|
||||||
|
ssh_public_keys = var.ssh_public_keys
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Generate ansible inventory
|
||||||
|
#
|
||||||
|
|
||||||
|
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",
|
||||||
|
keys(module.kubernetes.master_ip),
|
||||||
|
values(module.kubernetes.master_ip),
|
||||||
|
range(1, length(module.kubernetes.master_ip) + 1)))
|
||||||
|
connection_strings_worker = join("\n", formatlist("%s ansible_user=ubuntu ansible_host=%s",
|
||||||
|
keys(module.kubernetes.worker_ip),
|
||||||
|
values(module.kubernetes.worker_ip)))
|
||||||
|
list_master = join("\n", formatlist("%s",
|
||||||
|
keys(module.kubernetes.master_ip)))
|
||||||
|
list_worker = join("\n", formatlist("%s",
|
||||||
|
keys(module.kubernetes.worker_ip)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "null_resource" "inventories" {
|
||||||
|
provisioner "local-exec" {
|
||||||
|
command = "echo '${data.template_file.inventory.rendered}' > ${var.inventory_file}"
|
||||||
|
}
|
||||||
|
|
||||||
|
triggers = {
|
||||||
|
template = data.template_file.inventory.rendered
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
|
||||||
|
resource "upcloud_server" "master" {
|
||||||
|
for_each = {
|
||||||
|
for name, machine in var.machines :
|
||||||
|
name => machine
|
||||||
|
if machine.node_type == "master"
|
||||||
|
}
|
||||||
|
|
||||||
|
hostname = "${each.key}.${var.hostname}"
|
||||||
|
cpu = each.value.cpu
|
||||||
|
mem = each.value.mem
|
||||||
|
zone = var.zone
|
||||||
|
|
||||||
|
template {
|
||||||
|
storage = var.template_name
|
||||||
|
size = each.value.disk_size
|
||||||
|
}
|
||||||
|
|
||||||
|
# Network interfaces
|
||||||
|
network_interface {
|
||||||
|
type = "public"
|
||||||
|
}
|
||||||
|
|
||||||
|
network_interface {
|
||||||
|
type = "utility"
|
||||||
|
}
|
||||||
|
# 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
|
||||||
|
|
||||||
|
template {
|
||||||
|
storage = var.template_name
|
||||||
|
size = each.value.disk_size
|
||||||
|
}
|
||||||
|
|
||||||
|
# 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
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
|
||||||
|
output "master_ip" {
|
||||||
|
value = {
|
||||||
|
for instance in upcloud_server.master :
|
||||||
|
instance.hostname => instance.network_interface[0].ip_address
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output "worker_ip" {
|
||||||
|
value = {
|
||||||
|
for instance in upcloud_server.worker :
|
||||||
|
instance.hostname => instance.network_interface[0].ip_address
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
variable "zone" {
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "hostname"{
|
||||||
|
default ="example.com"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "template_name"{}
|
||||||
|
|
||||||
|
variable "username"{}
|
||||||
|
|
||||||
|
variable "machines" {
|
||||||
|
description = "Cluster machines"
|
||||||
|
type = map(object({
|
||||||
|
node_type = string
|
||||||
|
cpu = string
|
||||||
|
mem = string
|
||||||
|
disk_size = number
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "ssh_public_keys" {
|
||||||
|
type = list(string)
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
terraform {
|
||||||
|
required_providers {
|
||||||
|
upcloud = {
|
||||||
|
source = "UpCloudLtd/upcloud"
|
||||||
|
version = "~>2.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
required_version = ">= 0.13"
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
|
||||||
|
output "master_ip" {
|
||||||
|
value = module.kubernetes.master_ip
|
||||||
|
}
|
||||||
|
|
||||||
|
output "worker_ip" {
|
||||||
|
value = module.kubernetes.worker_ip
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
# See: https://developers.upcloud.com/1.3/5-zones/
|
||||||
|
zone = "fi-hel1"
|
||||||
|
username = "ubuntu"
|
||||||
|
|
||||||
|
inventory_file = "inventory.ini"
|
||||||
|
|
||||||
|
# A valid domain name, e.g. host.example.com. The maximum length is 128 characters.
|
||||||
|
hostname = "example.com"
|
||||||
|
|
||||||
|
# Set the operating system using UUID or exact name
|
||||||
|
template_name = "Ubuntu Server 20.04 LTS (Focal Fossa)"
|
||||||
|
ssh_public_keys = [
|
||||||
|
# Put your public SSH key here
|
||||||
|
"ssh-rsa I-did-not-read-the-docs",
|
||||||
|
"ssh-rsa I-did-not-read-the-docs 2",
|
||||||
|
]
|
||||||
|
|
||||||
|
check list of available plan https://developers.upcloud.com/1.3/7-plans/
|
||||||
|
machines = {
|
||||||
|
"master-0" : {
|
||||||
|
"node_type" : "master",
|
||||||
|
#number of cpu cores
|
||||||
|
"cpu" : "2",
|
||||||
|
#memory size in MB
|
||||||
|
"mem" : "4096"
|
||||||
|
# The size of the storage in GB
|
||||||
|
"disk_size" : 250
|
||||||
|
},
|
||||||
|
"worker-0" : {
|
||||||
|
"node_type" : "worker",
|
||||||
|
#number of cpu cores
|
||||||
|
"cpu" : "2",
|
||||||
|
#memory size in MB
|
||||||
|
"mem" : "4096"
|
||||||
|
# The size of the storage in GB
|
||||||
|
"disk_size" : 250
|
||||||
|
},
|
||||||
|
"worker-1" : {
|
||||||
|
"node_type" : "worker",
|
||||||
|
#number of cpu cores
|
||||||
|
"cpu" : "2",
|
||||||
|
#memory size in MB
|
||||||
|
"mem" : "4096"
|
||||||
|
# The size of the storage in GB
|
||||||
|
"disk_size" : 250
|
||||||
|
},
|
||||||
|
"worker-2" : {
|
||||||
|
"node_type" : "worker",
|
||||||
|
#number of cpu cores
|
||||||
|
"cpu" : "2",
|
||||||
|
#memory size in MB
|
||||||
|
"mem" : "4096"
|
||||||
|
# The size of the storage in GB
|
||||||
|
"disk_size" : 250
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
../../../../inventory/sample/group_vars/
|
|
@ -0,0 +1,17 @@
|
||||||
|
|
||||||
|
[all]
|
||||||
|
${connection_strings_master}
|
||||||
|
${connection_strings_worker}
|
||||||
|
|
||||||
|
[kube-master]
|
||||||
|
${list_master}
|
||||||
|
|
||||||
|
[etcd]
|
||||||
|
${list_master}
|
||||||
|
|
||||||
|
[kube-node]
|
||||||
|
${list_worker}
|
||||||
|
|
||||||
|
[k8s-cluster:children]
|
||||||
|
kube-master
|
||||||
|
kube-node
|
|
@ -0,0 +1,35 @@
|
||||||
|
|
||||||
|
variable "zone" {
|
||||||
|
description = "The zone where to run the cluster"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "hostname" {
|
||||||
|
default = "example.com"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "template_name" {}
|
||||||
|
|
||||||
|
variable "username" {}
|
||||||
|
|
||||||
|
variable "machines" {
|
||||||
|
description = "Cluster machines"
|
||||||
|
type = map(object({
|
||||||
|
node_type = string
|
||||||
|
cpu = string
|
||||||
|
mem = string
|
||||||
|
disk_size = number
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "ssh_public_keys" {
|
||||||
|
description = "List of public SSH keys which are injected into the VMs."
|
||||||
|
type = list(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "inventory_file" {
|
||||||
|
description = "Where to store the generated inventory file"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "UPCLOUD_USERNAME" {}
|
||||||
|
|
||||||
|
variable "UPCLOUD_PASSWORD" {}
|
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
terraform {
|
||||||
|
required_providers {
|
||||||
|
upcloud = {
|
||||||
|
source = "UpCloudLtd/upcloud"
|
||||||
|
version = "~>2.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
required_version = ">= 0.13"
|
||||||
|
}
|
Loading…
Reference in New Issue