NodePool says which nodes are acceptable; EC2NodeClass says how AWS builds them.
That separation lets several pools share one infrastructure recipe, or one pool target different recipes.
NodePool (scheduling policy)
apiVersion: karpenter.sh/v1 kind: NodePool metadata: {name: general} spec: template: spec: requirements: - {key: karpenter.sh/capacity-type, operator: In, values: [spot, on-demand]} - {key: kubernetes.io/arch, operator: In, values: [amd64, arm64]} - {key: karpenter.k8s.aws/instance-category, operator: In, values: [c, m, r]} nodeClassRef: {group: karpenter.k8s.aws, kind: EC2NodeClass, name: default} expireAfter: 720h limits: {cpu: "1000"} disruption: {consolidationPolicy: WhenEmptyOrUnderutilized, consolidateAfter: 1m}
EC2NodeClass (infrastructure)
kind: EC2NodeClass metadata: {name: default} spec: amiSelectorTerms: [{alias: al2023@latest}] role: KarpenterNodeRole-shop-eu subnetSelectorTerms: [{tags: {karpenter.sh/discovery: shop-eu}}] securityGroupSelectorTerms: [{tags: {karpenter.sh/discovery: shop-eu}}]
Limits cap the bill
limits.cpu stops a runaway scale-up from launching unlimited nodes.
Check your version
Field names changed between Karpenter releases. This is the v1 API shape; confirm against the docs for your installed version.