Skip to main content

AWSNodeClass API Reference

The AWSNodeClass resource is a cluster-scoped custom resource that defines AWS EC2 configuration for nodes managed by Stratos NodePools. This resource follows the Karpenter pattern of separating cloud-specific configuration from pool management, enabling reusability and independent schema evolution per cloud provider.

Overview

AWSNodeClass decouples AWS-specific instance configuration from NodePool resources:

  • NodePool: Defines pool sizing, scaling behavior, and node template (labels, taints)
  • AWSNodeClass: Defines AWS EC2 configuration (instance type, AMI, networking, IAM)

This separation allows:

  • Multiple NodePools to share the same EC2 configuration
  • Independent updates to pool sizing vs. instance configuration
  • Clean path to multi-cloud support (GCPNodeClass, AzureNodeClass)

Resource Definition

apiVersion: stratos.sh/v1alpha1
kind: AWSNodeClass
metadata:
name: <nodeclass-name>
spec:
region: <string>
instanceType: <string>
ami: <string>
subnetIds: <[]string>
securityGroupIds: <[]string>
iamInstanceProfile: <string>
userData: <string>
blockDeviceMappings: <[]BlockDeviceMapping>
tags: <map[string]string>
status:
nodePoolCount: <int32>
conditions: <[]Condition>

Spec Fields

Required Fields

FieldTypeDescription
instanceTypestringEC2 instance type (e.g., m5.large, c5.xlarge, m8g.large).
amistringAmazon Machine Image ID. Must match pattern ^ami-[a-z0-9]+$. Use EKS-optimized AMIs for EKS clusters.
subnetIds[]stringList of subnet IDs for instance placement. Instances are distributed round-robin across subnets for AZ distribution. Minimum 1 required.
securityGroupIds[]stringList of security group IDs to attach to instances. Minimum 1 required.
iamInstanceProfilestringIAM instance profile ARN or name. The profile must have permissions to join the Kubernetes cluster.

Optional Fields

FieldTypeDefaultDescription
regionstringController regionAWS region for launching instances (e.g., us-east-1). Defaults to the region where the controller is running.
userDatastring-User data script. For AL2/AL2023, this is a shell script. For Bottlerocket, this is TOML configuration. Not base64 encoded - Stratos handles encoding.
blockDeviceMappings[]BlockDeviceMapping-EBS volume configuration. See Block Device Mapping below.
tagsmap[string]string-Additional tags to apply to instances. Stratos management tags (managed-by, stratos.sh/pool, etc.) are added automatically.

Block Device Mapping

FieldTypeRequiredDefaultDescription
deviceNamestringYes-Device name (e.g., /dev/xvda, /dev/xvdb).
volumeSizeint32Yes-Volume size in GiB. Minimum: 1.
volumeTypestringYes-EBS volume type: gp3, gp2, io1, io2.
encryptedboolNofalseEnable EBS encryption.
iopsint32No-IOPS for io1/io2 volumes, or provisioned IOPS for gp3.
throughputint32No-Throughput in MB/s for gp3 volumes.

Status Fields

The AWSNodeClass status is updated by the controller:

FieldTypeDescription
nodePoolCountint32Number of NodePools currently referencing this AWSNodeClass.
conditions[]ConditionCurrent conditions (Valid, InUse).

Conditions

ConditionDescription
ValidThe AWSNodeClass spec is valid (AMI exists, networking configured correctly).
InUseThe AWSNodeClass is referenced by one or more NodePools.

Lifecycle Management

Deletion Protection

AWSNodeClass uses a finalizer (stratos.sh/in-use) to prevent deletion while referenced by NodePools. You must delete all referencing NodePools before deleting an AWSNodeClass.

# This will fail if NodePools reference it
kubectl delete awsnodeclass my-nodeclass

# Check which NodePools reference it
kubectl get nodepools -o json | jq '.items[] | select(.spec.template.nodeClassRef.name == "my-nodeclass") | .metadata.name'

# Delete the NodePools first, then the AWSNodeClass
kubectl delete nodepool my-pool
kubectl delete awsnodeclass my-nodeclass

Reference from NodePool

NodePools reference AWSNodeClass via spec.template.nodeClassRef:

apiVersion: stratos.sh/v1alpha1
kind: NodePool
metadata:
name: workers
spec:
poolSize: 10
minStandby: 3
template:
nodeClassRef:
kind: AWSNodeClass
name: standard-nodes # References AWSNodeClass by name
labels:
stratos.sh/pool: workers

Examples

Amazon Linux 2023 (AL2023)

awsnodeclass-al2023.yaml
apiVersion: stratos.sh/v1alpha1
kind: AWSNodeClass
metadata:
name: al2023-standard
spec:
region: us-east-1
instanceType: m8g.large # ARM64 for AL2023 ARM64 AMI

# AL2023 ARM64 AMI (EKS 1.34)
# aws ssm get-parameter --name /aws/service/eks/optimized-ami/1.34/amazon-linux-2023/arm64/standard/recommended/image_id
ami: ami-00171c2155dff951e

subnetIds:
- subnet-12345678
- subnet-87654321
securityGroupIds:
- sg-12345678
iamInstanceProfile: arn:aws:iam::123456789012:instance-profile/eks-node-role

blockDeviceMappings:
- deviceName: /dev/xvda
volumeSize: 20
volumeType: gp3
encrypted: true

tags:
Environment: production
OS: al2023
Architecture: arm64

# AL2023 uses nodeadm with MIME multipart user data
userData: |
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="BOUNDARY"

--BOUNDARY
Content-Type: application/node.eks.aws

---
apiVersion: node.eks.aws/v1alpha1
kind: NodeConfig
spec:
cluster:
name: my-cluster
apiServerEndpoint: https://ABCDEF.gr7.us-east-1.eks.amazonaws.com
certificateAuthority: LS0tLS1CRUdJTi...
cidr: 10.100.0.0/16
kubelet:
flags:
- --register-with-taints=node.eks.amazonaws.com/not-ready=true:NoSchedule

--BOUNDARY
Content-Type: text/x-shellscript; charset="us-ascii"

#!/bin/bash
# Wait for kubelet, then poweroff for Stratos standby
(
until curl -sf http://localhost:10248/healthz; do sleep 5; done
sleep 30
poweroff
) &> /var/log/stratos-warmup.log &

--BOUNDARY--

Bottlerocket

awsnodeclass-bottlerocket.yaml
apiVersion: stratos.sh/v1alpha1
kind: AWSNodeClass
metadata:
name: bottlerocket-standard
spec:
region: us-east-1
instanceType: m5.large

# Bottlerocket x86_64 AMI (EKS 1.34)
# aws ssm get-parameter --name /aws/service/bottlerocket/aws-k8s-1.34/x86_64/latest/image_id
ami: ami-02471ee0da5a34d1e

subnetIds:
- subnet-12345678
securityGroupIds:
- sg-12345678
iamInstanceProfile: arn:aws:iam::123456789012:instance-profile/eks-node-role

# Bottlerocket has two volumes: root (small) and data
blockDeviceMappings:
- deviceName: /dev/xvda # Root volume (OS)
volumeSize: 8
volumeType: gp3
encrypted: true
- deviceName: /dev/xvdb # Data volume (containers, images)
volumeSize: 20
volumeType: gp3
encrypted: true

tags:
Environment: production
OS: bottlerocket

# Bottlerocket TOML configuration
# No shutdown script - use ControllerStop mode in NodePool
userData: |
[settings.kubernetes]
cluster-name = "my-cluster"
api-server = "https://ABCDEF.gr7.us-east-1.eks.amazonaws.com"
cluster-certificate = "LS0tLS1CRUdJTi..."

[settings.kubernetes.node-taints]
"node.eks.amazonaws.com/not-ready" = "true:NoSchedule"

[settings.kubernetes.node-labels]
"stratos.sh/pool" = "bottlerocket-workers"

Minimal Configuration

awsnodeclass-minimal.yaml
apiVersion: stratos.sh/v1alpha1
kind: AWSNodeClass
metadata:
name: minimal
spec:
instanceType: m5.large
ami: ami-0123456789abcdef0
subnetIds:
- subnet-12345678
securityGroupIds:
- sg-12345678
iamInstanceProfile: arn:aws:iam::123456789012:instance-profile/eks-node-role

High-Performance Configuration

awsnodeclass-performance.yaml
apiVersion: stratos.sh/v1alpha1
kind: AWSNodeClass
metadata:
name: high-performance
spec:
region: us-east-1
instanceType: c5.4xlarge
ami: ami-0123456789abcdef0

subnetIds:
- subnet-12345678
- subnet-87654321
- subnet-abcdefgh
securityGroupIds:
- sg-12345678
iamInstanceProfile: arn:aws:iam::123456789012:instance-profile/eks-node-role

blockDeviceMappings:
- deviceName: /dev/xvda
volumeSize: 100
volumeType: gp3
encrypted: true
iops: 6000
throughput: 500

tags:
Environment: production
Tier: compute
CostCenter: engineering

Finding AMI IDs

EKS-Optimized AMIs

# Amazon Linux 2 (x86_64)
aws ssm get-parameter \
--name /aws/service/eks/optimized-ami/1.34/amazon-linux-2/recommended/image_id \
--query "Parameter.Value" --output text

# Amazon Linux 2023 (x86_64)
aws ssm get-parameter \
--name /aws/service/eks/optimized-ami/1.34/amazon-linux-2023/x86_64/standard/recommended/image_id \
--query "Parameter.Value" --output text

# Amazon Linux 2023 (ARM64)
aws ssm get-parameter \
--name /aws/service/eks/optimized-ami/1.34/amazon-linux-2023/arm64/standard/recommended/image_id \
--query "Parameter.Value" --output text

# Bottlerocket (x86_64)
aws ssm get-parameter \
--name /aws/service/bottlerocket/aws-k8s-1.34/x86_64/latest/image_id \
--query "Parameter.Value" --output text

# Bottlerocket (ARM64)
aws ssm get-parameter \
--name /aws/service/bottlerocket/aws-k8s-1.34/arm64/latest/image_id \
--query "Parameter.Value" --output text

Replace 1.34 with your EKS cluster version.

Kubectl Commands

# List all AWSNodeClasses
kubectl get awsnodeclasses

# Short name
kubectl get awsnc

# Get detailed status
kubectl describe awsnodeclass al2023-standard

# Get YAML output
kubectl get awsnodeclass al2023-standard -o yaml

# Check which NodePools reference an AWSNodeClass
kubectl get nodepools -o custom-columns='NAME:.metadata.name,NODECLASS:.spec.template.nodeClassRef.name'

Migration from Inline CloudProvider

If you have existing NodePools using the inline cloudProvider configuration, migrate to AWSNodeClass:

Before (Inline Configuration)

# OLD FORMAT - No longer supported
apiVersion: stratos.sh/v1alpha1
kind: NodePool
metadata:
name: workers
spec:
poolSize: 10
minStandby: 3
template:
labels:
stratos.sh/pool: workers
cloudProvider: # Inline configuration
provider: aws
aws:
instanceType: m5.large
ami: ami-0123456789abcdef0
subnetIds:
- subnet-12345678
securityGroupIds:
- sg-12345678
iamInstanceProfile: arn:aws:iam::123456789012:instance-profile/eks-node-role

After (AWSNodeClass Reference)

# Step 1: Create the AWSNodeClass
apiVersion: stratos.sh/v1alpha1
kind: AWSNodeClass
metadata:
name: standard-nodes
spec:
instanceType: m5.large
ami: ami-0123456789abcdef0
subnetIds:
- subnet-12345678
securityGroupIds:
- sg-12345678
iamInstanceProfile: arn:aws:iam::123456789012:instance-profile/eks-node-role
---
# Step 2: Update NodePool to reference AWSNodeClass
apiVersion: stratos.sh/v1alpha1
kind: NodePool
metadata:
name: workers
spec:
poolSize: 10
minStandby: 3
template:
nodeClassRef: # Reference to AWSNodeClass
kind: AWSNodeClass
name: standard-nodes
labels:
stratos.sh/pool: workers
Breaking Change

The inline cloudProvider configuration is no longer supported. You must migrate to the AWSNodeClass pattern. Since Stratos is in v1alpha1, breaking changes are expected.

Next Steps