Move infra-setup and k3s-setup into dedicated directories
This changes makes it easier to differentiate and understand the different parts of the kubernetes setup. On one hand we have the bare infrastructure (servers, network, etc), on the other hand we have the software (k3s in this case). In the future we'll have a few more parts, like the minimal configuration of the kubernetes cluster, e.g. with a cert-manager. This is easier to manage with helm or terraform than with ansible. Therefore it makes even more sense to split the responsibilities into dedicated directories.
This commit is contained in:
25
infra/modules/hetzner/dns/main.tf
Normal file
25
infra/modules/hetzner/dns/main.tf
Normal file
@@ -0,0 +1,25 @@
|
||||
resource "hetznerdns_zone" "this" {
|
||||
name = var.zone
|
||||
ttl = var.zone_ttl
|
||||
}
|
||||
|
||||
locals {
|
||||
records = nonsensitive({
|
||||
for record in var.records : "${record.type}#${record.name}#${md5(record.value)}" => {
|
||||
for key, value in record : key => value
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
resource "hetznerdns_record" "this" {
|
||||
for_each = local.records
|
||||
zone_id = hetznerdns_zone.this.id
|
||||
name = each.value.name
|
||||
type = each.value.type
|
||||
value = (each.value.type == "TXT"
|
||||
? "\"${join("\" \"", [for c in chunklist(split("", each.value.value), 255) : join("", c)])}\""
|
||||
: each.value.value
|
||||
)
|
||||
ttl = each.value.ttl
|
||||
}
|
||||
|
||||
0
infra/modules/hetzner/dns/outputs.tf
Normal file
0
infra/modules/hetzner/dns/outputs.tf
Normal file
19
infra/modules/hetzner/dns/variables.tf
Normal file
19
infra/modules/hetzner/dns/variables.tf
Normal file
@@ -0,0 +1,19 @@
|
||||
variable "zone" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "zone_ttl" {
|
||||
type = number
|
||||
default = 3600
|
||||
}
|
||||
|
||||
variable "records" {
|
||||
type = set(object({
|
||||
name = string
|
||||
value = string
|
||||
type = string
|
||||
ttl = optional(number, null)
|
||||
}))
|
||||
default = []
|
||||
}
|
||||
|
||||
10
infra/modules/hetzner/dns/versions.tf
Normal file
10
infra/modules/hetzner/dns/versions.tf
Normal file
@@ -0,0 +1,10 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
hetznerdns = {
|
||||
source = "timohirt/hetznerdns"
|
||||
version = "2.2.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
17
infra/modules/hetzner/kubernetes/agent-init.yaml.tftpl
Normal file
17
infra/modules/hetzner/kubernetes/agent-init.yaml.tftpl
Normal file
@@ -0,0 +1,17 @@
|
||||
#cloud-config
|
||||
packages:
|
||||
- curl
|
||||
users:
|
||||
- name: cluster
|
||||
shell: /bin/bash
|
||||
runcmd:
|
||||
# configure correct routing via NAT
|
||||
- ip route add default via ${network_gateway}
|
||||
- NIC=$(ifconfig | grep -q enp7s0 && echo enp7s0 || echo ens10)
|
||||
- echo "[Match]" > /etc/systemd/network/10-$NIC.network
|
||||
- echo "Name=$NIC" >> /etc/systemd/network/10-$NIC.network
|
||||
- echo "[Network]" >> /etc/systemd/network/10-$NIC.network
|
||||
- echo "DHCP=yes" >> /etc/systemd/network/10-$NIC.network
|
||||
- echo "Gateway=${network_gateway}" >> /etc/systemd/network/10-$NIC.network
|
||||
- sed -e "s/#DNS=/DNS=${dns_servers}/" -i /etc/systemd/resolved.conf
|
||||
- systemctl restart systemd-resolved
|
||||
133
infra/modules/hetzner/kubernetes/main.tf
Normal file
133
infra/modules/hetzner/kubernetes/main.tf
Normal file
@@ -0,0 +1,133 @@
|
||||
locals {
|
||||
network = "10.0.0.0/16"
|
||||
subnet_eu_central = "10.0.0.0/24"
|
||||
servers = {
|
||||
for idx, config in var.servers : "${var.name}-server-${idx + 1}" => merge(
|
||||
config,
|
||||
{
|
||||
ip = cidrhost(local.subnet_eu_central, idx + 2)
|
||||
first_ip = idx == 0 ? "" : cidrhost(local.subnet_eu_central, 2)
|
||||
}
|
||||
)
|
||||
}
|
||||
agents = merge([
|
||||
for idx, config in var.agents : {
|
||||
for n in range(0, config.count) : "${var.name}-agent-${idx + 1}-${n + 1}" => merge(
|
||||
config,
|
||||
{ ip = cidrhost(local.subnet_eu_central, 255 - (idx * 20) - n - 1) }
|
||||
)
|
||||
}
|
||||
]...)
|
||||
all_ips = ["0.0.0.0/0", "::/0"]
|
||||
ping_firewall = var.ping_enabled ? { "ping" : [{ protocol = "icmp", port = null }] } : {}
|
||||
k8s_firewall = { "kubernetes" : [{ port = "6443", source_ips = concat([local.network], var.kubernetes_exposed_ips) }] }
|
||||
ssh_firewall = length(var.ssh_exposed_ips) > 0 ? { "ssh" : [{ port = 1022, source_ips = var.ssh_exposed_ips }] } : {}
|
||||
service_firewalls = { for service, ports in var.public_tcp_services : service => [for port in ports : { port = port }] }
|
||||
firewalls = merge(
|
||||
local.ping_firewall,
|
||||
local.k8s_firewall,
|
||||
local.ssh_firewall,
|
||||
local.service_firewalls
|
||||
)
|
||||
}
|
||||
|
||||
resource "hcloud_network" "this" {
|
||||
name = var.name
|
||||
ip_range = local.network
|
||||
}
|
||||
|
||||
resource "hcloud_network_subnet" "this" {
|
||||
type = "cloud"
|
||||
network_id = hcloud_network.this.id
|
||||
network_zone = "eu-central"
|
||||
ip_range = local.subnet_eu_central
|
||||
}
|
||||
|
||||
resource "hcloud_network_route" "this" {
|
||||
network_id = hcloud_network.this.id
|
||||
destination = "0.0.0.0/0"
|
||||
gateway = cidrhost(local.subnet_eu_central, 2)
|
||||
}
|
||||
|
||||
resource "random_string" "k3s_token" {
|
||||
length = 100
|
||||
special = false
|
||||
}
|
||||
|
||||
resource "hcloud_firewall" "this" {
|
||||
for_each = local.firewalls
|
||||
|
||||
name = each.key
|
||||
dynamic "rule" {
|
||||
for_each = each.value
|
||||
content {
|
||||
direction = lookup(rule.value, "direction", "in")
|
||||
protocol = lookup(rule.value, "protocol", "tcp")
|
||||
source_ips = lookup(rule.value, "source_ips", local.all_ips)
|
||||
port = lookup(rule.value, "port")
|
||||
}
|
||||
}
|
||||
}
|
||||
resource "hcloud_server" "server" {
|
||||
depends_on = [hcloud_network_subnet.this]
|
||||
for_each = local.servers
|
||||
|
||||
lifecycle {
|
||||
ignore_changes = [ user_data ]
|
||||
}
|
||||
|
||||
name = each.key
|
||||
image = "ubuntu-24.04"
|
||||
server_type = each.value.type
|
||||
location = each.value.location
|
||||
ssh_keys = var.ssh_keys
|
||||
public_net {
|
||||
ipv4 = each.value.ipv4_id
|
||||
ipv6 = each.value.ipv6_id
|
||||
}
|
||||
network {
|
||||
network_id = hcloud_network.this.id
|
||||
ip = each.value.ip
|
||||
}
|
||||
user_data = templatefile(
|
||||
"${path.module}/server-init.yaml.tftpl",
|
||||
{
|
||||
network_ip_range = local.network
|
||||
k3s_token = random_string.k3s_token.result
|
||||
first_ip = each.value.first_ip
|
||||
}
|
||||
)
|
||||
firewall_ids = [for firewall in hcloud_firewall.this : firewall.id]
|
||||
}
|
||||
|
||||
resource "hcloud_server" "agent" {
|
||||
depends_on = [hcloud_server.server]
|
||||
for_each = local.agents
|
||||
|
||||
lifecycle {
|
||||
ignore_changes = [ user_data ]
|
||||
}
|
||||
|
||||
name = each.key
|
||||
image = "ubuntu-24.04"
|
||||
server_type = each.value.type
|
||||
location = each.value.location
|
||||
ssh_keys = var.ssh_keys
|
||||
public_net {
|
||||
ipv4_enabled = false
|
||||
ipv6_enabled = false
|
||||
}
|
||||
network {
|
||||
network_id = hcloud_network.this.id
|
||||
ip = each.value.ip
|
||||
}
|
||||
user_data = templatefile(
|
||||
"${path.module}/agent-init.yaml.tftpl",
|
||||
{
|
||||
server_ip = cidrhost(local.subnet_eu_central, 2)
|
||||
network_gateway = cidrhost(local.subnet_eu_central, 1)
|
||||
dns_servers = "8.8.8.8 8.8.4.4"
|
||||
k3s_token = random_string.k3s_token.result
|
||||
}
|
||||
)
|
||||
}
|
||||
11
infra/modules/hetzner/kubernetes/outputs.tf
Normal file
11
infra/modules/hetzner/kubernetes/outputs.tf
Normal file
@@ -0,0 +1,11 @@
|
||||
output "server_ips_v4" {
|
||||
value = [for key, value in hcloud_server.server : value.ipv4_address]
|
||||
}
|
||||
|
||||
output "server_ips_v6" {
|
||||
value = [for key, value in hcloud_server.server : value.ipv6_address]
|
||||
}
|
||||
|
||||
output "agent_ips_v4" {
|
||||
value = flatten([for key, value in hcloud_server.agent : value.network.*.ip])
|
||||
}
|
||||
13
infra/modules/hetzner/kubernetes/server-init.yaml.tftpl
Normal file
13
infra/modules/hetzner/kubernetes/server-init.yaml.tftpl
Normal file
@@ -0,0 +1,13 @@
|
||||
#cloud-config
|
||||
packages:
|
||||
- curl
|
||||
users:
|
||||
- name: cluster
|
||||
shell: /bin/bash
|
||||
runcmd:
|
||||
# configure NAT
|
||||
- echo '#!/bin/bash' > /etc/networkd-dispatcher/routable.d/10-eth0-post-up
|
||||
- echo 'echo 1 > /proc/sys/net/ipv4/ip_forward' >> /etc/networkd-dispatcher/routable.d/10-eth0-post-up
|
||||
- echo 'iptables -t nat -A POSTROUTING -s ${network_ip_range} -o eth0 -j MASQUERADE' >> /etc/networkd-dispatcher/routable.d/10-eth0-post-up
|
||||
- chmod +x /etc/networkd-dispatcher/routable.d/10-eth0-post-up
|
||||
- /etc/networkd-dispatcher/routable.d/10-eth0-post-up
|
||||
44
infra/modules/hetzner/kubernetes/variables.tf
Normal file
44
infra/modules/hetzner/kubernetes/variables.tf
Normal file
@@ -0,0 +1,44 @@
|
||||
variable "name" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "ssh_keys" {
|
||||
type = list(string)
|
||||
}
|
||||
|
||||
variable "servers" {
|
||||
type = list(object({
|
||||
ipv4_id = number
|
||||
ipv6_id = number
|
||||
type = string
|
||||
location = string
|
||||
}))
|
||||
}
|
||||
|
||||
variable "agents" {
|
||||
type = list(object({
|
||||
count = optional(number, 1)
|
||||
type = string
|
||||
location = string
|
||||
}))
|
||||
}
|
||||
|
||||
variable "ping_enabled" {
|
||||
type = bool
|
||||
default = true
|
||||
}
|
||||
|
||||
variable "public_tcp_services" {
|
||||
type = map(list(string))
|
||||
default = {}
|
||||
}
|
||||
|
||||
variable "kubernetes_exposed_ips" {
|
||||
type = list(string)
|
||||
default = []
|
||||
}
|
||||
|
||||
variable "ssh_exposed_ips" {
|
||||
type = list(string)
|
||||
default = []
|
||||
}
|
||||
14
infra/modules/hetzner/kubernetes/versions.tf
Normal file
14
infra/modules/hetzner/kubernetes/versions.tf
Normal file
@@ -0,0 +1,14 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
hcloud = {
|
||||
source = "hetznercloud/hcloud"
|
||||
version = "1.50.0"
|
||||
}
|
||||
random = {
|
||||
source = "hashicorp/random"
|
||||
version = "3.7.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user