Description
Hi! We ran into an issue during a migration from spec.instanceProfile to spec.role on an EC2NodeClass. After the switch, karpenter continued using the old static instance profile instead of creating a dynamic one. This affected all newly-launched nodes, including drift replacements.
We traced it through the source and believe we understand the mechanism — writing it up here in case it's helpful.
Version
v1.8.6
What We Observed
- EC2NodeClass originally had
spec.instanceProfile: OurStaticProfile (with role OurNodeRole attached)
- Changed to
spec.role: OurNodeRole (removed spec.instanceProfile)
- Karpenter detected drift on existing NodeClaims (hash changed) — correct
- Replacement nodes were launched with the old static profile, not a new dynamic one
status.instanceProfile continued to show the old static profile name
- Restarting karpenter didn't help — same behavior
- Only when we deleted the static profile from IAM did karpenter create a dynamic profile
What We Think Is Happening
In pkg/controllers/nodeclass/instanceprofile.go, when spec.role is set:
status.instanceProfile still holds the old static profile name from the spec.instanceProfile era
- The reconciler calls
GetInstanceProfile() on it — the profile exists and has the correct role attached
currentRole != nodeClass.Spec.Role evaluates to false, so the reconciler skips creating a dynamic profile
- Launch templates read from
status.instanceProfile, so all new nodes get the old static profile
The reconciler checks whether the attached role matches, but doesn't distinguish between karpenter-managed profiles (under the /karpenter/ IAM path) and user-provided static ones.
Steps to Reproduce
- Create a static IAM instance profile with a role (e.g.,
MyStaticProfile with MyNodeRole)
- Create an EC2NodeClass with
spec.instanceProfile: MyStaticProfile
- Let karpenter launch nodes — they use
MyStaticProfile correctly
- Change the EC2NodeClass to
spec.role: MyNodeRole (remove spec.instanceProfile)
- Karpenter detects drift, launches replacements — replacements still use
MyStaticProfile
- Delete
MyStaticProfile from IAM — karpenter now creates a dynamic profile
Reproduced on a dev cluster (2026-03-23).
Impact
In our case, the old static profile was later deleted via Terraform, which caused nodes to lose IMDS credentials. STS credential caching delayed the visible impact by several hours.
Possible Fix
One approach might be to check whether the profile in status.instanceProfile is karpenter-managed (e.g., by IAM path prefix) when spec.role is set. If it's a static/user-provided profile, the reconciler could create a new dynamic one regardless of whether the role matches.
Description
Hi! We ran into an issue during a migration from
spec.instanceProfiletospec.roleon an EC2NodeClass. After the switch, karpenter continued using the old static instance profile instead of creating a dynamic one. This affected all newly-launched nodes, including drift replacements.We traced it through the source and believe we understand the mechanism — writing it up here in case it's helpful.
Version
v1.8.6
What We Observed
spec.instanceProfile: OurStaticProfile(with roleOurNodeRoleattached)spec.role: OurNodeRole(removedspec.instanceProfile)status.instanceProfilecontinued to show the old static profile nameWhat We Think Is Happening
In
pkg/controllers/nodeclass/instanceprofile.go, whenspec.roleis set:status.instanceProfilestill holds the old static profile name from thespec.instanceProfileeraGetInstanceProfile()on it — the profile exists and has the correct role attachedcurrentRole != nodeClass.Spec.Roleevaluates to false, so the reconciler skips creating a dynamic profilestatus.instanceProfile, so all new nodes get the old static profileThe reconciler checks whether the attached role matches, but doesn't distinguish between karpenter-managed profiles (under the
/karpenter/IAM path) and user-provided static ones.Steps to Reproduce
MyStaticProfilewithMyNodeRole)spec.instanceProfile: MyStaticProfileMyStaticProfilecorrectlyspec.role: MyNodeRole(removespec.instanceProfile)MyStaticProfileMyStaticProfilefrom IAM — karpenter now creates a dynamic profileReproduced on a dev cluster (2026-03-23).
Impact
In our case, the old static profile was later deleted via Terraform, which caused nodes to lose IMDS credentials. STS credential caching delayed the visible impact by several hours.
Possible Fix
One approach might be to check whether the profile in
status.instanceProfileis karpenter-managed (e.g., by IAM path prefix) whenspec.roleis set. If it's a static/user-provided profile, the reconciler could create a new dynamic one regardless of whether the role matches.