Skip to content

feat(cluster): support regional Autopilot clusters in environments where the API only accepts region-level locations#2552

Open
jbrt wants to merge 1 commit into
terraform-google-modules:mainfrom
jbrt:feat/adds-support-of-regional-clusters-on-partner-clouds
Open

feat(cluster): support regional Autopilot clusters in environments where the API only accepts region-level locations#2552
jbrt wants to merge 1 commit into
terraform-google-modules:mainfrom
jbrt:feat/adds-support-of-regional-clusters-on-partner-clouds

Conversation

@jbrt
Copy link
Copy Markdown

@jbrt jbrt commented Mar 6, 2026

Support for GCP environments with region/zone API limitations

Why this change

Some GCP-like environments (sovereign or partner clouds) use a Container API that does not behave like standard GCP for regional clusters:

  1. Version lookup: The API may only accept region-level location for google_container_engine_versions. A zone-level lookup (e.g. u-france-east1-a) can return "Location does not exist".
  2. Cluster create: The API may accept the region as cluster location but reject explicit zone names in node_locations at create time (e.g. "Specified location is not a valid zone"). If we then send the same zones on a later apply, the API can report "Cluster location change not allowed" because it has already populated zones itself.

This PR keeps the module working for standard GCP and adds optional behaviour so it also works in those environments.

What we changed

1. Regional clusters: no zone-level version lookup

  • main.tf: data "google_container_engine_versions" "zone" is only created when var.regional is false (count = var.regional ? 0 : 1). For regional clusters we never call the API with a zone.
  • The version used for regional clusters is taken only from data.google_container_engine_versions.region; the existing master_version_* locals are adjusted so the zonal data source is used only when it exists.

When it matters: Use the module as today for standard GCP. In environments where the Container API accepts only region-level location for version lookup, regional clusters no longer fail on that data source.

2. Optional cluster location override

  • variables.tf: New optional variable cluster_location_override (string, default null).
  • main.tf: New locals cluster_location_input and use_zone_location. The cluster resource uses cluster_location_input for location; when the override is set to the first zone and regional = true, node_locations is set to the remaining zones so the cluster is created as zonal from the API’s point of view.

When it matters: If the API rejects a region as cluster location, callers can set cluster_location_override to an accepted value (e.g. a zone). No change required if you do not set it.

3. Optional empty node_locations for regional create (no drift)

  • variables.tf: New optional variable omit_node_locations_for_regional (bool, default false).
  • main.tf: When omit_node_locations_for_regional && regional, we set cluster_node_locations = []. A single local cluster_self points to the cluster resource that is actually created (see below). All existing outputs and internals use cluster_self so the rest of the module is unchanged.
  • cluster.tf: We use two cluster resources with opposite count:
    • primary: created when omit_node_locations_for_regional is false; uses explicit node_locations as before.
    • primary_omit_nodelocs: created when omit_node_locations_for_regional is true; sets node_locations = [] so the API accepts create, and lifecycle { ignore_changes = [node_locations] } so we never try to update the API-populated zones. That avoids drift and allows destroy/recreate (recreate again sends []).
  • outputs.tf and firewall.tf: All references to the cluster use local.cluster_self; outputs’ depends_on list both resources so dependency order is correct.

When it matters: In environments where the API accepts the region as location but rejects explicit zones at create, set omit_node_locations_for_regional = true. Create succeeds with node_locations = []; the API fills zones; we do not touch node_locations again, so no drift and destroy/recreate works.

Backward compatibility

  • No breaking changes: Existing callers do not need to change anything. Both new variables default to null / false.
  • Regional clusters: Version still comes from region-level lookup; we simply skip the zone-level data source when regional = true.
  • Zonal clusters: Unchanged; zone data source and explicit node_locations behaviour are unchanged.
  • Cluster resources: When omit_node_locations_for_regional is false, only primary is created (count=1), as today. When true, only primary_omit_nodelocs is created. Outputs and behaviour are the same from the caller’s perspective.

Documentation

  • modules/beta-autopilot-private-cluster/README.md: "Kubernetes version lookup" and "Cluster location override" sections describe the new behaviour and when to use the new variables.
  • Variable descriptions in variables.tf explain cluster_location_override and omit_node_locations_for_regional.

Testing

  • Standard GCP: No new variables → behaviour unchanged; primary is used; zone data source still created for zonal clusters.
  • Regional with omit: Set omit_node_locations_for_regional = true and regional = true → only primary_omit_nodelocs is created; create/apply/destroy and destroy+recreate should succeed in environments that require this path.

Existing tests that use regional or zonal clusters should pass without modification.

…ere the API only accepts region-level locations
@google-cla
Copy link
Copy Markdown

google-cla Bot commented Mar 6, 2026

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the GKE Autopilot cluster module to support deployment in GCP-like environments that have specific API constraints regarding regional clusters. It addresses issues where the Container API might only accept region-level locations for version lookups or reject explicit zone names during cluster creation. The changes introduce flexible configuration options to adapt to these environments while maintaining compatibility with standard GCP.

Highlights

  • Regional Cluster API Compatibility: Introduced support for regional GKE Autopilot clusters in environments where the Container API only accepts region-level locations for version lookups or rejects explicit zone names during cluster creation.
  • Conditional Kubernetes Version Lookup: Modified the Kubernetes version lookup logic for regional clusters to exclusively perform region-level lookups, bypassing zone-level API calls that might fail in specific environments.
  • Flexible Cluster Location Configuration: Added an optional cluster_location_override variable, allowing users to specify an alternative cluster location (e.g., a zone instead of a region) when the API requires it.
  • Handling Node Location API Constraints: Implemented an optional omit_node_locations_for_regional variable and a new conditional cluster resource variant to manage scenarios where the API rejects explicit node_locations during regional cluster creation, enabling the API to auto-populate them without causing Terraform drift.
Changelog
  • autogen/main/README.md
    • Added a new section detailing Kubernetes version lookup behavior for regional and zonal clusters.
  • autogen/main/cluster.tf.tmpl
    • Updated the location and node_locations attributes to utilize new local variables for increased flexibility.
  • autogen/main/main.tf.tmpl
    • Introduced new local variables (cluster_location_input, use_zone_location, cluster_node_locations) to conditionally manage cluster and node locations.
    • Modified the master_version_zonal local to conditionally use the regional master version for regional clusters, avoiding unnecessary zone-level lookups.
    • Applied a count argument to the google_container_engine_versions.zone data source, making its creation conditional based on the regional variable.
  • autogen/main/variables.tf.tmpl
    • Added a new cluster_location_override variable (string, default null) for overriding the cluster's location.
    • Added a new omit_node_locations_for_regional variable (bool, default false) to control node_locations behavior for regional clusters.
  • main.tf
    • Modified the master_version_zonal local to conditionally use the regional master version for regional clusters.
    • Applied a count argument to the google_container_engine_versions.zone data source, making its creation conditional based on the regional variable.
  • modules/beta-autopilot-private-cluster/README.md
    • Added new documentation sections for 'Kubernetes version lookup' and 'Cluster location override'.
  • modules/beta-autopilot-private-cluster/cluster.tf
    • Introduced a new google_container_cluster.primary_omit_nodelocs resource with node_locations=[] and lifecycle { ignore_changes = [node_locations] } for specific regional cluster scenarios.
    • Made the original google_container_cluster.primary resource conditional, ensuring only one cluster resource is created based on omit_node_locations_for_regional and regional variables.
    • Updated location and node_locations attributes to reference new local variables cluster_location_input and cluster_node_locations.
  • modules/beta-autopilot-private-cluster/firewall.tf
    • Updated destination_ranges to reference local.cluster_self.tpu_ipv4_cidr_block, ensuring it points to the active cluster resource.
  • modules/beta-autopilot-private-cluster/main.tf
    • Introduced new local variables (cluster_location_input, use_zone_location, cluster_node_locations, cluster_self) for dynamic cluster configuration.
    • Modified the master_version_zonal local to conditionally use the regional master version for regional clusters.
    • Updated various references from google_container_cluster.primary to local.cluster_self to dynamically select the correct cluster resource.
    • Applied a count argument to the google_container_engine_versions.zone data source, making its creation conditional based on the regional variable.
  • modules/beta-autopilot-private-cluster/outputs.tf
    • Updated depends_on for name, endpoint, and endpoint_dns outputs to include both google_container_cluster.primary and google_container_cluster.primary_omit_nodelocs.
    • Updated endpoint_dns, master_authorized_networks_config, tpu_ipv4_cidr_block, and master_ipv4_cidr_block outputs to reference local.cluster_self.
  • modules/beta-autopilot-private-cluster/variables.tf
    • Added a new cluster_location_override variable (string, default null) for overriding the cluster's location.
    • Added a new omit_node_locations_for_regional variable (bool, default false) to control node_locations behavior for regional clusters.
  • modules/beta-autopilot-public-cluster/main.tf
    • Modified the master_version_zonal local to conditionally use the regional master version for regional clusters.
    • Applied a count argument to the google_container_engine_versions.zone data source, making its creation conditional based on the regional variable.
  • modules/beta-private-cluster-update-variant/main.tf
    • Modified the master_version_zonal local to conditionally use the regional master version for regional clusters.
    • Applied a count argument to the google_container_engine_versions.zone data source, making its creation conditional based on the regional variable.
  • modules/beta-private-cluster/main.tf
    • Modified the master_version_zonal local to conditionally use the regional master version for regional clusters.
    • Applied a count argument to the google_container_engine_versions.zone data source, making its creation conditional based on the regional variable.
  • modules/beta-public-cluster-update-variant/main.tf
    • Modified the master_version_zonal local to conditionally use the regional master version for regional clusters.
    • Applied a count argument to the google_container_engine_versions.zone data source, making its creation conditional based on the regional variable.
  • modules/beta-public-cluster/main.tf
    • Modified the master_version_zonal local to conditionally use the regional master version for regional clusters.
    • Applied a count argument to the google_container_engine_versions.zone data source, making its creation conditional based on the regional variable.
  • modules/private-cluster-update-variant/main.tf
    • Modified the master_version_zonal local to conditionally use the regional master version for regional clusters.
    • Applied a count argument to the google_container_engine_versions.zone data source, making its creation conditional based on the regional variable.
  • modules/private-cluster/main.tf
    • Modified the master_version_zonal local to conditionally use the regional master version for regional clusters.
    • Applied a count argument to the google_container_engine_versions.zone data source, making its creation conditional based on the regional variable.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for regional Autopilot clusters in environments with specific API limitations by introducing new optional variables and logic. It also standardizes the GKE version lookup for regional clusters across multiple modules. The changes are well-documented.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 5, 2026

This PR is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days

@github-actions github-actions Bot added the Stale label May 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant