diff --git a/pkg/apis/kops/model/features.go b/pkg/apis/kops/model/features.go index 97e33db1d9..ca42e88cb6 100644 --- a/pkg/apis/kops/model/features.go +++ b/pkg/apis/kops/model/features.go @@ -52,11 +52,14 @@ func UseChallengeCallback(cloudProvider kops.CloudProviderID) bool { // UseKopsControllerForNodeConfig checks if nodeup should use kops-controller to get nodeup.Config. func UseKopsControllerForNodeConfig(cluster *kops.Cluster) bool { - switch cluster.Spec.GetCloudProvider() { - case kops.CloudProviderGCE: - // We can use cloud-discovery here. - default: - if cluster.UsesLegacyGossip() { + if cluster.UsesLegacyGossip() { + switch cluster.Spec.GetCloudProvider() { + case kops.CloudProviderGCE: + // We can use cloud-discovery here. + case kops.CloudProviderHetzner: + // We don't have a cloud-discovery mechanism implemented in nodeup for hetzner, + // but we assume that we're using a load balancer with a fixed IP address + default: return false } } diff --git a/pkg/model/hetznermodel/loadbalancer.go b/pkg/model/hetznermodel/loadbalancer.go index c053f8acd3..082d14bbdf 100644 --- a/pkg/model/hetznermodel/loadbalancer.go +++ b/pkg/model/hetznermodel/loadbalancer.go @@ -60,7 +60,7 @@ func (b *LoadBalancerModelBuilder) Build(c *fi.CloudupModelBuilderContext) error }, } - if b.Cluster.UsesNoneDNS() { + if b.Cluster.UsesNoneDNS() || b.UseKopsControllerForNodeBootstrap() { loadbalancer.Services = append(loadbalancer.Services, &hetznertasks.LoadBalancerService{ Protocol: string(hcloud.LoadBalancerServiceProtocolTCP), ListenerPort: fi.PtrTo(wellknownports.KopsControllerPort), diff --git a/upup/pkg/fi/cloudup/apply_cluster.go b/upup/pkg/fi/cloudup/apply_cluster.go index 94c2f40ebb..fead5b806f 100644 --- a/upup/pkg/fi/cloudup/apply_cluster.go +++ b/upup/pkg/fi/cloudup/apply_cluster.go @@ -1419,44 +1419,64 @@ func (n *nodeUpConfigBuilder) BuildConfig(ig *kops.InstanceGroup, apiserverAddit } // Set API server address to an IP from the cluster network CIDR + var controlPlaneIPs []string + switch cluster.Spec.GetCloudProvider() { + case kops.CloudProviderAWS, kops.CloudProviderHetzner, kops.CloudProviderOpenstack: + // Use a private IP address that belongs to the cluster network CIDR (some additional addresses may be FQDNs or public IPs) + for _, additionalIP := range apiserverAdditionalIPs { + for _, networkCIDR := range append(cluster.Spec.Networking.AdditionalNetworkCIDRs, cluster.Spec.Networking.NetworkCIDR) { + _, cidr, err := net.ParseCIDR(networkCIDR) + if err != nil { + return nil, nil, fmt.Errorf("failed to parse network CIDR %q: %w", networkCIDR, err) + } + if cidr.Contains(net.ParseIP(additionalIP)) { + controlPlaneIPs = append(controlPlaneIPs, additionalIP) + } + } + } + + case kops.CloudProviderDO, kops.CloudProviderScaleway: + // Use any IP address that is found (including public ones) + for _, additionalIP := range apiserverAdditionalIPs { + controlPlaneIPs = append(controlPlaneIPs, additionalIP) + } + + case kops.CloudProviderGCE: + // Use any IP address that is found (including public ones) + for _, additionalIP := range apiserverAdditionalIPs { + controlPlaneIPs = append(controlPlaneIPs, additionalIP) + } + } + if cluster.UsesNoneDNS() { switch cluster.Spec.GetCloudProvider() { case kops.CloudProviderAWS, kops.CloudProviderHetzner, kops.CloudProviderOpenstack: - // Use a private IP address that belongs to the cluster network CIDR (some additional addresses may be FQDNs or public IPs) - for _, additionalIP := range apiserverAdditionalIPs { - for _, networkCIDR := range append(cluster.Spec.Networking.AdditionalNetworkCIDRs, cluster.Spec.Networking.NetworkCIDR) { - _, cidr, err := net.ParseCIDR(networkCIDR) - if err != nil { - return nil, nil, fmt.Errorf("failed to parse network CIDR %q: %w", networkCIDR, err) - } - if cidr.Contains(net.ParseIP(additionalIP)) { - bootConfig.APIServerIPs = append(bootConfig.APIServerIPs, additionalIP) - } - } - } + bootConfig.APIServerIPs = controlPlaneIPs case kops.CloudProviderDO, kops.CloudProviderScaleway: - // Use any IP address that is found (including public ones) - for _, additionalIP := range apiserverAdditionalIPs { - bootConfig.APIServerIPs = append(bootConfig.APIServerIPs, additionalIP) - } + bootConfig.APIServerIPs = controlPlaneIPs case kops.CloudProviderGCE: - // Use any IP address that is found (including public ones) - for _, additionalIP := range apiserverAdditionalIPs { - bootConfig.APIServerIPs = append(bootConfig.APIServerIPs, additionalIP) - } + bootConfig.APIServerIPs = controlPlaneIPs + default: return nil, nil, fmt.Errorf("'none' DNS topology is not supported for cloud %q", cluster.Spec.GetCloudProvider()) } + } else { + // If we do have a fixed IP, we use it (on some clouds, initially) + switch cluster.Spec.GetCloudProvider() { + case kops.CloudProviderHetzner: + bootConfig.APIServerIPs = controlPlaneIPs + } } useConfigServer := apiModel.UseKopsControllerForNodeConfig(cluster) && !ig.HasAPIServer() if useConfigServer { hosts := []string{"kops-controller.internal." + cluster.ObjectMeta.Name} - if cluster.UsesNoneDNS() && len(bootConfig.APIServerIPs) > 0 { + if len(bootConfig.APIServerIPs) > 0 { hosts = bootConfig.APIServerIPs } + configServer := &nodeup.ConfigServerOptions{ CACertificates: config.CAs[fi.CertificateIDCA], }