Skip to content

feat: add CPU options with nested virtualization and instance-type filtering#9043

Open
windsornguyen wants to merge 3 commits intoaws:mainfrom
windsornguyen:feat/cpu-options-nested-virt
Open

feat: add CPU options with nested virtualization and instance-type filtering#9043
windsornguyen wants to merge 3 commits intoaws:mainfrom
windsornguyen:feat/cpu-options-nested-virt

Conversation

@windsornguyen
Copy link
Copy Markdown

Fixes #8966

Description

Adds cpuOptions to EC2NodeClassSpec with coreCount, threadsPerCore, and nestedVirtualization fields. Builds on the plumbing from #8971 (co-authored with @salla2) and adds three production-hardened fixes discovered while running this in a vendored snapshot:

  1. Instance-type filtering: New NestedVirtualizationFilter that rejects instance types lacking nested-virtualization in ProcessorInfo.SupportedFeatures from DescribeInstanceTypes. A new well-known label karpenter.k8s.aws/instance-nested-virtualization is populated during instance type resolution. Today only *8i* families (c8i, m8i, r8i and flex variants) report this feature.

  2. CEL mutual exclusion: nestedVirtualization: enabled cannot be combined with coreCount or threadsPerCore (EC2 rejects this combination at the API level).

  3. Error caching: UnsupportedOperation added to unfulfillableCapacityErrorCodes so launches against incompatible types are cached instead of retried.

RFC included in designs/cpu-options-nested-virtualization.md per @AndrewMitchell25's request.

Verified across 5 AWS regions (us-east-1, us-west-2, eu-west-1, ap-southeast-1, ap-northeast-1) that ProcessorInfo.SupportedFeatures correctly identifies supported types.

How was this change tested?

  • Unit tests for cpuOptions() converter (5 tests)
  • Ginkgo tests for NestedVirtualizationFilter (4 tests)
  • go build ./pkg/... and go vet ./pkg/... pass
  • Production-validated in a vendored snapshot running on EKS with Graviton system nodes and m8i workspace nodes

Does this change impact docs?

  • Yes, PR includes docs updates
  • Yes, issue opened: #
  • No

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

Satya Alla and others added 3 commits March 30, 2026 18:38
- Add CPUOptions struct to EC2NodeClassSpec with coreCount, threadsPerCore, and nestedVirtualization fields
- Integrate CPU options into launch template creation pipeline
- Add comprehensive validation tests for CPU options
- Add integration test for end-to-end CPU options verification
- Add documentation and usage examples
- Addresses issue aws#8966: Support enabling Nested Virtualization in CPU options
- Uncomment NestedVirtualization field in cpuOptions function
- Remove comment lines indicating AWS SDK doesn't support it
…ltering

Add CPUOptions struct to EC2NodeClassSpec with coreCount, threadsPerCore,
and nestedVirtualization fields. Integrate into the launch template pipeline
and add instance-type filtering based on ProcessorInfo.SupportedFeatures
from DescribeInstanceTypes.

Key changes:
- CPUOptions API with CEL validation (nestedVirtualization mutually
  exclusive with coreCount/threadsPerCore)
- New karpenter.k8s.aws/instance-nested-virtualization label populated
  from EC2 ProcessorInfo.SupportedFeatures
- NestedVirtualizationFilter rejects instance types lacking the feature
- UnsupportedOperation added to unfulfillable capacity error codes
- cpuOptions() converter returns nil for empty struct to avoid sending
  empty CpuOptions to EC2
- RFC in designs/

Fixes aws#8966

Co-authored-by: Satya Alla <satya.alla@walmart.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 2, 2026

Preview deployment ready!

Preview URL: https://pr-9043.d18coufmbnnaag.amplifyapp.com

Built from commit 43fbebc2aaa20da77ccb3fc39c42588af97fb74d

Copy link
Copy Markdown
Contributor

@jmdeal jmdeal left a comment

Choose a reason for hiding this comment

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

I didn't go deep into the implementation since I had some high-level comments on the design. Let me know if you have any questions.

Comment on lines +44 to +45
CoreCount *int32 `json:"coreCount,omitempty"`
ThreadsPerCore *int32 `json:"threadsPerCore,omitempty"`
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.

Is support for coreCount and threadsPerCore a requirement for this integration? I think there's room for integration with these features in Karpenter, but it adds additional design ambiguity that nested virtualization doesn't necessarily have.

A straightforward implementation of these two features would filter out instances which don't support the configured values (we should do this if we go forward with it). The downside of this approach is that it severely restricts the diversity of NodePools. We may want to introduce a way to dynamically scale or select these values based on the selected instance type that way we can retain NodePool diversity. Nested virtualization doesn't have the same concern because it's on or off. Additionally, you likely don't want or need to mix instance types with nested virtualization enabled in the same NodePool.

Comment on lines +55 to +58
A new well-known label `karpenter.k8s.aws/instance-nested-virtualization` is populated
from `ProcessorInfo.SupportedFeatures` during instance type resolution. Instance types
that report `nested-virtualization` in their supported features receive the label value
`"true"`.
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.

If we include a label, I don't think we want to set it to true just because an instance is compatible with nested virtualization. It should only be true if the feature is actually enabled. You can imagine that application owners may configure their pods with a label selector like karpenter.k8s.aws/instance-nested-virtualization IN 'true' and expect it to land on a node with nested virtualization enabled, not just a node that's capable of having it enabled.

CEL validation enforces that `nestedVirtualization: enabled` cannot be combined with
`coreCount` or `threadsPerCore` (EC2 rejects the combination).

### Instance Type Label
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.

I don't know if we want to include a label unless we use that label to drive the configuration of the instance. This would be consistent with other features, such as instance-tenancy. For that feature, the label can take on two values (default or dedicated) and each instance type is compatible with both. If a NodeClaim is compatible with both we'll use default, but if it's only compatible with dedicated we'll use dedicated. This behavior gives customers increased flexibility - they can have a lightly-constrained NodePool and use pods requirements to drive configuration, or they can enforce a setting via a NodePool requirement. At that point adding the configuration surface on the NodeClass is technically optional, but there is value in including it since the NodeClass is often considered a more privileged resource owned by cluster administrators.

These are the options in my order of preference. I heavily lean towards 1 or 2, though all three options have precedent in the project.

  1. No label, only NodeClass configuration (applications can select via NodePool / NodeClass labels). Label based selection can be added in the future based on presented real-world use-cases.
  2. Both label and NodeClass configuration
  3. No NodeClass configuration, only label-based configuration

empty `CpuOptions` block in the API call). The `NestedVirtualization` string is cast to
the SDK enum type `ec2types.NestedVirtualizationSpecification`.

### Error Handling
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.

I agree with this approach since it ensures we'll always be able to make provisioning progress, but is this just defensive or are there existing gaps in the filter that you're aware of?

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.

Let's continue to use ginkgo for all tests.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature: Support enabling Nested Virtualization in CPU options

2 participants