Skip to content

Stop GCPManagedNodePool scaling being blocked by multiple factors#1657

Open
jonathanrainer wants to merge 5 commits into
kubernetes-sigs:mainfrom
jonathanrainer:fix/gcpmanagedmachinepool-scaling-blocked
Open

Stop GCPManagedNodePool scaling being blocked by multiple factors#1657
jonathanrainer wants to merge 5 commits into
kubernetes-sigs:mainfrom
jonathanrainer:fix/gcpmanagedmachinepool-scaling-blocked

Conversation

@jonathanrainer

Copy link
Copy Markdown
Contributor

What type of PR is this?
/kind bug

What this PR does / why we need it:
This PR tackles the 4 bugs that are listed out in #1656 which prevent manual MachinePool scaling from working with a GCPManagedNodePool. Namely:

  1. Add a nil guard to the Autoscaling check - This means that nodepools that don't have an Autoscaling config won't return early, so manual scaling can occur
  2. Add a nil guard to LinuxNodeConfig - This means that LinuxNodeConfig is only compared when it's set, rather than comparing a non-nil empty struct generated by ConvertToSdkLinuxNodeConfig to the nil that GKE returns
  3. Sync AdditionalLabels via the InstanceTemplate not the NodePool - The NodePool object doesn't have a labels attribute on it, so instead of that we create an InstanceTemplate client, look up the template that's relevant and check the labels we're setting are correctly set there, and rely on GKE to propagate those into the nodes themselves.
  4. Run all three checks (checkDiffAndPrepareUpdateSize, checkDiffAndPrepareUpdateAutoscaling, checkDiffAndPrepareUpdateConfig) before any update is applied - This means the current behaviour where updates are run sequentially and there's an early exit (and in turn causes size updates to be starved because of (3)), doesn't happen anymore. Updates are all checked and then run in priority order (size -> autoscaling -> general).

Which issue(s) this PR fixes (optional, in fixes #<issue number>(, fixes #<issue_number>, ...) format, will close the issue(s) when PR gets merged):
Fixes #1656

Special notes for your reviewer:
I've verified as much of this as I can on my own cluster, particularly the additionalLabels checks, but I also appreciate there's an alternative approach where you could fetch the Instances themselves and check, and I'm happy to pivot to that approach if we think that's demonstrably better.

Please confirm that if this PR changes any image versions, then that's the sole change this PR makes.

TODOs:

  • squashed commits
  • includes documentation
  • adds unit tests

Release note:

Ensure that GCPManagedNodePool scaling always works and improve how labels are synced to NodePools

@k8s-ci-robot k8s-ci-robot added release-note Denotes a PR that will be considered when it comes time to generate release notes. kind/bug Categorizes issue or PR as related to a bug. labels May 7, 2026
@netlify

netlify Bot commented May 7, 2026

Copy link
Copy Markdown

Deploy Preview for kubernetes-sigs-cluster-api-gcp ready!

Name Link
🔨 Latest commit f3e7bac
🔍 Latest deploy log https://app.netlify.com/projects/kubernetes-sigs-cluster-api-gcp/deploys/6a46d8524b4257000870eb6f
😎 Deploy Preview https://deploy-preview-1657--kubernetes-sigs-cluster-api-gcp.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@k8s-ci-robot

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: jonathanrainer
Once this PR has been reviewed and has the lgtm label, please assign damdo for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot requested review from damdo and dims May 7, 2026 06:21
@k8s-ci-robot k8s-ci-robot added needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. labels May 7, 2026
@k8s-ci-robot

Copy link
Copy Markdown
Contributor

Hi @jonathanrainer. Thanks for your PR.

I'm waiting for a kubernetes-sigs member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work.

Tip

We noticed you've done this a few times! Consider joining the org to skip this step and gain /lgtm and other bot rights. We recommend asking approvers on your previous PRs to sponsor you.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@k8s-ci-robot k8s-ci-robot added the size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. label May 7, 2026
@jonathanrainer jonathanrainer force-pushed the fix/gcpmanagedmachinepool-scaling-blocked branch from 28c76df to 4b12c02 Compare May 28, 2026 13:17
@jonathanrainer jonathanrainer force-pushed the fix/gcpmanagedmachinepool-scaling-blocked branch from 4b12c02 to 1b58050 Compare June 6, 2026 10:15

@salasberryfin salasberryfin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

/ok-to-test

@k8s-ci-robot k8s-ci-robot added ok-to-test Indicates a non-member PR verified by an org member that is safe to test. and removed needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. labels Jun 11, 2026
@jonathanrainer jonathanrainer force-pushed the fix/gcpmanagedmachinepool-scaling-blocked branch from 1b58050 to 0800f21 Compare June 11, 2026 14:10
ConvertToSdkAutoscaling returns {Enabled: true} when passed nil, causing
checkDiffAndPrepareUpdateSize to unconditionally suppress manual scaling
for any node pool that has no Spec.Scaling block. Guard the check on
Spec.Scaling being non-nil so only explicitly-configured autoscaling
suppresses size updates.
ConvertToSdkLinuxNodeConfig returns a non-nil pointer even when passed
nil, so comparing it against the nil value GKE returns in GetNodePool for
unconfigured pools always produces a diff and triggers a spurious update.
Guard the comparison on Spec.LinuxNodeConfig being non-nil.
GKE does not return NodeConfig.ResourceLabels in GetNodePool responses,
so comparing desiredNodePool.ResourceLabels against the existing value
always produces a diff (existing is always nil) and triggers a perpetual
UpdateNodePool loop that blocks all other reconcile operations.

Fix the comparison by reading labels from the node pool's instance
template (properties.labels), which is the authoritative source GKE uses
to stamp labels onto every node in the pool. This requires one additional
Get call per reconcile cycle: InstanceGroupManagersClient.Get() to
resolve the template URL, then InstanceTemplatesClient.Get() to read the
template properties. A new InstanceTemplatesClient is added to the scope
following the same pattern as InstanceGroupManagersClient.

The comparison is a subset check — all desired labels must be present
with the correct value; GKE-internal labels on the template are ignored
to avoid spurious updates.
…starvation

The original loop ran checks sequentially with an early return on the first
positive result (config → autoscaling → size). Any persistent config diff
would trigger a config update and return, meaning size and autoscaling
checks never ran in that cycle. After the config update GKE enters
RECONCILING state, causing the next cycle to return early too, so scaling
changes via MachinePool.spec.replicas had no effect.

Run all three checks unconditionally before applying any update, then
apply in priority order: size (user-initiated scaling, most time-sensitive)
→ autoscaling config → general config. GKE still only allows one
concurrent operation per node pool, so we apply one per cycle and requeue
for any remaining work.
Table-driven tests for checkDiffAndPrepareUpdateConfig and
checkDiffAndPrepareUpdateSize covering the cases fixed in the preceding
commits: resource label sync via instance template (present, missing,
unavailable), Kubernetes label diff, image type case-insensitive match,
network tags, node locations, autoscaling suppression, nil Scaling guard,
and regional cluster replica division.
@jonathanrainer jonathanrainer force-pushed the fix/gcpmanagedmachinepool-scaling-blocked branch from 0800f21 to f3e7bac Compare July 2, 2026 21:29
@kubernetes-prow

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: jonathanrainer
Once this PR has been reviewed and has the lgtm label, please assign damdo for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@jonathanrainer

Copy link
Copy Markdown
Contributor Author

/retest

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. kind/bug Categorizes issue or PR as related to a bug. ok-to-test Indicates a non-member PR verified by an org member that is safe to test. release-note Denotes a PR that will be considered when it comes time to generate release notes. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GCPManagedMachinePool scaling via MachinePool.spec.replicas is silently ignored

3 participants