From 4b7fb7f2a9c639b546f40a068b834a78c12e07bf Mon Sep 17 00:00:00 2001 From: Marcel Richter Date: Wed, 20 Mar 2024 17:03:14 +0100 Subject: [PATCH] feat(network): add support for optional IPv6 configuration IPv4/IPv6 dual-stack is actually not supported, it keeps being an IPv4 single stack. PRs welcome! Added the `enable_ipv6` variable to conditionally enable IPv6 addresses for servers. This update allows users to specify whether their infrastructure should support IPv6, making the setup more flexible for different network requirements. Additionally, updated resources and configurations to respect the `enable_ipv6` flag, including adjustments to server and network configurations to properly handle IPv6 addresses and subnets when enabled. This change enhances network configuration options, enabling users to opt for IPv6 support based on their specific needs or restrictions. The update includes: - A new variable `enable_ipv6` to toggle IPv6 support. - Conditional logic in Terraform configurations to apply IPv6 settings. - Adjustments to server provisioning scripts to enable or disable IPv6 based on the new variable. This enhancement simplifies network configuration management in environments where IPv6 support is either required or needs to be explicitly disabled, providing greater flexibility in how infrastructure is deployed. --- network.tf | 13 +++- server.tf | 14 ++-- talos_patch_control_plane.tf | 19 ++++- talos_patch_worker.tf | 130 +++++++++++++++++++---------------- variables.tf | 9 +++ 5 files changed, 118 insertions(+), 67 deletions(-) diff --git a/network.tf b/network.tf index 13a7e68..4d68f2f 100644 --- a/network.tf +++ b/network.tf @@ -43,7 +43,7 @@ resource "hcloud_primary_ip" "control_plane_ipv4" { } resource "hcloud_primary_ip" "control_plane_ipv6" { - count = var.control_plane_count + count = var.control_plane_count > 0 && var.enable_ipv6 ? var.control_plane_count : 0 name = "control-plane-${count.index + 1}-ipv6" datacenter = data.hcloud_datacenter.this.name type = "ipv6" @@ -61,7 +61,7 @@ resource "hcloud_primary_ip" "worker_ipv4" { } resource "hcloud_primary_ip" "worker_ipv6" { - count = var.worker_count + count = var.worker_count > 0 && var.enable_ipv6 ? var.worker_count : 0 name = "worker-${count.index + 1}-ipv6" datacenter = data.hcloud_datacenter.this.name type = "ipv6" @@ -76,9 +76,18 @@ locals { control_plane_public_ipv6_list = [ for ipv6 in hcloud_primary_ip.control_plane_ipv6 : ipv6.ip_address ] + control_plane_public_ipv6_subnet_list = [ + for ipv6 in hcloud_primary_ip.control_plane_ipv6 : ipv6.ip_network + ] worker_public_ipv4_list = [ for ipv4 in hcloud_primary_ip.worker_ipv4 : ipv4.ip_address ] + worker_public_ipv6_list = [ + for ipv6 in hcloud_primary_ip.worker_ipv6 : ipv6.ip_address + ] + worker_public_ipv6_subnet_list = [ + for ipv6 in hcloud_primary_ip.worker_ipv6 : ipv6.ip_network + ] # https://docs.hetzner.com/cloud/networks/faq/#are-any-ip-addresses-reserved # We may not use th following IP addresses: diff --git a/server.tf b/server.tf index 0e7a632..959f2a7 100644 --- a/server.tf +++ b/server.tf @@ -41,8 +41,8 @@ resource "hcloud_server" "control_planes" { public_net { ipv4_enabled = true ipv4 = hcloud_primary_ip.control_plane_ipv4[count.index].id - ipv6_enabled = true - ipv6 = hcloud_primary_ip.control_plane_ipv6[count.index].id + ipv6_enabled = var.enable_ipv6 + ipv6 = var.enable_ipv6 ? hcloud_primary_ip.control_plane_ipv6[count.index].id : null } network { @@ -77,8 +77,8 @@ resource "hcloud_server" "workers" { public_net { ipv4_enabled = true ipv4 = hcloud_primary_ip.worker_ipv4[count.index].id - ipv6_enabled = true - ipv6 = hcloud_primary_ip.worker_ipv6[count.index].id + ipv6_enabled = var.enable_ipv6 + ipv6 = var.enable_ipv6 ? hcloud_primary_ip.worker_ipv6[count.index].id : null } network { @@ -90,4 +90,10 @@ resource "hcloud_server" "workers" { hcloud_network_subnet.nodes, data.talos_machine_configuration.worker ] + + lifecycle { + ignore_changes = [ + user_data + ] + } } diff --git a/talos_patch_control_plane.tf b/talos_patch_control_plane.tf index 7d995cd..0f85617 100644 --- a/talos_patch_control_plane.tf +++ b/talos_patch_control_plane.tf @@ -2,6 +2,11 @@ locals { controlplane_yaml = [ for index in range(0, var.control_plane_count) : yamlencode({ machine = { + install = { + extraKernelArgs = [ + "ipv6.disable=${var.enable_ipv6 ? 0 : 1}", + ] + } certSANs = local.cert_SANs kubelet = { extraArgs = { @@ -23,9 +28,10 @@ locals { interface = "eth0" dhcp = false addresses : compact([ - local.control_plane_public_ipv4_list[index] + local.control_plane_public_ipv4_list[index], + var.enable_ipv6 ? local.control_plane_public_ipv6_list[index] : null ]) - routes = [ + routes = concat([ { network = "172.31.1.1/32" }, @@ -33,7 +39,14 @@ locals { network = "0.0.0.0/0" gateway : "172.31.1.1" } - ] + ], + var.enable_ipv6 ? [ + { + network = local.control_plane_public_ipv6_subnet_list[index] + gateway : "fe80::1" + } + ] : [] + ) vip = var.enable_floating_ip ? { ip = hcloud_floating_ip.control_plane_ipv4[0].ip_address hcloud = { diff --git a/talos_patch_worker.tf b/talos_patch_worker.tf index d1f4580..0d5aacb 100644 --- a/talos_patch_worker.tf +++ b/talos_patch_worker.tf @@ -1,68 +1,82 @@ locals { - worker_yaml = [for index in range(0, var.control_plane_count) : yamlencode({ - machine = { - kubelet = { - extraArgs = { - "cloud-provider" = "external" - "rotate-server-certificates" = true - } - clusterDNS = concat( - [cidrhost(local.service_ipv4_cidr, 10)] - ) - nodeIP = { - validSubnets = [ - local.node_ipv4_cidr + worker_yaml = [ + for index in range(0, var.control_plane_count) : yamlencode({ + machine = { + install = { + extraKernelArgs = [ + "ipv6.disable=${var.enable_ipv6 ? 0 : 1}", ] } - } - network = { - interfaces = [ - { - interface = "eth0" - dhcp = false - addresses : [ - local.worker_public_ipv4_list[index], - ] - routes = [ - { - network = "172.31.1.1/32" - }, - { - network = "0.0.0.0/0" - gateway : "172.31.1.1" - } + kubelet = { + extraArgs = { + "cloud-provider" = "external" + "rotate-server-certificates" = true + } + clusterDNS = concat( + [cidrhost(local.service_ipv4_cidr, 10)] + ) + nodeIP = { + validSubnets = [ + local.node_ipv4_cidr ] } - ] - extraHostEntries = local.extra_host_entries - } - sysctls = { - "net.core.somaxconn" = "65535" - "net.core.netdev_max_backlog" = "4096" - } - time = { - servers = [ - "ntp1.hetzner.de", - "ntp2.hetzner.com", - "ntp3.hetzner.net", - "time.cloudflare.com" - ] - } - } - cluster = { - network = { - dnsDomain = local.cluster_domain - podSubnets = [ - local.pod_ipv4_cidr - ] - serviceSubnets = [ - local.service_ipv4_cidr - ] + } + network = { + interfaces = [ + { + interface = "eth0" + dhcp = false + addresses : [ + local.worker_public_ipv4_list[index], + var.enable_ipv6 ? local.worker_public_ipv6_list[index] : null + ] + routes = concat([ + { + network = "172.31.1.1/32" + }, + { + network = "0.0.0.0/0" + gateway : "172.31.1.1" + } + ], + var.enable_ipv6 ? [ + { + network = local.worker_public_ipv6_subnet_list[index] + gateway : "fe80::1" + } + ] : [] + ) + } + ] + extraHostEntries = local.extra_host_entries + } + sysctls = { + "net.core.somaxconn" = "65535" + "net.core.netdev_max_backlog" = "4096" + } + time = { + servers = [ + "ntp1.hetzner.de", + "ntp2.hetzner.com", + "ntp3.hetzner.net", + "time.cloudflare.com" + ] + } } - proxy = { - disabled = true + cluster = { + network = { + dnsDomain = local.cluster_domain + podSubnets = [ + local.pod_ipv4_cidr + ] + serviceSubnets = [ + local.service_ipv4_cidr + ] + } + proxy = { + disabled = true + } } - } }) ] } \ No newline at end of file diff --git a/variables.tf b/variables.tf index e7ac9e1..ae841bf 100644 --- a/variables.tf +++ b/variables.tf @@ -66,6 +66,15 @@ variable "enable_floating_ip" { description = "If true, a floating IP will be created and assigned to the control plane nodes." } +variable "enable_ipv6" { + type = bool + default = false + description = <