From 43708777b402a0887af1690e5a808d5d8be7a7d9 Mon Sep 17 00:00:00 2001 From: Vojtech Mares Date: Mon, 13 May 2024 09:46:54 +0200 Subject: [PATCH] feat: add terraform --- .gitignore | 3 +- .terraform.lock.hcl | 66 ++++++++++++++++++++++++++++++++ dns.tf | 89 +++++++++++++++++++++++++++++++++++++++++++ loadbalancer.tf | 58 ++++++++++++++++++++++++++++ machines.tf | 80 ++++++++++++++++++++++++++++++++++++++ main.tf | 7 ++++ network.tf | 25 ++++++++++++ placement_groups.tf | 9 +++++ variables.auto.tfvars | 4 ++ versions.tf | 39 +++++++++++++++++++ 10 files changed, 379 insertions(+), 1 deletion(-) create mode 100644 .terraform.lock.hcl create mode 100644 dns.tf create mode 100644 loadbalancer.tf create mode 100644 machines.tf create mode 100644 main.tf create mode 100644 network.tf create mode 100644 placement_groups.tf create mode 100644 variables.auto.tfvars create mode 100644 versions.tf diff --git a/.gitignore b/.gitignore index 22caa2b..dc50c1e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .terraform -terraform.tfstate* \ No newline at end of file +terraform.tfstate* +k3s/kubeconfig.yaml diff --git a/.terraform.lock.hcl b/.terraform.lock.hcl new file mode 100644 index 0000000..8aee34d --- /dev/null +++ b/.terraform.lock.hcl @@ -0,0 +1,66 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/cloudflare/cloudflare" { + version = "4.32.0" + constraints = ">= 4.19.0" + hashes = [ + "h1:VkvPnLqX3nw7GdV9rgtTIrxgfmmTRTHPAXQmMqPWO3o=", + "zh:307dd2bc31c8fb2837fcc3f4aeddad71f22a187013a83447bfbc8854e9c04a0b", + "zh:3f602288229c2972cbbb724736f5894c3199fb9b2a34dc84116c1e4827d5cea9", + "zh:42416df3c78205560fb3dced6c0b488cacc965bdc6a976ecf12763b9e917c214", + "zh:46c7cd5a7cc6337b37c64c12814762c67af66d8ee0286183732c8cf15c428d87", + "zh:5581dd946165b11c2cffcf8f183269560b66f64bf64539a0c9825ed36473279c", + "zh:5bd23ab7381bdeb1498cd5b896d2f036307710f9744c708409e5f8bf45d6fa10", + "zh:7700bb5f76be11dd8ec7a1d21a4767cc2c9970473417f9b1ac2cde41faec52ff", + "zh:82027285efdb0f6843bfd36c76c660425ae5f6a816e12c8369cbc6a8240816d0", + "zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f", + "zh:91e199d6777d0aa796a169121e6ed673bd9368e742538fc4d9c29a4726eabf89", + "zh:a5c7472485e08019eae16cd73ed1e35bfab1617ffb93d5aedb7343d808db72f5", + "zh:bee90ade6dfccd2165406216c5150418869c2fb37543d85fd964341a54453e59", + "zh:bfee5bf91c7d27fdf19de0425710506518ebc6d39824124d2aa1e0610105d2ee", + "zh:ce4bd4b218ea2da725ff2f99c96d037402f7d977b03c3ff53efe2e23dcb775bc", + "zh:f2d6da62fd093f5612bbd76f8d4613617eb2cc0fc9042fd8e76ab43330a25c57", + ] +} + +provider "registry.terraform.io/hashicorp/random" { + version = "3.6.1" + hashes = [ + "h1:a+Goawwh6Qtg4/bRWzfDtIdrEFfPlnVy0y4LdUQY3nI=", + "zh:2a0ec154e39911f19c8214acd6241e469157489fc56b6c739f45fbed5896a176", + "zh:57f4e553224a5e849c99131f5e5294be3a7adcabe2d867d8a4fef8d0976e0e52", + "zh:58f09948c608e601bd9d0a9e47dcb78e2b2c13b4bda4d8f097d09152ea9e91c5", + "zh:5c2a297146ed6fb3fe934c800e78380f700f49ff24dbb5fb5463134948e3a65f", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:7ce41e26f0603e31cdac849085fc99e5cd5b3b73414c6c6d955c0ceb249b593f", + "zh:8c9e8d30c4ef08ee8bcc4294dbf3c2115cd7d9049c6ba21422bd3471d92faf8a", + "zh:93e91be717a7ffbd6410120eb925ebb8658cc8f563de35a8b53804d33c51c8b0", + "zh:982542e921970d727ce10ed64795bf36c4dec77a5db0741d4665230d12250a0d", + "zh:b9d1873f14d6033e216510ef541c891f44d249464f13cc07d3f782d09c7d18de", + "zh:cfe27faa0bc9556391c8803ade135a5856c34a3fe85b9ae3bdd515013c0c87c1", + "zh:e4aabf3184bbb556b89e4b195eab1514c86a2914dd01c23ad9813ec17e863a8a", + ] +} + +provider "registry.terraform.io/hetznercloud/hcloud" { + version = "1.47.0" + constraints = ">= 1.47.0" + hashes = [ + "h1:KQbtq1sXF4deoc0DKgjyyJMdIuHfhfhAPkVV0DlTMRI=", + "zh:0759f0c23d0e59baab3382320eef4eb314e0c5967b6ef67ff07135da07a97b34", + "zh:0e9ca84c4059d6d7e2c9f13d3c2b1cd91f7d9a47bedcb4b80c7c77d536eff887", + "zh:17a033ac4650a39ddacf3265a449edabaea528f81542c4e63e254272d5aac340", + "zh:2997c76a500e42b7519b24fa1f8646d9baab70c68277f80394560d3e1fd06e6d", + "zh:37f3fe7bb34cac63c69123e43e5426bab75816b3665dbe7125276a8d2ee6b2d8", + "zh:45d4b04dc470f24ad96c1c0b6636ea5422c659004f3e472c863bc50130fabf25", + "zh:46df99d972a78af6875565e53a73df66d870c474a20cd90e9e0a3092aa25197f", + "zh:4b5bb8d49366ad895c6c767efe16a1b8143802414abfe3fdb1184cbbecf424eb", + "zh:55c6199eb401c4b0a6c948ceac8b50f352e252e1c985903ed173bf26ad0f109e", + "zh:7b6efe897bffa37248064155a699e67953350b5b9a5476456c0160ce59254557", + "zh:7bc004bcb649ce1ec70e2cf848392e10a1edbcbf11b3292a4cc5c5d49bd769e4", + "zh:e1b17b7595f158fbb3021afa8869b541b5c10bdd2d8d2b2b3eaa82200b104ddd", + "zh:f741ca40e8e99a3e4114ad108ea2b5a5bccbedb008326c7f647f250580e69c0e", + "zh:fae9c7f8d08a447bb0972529f6db06999c35391046320206041a988aeca6b54c", + ] +} diff --git a/dns.tf b/dns.tf new file mode 100644 index 0000000..01edec2 --- /dev/null +++ b/dns.tf @@ -0,0 +1,89 @@ +# data "cloudflare_zone" "cthulhunetes" { +# name = "cthulhunetes.net" +# } + +# resource "cloudflare_zone" "cthulhunetes" { +# account_id = "f24333bb3c47d6db753e57e2a0c90082" +# zone = "cthulhunetes.net" +# } + +# resource "cloudflare_zone_dnssec" "cthulhunetes" { +# zone_id = cloudflare_zone.cthulhunetes.id +# } + +# resource "cloudflare_zone_settings_override" "cthulhunetes" { +# zone_id = cloudflare_zone.cthulhunetes.id +# settings { +# always_use_https = "on" +# automatic_https_rewrites = "on" +# ssl = "full" +# } +# } + +resource "cloudflare_record" "cthulhu_control_plane" { + count = length(hcloud_server.cthulhu_control_plane) + + zone_id = data.cloudflare_zone.vxm_cz.id + name = "control-plane-${count.index}.cthulhu.k8s" + value = hcloud_server.cthulhu_control_plane[count.index].ipv4_address + type = "A" + proxied = false +} + +resource "cloudflare_record" "cthulhu_control_plane_ipv6" { + count = length(hcloud_server.cthulhu_control_plane) + + zone_id = data.cloudflare_zone.vxm_cz.id + name = "control-plane-${count.index}.cthulhu.k8s" + value = hcloud_server.cthulhu_control_plane[count.index].ipv6_address + type = "AAAA" + proxied = false +} + +resource "cloudflare_record" "cthulhu_kubeapi_singlenode" { + count = length(hcloud_server.cthulhu_control_plane) == 1 ? 1 : 0 + + zone_id = data.cloudflare_zone.vxm_cz.id + name = "api.cthulhu.k8s" + value = hcloud_server.cthulhu_control_plane[0].ipv4_address + type = "A" + proxied = false +} + +resource "cloudflare_record" "cthulhu_kubeapi_singlenode_ipv6" { + count = length(hcloud_server.cthulhu_control_plane) == 1 ? 1 : 0 + + zone_id = data.cloudflare_zone.vxm_cz.id + name = "api.cthulhu.k8s" + value = hcloud_server.cthulhu_control_plane[0].ipv6_address + type = "AAAA" + proxied = false +} + +resource "cloudflare_record" "cthulhu_workers" { + count = length(hcloud_server.cthulhu_workers) + + zone_id = data.cloudflare_zone.vxm_cz.id + name = "worker-${random_string.workers_suffix.result}-${count.index}.cthulhu.k8s" + value = hcloud_server.cthulhu_workers[count.index].ipv4_address + type = "A" + proxied = false +} + +resource "cloudflare_record" "cthulhu_workers_ipv6" { + count = length(hcloud_server.cthulhu_workers) + + zone_id = data.cloudflare_zone.vxm_cz.id + name = "worker-${random_string.workers_suffix.result}-${count.index}.cthulhu.k8s" + value = hcloud_server.cthulhu_workers[count.index].ipv6_address + type = "AAAA" + proxied = false +} + +resource "cloudflare_record" "cthulhu_wildcard" { + zone_id = data.cloudflare_zone.vxm_cz.id + name = "*.cthulhu.k8s" + value = cloudflare_record.ingress_cthulhu_k8s_vxm_cz.hostname + type = "CNAME" + proxied = false +} \ No newline at end of file diff --git a/loadbalancer.tf b/loadbalancer.tf new file mode 100644 index 0000000..a55801f --- /dev/null +++ b/loadbalancer.tf @@ -0,0 +1,58 @@ +resource "hcloud_load_balancer" "ingress" { + name = "cthulhu-ingress" + load_balancer_type = "lb11" + location = "fsn1" + labels = { + "env" = "production" + "k8s.cluster.name" = "cthulhu" + } +} + +resource "hcloud_load_balancer_target" "ingress" { + type = "label_selector" + label_selector = "k8s.node.role=worker" + use_private_ip = true + + load_balancer_id = hcloud_load_balancer.ingress.id + + depends_on = [hcloud_load_balancer_network.ingress_to_network] +} + +resource "hcloud_load_balancer_service" "ingress_workers_tcp_80" { + load_balancer_id = hcloud_load_balancer.ingress.id + protocol = "tcp" + listen_port = 80 + destination_port = 32080 + proxyprotocol = true +} + +resource "hcloud_load_balancer_service" "ingress_workers_tcp_443" { + load_balancer_id = hcloud_load_balancer.ingress.id + protocol = "tcp" + listen_port = 443 + destination_port = 32443 + proxyprotocol = true +} + +resource "cloudflare_record" "ingress_cthulhu_k8s_vxm_cz" { + zone_id = data.cloudflare_zone.vxm_cz.id + name = "ingress.cthulhu.k8s" + value = hcloud_load_balancer.ingress.ipv4 + type = "A" + proxied = false +} + +resource "cloudflare_record" "ingress_cthulhu_k8s_vxm_cz_ipv6" { + zone_id = data.cloudflare_zone.vxm_cz.id + name = "ingress.cthulhu.k8s" + value = hcloud_load_balancer.ingress.ipv6 + type = "AAAA" + proxied = false +} + +resource "hcloud_load_balancer_network" "ingress_to_network" { + load_balancer_id = hcloud_load_balancer.ingress.id + network_id = hcloud_network.cthulhu.id + ip = cidrhost(hcloud_network_subnet.service.ip_range, 1) +} + diff --git a/machines.tf b/machines.tf new file mode 100644 index 0000000..125c5d7 --- /dev/null +++ b/machines.tf @@ -0,0 +1,80 @@ +resource "hcloud_server" "cthulhu_control_plane" { + count = 1 + + name = "control-plane-${count.index}" + image = "rocky-9" + server_type = "cax11" + location = "fsn1" + + backups = true + shutdown_before_deletion = true + + placement_group_id = hcloud_placement_group.cthulhu_control_plane.id + + # firewall_ids = [ + # hcloud_firewall.cthulhu_nodes_public.id, + # hcloud_firewall.cthulhu_nodes_private.id, + # ] + + ssh_keys = [data.hcloud_ssh_key.vojtechmares.id] + + labels = { + "k8s.node.role" = "master" + "k8s.node.name" = "master-${count.index}" + "k8s.cluster.name" = "cthulhu" + } + + public_net { + ipv4_enabled = true + ipv6_enabled = true + } + + network { + network_id = hcloud_network.cthulhu.id + ip = cidrhost(hcloud_network_subnet.control_plane.ip_range, count.index + 1) + } +} + +resource "random_string" "workers_suffix" { + length = 4 + special = false + upper = false +} + +resource "hcloud_server" "cthulhu_workers" { + count = 3 + + name = "worker-${random_string.workers_suffix.result}-${count.index}" + image = "rocky-9" + server_type = "cax21" + location = "fsn1" + + backups = false + shutdown_before_deletion = true + + placement_group_id = hcloud_placement_group.cthulhu_workers.id + + # firewall_ids = [ + # hcloud_firewall.cthulhu_nodes_public.id, + # hcloud_firewall.cthulhu_nodes_private.id, + # ] + + ssh_keys = [data.hcloud_ssh_key.vojtechmares.id] + + labels = { + "k8s.node.role" = "worker" + "k8s.node.name" = "worker-${random_string.workers_suffix.result}-${count.index}" + "k8s.cluster.name" = "cthulhu" + "k8s.node.pool" = random_string.workers_suffix.result + } + + public_net { + ipv4_enabled = true + ipv6_enabled = true + } + + network { + network_id = hcloud_network.cthulhu.id + ip = cidrhost(hcloud_network_subnet.workers.ip_range, count.index + 1) + } +} diff --git a/main.tf b/main.tf new file mode 100644 index 0000000..cc5934a --- /dev/null +++ b/main.tf @@ -0,0 +1,7 @@ +data "hcloud_ssh_key" "vojtechmares" { + name = "iam@vojtechmares.com" +} + +data "cloudflare_zone" "vxm_cz" { + name = "vxm.cz" +} \ No newline at end of file diff --git a/network.tf b/network.tf new file mode 100644 index 0000000..842fbfe --- /dev/null +++ b/network.tf @@ -0,0 +1,25 @@ +resource "hcloud_network" "cthulhu" { + name = "cthulhu-net" + ip_range = "172.16.0.0/16" +} + +resource "hcloud_network_subnet" "control_plane" { + network_id = hcloud_network.cthulhu.id + type = "cloud" + network_zone = "eu-central" + ip_range = "172.16.1.0/24" +} + +resource "hcloud_network_subnet" "workers" { + network_id = hcloud_network.cthulhu.id + type = "cloud" + network_zone = "eu-central" + ip_range = "172.16.10.0/24" +} + +resource "hcloud_network_subnet" "service" { + network_id = hcloud_network.cthulhu.id + type = "cloud" + network_zone = "eu-central" + ip_range = "172.16.250.0/24" +} diff --git a/placement_groups.tf b/placement_groups.tf new file mode 100644 index 0000000..e66f064 --- /dev/null +++ b/placement_groups.tf @@ -0,0 +1,9 @@ +resource "hcloud_placement_group" "cthulhu_control_plane" { + name = "cthulhu-control-plane" + type = "spread" +} + +resource "hcloud_placement_group" "cthulhu_workers" { + name = "cthulhu-workers" + type = "spread" +} \ No newline at end of file diff --git a/variables.auto.tfvars b/variables.auto.tfvars new file mode 100644 index 0000000..3c7f0f4 --- /dev/null +++ b/variables.auto.tfvars @@ -0,0 +1,4 @@ +cloudflare_api_key = "9e19ed1d8baf979e7a4eda5c99ac38d59db38" +cloudflare_email = "iam@vojtechmares.com" + +hcloud_token = "KDwuUtV0gGqdY19HJ718eOBThVJClFLbKyPh2oCQIcORMCnkSwFtgv2KzesEAtBY" diff --git a/versions.tf b/versions.tf new file mode 100644 index 0000000..d56660a --- /dev/null +++ b/versions.tf @@ -0,0 +1,39 @@ +terraform { + required_providers { + cloudflare = { + source = "cloudflare/cloudflare" + version = ">=4.32.0" + } + + hcloud = { + source = "hetznercloud/hcloud" + version = ">=1.47.0" + } + } + required_version = "~> 1.7.0" +} + +provider "cloudflare" { + api_key = var.cloudflare_api_key + email = var.cloudflare_email +} + +provider "hcloud" { + token = var.hcloud_token +} + +variable "cloudflare_api_key" { + type = string + sensitive = true +} + +variable "cloudflare_email" { + type = string +} + +variable "hcloud_token" { + type = string + sensitive = true +} + +