diff --git a/package.json b/package.json index 65f78e85c6d42..6442b77109e93 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,8 @@ "@aws-cdk/aws-codepipeline-actions/case/**", "@aws-cdk/aws-ecr-assets/minimatch", "@aws-cdk/aws-ecr-assets/minimatch/**", + "@aws-cdk/aws-eks/yaml", + "@aws-cdk/aws-eks/yaml/**", "@aws-cdk/aws-lambda-nodejs/parcel-bundler", "@aws-cdk/aws-lambda-nodejs/parcel-bundler/**", "@aws-cdk/cloud-assembly-schema/jsonschema", diff --git a/packages/@aws-cdk/aws-eks/lib/addons/neuron-device-plugin.yaml b/packages/@aws-cdk/aws-eks/lib/addons/neuron-device-plugin.yaml new file mode 100644 index 0000000000000..48d66be1c8343 --- /dev/null +++ b/packages/@aws-cdk/aws-eks/lib/addons/neuron-device-plugin.yaml @@ -0,0 +1,66 @@ +# source: https://github.com/aws/aws-neuron-sdk/blob/master/docs/neuron-container-tools/k8s-neuron-device-plugin.yml +# https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins/ +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: neuron-device-plugin-daemonset + namespace: kube-system +spec: + selector: + matchLabels: + name: neuron-device-plugin-ds + updateStrategy: + type: RollingUpdate + template: + metadata: + annotations: + scheduler.alpha.kubernetes.io/critical-pod: "" + labels: + name: neuron-device-plugin-ds + spec: + tolerations: + - key: CriticalAddonsOnly + operator: Exists + - key: aws.amazon.com/neuron + operator: Exists + effect: NoSchedule + # Mark this pod as a critical add-on; when enabled, the critical add-on + # scheduler reserves resources for critical add-on pods so that they can + # be rescheduled after a failure. + # See https://kubernetes.io/docs/tasks/administer-cluster/guaranteed-scheduling-critical-addon-pods/ + priorityClassName: "system-node-critical" + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: "beta.kubernetes.io/instance-type" + operator: In + values: + - inf1.xlarge + - inf1.2xlarge + - inf1.6xlarge + - inf1.4xlarge + - matchExpressions: + - key: "node.kubernetes.io/instance-type" + operator: In + values: + - inf1.xlarge + - inf1.2xlarge + - inf1.6xlarge + - inf1.24xlarge + containers: + - image: 790709498068.dkr.ecr.us-west-2.amazonaws.com/neuron-device-plugin:1.0.9043.0 + imagePullPolicy: Always + name: k8s-neuron-device-plugin-ctr + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + volumeMounts: + - name: device-plugin + mountPath: /var/lib/kubelet/device-plugins + volumes: + - name: device-plugin + hostPath: + path: /var/lib/kubelet/device-plugins \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/lib/cluster.ts b/packages/@aws-cdk/aws-eks/lib/cluster.ts index 491d357387073..5cf344f067f75 100644 --- a/packages/@aws-cdk/aws-eks/lib/cluster.ts +++ b/packages/@aws-cdk/aws-eks/lib/cluster.ts @@ -3,6 +3,9 @@ import * as ec2 from '@aws-cdk/aws-ec2'; import * as iam from '@aws-cdk/aws-iam'; import * as ssm from '@aws-cdk/aws-ssm'; import { CfnOutput, Construct, IResource, Resource, Stack, Tag, Token } from '@aws-cdk/core'; +import * as fs from 'fs'; +import * as path from 'path'; +import * as YAML from 'yaml'; import { AwsAuth } from './aws-auth'; import { clusterArnComponents, ClusterResource } from './cluster-resource'; import { CfnCluster, CfnClusterProps } from './eks.generated'; @@ -385,6 +388,8 @@ export class Cluster extends Resource implements ICluster { private _spotInterruptHandler?: HelmChart; + private _neuronDevicePlugin?: KubernetesResource; + private readonly version: string | undefined; /** @@ -537,6 +542,10 @@ export class Cluster extends Resource implements ICluster { machineImageType: options.machineImageType, }); + if (nodeTypeForInstanceType(options.instanceType) === NodeType.INFERENTIA) { + this.addNeuronDevicePlugin(); + } + return asg; } @@ -834,6 +843,20 @@ export class Cluster extends Resource implements ICluster { return this._spotInterruptHandler; } + /** + * Installs the Neuron device plugin on the cluster if it's not + * already added. + */ + private addNeuronDevicePlugin() { + if (!this._neuronDevicePlugin) { + const fileContents = fs.readFileSync(path.join(__dirname, 'addons/neuron-device-plugin.yaml'), 'utf8'); + const sanitized = YAML.parse(fileContents); + this._neuronDevicePlugin = this.addResource('NeuronDevicePlugin', sanitized); + } + + return this._neuronDevicePlugin; + } + /** * Opportunistically tag subnets with the required tags. * @@ -1112,6 +1135,7 @@ export class EksOptimizedImage implements ec2.IMachineImage { this.amiParameterName = `/aws/service/eks/optimized-ami/${this.kubernetesVersion}/` + ( this.nodeType === NodeType.STANDARD ? 'amazon-linux-2/' : '' ) + ( this.nodeType === NodeType.GPU ? 'amazon-linux-2-gpu/' : '' ) + + (this.nodeType === NodeType.INFERENTIA ? 'amazon-linux-2-gpu/' : '') + 'recommended/image_id'; } @@ -1176,6 +1200,11 @@ export enum NodeType { * GPU instances */ GPU = 'GPU', + + /** + * Inferentia instances + */ + INFERENTIA = 'INFERENTIA', } /** @@ -1222,7 +1251,10 @@ export enum MachineImageType { } const GPU_INSTANCETYPES = ['p2', 'p3', 'g4']; +const INFERENTIA_INSTANCETYPES = ['inf1']; function nodeTypeForInstanceType(instanceType: ec2.InstanceType) { - return GPU_INSTANCETYPES.includes(instanceType.toString().substring(0, 2)) ? NodeType.GPU : NodeType.STANDARD; + return GPU_INSTANCETYPES.includes(instanceType.toString().substring(0, 2)) ? NodeType.GPU : + INFERENTIA_INSTANCETYPES.includes(instanceType.toString().substring(0, 4)) ? NodeType.INFERENTIA : + NodeType.STANDARD; } diff --git a/packages/@aws-cdk/aws-eks/package.json b/packages/@aws-cdk/aws-eks/package.json index e4cc3e8273dfb..df01d4bdbe553 100644 --- a/packages/@aws-cdk/aws-eks/package.json +++ b/packages/@aws-cdk/aws-eks/package.json @@ -64,6 +64,7 @@ "devDependencies": { "@aws-cdk/assert": "0.0.0", "@types/nodeunit": "^0.0.31", + "@types/yaml": "1.2.0", "aws-sdk": "^2.706.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", @@ -80,8 +81,12 @@ "@aws-cdk/aws-ssm": "0.0.0", "@aws-cdk/core": "0.0.0", "@aws-cdk/custom-resources": "0.0.0", - "constructs": "^3.0.2" + "constructs": "^3.0.2", + "yaml": "1.10.0" }, + "bundledDependencies": [ + "yaml" + ], "homepage": "https://github.com/aws/aws-cdk", "peerDependencies": { "@aws-cdk/aws-autoscaling": "0.0.0", diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.expected.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.expected.json index 4278bee450139..a787602404c54 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.expected.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.expected.json @@ -28,7 +28,7 @@ } } }, - "ClusterDefaultVpcFA9F2722": { + "Vpc8378EB38": { "Type": "AWS::EC2::VPC", "Properties": { "CidrBlock": "10.0.0.0/16", @@ -38,17 +38,17 @@ "Tags": [ { "Key": "Name", - "Value": "aws-cdk-eks-cluster-test/Cluster/DefaultVpc" + "Value": "aws-cdk-eks-cluster-test/Vpc" } ] } }, - "ClusterDefaultVpcPublicSubnet1Subnet3BFE1BDA": { + "VpcPublicSubnet1Subnet5C2D37C4": { "Type": "AWS::EC2::Subnet", "Properties": { "CidrBlock": "10.0.0.0/19", "VpcId": { - "Ref": "ClusterDefaultVpcFA9F2722" + "Ref": "Vpc8378EB38" }, "AvailabilityZone": "test-region-1a", "MapPublicIpOnLaunch": true, @@ -67,16 +67,16 @@ }, { "Key": "Name", - "Value": "aws-cdk-eks-cluster-test/Cluster/DefaultVpc/PublicSubnet1" + "Value": "aws-cdk-eks-cluster-test/Vpc/PublicSubnet1" } ] } }, - "ClusterDefaultVpcPublicSubnet1RouteTable1DCCDD98": { + "VpcPublicSubnet1RouteTable6C95E38E": { "Type": "AWS::EC2::RouteTable", "Properties": { "VpcId": { - "Ref": "ClusterDefaultVpcFA9F2722" + "Ref": "Vpc8378EB38" }, "Tags": [ { @@ -85,38 +85,38 @@ }, { "Key": "Name", - "Value": "aws-cdk-eks-cluster-test/Cluster/DefaultVpc/PublicSubnet1" + "Value": "aws-cdk-eks-cluster-test/Vpc/PublicSubnet1" } ] } }, - "ClusterDefaultVpcPublicSubnet1RouteTableAssociationAFBE6789": { + "VpcPublicSubnet1RouteTableAssociation97140677": { "Type": "AWS::EC2::SubnetRouteTableAssociation", "Properties": { "RouteTableId": { - "Ref": "ClusterDefaultVpcPublicSubnet1RouteTable1DCCDD98" + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" }, "SubnetId": { - "Ref": "ClusterDefaultVpcPublicSubnet1Subnet3BFE1BDA" + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" } } }, - "ClusterDefaultVpcPublicSubnet1DefaultRouteCF22EF6E": { + "VpcPublicSubnet1DefaultRoute3DA9E72A": { "Type": "AWS::EC2::Route", "Properties": { "RouteTableId": { - "Ref": "ClusterDefaultVpcPublicSubnet1RouteTable1DCCDD98" + "Ref": "VpcPublicSubnet1RouteTable6C95E38E" }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { - "Ref": "ClusterDefaultVpcIGW756BE43E" + "Ref": "VpcIGWD7BA715C" } }, "DependsOn": [ - "ClusterDefaultVpcVPCGWC1D00388" + "VpcVPCGWBF912B6E" ] }, - "ClusterDefaultVpcPublicSubnet1EIP498E2BD2": { + "VpcPublicSubnet1EIPD7E02669": { "Type": "AWS::EC2::EIP", "Properties": { "Domain": "vpc", @@ -127,22 +127,22 @@ }, { "Key": "Name", - "Value": "aws-cdk-eks-cluster-test/Cluster/DefaultVpc/PublicSubnet1" + "Value": "aws-cdk-eks-cluster-test/Vpc/PublicSubnet1" } ] } }, - "ClusterDefaultVpcPublicSubnet1NATGateway6E21013E": { + "VpcPublicSubnet1NATGateway4D7517AA": { "Type": "AWS::EC2::NatGateway", "Properties": { "AllocationId": { "Fn::GetAtt": [ - "ClusterDefaultVpcPublicSubnet1EIP498E2BD2", + "VpcPublicSubnet1EIPD7E02669", "AllocationId" ] }, "SubnetId": { - "Ref": "ClusterDefaultVpcPublicSubnet1Subnet3BFE1BDA" + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" }, "Tags": [ { @@ -151,17 +151,17 @@ }, { "Key": "Name", - "Value": "aws-cdk-eks-cluster-test/Cluster/DefaultVpc/PublicSubnet1" + "Value": "aws-cdk-eks-cluster-test/Vpc/PublicSubnet1" } ] } }, - "ClusterDefaultVpcPublicSubnet2SubnetC4E9A966": { + "VpcPublicSubnet2Subnet691E08A3": { "Type": "AWS::EC2::Subnet", "Properties": { "CidrBlock": "10.0.32.0/19", "VpcId": { - "Ref": "ClusterDefaultVpcFA9F2722" + "Ref": "Vpc8378EB38" }, "AvailabilityZone": "test-region-1b", "MapPublicIpOnLaunch": true, @@ -180,16 +180,16 @@ }, { "Key": "Name", - "Value": "aws-cdk-eks-cluster-test/Cluster/DefaultVpc/PublicSubnet2" + "Value": "aws-cdk-eks-cluster-test/Vpc/PublicSubnet2" } ] } }, - "ClusterDefaultVpcPublicSubnet2RouteTable6F1F5F47": { + "VpcPublicSubnet2RouteTable94F7E489": { "Type": "AWS::EC2::RouteTable", "Properties": { "VpcId": { - "Ref": "ClusterDefaultVpcFA9F2722" + "Ref": "Vpc8378EB38" }, "Tags": [ { @@ -198,83 +198,43 @@ }, { "Key": "Name", - "Value": "aws-cdk-eks-cluster-test/Cluster/DefaultVpc/PublicSubnet2" + "Value": "aws-cdk-eks-cluster-test/Vpc/PublicSubnet2" } ] } }, - "ClusterDefaultVpcPublicSubnet2RouteTableAssociationA8539C50": { + "VpcPublicSubnet2RouteTableAssociationDD5762D8": { "Type": "AWS::EC2::SubnetRouteTableAssociation", "Properties": { "RouteTableId": { - "Ref": "ClusterDefaultVpcPublicSubnet2RouteTable6F1F5F47" + "Ref": "VpcPublicSubnet2RouteTable94F7E489" }, "SubnetId": { - "Ref": "ClusterDefaultVpcPublicSubnet2SubnetC4E9A966" + "Ref": "VpcPublicSubnet2Subnet691E08A3" } } }, - "ClusterDefaultVpcPublicSubnet2DefaultRoute1FA8621E": { + "VpcPublicSubnet2DefaultRoute97F91067": { "Type": "AWS::EC2::Route", "Properties": { "RouteTableId": { - "Ref": "ClusterDefaultVpcPublicSubnet2RouteTable6F1F5F47" + "Ref": "VpcPublicSubnet2RouteTable94F7E489" }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { - "Ref": "ClusterDefaultVpcIGW756BE43E" + "Ref": "VpcIGWD7BA715C" } }, "DependsOn": [ - "ClusterDefaultVpcVPCGWC1D00388" + "VpcVPCGWBF912B6E" ] }, - "ClusterDefaultVpcPublicSubnet2EIP265F4810": { - "Type": "AWS::EC2::EIP", - "Properties": { - "Domain": "vpc", - "Tags": [ - { - "Key": "kubernetes.io/role/elb", - "Value": "1" - }, - { - "Key": "Name", - "Value": "aws-cdk-eks-cluster-test/Cluster/DefaultVpc/PublicSubnet2" - } - ] - } - }, - "ClusterDefaultVpcPublicSubnet2NATGateway4AF4B728": { - "Type": "AWS::EC2::NatGateway", - "Properties": { - "AllocationId": { - "Fn::GetAtt": [ - "ClusterDefaultVpcPublicSubnet2EIP265F4810", - "AllocationId" - ] - }, - "SubnetId": { - "Ref": "ClusterDefaultVpcPublicSubnet2SubnetC4E9A966" - }, - "Tags": [ - { - "Key": "kubernetes.io/role/elb", - "Value": "1" - }, - { - "Key": "Name", - "Value": "aws-cdk-eks-cluster-test/Cluster/DefaultVpc/PublicSubnet2" - } - ] - } - }, - "ClusterDefaultVpcPublicSubnet3Subnet1A46184A": { + "VpcPublicSubnet3SubnetBE12F0B6": { "Type": "AWS::EC2::Subnet", "Properties": { "CidrBlock": "10.0.64.0/19", "VpcId": { - "Ref": "ClusterDefaultVpcFA9F2722" + "Ref": "Vpc8378EB38" }, "AvailabilityZone": "test-region-1c", "MapPublicIpOnLaunch": true, @@ -293,16 +253,16 @@ }, { "Key": "Name", - "Value": "aws-cdk-eks-cluster-test/Cluster/DefaultVpc/PublicSubnet3" + "Value": "aws-cdk-eks-cluster-test/Vpc/PublicSubnet3" } ] } }, - "ClusterDefaultVpcPublicSubnet3RouteTableC81F99EF": { + "VpcPublicSubnet3RouteTable93458DBB": { "Type": "AWS::EC2::RouteTable", "Properties": { "VpcId": { - "Ref": "ClusterDefaultVpcFA9F2722" + "Ref": "Vpc8378EB38" }, "Tags": [ { @@ -311,83 +271,43 @@ }, { "Key": "Name", - "Value": "aws-cdk-eks-cluster-test/Cluster/DefaultVpc/PublicSubnet3" + "Value": "aws-cdk-eks-cluster-test/Vpc/PublicSubnet3" } ] } }, - "ClusterDefaultVpcPublicSubnet3RouteTableAssociation7C5D21CC": { + "VpcPublicSubnet3RouteTableAssociation1F1EDF02": { "Type": "AWS::EC2::SubnetRouteTableAssociation", "Properties": { "RouteTableId": { - "Ref": "ClusterDefaultVpcPublicSubnet3RouteTableC81F99EF" + "Ref": "VpcPublicSubnet3RouteTable93458DBB" }, "SubnetId": { - "Ref": "ClusterDefaultVpcPublicSubnet3Subnet1A46184A" + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" } } }, - "ClusterDefaultVpcPublicSubnet3DefaultRouteB6080504": { + "VpcPublicSubnet3DefaultRoute4697774F": { "Type": "AWS::EC2::Route", "Properties": { "RouteTableId": { - "Ref": "ClusterDefaultVpcPublicSubnet3RouteTableC81F99EF" + "Ref": "VpcPublicSubnet3RouteTable93458DBB" }, "DestinationCidrBlock": "0.0.0.0/0", "GatewayId": { - "Ref": "ClusterDefaultVpcIGW756BE43E" + "Ref": "VpcIGWD7BA715C" } }, "DependsOn": [ - "ClusterDefaultVpcVPCGWC1D00388" + "VpcVPCGWBF912B6E" ] }, - "ClusterDefaultVpcPublicSubnet3EIP0CBF6D05": { - "Type": "AWS::EC2::EIP", - "Properties": { - "Domain": "vpc", - "Tags": [ - { - "Key": "kubernetes.io/role/elb", - "Value": "1" - }, - { - "Key": "Name", - "Value": "aws-cdk-eks-cluster-test/Cluster/DefaultVpc/PublicSubnet3" - } - ] - } - }, - "ClusterDefaultVpcPublicSubnet3NATGatewayEF4BA49A": { - "Type": "AWS::EC2::NatGateway", - "Properties": { - "AllocationId": { - "Fn::GetAtt": [ - "ClusterDefaultVpcPublicSubnet3EIP0CBF6D05", - "AllocationId" - ] - }, - "SubnetId": { - "Ref": "ClusterDefaultVpcPublicSubnet3Subnet1A46184A" - }, - "Tags": [ - { - "Key": "kubernetes.io/role/elb", - "Value": "1" - }, - { - "Key": "Name", - "Value": "aws-cdk-eks-cluster-test/Cluster/DefaultVpc/PublicSubnet3" - } - ] - } - }, - "ClusterDefaultVpcPrivateSubnet1Subnet03F39409": { + "VpcPrivateSubnet1Subnet536B997A": { "Type": "AWS::EC2::Subnet", "Properties": { "CidrBlock": "10.0.96.0/19", "VpcId": { - "Ref": "ClusterDefaultVpcFA9F2722" + "Ref": "Vpc8378EB38" }, "AvailabilityZone": "test-region-1a", "MapPublicIpOnLaunch": false, @@ -406,16 +326,16 @@ }, { "Key": "Name", - "Value": "aws-cdk-eks-cluster-test/Cluster/DefaultVpc/PrivateSubnet1" + "Value": "aws-cdk-eks-cluster-test/Vpc/PrivateSubnet1" } ] } }, - "ClusterDefaultVpcPrivateSubnet1RouteTable7844020C": { + "VpcPrivateSubnet1RouteTableB2C5B500": { "Type": "AWS::EC2::RouteTable", "Properties": { "VpcId": { - "Ref": "ClusterDefaultVpcFA9F2722" + "Ref": "Vpc8378EB38" }, "Tags": [ { @@ -424,40 +344,40 @@ }, { "Key": "Name", - "Value": "aws-cdk-eks-cluster-test/Cluster/DefaultVpc/PrivateSubnet1" + "Value": "aws-cdk-eks-cluster-test/Vpc/PrivateSubnet1" } ] } }, - "ClusterDefaultVpcPrivateSubnet1RouteTableAssociationF8A67D95": { + "VpcPrivateSubnet1RouteTableAssociation70C59FA6": { "Type": "AWS::EC2::SubnetRouteTableAssociation", "Properties": { "RouteTableId": { - "Ref": "ClusterDefaultVpcPrivateSubnet1RouteTable7844020C" + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" }, "SubnetId": { - "Ref": "ClusterDefaultVpcPrivateSubnet1Subnet03F39409" + "Ref": "VpcPrivateSubnet1Subnet536B997A" } } }, - "ClusterDefaultVpcPrivateSubnet1DefaultRouteD624C8BD": { + "VpcPrivateSubnet1DefaultRouteBE02A9ED": { "Type": "AWS::EC2::Route", "Properties": { "RouteTableId": { - "Ref": "ClusterDefaultVpcPrivateSubnet1RouteTable7844020C" + "Ref": "VpcPrivateSubnet1RouteTableB2C5B500" }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { - "Ref": "ClusterDefaultVpcPublicSubnet1NATGateway6E21013E" + "Ref": "VpcPublicSubnet1NATGateway4D7517AA" } } }, - "ClusterDefaultVpcPrivateSubnet2SubnetA526AEA7": { + "VpcPrivateSubnet2Subnet3788AAA1": { "Type": "AWS::EC2::Subnet", "Properties": { "CidrBlock": "10.0.128.0/19", "VpcId": { - "Ref": "ClusterDefaultVpcFA9F2722" + "Ref": "Vpc8378EB38" }, "AvailabilityZone": "test-region-1b", "MapPublicIpOnLaunch": false, @@ -476,16 +396,16 @@ }, { "Key": "Name", - "Value": "aws-cdk-eks-cluster-test/Cluster/DefaultVpc/PrivateSubnet2" + "Value": "aws-cdk-eks-cluster-test/Vpc/PrivateSubnet2" } ] } }, - "ClusterDefaultVpcPrivateSubnet2RouteTable1F9A5298": { + "VpcPrivateSubnet2RouteTableA678073B": { "Type": "AWS::EC2::RouteTable", "Properties": { "VpcId": { - "Ref": "ClusterDefaultVpcFA9F2722" + "Ref": "Vpc8378EB38" }, "Tags": [ { @@ -494,40 +414,40 @@ }, { "Key": "Name", - "Value": "aws-cdk-eks-cluster-test/Cluster/DefaultVpc/PrivateSubnet2" + "Value": "aws-cdk-eks-cluster-test/Vpc/PrivateSubnet2" } ] } }, - "ClusterDefaultVpcPrivateSubnet2RouteTableAssociationE1240DF2": { + "VpcPrivateSubnet2RouteTableAssociationA89CAD56": { "Type": "AWS::EC2::SubnetRouteTableAssociation", "Properties": { "RouteTableId": { - "Ref": "ClusterDefaultVpcPrivateSubnet2RouteTable1F9A5298" + "Ref": "VpcPrivateSubnet2RouteTableA678073B" }, "SubnetId": { - "Ref": "ClusterDefaultVpcPrivateSubnet2SubnetA526AEA7" + "Ref": "VpcPrivateSubnet2Subnet3788AAA1" } } }, - "ClusterDefaultVpcPrivateSubnet2DefaultRouteAB55737C": { + "VpcPrivateSubnet2DefaultRoute060D2087": { "Type": "AWS::EC2::Route", "Properties": { "RouteTableId": { - "Ref": "ClusterDefaultVpcPrivateSubnet2RouteTable1F9A5298" + "Ref": "VpcPrivateSubnet2RouteTableA678073B" }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { - "Ref": "ClusterDefaultVpcPublicSubnet2NATGateway4AF4B728" + "Ref": "VpcPublicSubnet1NATGateway4D7517AA" } } }, - "ClusterDefaultVpcPrivateSubnet3SubnetB64BC839": { + "VpcPrivateSubnet3SubnetF258B56E": { "Type": "AWS::EC2::Subnet", "Properties": { "CidrBlock": "10.0.160.0/19", "VpcId": { - "Ref": "ClusterDefaultVpcFA9F2722" + "Ref": "Vpc8378EB38" }, "AvailabilityZone": "test-region-1c", "MapPublicIpOnLaunch": false, @@ -546,16 +466,16 @@ }, { "Key": "Name", - "Value": "aws-cdk-eks-cluster-test/Cluster/DefaultVpc/PrivateSubnet3" + "Value": "aws-cdk-eks-cluster-test/Vpc/PrivateSubnet3" } ] } }, - "ClusterDefaultVpcPrivateSubnet3RouteTableF71314D0": { + "VpcPrivateSubnet3RouteTableD98824C7": { "Type": "AWS::EC2::RouteTable", "Properties": { "VpcId": { - "Ref": "ClusterDefaultVpcFA9F2722" + "Ref": "Vpc8378EB38" }, "Tags": [ { @@ -564,53 +484,53 @@ }, { "Key": "Name", - "Value": "aws-cdk-eks-cluster-test/Cluster/DefaultVpc/PrivateSubnet3" + "Value": "aws-cdk-eks-cluster-test/Vpc/PrivateSubnet3" } ] } }, - "ClusterDefaultVpcPrivateSubnet3RouteTableAssociation3007DC36": { + "VpcPrivateSubnet3RouteTableAssociation16BDDC43": { "Type": "AWS::EC2::SubnetRouteTableAssociation", "Properties": { "RouteTableId": { - "Ref": "ClusterDefaultVpcPrivateSubnet3RouteTableF71314D0" + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" }, "SubnetId": { - "Ref": "ClusterDefaultVpcPrivateSubnet3SubnetB64BC839" + "Ref": "VpcPrivateSubnet3SubnetF258B56E" } } }, - "ClusterDefaultVpcPrivateSubnet3DefaultRoute932EDFF0": { + "VpcPrivateSubnet3DefaultRoute94B74F0D": { "Type": "AWS::EC2::Route", "Properties": { "RouteTableId": { - "Ref": "ClusterDefaultVpcPrivateSubnet3RouteTableF71314D0" + "Ref": "VpcPrivateSubnet3RouteTableD98824C7" }, "DestinationCidrBlock": "0.0.0.0/0", "NatGatewayId": { - "Ref": "ClusterDefaultVpcPublicSubnet3NATGatewayEF4BA49A" + "Ref": "VpcPublicSubnet1NATGateway4D7517AA" } } }, - "ClusterDefaultVpcIGW756BE43E": { + "VpcIGWD7BA715C": { "Type": "AWS::EC2::InternetGateway", "Properties": { "Tags": [ { "Key": "Name", - "Value": "aws-cdk-eks-cluster-test/Cluster/DefaultVpc" + "Value": "aws-cdk-eks-cluster-test/Vpc" } ] } }, - "ClusterDefaultVpcVPCGWC1D00388": { + "VpcVPCGWBF912B6E": { "Type": "AWS::EC2::VPCGatewayAttachment", "Properties": { "VpcId": { - "Ref": "ClusterDefaultVpcFA9F2722" + "Ref": "Vpc8378EB38" }, "InternetGatewayId": { - "Ref": "ClusterDefaultVpcIGW756BE43E" + "Ref": "VpcIGWD7BA715C" } } }, @@ -657,7 +577,7 @@ } ], "VpcId": { - "Ref": "ClusterDefaultVpcFA9F2722" + "Ref": "Vpc8378EB38" } } }, @@ -724,6 +644,27 @@ "ToPort": 443 } }, + "ClusterControlPlaneSecurityGroupfromawscdkeksclustertestClusterInferenceInstancesInstanceSecurityGroup42C57C51443E3176F85": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "IpProtocol": "tcp", + "Description": "from awscdkeksclustertestClusterInferenceInstancesInstanceSecurityGroup42C57C51:443", + "FromPort": 443, + "GroupId": { + "Fn::GetAtt": [ + "ClusterControlPlaneSecurityGroupD274242C", + "GroupId" + ] + }, + "SourceSecurityGroupId": { + "Fn::GetAtt": [ + "ClusterInferenceInstancesInstanceSecurityGroupECB3FC45", + "GroupId" + ] + }, + "ToPort": 443 + } + }, "ClusterCreationRole360249B6": { "Type": "AWS::IAM::Role", "Properties": { @@ -873,22 +814,22 @@ ], "subnetIds": [ { - "Ref": "ClusterDefaultVpcPublicSubnet1Subnet3BFE1BDA" + "Ref": "VpcPublicSubnet1Subnet5C2D37C4" }, { - "Ref": "ClusterDefaultVpcPublicSubnet2SubnetC4E9A966" + "Ref": "VpcPublicSubnet2Subnet691E08A3" }, { - "Ref": "ClusterDefaultVpcPublicSubnet3Subnet1A46184A" + "Ref": "VpcPublicSubnet3SubnetBE12F0B6" }, { - "Ref": "ClusterDefaultVpcPrivateSubnet1Subnet03F39409" + "Ref": "VpcPrivateSubnet1Subnet536B997A" }, { - "Ref": "ClusterDefaultVpcPrivateSubnet2SubnetA526AEA7" + "Ref": "VpcPrivateSubnet2Subnet3788AAA1" }, { - "Ref": "ClusterDefaultVpcPrivateSubnet3SubnetB64BC839" + "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ] } @@ -963,6 +904,13 @@ "Arn" ] }, + "\\\",\\\"username\\\":\\\"system:node:{{EC2PrivateDNSName}}\\\",\\\"groups\\\":[\\\"system:bootstrappers\\\",\\\"system:nodes\\\"]},{\\\"rolearn\\\":\\\"", + { + "Fn::GetAtt": [ + "ClusterInferenceInstancesInstanceRole59AC6F56", + "Arn" + ] + }, "\\\",\\\"username\\\":\\\"system:node:{{EC2PrivateDNSName}}\\\",\\\"groups\\\":[\\\"system:bootstrappers\\\",\\\"system:nodes\\\"]}]\",\"mapUsers\":\"[]\",\"mapAccounts\":\"[]\"}}]" ] ] @@ -1059,13 +1007,13 @@ }, "Subnets": [ { - "Ref": "ClusterDefaultVpcPrivateSubnet1Subnet03F39409" + "Ref": "VpcPrivateSubnet1Subnet536B997A" }, { - "Ref": "ClusterDefaultVpcPrivateSubnet2SubnetA526AEA7" + "Ref": "VpcPrivateSubnet2Subnet3788AAA1" }, { - "Ref": "ClusterDefaultVpcPrivateSubnet3SubnetB64BC839" + "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], "ForceUpdateEnabled": true, @@ -1177,7 +1125,7 @@ } ], "VpcId": { - "Ref": "ClusterDefaultVpcFA9F2722" + "Ref": "Vpc8378EB38" } } }, @@ -1406,13 +1354,13 @@ ], "VPCZoneIdentifier": [ { - "Ref": "ClusterDefaultVpcPrivateSubnet1Subnet03F39409" + "Ref": "VpcPrivateSubnet1Subnet536B997A" }, { - "Ref": "ClusterDefaultVpcPrivateSubnet2SubnetA526AEA7" + "Ref": "VpcPrivateSubnet2Subnet3788AAA1" }, { - "Ref": "ClusterDefaultVpcPrivateSubnet3SubnetB64BC839" + "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ] }, @@ -1465,7 +1413,7 @@ } ], "VpcId": { - "Ref": "ClusterDefaultVpcFA9F2722" + "Ref": "Vpc8378EB38" } } }, @@ -1708,13 +1656,13 @@ ], "VPCZoneIdentifier": [ { - "Ref": "ClusterDefaultVpcPrivateSubnet1Subnet03F39409" + "Ref": "VpcPrivateSubnet1Subnet536B997A" }, { - "Ref": "ClusterDefaultVpcPrivateSubnet2SubnetA526AEA7" + "Ref": "VpcPrivateSubnet2Subnet3788AAA1" }, { - "Ref": "ClusterDefaultVpcPrivateSubnet3SubnetB64BC839" + "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ] }, @@ -1767,7 +1715,7 @@ } ], "VpcId": { - "Ref": "ClusterDefaultVpcFA9F2722" + "Ref": "Vpc8378EB38" } } }, @@ -1997,13 +1945,13 @@ ], "VPCZoneIdentifier": [ { - "Ref": "ClusterDefaultVpcPrivateSubnet1Subnet03F39409" + "Ref": "VpcPrivateSubnet1Subnet536B997A" }, { - "Ref": "ClusterDefaultVpcPrivateSubnet2SubnetA526AEA7" + "Ref": "VpcPrivateSubnet2Subnet3788AAA1" }, { - "Ref": "ClusterDefaultVpcPrivateSubnet3SubnetB64BC839" + "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ] }, @@ -2053,6 +2001,317 @@ "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" }, + "ClusterInferenceInstancesInstanceSecurityGroupECB3FC45": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "aws-cdk-eks-cluster-test/Cluster/InferenceInstances/InstanceSecurityGroup", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "Tags": [ + { + "Key": { + "Fn::Join": [ + "", + [ + "kubernetes.io/cluster/", + { + "Ref": "Cluster9EE0221C" + } + ] + ] + }, + "Value": "owned" + }, + { + "Key": "Name", + "Value": "aws-cdk-eks-cluster-test/Cluster/InferenceInstances" + } + ], + "VpcId": { + "Ref": "Vpc8378EB38" + } + } + }, + "ClusterInferenceInstancesInstanceSecurityGroupfromawscdkeksclustertestClusterInferenceInstancesInstanceSecurityGroup42C57C51ALLTRAFFICB6138869": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "IpProtocol": "-1", + "Description": "from awscdkeksclustertestClusterInferenceInstancesInstanceSecurityGroup42C57C51:ALL TRAFFIC", + "GroupId": { + "Fn::GetAtt": [ + "ClusterInferenceInstancesInstanceSecurityGroupECB3FC45", + "GroupId" + ] + }, + "SourceSecurityGroupId": { + "Fn::GetAtt": [ + "ClusterInferenceInstancesInstanceSecurityGroupECB3FC45", + "GroupId" + ] + } + } + }, + "ClusterInferenceInstancesInstanceSecurityGroupfromawscdkeksclustertestClusterControlPlaneSecurityGroup2F1301344437B48FD33": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "IpProtocol": "tcp", + "Description": "from awscdkeksclustertestClusterControlPlaneSecurityGroup2F130134:443", + "FromPort": 443, + "GroupId": { + "Fn::GetAtt": [ + "ClusterInferenceInstancesInstanceSecurityGroupECB3FC45", + "GroupId" + ] + }, + "SourceSecurityGroupId": { + "Fn::GetAtt": [ + "ClusterControlPlaneSecurityGroupD274242C", + "GroupId" + ] + }, + "ToPort": 443 + } + }, + "ClusterInferenceInstancesInstanceSecurityGroupfromawscdkeksclustertestClusterControlPlaneSecurityGroup2F130134102565535A460F673": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "IpProtocol": "tcp", + "Description": "from awscdkeksclustertestClusterControlPlaneSecurityGroup2F130134:1025-65535", + "FromPort": 1025, + "GroupId": { + "Fn::GetAtt": [ + "ClusterInferenceInstancesInstanceSecurityGroupECB3FC45", + "GroupId" + ] + }, + "SourceSecurityGroupId": { + "Fn::GetAtt": [ + "ClusterControlPlaneSecurityGroupD274242C", + "GroupId" + ] + }, + "ToPort": 65535 + } + }, + "ClusterInferenceInstancesInstanceRole59AC6F56": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": { + "Fn::Join": [ + "", + [ + "ec2.", + { + "Ref": "AWS::URLSuffix" + } + ] + ] + } + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonEKSWorkerNodePolicy" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonEKS_CNI_Policy" + ] + ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" + ] + ] + } + ], + "Tags": [ + { + "Key": { + "Fn::Join": [ + "", + [ + "kubernetes.io/cluster/", + { + "Ref": "Cluster9EE0221C" + } + ] + ] + }, + "Value": "owned" + }, + { + "Key": "Name", + "Value": "aws-cdk-eks-cluster-test/Cluster/InferenceInstances" + } + ] + } + }, + "ClusterInferenceInstancesInstanceProfile5A1209B4": { + "Type": "AWS::IAM::InstanceProfile", + "Properties": { + "Roles": [ + { + "Ref": "ClusterInferenceInstancesInstanceRole59AC6F56" + } + ] + } + }, + "ClusterInferenceInstancesLaunchConfig03BF48FE": { + "Type": "AWS::AutoScaling::LaunchConfiguration", + "Properties": { + "ImageId": { + "Ref": "SsmParameterValueawsserviceeksoptimizedami116amazonlinux2gpurecommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter" + }, + "InstanceType": "inf1.2xlarge", + "IamInstanceProfile": { + "Ref": "ClusterInferenceInstancesInstanceProfile5A1209B4" + }, + "SecurityGroups": [ + { + "Fn::GetAtt": [ + "ClusterInferenceInstancesInstanceSecurityGroupECB3FC45", + "GroupId" + ] + } + ], + "UserData": { + "Fn::Base64": { + "Fn::Join": [ + "", + [ + "#!/bin/bash\nset -o xtrace\n/etc/eks/bootstrap.sh ", + { + "Ref": "Cluster9EE0221C" + }, + " --kubelet-extra-args \"--node-labels lifecycle=OnDemand\" --use-max-pods true\n/opt/aws/bin/cfn-signal --exit-code $? --stack aws-cdk-eks-cluster-test --resource ClusterInferenceInstancesASGE90717C7 --region test-region" + ] + ] + } + } + }, + "DependsOn": [ + "ClusterInferenceInstancesInstanceRole59AC6F56" + ] + }, + "ClusterInferenceInstancesASGE90717C7": { + "Type": "AWS::AutoScaling::AutoScalingGroup", + "Properties": { + "MaxSize": "1", + "MinSize": "1", + "LaunchConfigurationName": { + "Ref": "ClusterInferenceInstancesLaunchConfig03BF48FE" + }, + "Tags": [ + { + "Key": { + "Fn::Join": [ + "", + [ + "kubernetes.io/cluster/", + { + "Ref": "Cluster9EE0221C" + } + ] + ] + }, + "PropagateAtLaunch": true, + "Value": "owned" + }, + { + "Key": "Name", + "PropagateAtLaunch": true, + "Value": "aws-cdk-eks-cluster-test/Cluster/InferenceInstances" + } + ], + "VPCZoneIdentifier": [ + { + "Ref": "VpcPrivateSubnet1Subnet536B997A" + }, + { + "Ref": "VpcPrivateSubnet2Subnet3788AAA1" + }, + { + "Ref": "VpcPrivateSubnet3SubnetF258B56E" + } + ] + }, + "UpdatePolicy": { + "AutoScalingRollingUpdate": { + "WaitOnResourceSignals": false, + "PauseTime": "PT0S", + "SuspendProcesses": [ + "HealthCheck", + "ReplaceUnhealthy", + "AZRebalance", + "AlarmNotification", + "ScheduledActions" + ] + }, + "AutoScalingScheduledAction": { + "IgnoreUnmodifiedGroupSizeProperties": true + } + } + }, + "ClustermanifestNeuronDevicePlugin0B3E0D17": { + "Type": "Custom::AWSCDK-EKS-KubernetesResource", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "awscdkawseksKubectlProviderNestedStackawscdkawseksKubectlProviderNestedStackResourceA7AEBA6B", + "Outputs.awscdkeksclustertestawscdkawseksKubectlProviderframeworkonEventC681B49AArn" + ] + }, + "Manifest": "[{\"apiVersion\":\"apps/v1\",\"kind\":\"DaemonSet\",\"metadata\":{\"name\":\"neuron-device-plugin-daemonset\",\"namespace\":\"kube-system\"},\"spec\":{\"selector\":{\"matchLabels\":{\"name\":\"neuron-device-plugin-ds\"}},\"updateStrategy\":{\"type\":\"RollingUpdate\"},\"template\":{\"metadata\":{\"annotations\":{\"scheduler.alpha.kubernetes.io/critical-pod\":\"\"},\"labels\":{\"name\":\"neuron-device-plugin-ds\"}},\"spec\":{\"tolerations\":[{\"key\":\"CriticalAddonsOnly\",\"operator\":\"Exists\"},{\"key\":\"aws.amazon.com/neuron\",\"operator\":\"Exists\",\"effect\":\"NoSchedule\"}],\"priorityClassName\":\"system-node-critical\",\"affinity\":{\"nodeAffinity\":{\"requiredDuringSchedulingIgnoredDuringExecution\":{\"nodeSelectorTerms\":[{\"matchExpressions\":[{\"key\":\"beta.kubernetes.io/instance-type\",\"operator\":\"In\",\"values\":[\"inf1.xlarge\",\"inf1.2xlarge\",\"inf1.6xlarge\",\"inf1.4xlarge\"]}]},{\"matchExpressions\":[{\"key\":\"node.kubernetes.io/instance-type\",\"operator\":\"In\",\"values\":[\"inf1.xlarge\",\"inf1.2xlarge\",\"inf1.6xlarge\",\"inf1.24xlarge\"]}]}]}}},\"containers\":[{\"image\":\"790709498068.dkr.ecr.us-west-2.amazonaws.com/neuron-device-plugin:1.0.9043.0\",\"imagePullPolicy\":\"Always\",\"name\":\"k8s-neuron-device-plugin-ctr\",\"securityContext\":{\"allowPrivilegeEscalation\":false,\"capabilities\":{\"drop\":[\"ALL\"]}},\"volumeMounts\":[{\"name\":\"device-plugin\",\"mountPath\":\"/var/lib/kubelet/device-plugins\"}]}],\"volumes\":[{\"name\":\"device-plugin\",\"hostPath\":{\"path\":\"/var/lib/kubelet/device-plugins\"}}]}}}}]", + "ClusterName": { + "Ref": "Cluster9EE0221C" + }, + "RoleArn": { + "Fn::GetAtt": [ + "ClusterCreationRole360249B6", + "Arn" + ] + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, "ClusterNodegroupextrangNodeGroupRole23AE23D0": { "Type": "AWS::IAM::Role", "Properties": { @@ -2132,13 +2391,13 @@ }, "Subnets": [ { - "Ref": "ClusterDefaultVpcPrivateSubnet1Subnet03F39409" + "Ref": "VpcPrivateSubnet1Subnet536B997A" }, { - "Ref": "ClusterDefaultVpcPrivateSubnet2SubnetA526AEA7" + "Ref": "VpcPrivateSubnet2Subnet3788AAA1" }, { - "Ref": "ClusterDefaultVpcPrivateSubnet3SubnetB64BC839" + "Ref": "VpcPrivateSubnet3SubnetF258B56E" } ], "ForceUpdateEnabled": true, @@ -2832,6 +3091,10 @@ "SsmParameterValueawsservicebottlerocketawsk8s115x8664latestimageidC96584B6F00A464EAD1953AFF4B05118Parameter": { "Type": "AWS::SSM::Parameter::Value", "Default": "/aws/service/bottlerocket/aws-k8s-1.15/x86_64/latest/image_id" + }, + "SsmParameterValueawsserviceeksoptimizedami116amazonlinux2gpurecommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/aws/service/eks/optimized-ami/1.16/amazon-linux-2-gpu/recommended/image_id" } } -} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.ts index ff6d62e74c20f..122efbdd9ecc6 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.ts +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.ts @@ -14,14 +14,18 @@ class EksClusterStack extends TestStack { assumedBy: new iam.AccountRootPrincipal(), }); + // just need one nat gateway to simplify the test + const vpc = new ec2.Vpc(this, 'Vpc', { maxAzs: 3, natGateways: 1 }); + // create the cluster with a default nodegroup capacity const cluster = new eks.Cluster(this, 'Cluster', { + vpc, mastersRole, defaultCapacity: 2, version: '1.16', }); - // // fargate profile for resources in the "default" namespace + // fargate profile for resources in the "default" namespace cluster.addFargateProfile('default', { selectors: [{ namespace: 'default' }], }); @@ -51,6 +55,12 @@ class EksClusterStack extends TestStack { }, }); + // inference instances + cluster.addCapacity('InferenceInstances', { + instanceType: new ec2.InstanceType('inf1.2xlarge'), + minCapacity: 1, + }); + // add a extra nodegroup cluster.addNodegroup('extra-ng', { instanceType: new ec2.InstanceType('t3.small'), diff --git a/packages/@aws-cdk/aws-eks/test/test.cluster.ts b/packages/@aws-cdk/aws-eks/test/test.cluster.ts index 4b00ac1ec6e36..c7a09d794e7cc 100644 --- a/packages/@aws-cdk/aws-eks/test/test.cluster.ts +++ b/packages/@aws-cdk/aws-eks/test/test.cluster.ts @@ -2,7 +2,10 @@ import { countResources, expect, haveResource, haveResourceLike, not } from '@aw import * as ec2 from '@aws-cdk/aws-ec2'; import * as iam from '@aws-cdk/aws-iam'; import * as cdk from '@aws-cdk/core'; +import * as fs from 'fs'; import { Test } from 'nodeunit'; +import * as path from 'path'; +import * as YAML from 'yaml'; import * as eks from '../lib'; import { KubectlLayer } from '../lib/kubectl-layer'; import { testFixture, testFixtureNoVpc } from './util'; @@ -1156,4 +1159,23 @@ export = { })); test.done(); }, + 'inference instances are supported'(test: Test) { + // GIVEN + const { stack } = testFixtureNoVpc(); + const cluster = new eks.Cluster(stack, 'Cluster', { defaultCapacity: 0 }); + + // WHEN + cluster.addCapacity('InferenceInstances', { + instanceType: new ec2.InstanceType('inf1.2xlarge'), + minCapacity: 1, + }); + const fileContents = fs.readFileSync(path.join(__dirname, '../lib', 'addons/neuron-device-plugin.yaml'), 'utf8'); + const sanitized = YAML.parse(fileContents); + + // THEN + expect(stack).to(haveResource(eks.KubernetesResource.RESOURCE_TYPE, { + Manifest: JSON.stringify([sanitized]), + })); + test.done(); + }, }};