From c5709dc867bf4f4314aaa6667028d9a2e3f32b14 Mon Sep 17 00:00:00 2001 From: Serge Logvinov Date: Sat, 22 Oct 2022 21:23:09 +0300 Subject: [PATCH] init exoscale cloud --- exoscale/auth.tf | 5 ++ exoscale/common.tf | 11 +++ exoscale/instances-controlplane.tf | 25 ++++++ exoscale/instances-web.tf | 25 ++++++ exoscale/instances-werker.tf | 19 ++++ exoscale/network-lb.tf | 75 ++++++++++++++++ exoscale/prepare/auth.tf | 5 ++ exoscale/prepare/common.tf | 6 ++ exoscale/prepare/network-nat.tf | 17 ++++ exoscale/prepare/network-secgroup.tf | 127 +++++++++++++++++++++++++++ exoscale/prepare/network.tf | 10 +++ exoscale/prepare/output.tf | 29 ++++++ exoscale/prepare/variables.tf | 63 +++++++++++++ exoscale/prepare/versions.tf | 9 ++ exoscale/variables.tf | 60 +++++++++++++ exoscale/versions.tf | 9 ++ 16 files changed, 495 insertions(+) create mode 100644 exoscale/auth.tf create mode 100644 exoscale/common.tf create mode 100644 exoscale/instances-controlplane.tf create mode 100644 exoscale/instances-web.tf create mode 100644 exoscale/instances-werker.tf create mode 100644 exoscale/network-lb.tf create mode 100644 exoscale/prepare/auth.tf create mode 100644 exoscale/prepare/common.tf create mode 100644 exoscale/prepare/network-nat.tf create mode 100644 exoscale/prepare/network-secgroup.tf create mode 100644 exoscale/prepare/network.tf create mode 100644 exoscale/prepare/output.tf create mode 100644 exoscale/prepare/variables.tf create mode 100644 exoscale/prepare/versions.tf create mode 100644 exoscale/variables.tf create mode 100644 exoscale/versions.tf diff --git a/exoscale/auth.tf b/exoscale/auth.tf new file mode 100644 index 0000000..e88993e --- /dev/null +++ b/exoscale/auth.tf @@ -0,0 +1,5 @@ + +provider "exoscale" { + key = var.exoscale_api_key + secret = var.exoscale_api_secret +} diff --git a/exoscale/common.tf b/exoscale/common.tf new file mode 100644 index 0000000..fc5ba12 --- /dev/null +++ b/exoscale/common.tf @@ -0,0 +1,11 @@ + +data "exoscale_compute_template" "debian" { + for_each = { for idx, name in local.regions : name => idx } + zone = each.key + name = "Linux Debian 11 (Bullseye) 64-bit" +} + +resource "exoscale_ssh_key" "terraform" { + name = "terraform" + public_key = file("~/.ssh/terraform.pub") +} diff --git a/exoscale/instances-controlplane.tf b/exoscale/instances-controlplane.tf new file mode 100644 index 0000000..f849a79 --- /dev/null +++ b/exoscale/instances-controlplane.tf @@ -0,0 +1,25 @@ + +resource "exoscale_anti_affinity_group" "controlplane" { + name = "${local.project}-controlplane" + description = "controlplane" +} + +resource "exoscale_instance_pool" "controlplane" { + for_each = { for idx, name in local.regions : name => idx if try(var.controlplane[name].count, 0) > 0 } + zone = each.key + name = "controlplane-${each.key}" + instance_prefix = "controlplane-${each.key}" + size = var.controlplane[each.key].count + template_id = data.exoscale_compute_template.debian[each.key].id + + ipv6 = true + security_group_ids = [local.network_secgroup[each.key].controlplane, local.network_secgroup[each.key].common] + network_ids = [local.network[each.key].id] + affinity_group_ids = [exoscale_anti_affinity_group.controlplane.id] + + key_pair = exoscale_ssh_key.terraform.name + instance_type = try(var.controlplane[each.key].type, "standard.tiny") + disk_size = 10 + + labels = merge(var.tags, { type = "infra" }) +} diff --git a/exoscale/instances-web.tf b/exoscale/instances-web.tf new file mode 100644 index 0000000..65a0ec8 --- /dev/null +++ b/exoscale/instances-web.tf @@ -0,0 +1,25 @@ + +resource "exoscale_anti_affinity_group" "web" { + name = "${local.project}-web" + description = "web" +} + +resource "exoscale_instance_pool" "web" { + for_each = { for idx, name in local.regions : name => idx if try(var.instances[name].web_count, 0) > 0 } + zone = each.key + name = "web-${each.key}" + instance_prefix = "web" + size = var.instances[each.key].web_count + template_id = data.exoscale_compute_template.debian[each.key].id + + ipv6 = true + security_group_ids = [local.network_secgroup[each.key].web, local.network_secgroup[each.key].common] + network_ids = [local.network[each.key].id] + affinity_group_ids = [exoscale_anti_affinity_group.web.id] + + key_pair = exoscale_ssh_key.terraform.name + instance_type = try(var.instances[each.key].web_type, "standard.tiny") + disk_size = 10 + + labels = merge(var.tags, { type = "web" }) +} diff --git a/exoscale/instances-werker.tf b/exoscale/instances-werker.tf new file mode 100644 index 0000000..ad629da --- /dev/null +++ b/exoscale/instances-werker.tf @@ -0,0 +1,19 @@ + +resource "exoscale_instance_pool" "worker" { + for_each = { for idx, name in local.regions : name => idx if try(var.instances[name].worker_count, 0) > 0 } + zone = each.key + name = "worker-${each.key}" + instance_prefix = "worker" + size = var.instances[each.key].worker_count + template_id = data.exoscale_compute_template.debian[each.key].id + + ipv6 = true + security_group_ids = [local.network_secgroup[each.key].common] + network_ids = [local.network[each.key].id] + + key_pair = exoscale_ssh_key.terraform.name + instance_type = try(var.instances[each.key].worker_type, "standard.tiny") + disk_size = 10 + + labels = merge(var.tags, { type = "worker" }) +} diff --git a/exoscale/network-lb.tf b/exoscale/network-lb.tf new file mode 100644 index 0000000..e547918 --- /dev/null +++ b/exoscale/network-lb.tf @@ -0,0 +1,75 @@ + +resource "exoscale_nlb" "lb" { + for_each = { for idx, name in local.regions : name => idx if try(var.controlplane[name].count, 0) > 0 || try(var.instances[name].web_count, 0) > 0 } + zone = each.key + name = "lb-${each.key}" + + labels = merge(var.tags, { type = "infra" }) +} + +resource "exoscale_nlb_service" "controlplane" { + for_each = { for idx, name in local.regions : name => idx if try(var.controlplane[name].count, 0) > 0 } + zone = each.key + name = "controlplane-${each.key}" + + nlb_id = exoscale_nlb.lb[each.key].id + protocol = "tcp" + port = 6443 + target_port = 6443 + strategy = "round-robin" + + healthcheck { + mode = "tcp" + port = 6443 + interval = 15 + timeout = 3 + } + + instance_pool_id = exoscale_instance_pool.controlplane[each.key].id +} + +resource "exoscale_nlb_service" "http" { + for_each = { for idx, name in local.regions : name => idx if try(var.instances[name].web_count, 0) > 0 } + zone = each.key + name = "web-http-${each.key}" + + nlb_id = exoscale_nlb.lb[each.key].id + protocol = "tcp" + port = 80 + target_port = 80 + strategy = "round-robin" + + healthcheck { + mode = "http" + port = 80 + interval = 15 + timeout = 3 + retries = 2 + uri = "/" + } + + instance_pool_id = exoscale_instance_pool.web[each.key].id +} + +resource "exoscale_nlb_service" "https" { + for_each = { for idx, name in local.regions : name => idx if try(var.instances[name].web_count, 0) > 0 } + zone = each.key + name = "web-https-${each.key}" + + nlb_id = exoscale_nlb.lb[each.key].id + protocol = "tcp" + port = 443 + target_port = 443 + strategy = "round-robin" + + healthcheck { + mode = "https" + port = 443 + interval = 15 + timeout = 3 + retries = 2 + uri = "/" + } + + instance_pool_id = exoscale_instance_pool.web[each.key].id +} diff --git a/exoscale/prepare/auth.tf b/exoscale/prepare/auth.tf new file mode 100644 index 0000000..e88993e --- /dev/null +++ b/exoscale/prepare/auth.tf @@ -0,0 +1,5 @@ + +provider "exoscale" { + key = var.exoscale_api_key + secret = var.exoscale_api_secret +} diff --git a/exoscale/prepare/common.tf b/exoscale/prepare/common.tf new file mode 100644 index 0000000..3f8c7e1 --- /dev/null +++ b/exoscale/prepare/common.tf @@ -0,0 +1,6 @@ + +data "exoscale_compute_template" "debian" { + for_each = { for idx, name in var.regions : name => idx } + zone = each.key + name = "Linux Debian 11 (Bullseye) 64-bit" +} diff --git a/exoscale/prepare/network-nat.tf b/exoscale/prepare/network-nat.tf new file mode 100644 index 0000000..041bded --- /dev/null +++ b/exoscale/prepare/network-nat.tf @@ -0,0 +1,17 @@ + +resource "exoscale_compute_instance" "gw" { + for_each = { for idx, name in var.regions : name => idx if try(var.capabilities[name].network_gw_enable, false) } + zone = each.key + name = "${var.project}-${each.key}-gw" + template_id = data.exoscale_compute_template.debian[each.key].id + + ipv6 = true + security_group_ids = [exoscale_security_group.gw.id, exoscale_security_group.common.id] + network_interface { + network_id = exoscale_private_network.main[each.key].id + ip_address = cidrhost("${exoscale_private_network.main[each.key].start_ip}/24", -3) + } + + type = try(var.capabilities[each.key].network_gw_type, "standard.micro") + disk_size = 10 +} diff --git a/exoscale/prepare/network-secgroup.tf b/exoscale/prepare/network-secgroup.tf new file mode 100644 index 0000000..5df3c2c --- /dev/null +++ b/exoscale/prepare/network-secgroup.tf @@ -0,0 +1,127 @@ + +resource "exoscale_security_group" "gw" { + name = "${var.project}-gw" + description = "gateway" +} + +resource "exoscale_security_group_rule" "gw_ssh_v4" { + for_each = { for idx, ip in var.whitelist_admin : ip => idx } + security_group_id = exoscale_security_group.gw.id + description = "ssh" + type = "INGRESS" + protocol = "TCP" + cidr = each.key + start_port = 22 + end_port = 22 +} + +resource "exoscale_security_group" "common" { + name = "${var.project}-common" + description = "common" +} + +resource "exoscale_security_group_rule" "common_ssh_v4" { + security_group_id = exoscale_security_group.common.id + description = "ssh (IPv4)" + type = "INGRESS" + protocol = "TCP" + cidr = "0.0.0.0/0" + start_port = 22 + end_port = 22 +} + +# resource "exoscale_security_group_rule" "common_localnet_tcp_v4" { +# security_group_id = exoscale_security_group.common.id +# description = "local network" +# type = "INGRESS" +# protocol = "TCP" +# cidr = var.network_cidr +# start_port = 1 +# end_port = 65535 +# } + +# resource "exoscale_security_group_rule" "common_localnet_udp_v4" { +# security_group_id = exoscale_security_group.common.id +# description = "local network" +# type = "INGRESS" +# protocol = "UDP" +# cidr = var.network_cidr +# start_port = 1 +# end_port = 65535 +# } + +resource "exoscale_security_group_rule" "common_talos_kubespan" { + for_each = { for idx, ip in ["0.0.0.0/0", "::/0"] : ip => idx } + security_group_id = exoscale_security_group.common.id + description = "talos kubespan" + type = "INGRESS" + protocol = "UDP" + cidr = each.key + start_port = 51820 + end_port = 51820 +} + +resource "exoscale_security_group" "controlplane" { + name = "${var.project}-controlplane" + description = "controlplane" +} + +resource "exoscale_security_group_rule" "controlplane_api" { + for_each = { for idx, ip in var.whitelist_admin : ip => idx } + security_group_id = exoscale_security_group.controlplane.id + description = "controlplane api" + type = "INGRESS" + protocol = "TCP" + cidr = each.key + start_port = 6443 + end_port = 6443 +} + +resource "exoscale_security_group_rule" "controlplane_talos" { + for_each = { for idx, ip in var.whitelist_admin : ip => idx } + security_group_id = exoscale_security_group.controlplane.id + description = "talos" + type = "INGRESS" + protocol = "TCP" + cidr = each.key + start_port = 50000 + end_port = 50001 +} + +resource "exoscale_security_group_rule" "controlplane_icmp" { + for_each = { for idx, ip in var.whitelist_admin : ip => idx if length(split(".", ip)) > 1 } + security_group_id = exoscale_security_group.controlplane.id + description = "ping" + type = "INGRESS" + protocol = "ICMP" + cidr = each.key + icmp_type = 8 + icmp_code = 0 +} + +resource "exoscale_security_group" "web" { + name = "${var.project}-web" + description = "web" +} + +resource "exoscale_security_group_rule" "web_http" { + for_each = { for idx, ip in var.whitelist_web : ip => idx } + security_group_id = exoscale_security_group.web.id + description = "http" + type = "INGRESS" + protocol = "TCP" + cidr = each.key + start_port = 80 + end_port = 80 +} + +resource "exoscale_security_group_rule" "web_https" { + for_each = { for idx, ip in var.whitelist_web : ip => idx } + security_group_id = exoscale_security_group.web.id + description = "https" + type = "INGRESS" + protocol = "TCP" + cidr = each.key + start_port = 443 + end_port = 443 +} diff --git a/exoscale/prepare/network.tf b/exoscale/prepare/network.tf new file mode 100644 index 0000000..80e97c5 --- /dev/null +++ b/exoscale/prepare/network.tf @@ -0,0 +1,10 @@ + +resource "exoscale_private_network" "main" { + for_each = { for idx, name in var.regions : name => idx } + zone = each.key + name = "${var.project}-${each.key}" + + netmask = "255.255.255.0" + start_ip = cidrhost(cidrsubnet(var.network_cidr, 8, var.network_shift + each.value * 2), 60) + end_ip = cidrhost(cidrsubnet(var.network_cidr, 8, var.network_shift + each.value * 2), -6) +} diff --git a/exoscale/prepare/output.tf b/exoscale/prepare/output.tf new file mode 100644 index 0000000..a84770d --- /dev/null +++ b/exoscale/prepare/output.tf @@ -0,0 +1,29 @@ + +output "project" { + description = "Exoscale project name" + value = var.project +} + +output "regions" { + description = "Exoscale regions" + value = var.regions +} + +output "network" { + description = "List of network" + value = { for zone, net in exoscale_private_network.main : zone => { + name = net.name + id = net.id + cidr = "${net.start_ip}/24" + gateway = cidrhost("${exoscale_private_network.main[zone].start_ip}/24", -3) + } } +} + +output "secgroups" { + description = "List of secgroups" + value = { for zone, net in exoscale_private_network.main : zone => { + common = exoscale_security_group.common.id + controlplane = exoscale_security_group.controlplane.id + web = exoscale_security_group.web.id + } } +} diff --git a/exoscale/prepare/variables.tf b/exoscale/prepare/variables.tf new file mode 100644 index 0000000..2d8e3fc --- /dev/null +++ b/exoscale/prepare/variables.tf @@ -0,0 +1,63 @@ + +variable "exoscale_api_key" { type = string } +variable "exoscale_api_secret" { type = string } + +variable "project" { + type = string + default = "main" +} + +variable "regions" { + description = "The region name list" + type = list(string) + default = ["de-fra-1", "de-muc-1"] +} + +variable "tags" { + description = "Defined Tags of resources" + type = map(string) + default = { + "env" = "develop" + } +} + +variable "network_name" { + type = string + default = "main" +} + +variable "network_cidr" { + description = "Local subnet rfc1918/ULA" + type = string + default = "172.16.0.0/16" +} + +variable "network_shift" { + description = "Network number shift" + type = number + default = 34 +} + +variable "whitelist_admin" { + default = ["0.0.0.0/0"] +} + +variable "whitelist_web" { + default = ["0.0.0.0/0"] +} + +variable "capabilities" { + type = map(any) + default = { + "de-fra-1" = { + network_lb = false, + network_gw_enable = false, + network_gw_type = "standard.micro", + }, + "de-muc-1" = { + network_lb = false, + network_gw_enable = false, + network_gw_type = "standard.micro", + }, + } +} diff --git a/exoscale/prepare/versions.tf b/exoscale/prepare/versions.tf new file mode 100644 index 0000000..fbfaa23 --- /dev/null +++ b/exoscale/prepare/versions.tf @@ -0,0 +1,9 @@ + +terraform { + required_providers { + exoscale = { + source = "exoscale/exoscale" + version = "0.41.0" + } + } +} diff --git a/exoscale/variables.tf b/exoscale/variables.tf new file mode 100644 index 0000000..4dd7bf2 --- /dev/null +++ b/exoscale/variables.tf @@ -0,0 +1,60 @@ + +variable "exoscale_api_key" { type = string } +variable "exoscale_api_secret" { type = string } + +data "terraform_remote_state" "prepare" { + backend = "local" + config = { + path = "${path.module}/prepare/terraform.tfstate" + } +} + +locals { + project = data.terraform_remote_state.prepare.outputs.project + regions = data.terraform_remote_state.prepare.outputs.regions + + network = data.terraform_remote_state.prepare.outputs.network + network_secgroup = data.terraform_remote_state.prepare.outputs.secgroups +} + +variable "tags" { + description = "Tags of resources" + type = map(string) + default = { + "env" = "develop" + } +} + +variable "controlplane" { + description = "Controlplane config" + type = map(any) + default = { + "de-fra-1" = { + count = 0, + type = "standard.tiny", + }, + "de-muc-1" = { + count = 0, + type = "standard.tiny", + }, + } +} + +variable "instances" { + description = "Map of region's properties" + type = map(any) + default = { + "de-fra-1" = { + web_count = 0, + web_type = "standard.tiny", + worker_count = 0, + worker_type = "standard.tiny", + }, + "de-muc-1" = { + web_count = 0, + web_type = "standard.tiny", + worker_count = 0, + worker_type = "standard.tiny", + }, + } +} diff --git a/exoscale/versions.tf b/exoscale/versions.tf new file mode 100644 index 0000000..fbfaa23 --- /dev/null +++ b/exoscale/versions.tf @@ -0,0 +1,9 @@ + +terraform { + required_providers { + exoscale = { + source = "exoscale/exoscale" + version = "0.41.0" + } + } +}