Skip to content

gce: add support karpenter-managed Instance groups - #18628

Draft
hakman wants to merge 6 commits into
kubernetes:masterfrom
hakman:karpenter-gce
Draft

gce: add support karpenter-managed Instance groups#18628
hakman wants to merge 6 commits into
kubernetes:masterfrom
hakman:karpenter-gce

Conversation

@hakman

@hakman hakman commented Jul 26, 2026

Copy link
Copy Markdown
Member

This adds support for spec.manager: Karpenter on GCE node InstanceGroups, mirroring the existing AWS integration. It deploys karpenter-provider-gcp in its new self-hosted provisioning mode (cloudpilot-ai/karpenter-provider-gcp#540), where nodes bootstrap through the kOps nodeup script and the controller uses only the Compute API, with no GKE dependency.

For a Karpenter-managed InstanceGroup, kOps no longer creates an InstanceTemplate or MIG. Instead it publishes the IG's nodeup script to the state store and generates one GCENodeClass and one NodePool per InstanceGroup, delivered by the karpenter.sh addon and pruned when the IG is removed. The generated GCENodeClass carries the IG image, a boot disk from the rootVolume settings, kubeletConfiguration.maxPods matching the kubelet, the kOps ownership labels and instance group metadata, the node role network tag, the node service account, a Shielded VM config with vTPM enabled (required by the kops-controller TPM node authorization), and the nodeup script as startupScript. A kops update cluster that changes the IG's nodeup configuration updates the startupScript, and Karpenter then rolls that NodeClass's nodes through drift, matching the AWS userData behavior.

@kubernetes-prow

Copy link
Copy Markdown
Contributor

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@kubernetes-prow kubernetes-prow Bot added do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels Jul 26, 2026
@kubernetes-prow
kubernetes-prow Bot requested a review from olemarkus July 26, 2026 19:06
@kubernetes-prow

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign hakman 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

@kubernetes-prow
kubernetes-prow Bot requested a review from zetaab July 26, 2026 19:06
@kubernetes-prow kubernetes-prow Bot added area/api area/documentation area/provider/gcp Issues or PRs related to gcp provider labels Jul 26, 2026
@hakman
hakman force-pushed the karpenter-gce branch 2 times, most recently from 4164ad2 to c71f384 Compare July 26, 2026 19:19
hakman added 4 commits July 26, 2026 22:31
GCE label keys and values cannot contain "/", "." or ":", so rendering
cluster-autoscaler scale-from-zero taint hints as instance template labels
makes 'kops update cluster' fail for any GCE instance group that sets
spec.taints (for example a taint key like karpenter.sh/unregistered).

On GCE the cluster autoscaler reads scale-from-zero taints from
AUTOSCALER_ENV_VARS in the instance template's kube-env metadata, which
kOps already emits, so these labels were never consumed there. Skip them
on GCE, matching the existing handling of node label hints.
…ud groups)

Allow spec.manager=Karpenter on GCE instance groups:

- validation: accept GCE alongside AWS; keep the AMI selector checks and
  the IRSA requirement AWS-only (on GCE the controller uses the instance
  service account).
- gcemodel: for Karpenter instance groups, build only the bootstrap
  script tasks (which publish igconfig/node/<ig>/nodeupscript.sh and
  nodeupconfig.yaml to the state store) and skip the InstanceTemplate
  and InstanceGroupManager, mirroring the AWS model.
- populate spec: no default machine type for GCE Karpenter instance
  groups; without one the generated NodePool carries no instance-type
  requirement.
- components: default cluster.spec.karpenter.image to the
  karpenter-provider-gcp controller image on GCE.
- GetCloudGroups: synthesize a cloud instance group per Karpenter
  instance group, discovering instances by the kOps ownership labels
  the generated GCENodeClass applies, so 'kops validate cluster' and
  rolling-update see these nodes.

The karpenter.sh/unregistered:NoExecute registration taint and the
state-store script publication were already cloud-agnostic.
The GCE node identifier required MIG membership (via the created-by
metadata) to derive the owning instance group, so nodes launched
directly by Karpenter never received their role label or instance
group label ('cannot find owner for instance' in kops-controller logs).

When created-by is absent, derive ownership from the instance's own
kops-k8s-io-instance-group-name metadata after checking the exact
cluster-name metadata, mirroring the trust anchor already used by the
bootstrap TPM verifier: both values are read through the Compute API
and can only be changed with Compute API write permissions, which
nodes are not granted. MIG-managed instances keep the existing
membership-verified path.
…NodePool

On GCE clusters with spec.karpenter.enabled, the karpenter.sh addon now
deploys karpenter-provider-gcp in self-hosted mode (PROVISION_MODE,
PROJECT_ID, CLUSTER_LOCATION, CLUSTER_NAME) on the control plane, using
Application Default Credentials from the instance metadata server.

One GCENodeClass and one NodePool are generated per Karpenter instance
group, regenerated on every kops update cluster:

- imageSelectorTerms from the instance group image;
- boot disk from rootVolume settings with the MIG template defaults;
- kubeletConfiguration.maxPods matching the kubelet (default 110);
- the kOps ownership labels the MIG instance template would carry;
- kops-k8s-io-instance-group-name metadata (bootstrap and node
  identity ownership), the node role network tag, the node service
  account, vTPM enabled (required by the bootstrap TPM verifier);
- the instance group's nodeup script from the state store as
  startupScript, so a NodeupConfig change rolls nodes via drift.

The addon manifest is generated from the karpenter-provider-gcp Helm
chart via kustomize, mirroring the AWS pipeline; generated GCENodeClass
objects are pruned when their instance group is removed.

Self-hosted mode requires the karpenter-provider-gcp release containing
cloudpilot-ai/karpenter-provider-gcp#511; the manifest was generated
from that chart source and the pinned versions should be bumped to the
first release that includes it.
hakman added 2 commits July 26, 2026 22:48
…cumentation

TestMinimalGossipGCE's fixture gains spec.karpenter.enabled and two
Karpenter instance groups: one with a machine type and static capacity,
one without a machine type (dynamic, custom maxPods), reusing the
existing test rather than growing the GCE suite.
Generated with ./hack/update-expected.sh:

- gossip-gce now includes the karpenter.sh addon and the generated
  GCENodeClass/NodePool objects;
- ha_gce no longer renders the cluster-autoscaler taint hint as an
  instance template label.
@kubernetes-prow kubernetes-prow Bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jul 28, 2026
@kubernetes-prow

Copy link
Copy Markdown
Contributor

PR needs rebase.

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.

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

Labels

area/addons area/api area/documentation area/provider/gcp Issues or PRs related to gcp provider cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant