From e0868c1038b8a45a32208cb5190987a2fed01c9b Mon Sep 17 00:00:00 2001 From: Artiom Diomin Date: Fri, 13 Sep 2024 12:00:24 +0300 Subject: [PATCH] GCE dualstack support Signed-off-by: Artiom Diomin --- examples/terraform/gce/main.tf | 11 ++++++++--- examples/terraform/gce/output.tf | 1 + examples/terraform/gce/variables.tf | 12 ++++++++++++ examples/terraform/gce/versions.tf | 2 +- pkg/apis/kubeone/validation/validation.go | 23 ++++++++++++++++++----- 5 files changed, 40 insertions(+), 9 deletions(-) diff --git a/examples/terraform/gce/main.tf b/examples/terraform/gce/main.tf index aefbf09ba..65e73a8b0 100644 --- a/examples/terraform/gce/main.tf +++ b/examples/terraform/gce/main.tf @@ -38,11 +38,11 @@ data "google_compute_image" "control_plane_image" { } data "google_compute_network" "network" { - name = "default" + name = var.google_compute_network } data "google_compute_subnetwork" "subnet" { - name = "default" + name = var.google_compute_subnetwork region = var.region } @@ -176,6 +176,12 @@ resource "google_compute_instance" "control_plane" { access_config { nat_ip = "" } + + ipv6_access_config { + network_tier = "PREMIUM" + } + + stack_type = "IPV4_IPV6" } metadata = { @@ -195,4 +201,3 @@ resource "google_compute_instance" "control_plane" { ] } } - diff --git a/examples/terraform/gce/output.tf b/examples/terraform/gce/output.tf index 5d7fd746a..a10ff14dd 100644 --- a/examples/terraform/gce/output.tf +++ b/examples/terraform/gce/output.tf @@ -32,6 +32,7 @@ output "kubeone_hosts" { cloud_provider = "gce" private_address = google_compute_instance.control_plane.*.network_interface.0.network_ip public_address = google_compute_instance.control_plane.*.network_interface.0.access_config.0.nat_ip + ipv6_addresses = [for ip in google_compute_instance.control_plane.*.network_interface.0.ipv6_access_config.0.external_ipv6 : [ip]] hostnames = google_compute_instance.control_plane.*.name ssh_agent_socket = var.ssh_agent_socket ssh_port = var.ssh_port diff --git a/examples/terraform/gce/variables.tf b/examples/terraform/gce/variables.tf index 7323d4c7f..045632e0e 100644 --- a/examples/terraform/gce/variables.tf +++ b/examples/terraform/gce/variables.tf @@ -167,3 +167,15 @@ Name of operating system profile for MachineDeployments, only applicable if oper If not specified, the default value will be added by machine-controller addon. EOF } + +variable "google_compute_subnetwork" { + default = "default" + type = string + description = "if given, will be used as a subnet" +} + +variable "google_compute_network" { + default = "default" + type = string + description = "if given, will be used as a network" +} diff --git a/examples/terraform/gce/versions.tf b/examples/terraform/gce/versions.tf index 9d285a351..9852e7dda 100644 --- a/examples/terraform/gce/versions.tf +++ b/examples/terraform/gce/versions.tf @@ -3,7 +3,7 @@ terraform { required_providers { google = { source = "hashicorp/google" - version = "~> 4.27.0" + version = "~> 6" } } } diff --git a/pkg/apis/kubeone/validation/validation.go b/pkg/apis/kubeone/validation/validation.go index a0a6373f1..19b77f8c1 100644 --- a/pkg/apis/kubeone/validation/validation.go +++ b/pkg/apis/kubeone/validation/validation.go @@ -392,8 +392,15 @@ func validateIPFamily(ipFamily kubeoneapi.IPFamily, prov kubeoneapi.CloudProvide allErrs = append(allErrs, field.Forbidden(fldPath, "ipv6 and ipv6+ipv4 ip families are currently not supported")) } - if ipFamily == kubeoneapi.IPFamilyIPv4IPv6 && !(prov.AWS != nil || prov.None != nil || prov.Vsphere != nil) { - allErrs = append(allErrs, field.Forbidden(fldPath, "dualstack is currently supported only on AWS, vSphere and baremetal (none)")) + if ipFamily == kubeoneapi.IPFamilyIPv4IPv6 { + switch { + case prov.AWS != nil: + case prov.GCE != nil: + case prov.Vsphere != nil: + case prov.None != nil: + default: + allErrs = append(allErrs, field.Forbidden(fldPath, "dualstack is currently supported only on AWS, GCE, vSphere and baremetal (none)")) + } } return allErrs @@ -781,9 +788,15 @@ func ValidateHostConfig(hosts []kubeoneapi.HostConfig, clusterNetwork kubeoneapi if len(host.PublicAddress) == 0 { allErrs = append(allErrs, field.Required(fldPath, "no public IP/address given")) } - - if (clusterNetwork.IPFamily == kubeoneapi.IPFamilyIPv6 || clusterNetwork.IPFamily == kubeoneapi.IPFamilyIPv4IPv6 || clusterNetwork.IPFamily == kubeoneapi.IPFamilyIPv6IPv4) && len(host.IPv6Addresses) == 0 { - allErrs = append(allErrs, field.Required(fldPath, "no IPv6 address given")) + switch clusterNetwork.IPFamily { + case kubeoneapi.IPFamilyIPv6: + fallthrough + case kubeoneapi.IPFamilyIPv4IPv6: + fallthrough + case kubeoneapi.IPFamilyIPv6IPv4: + if len(host.IPv6Addresses) == 0 { + allErrs = append(allErrs, field.Required(fldPath, "no IPv6 address given")) + } } if len(host.PrivateAddress) == 0 { allErrs = append(allErrs, field.Required(fldPath, "no private IP/address givevn"))