{"record":{"id":"620fd9e7543ed775","repo":"kubernetes/kops","slug":"hetzner-cloud-provider-currently-supports-only-one","errorCode":null,"errorMessage":"hetzner cloud provider currently supports only one zone (location)","messagePattern":"hetzner cloud provider currently supports only one zone \\(location\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/new_cluster.go","lineNumber":811,"sourceCode":"\n\t\t// For Akamai (Linode) we pass regions via --zones.\n\t\tregion := opt.Zones[0]\n\t\tsubnet := model.FindSubnet(cluster, region)\n\n\t\tif subnet == nil {\n\t\t\tsubnet = &api.ClusterSubnetSpec{\n\t\t\t\tName:   region,\n\t\t\t\tRegion: region,\n\t\t\t\tZone:   region,\n\t\t\t}\n\t\t\tcluster.Spec.Networking.Subnets = append(cluster.Spec.Networking.Subnets, *subnet)\n\t\t}\n\t\tzoneToSubnetsMap[region] = append(zoneToSubnetsMap[region], subnet)\n\t\treturn zoneToSubnetsMap, nil\n\n\tcase api.CloudProviderHetzner:\n\t\tif len(opt.Zones) > 1 {\n\t\t\treturn nil, fmt.Errorf(\"hetzner cloud provider currently supports only one zone (location)\")\n\t\t}\n\t\t// TODO(hakman): Add customizations for Hetzner Cloud\n\n\tcase api.CloudProviderAzure:\n\t\t// On Azure, subnets are regional - we create one per region, not per zone\n\t\tfor _, zoneName := range allZones.List() {\n\t\t\tlocation, err := azure.ZoneToLocation(zoneName)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\t\t// We create default subnets named the same as the cluster\n\t\t\tsubnetName := cluster.Name\n\n\t\t\tsubnet := model.FindSubnet(cluster, subnetName)\n\t\t\tif subnet == nil {\n\t\t\t\tsubnet = &api.ClusterSubnetSpec{\n\t\t\t\t\tName:   subnetName,","sourceCodeStart":793,"sourceCodeEnd":829,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/new_cluster.go#L793-L829","documentation":"During `kops create cluster`, setupZones validates the requested --zones list per cloud provider. Hetzner Cloud locations are the unit of deployment and kOps currently models a Hetzner cluster as living in exactly one zone (location). If more than one zone is passed, this error is returned to abort cluster creation rather than silently creating a misconfigured multi-location cluster.","triggerScenarios":"Running `kops create cluster --cloud hetzner --zones fsn1,hel1 ...` (or any --zones value containing a comma, producing >1 zone) while targeting CloudProviderHetzner.","commonSituations":"Users coming from AWS/GCP habitually pass multiple zones for HA; copy-pasted commands from AWS docs; scripts that build the --zones flag dynamically and add a second location for Hetzner.","solutions":["Pass exactly one Hetzner location, e.g. --zones fsn1 (valid: fsn1, nbg1, hel1, ash, hil).","Remove the extra zones from the --zones flag or the cluster spec's subnets/zones list.","If multi-AZ HA is required, choose a provider that supports multiple zones (AWS, GCE, Azure) instead of Hetzner."],"exampleFix":"// before\nkops create cluster --cloud hetzner --zones fsn1,hel1 mycluster.k8s.local\n// after\nkops create cluster --cloud hetzner --zones fsn1 mycluster.k8s.local","handlingStrategy":"validation","validationCode":"zones := strings.Split(*zonesFlag, \",\")\nif cloud == \"hetzner\" && len(zones) > 1 {\n    return fmt.Errorf(\"hetzner supports exactly one zone; got %q\", zones)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Hardcode the single --zones value for Hetzner clusters in scripts/templates.","Split comma-joined zone strings and assert len==1 before invoking kops.","Document the Hetzner one-location limitation wherever multi-zone flags are templated."],"tags":["hetzner","zones","cluster-creation","validation"],"backgroundTag":"single-zone-provider-limit","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}