From d3cb401002e1942345b5ab95e69150e542e7e2c2 Mon Sep 17 00:00:00 2001 From: Jinyu Pan Date: Wed, 22 Mar 2023 16:35:29 +0800 Subject: [PATCH] merge to 1.25 change the agent add readme Update aws_ec2_instance_types.go update g4dn.xlarge feat: support multi-arch feat: change the agent feat: change to amd64, arm64 would coredump fix: update the exec path fix: change to use alpine as base image fix: add more compilation args update update --- Jenkinsfile | 97 + cluster-autoscaler/Dockerfile | 21 + .../cloudprovider/aws/aws_manager.go | 4 + .../cloudprovider/aws/ec2_instance_types.go | 14 + .../cloudprovider/builder/builder_all.go | 4 + .../cloudprovider/cloud_provider.go | 2 + .../spotinst/aws_ec2_instance_types.go | 4388 +++++++++++++++++ .../spotinst/spotinst_cloud_provider.go | 155 + .../spotinst/spotinst_cloud_provider_test.go | 416 ++ .../spotinst/spotinst_manager.go | 503 ++ .../spotinst/spotinst_node_group.go | 232 + .../utils/gpumemory/gpumemory.go | 41 + .../utils/gpumemory/gpumemory_test.go | 83 + .../utils/mpscontext/mpscontext.go | 6 + cluster-autoscaler/visenze.md | 46 + 15 files changed, 6012 insertions(+) create mode 100644 Jenkinsfile create mode 100644 cluster-autoscaler/Dockerfile create mode 100644 cluster-autoscaler/cloudprovider/spotinst/aws_ec2_instance_types.go create mode 100644 cluster-autoscaler/cloudprovider/spotinst/spotinst_cloud_provider.go create mode 100644 cluster-autoscaler/cloudprovider/spotinst/spotinst_cloud_provider_test.go create mode 100644 cluster-autoscaler/cloudprovider/spotinst/spotinst_manager.go create mode 100644 cluster-autoscaler/cloudprovider/spotinst/spotinst_node_group.go create mode 100644 cluster-autoscaler/utils/gpumemory/gpumemory.go create mode 100644 cluster-autoscaler/utils/gpumemory/gpumemory_test.go create mode 100644 cluster-autoscaler/utils/mpscontext/mpscontext.go create mode 100644 cluster-autoscaler/visenze.md diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 000000000000..d223980934dd --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,97 @@ +// throttle concurrent build +properties([[$class: 'ThrottleJobProperty', categories: [], limitOneJobWithMatchingParams: false, maxConcurrentPerNode: 1, maxConcurrentTotal: 1, paramsToUseForLimit: '', throttleEnabled: true, throttleOption: 'project']]) + +library(identifier: "visenze-lib@${params['VISENZE_LIB_BRANCH'] ?: 'master'}", changelog: false) + +pipeline { + agent { + label "build-amd64" + } + + options { + ansiColor('xterm') + } + + tools { + go 'go1.15' + } + + stages { + stage('Checkout') { + steps { + checkout([ + $class: 'GitSCM', + branches: scm.branches, + doGenerateSubmoduleConfigurations: scm.doGenerateSubmoduleConfigurations, + extensions: [ + [ + $class: 'CloneOption', + noTags: true, + reference: '', + timeout: 60 + ], + [ + $class: 'SubmoduleOption', + disableSubmodules: false, + parentCredentials: true, + recursiveSubmodules: true, + trackingSubmodules: true, + reference: '', + timeout: 60 + ], + [$class: 'CleanBeforeCheckout'] + ], + userRemoteConfigs: scm.userRemoteConfigs + ]) + } + } + + stage('Test') { + when { + expression { + return canRun() + } + } + steps { + script { + dir('cluster-autoscaler') { + sh('make test-in-docker') + } + } + } + } + + stage('Docker Build&Push') { + when { + expression { + return canRun() + } + } + steps { + script { + dir('cluster-autoscaler') { + def version = sh(script: "grep ClusterAutoscalerVersion version/version.go", + returnStdout: true).split('"')[-2] + docker.withRegistry('', 'docker-hub-credential') { + sh("docker buildx create --use") + sh("docker buildx build -t visenze/cluster-autoscaler:${version} --push --platform linux/arm64,linux/amd64 .") + } + + build(job: 'devops_docker_registry_copy_image', parameters: [ + string(name: 'REPOSITORY', value: "visenze/cluster-autoscaler"), + string(name: 'DOCKER_TAG', value: version), + string(name: 'TIMEOUT', value: "30"), + string(name: 'SOURCE_DOCKER_REGISTRY_CREDENTIAL', value: "docker-hub-credential"), + string(name: 'DEST_DOCKER_REGISTRY', value: "https://741813507711.dkr.ecr.cn-northwest-1.amazonaws.com.cn"), + string(name: 'DEST_DOCKER_REGISTRY_CREDENTIAL', value: "ecr:cn-northwest-1:aws-cn-jenkins"), + ]) + } + } + } + } + } +} + +def canRun() { + return env.BRANCH_NAME.startsWith('release-') || env.BRANCH_NAME == 'master' +} \ No newline at end of file diff --git a/cluster-autoscaler/Dockerfile b/cluster-autoscaler/Dockerfile new file mode 100644 index 000000000000..a505c3986fad --- /dev/null +++ b/cluster-autoscaler/Dockerfile @@ -0,0 +1,21 @@ +FROM golang:1.19.7 AS build + +ARG TARGETARCH +ENV GOPATH /gopath/ +ENV PATH $GOPATH/bin:$PATH +ENV GO111MODULE auto +ENV GOARCH ${TARGETARCH} + +RUN apt-get update && apt-get --yes install libseccomp-dev +RUN go version +RUN go get github.com/tools/godep +RUN godep version + +WORKDIR /gopath/src/k8s.io/autoscaler/cluster-autoscaler +ADD . . +RUN CGO_ENABLED=0 GOOS=linux go build -o cluster-autoscaler --ldflags "-s" + +FROM alpine +COPY --from=build /gopath/src/k8s.io/autoscaler/cluster-autoscaler/cluster-autoscaler / + +CMD ["./cluster-autoscaler"] \ No newline at end of file diff --git a/cluster-autoscaler/cloudprovider/aws/aws_manager.go b/cluster-autoscaler/cloudprovider/aws/aws_manager.go index c18de984b1d6..f7438d54b7f0 100644 --- a/cluster-autoscaler/cloudprovider/aws/aws_manager.go +++ b/cluster-autoscaler/cloudprovider/aws/aws_manager.go @@ -43,6 +43,8 @@ import ( "k8s.io/autoscaler/cluster-autoscaler/cloudprovider/aws/aws-sdk-go/service/eks" "k8s.io/autoscaler/cluster-autoscaler/config" "k8s.io/autoscaler/cluster-autoscaler/utils/gpu" + "k8s.io/autoscaler/cluster-autoscaler/utils/gpumemory" + "k8s.io/autoscaler/cluster-autoscaler/utils/mpscontext" klog "k8s.io/klog/v2" provider_aws "k8s.io/legacy-cloud-providers/aws" ) @@ -405,6 +407,8 @@ func (m *AwsManager) buildNodeFromTemplate(asg *asg, template *asgTemplate) (*ap node.Status.Capacity[apiv1.ResourceCPU] = *resource.NewQuantity(template.InstanceType.VCPU, resource.DecimalSI) node.Status.Capacity[gpu.ResourceNvidiaGPU] = *resource.NewQuantity(template.InstanceType.GPU, resource.DecimalSI) node.Status.Capacity[apiv1.ResourceMemory] = *resource.NewQuantity(template.InstanceType.MemoryMb*1024*1024, resource.DecimalSI) + node.Status.Capacity[gpumemory.ResourceVisenzeGPUMemory] = *resource.NewQuantity(template.InstanceType.GPUMemory, resource.DecimalSI) + node.Status.Capacity[mpscontext.ResourceVisenzeMPSContext] = *resource.NewQuantity(template.InstanceType.MPSContext, resource.DecimalSI) if err := m.updateCapacityWithRequirementsOverrides(&node.Status.Capacity, asg.MixedInstancesPolicy); err != nil { return nil, err diff --git a/cluster-autoscaler/cloudprovider/aws/ec2_instance_types.go b/cluster-autoscaler/cloudprovider/aws/ec2_instance_types.go index be355cc1aff4..d15e77fb7893 100644 --- a/cluster-autoscaler/cloudprovider/aws/ec2_instance_types.go +++ b/cluster-autoscaler/cloudprovider/aws/ec2_instance_types.go @@ -25,6 +25,8 @@ type InstanceType struct { MemoryMb int64 GPU int64 Architecture string + GPUMemory int64 + MPSContext int64 } // StaticListLastUpdateTime is a string declaring the last time the static list was updated. @@ -1123,6 +1125,8 @@ var InstanceTypes = map[string]*InstanceType{ MemoryMb: 262144, GPU: 1, Architecture: "amd64", + GPUMemory: 15842934784, + MPSContext: 32, }, "g4dn.2xlarge": { InstanceType: "g4dn.2xlarge", @@ -1130,6 +1134,8 @@ var InstanceTypes = map[string]*InstanceType{ MemoryMb: 32768, GPU: 1, Architecture: "amd64", + GPUMemory: 15842934784, + MPSContext: 32, }, "g4dn.4xlarge": { InstanceType: "g4dn.4xlarge", @@ -1137,6 +1143,8 @@ var InstanceTypes = map[string]*InstanceType{ MemoryMb: 65536, GPU: 1, Architecture: "amd64", + GPUMemory: 15842934784, + MPSContext: 32, }, "g4dn.8xlarge": { InstanceType: "g4dn.8xlarge", @@ -1144,6 +1152,8 @@ var InstanceTypes = map[string]*InstanceType{ MemoryMb: 131072, GPU: 1, Architecture: "amd64", + GPUMemory: 15842934784, + MPSContext: 32, }, "g4dn.metal": { InstanceType: "g4dn.metal", @@ -2516,6 +2526,8 @@ var InstanceTypes = map[string]*InstanceType{ MemoryMb: 62464, GPU: 1, Architecture: "amd64", + GPUMemory: 12000000000, // Rough estimate of 12 GB + MPSContext: 16, }, "p3.16xlarge": { InstanceType: "p3.16xlarge", @@ -2530,6 +2542,8 @@ var InstanceTypes = map[string]*InstanceType{ MemoryMb: 62464, GPU: 1, Architecture: "amd64", + GPUMemory: 16000000000, // Rough estimate of 16 GB + MPSContext: 32, }, "p3.8xlarge": { InstanceType: "p3.8xlarge", diff --git a/cluster-autoscaler/cloudprovider/builder/builder_all.go b/cluster-autoscaler/cloudprovider/builder/builder_all.go index c23c827d67c1..ffdc2d85430a 100644 --- a/cluster-autoscaler/cloudprovider/builder/builder_all.go +++ b/cluster-autoscaler/cloudprovider/builder/builder_all.go @@ -46,6 +46,7 @@ import ( "k8s.io/autoscaler/cluster-autoscaler/cloudprovider/packet" "k8s.io/autoscaler/cluster-autoscaler/cloudprovider/rancher" "k8s.io/autoscaler/cluster-autoscaler/cloudprovider/scaleway" + "k8s.io/autoscaler/cluster-autoscaler/cloudprovider/spotinst" "k8s.io/autoscaler/cluster-autoscaler/cloudprovider/tencentcloud" "k8s.io/autoscaler/cluster-autoscaler/cloudprovider/vultr" "k8s.io/autoscaler/cluster-autoscaler/config" @@ -80,6 +81,7 @@ var AvailableCloudProviders = []string{ cloudprovider.CivoProviderName, cloudprovider.ScalewayProviderName, cloudprovider.RancherProviderName, + cloudprovider.SpotinstProviderName, } // DefaultCloudProvider is GCE. @@ -141,6 +143,8 @@ func buildCloudProvider(opts config.AutoscalingOptions, do cloudprovider.NodeGro return scaleway.BuildScaleway(opts, do, rl) case cloudprovider.RancherProviderName: return rancher.BuildRancher(opts, do, rl) + case cloudprovider.SpotinstProviderName: + return spotinst.BuildSpotinst(opts, do, rl) } return nil } diff --git a/cluster-autoscaler/cloudprovider/cloud_provider.go b/cluster-autoscaler/cloudprovider/cloud_provider.go index b35a7d5a8ed9..1e19a8ca4f90 100644 --- a/cluster-autoscaler/cloudprovider/cloud_provider.go +++ b/cluster-autoscaler/cloudprovider/cloud_provider.go @@ -84,6 +84,8 @@ const ( CivoProviderName = "civo" // RancherProviderName gets the provider name of rancher RancherProviderName = "rancher" + // SpotinstProviderName gets the provider name of aws + SpotinstProviderName = "spotinst" ) // CloudProvider contains configuration info and functions for interacting with diff --git a/cluster-autoscaler/cloudprovider/spotinst/aws_ec2_instance_types.go b/cluster-autoscaler/cloudprovider/spotinst/aws_ec2_instance_types.go new file mode 100644 index 000000000000..10af6850b6e5 --- /dev/null +++ b/cluster-autoscaler/cloudprovider/spotinst/aws_ec2_instance_types.go @@ -0,0 +1,4388 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// This file was generated by go generate; DO NOT EDIT + +package spotinst + +// InstanceType is spec of EC2 instance +type instanceType struct { + InstanceType string + VCPU int64 + MemoryMb int64 + GPU int64 + Architecture string + GPUMemory int64 + MPSContext int64 +} + +// InstanceTypes is a map of ec2 resources +var InstanceTypes = map[string]*instanceType{ + "a1": { + InstanceType: "a1", + VCPU: 16, + MemoryMb: 0, + GPU: 0, + Architecture: "arm64", + }, + "a1.2xlarge": { + InstanceType: "a1.2xlarge", + VCPU: 8, + MemoryMb: 16384, + GPU: 0, + Architecture: "arm64", + }, + "a1.4xlarge": { + InstanceType: "a1.4xlarge", + VCPU: 16, + MemoryMb: 32768, + GPU: 0, + Architecture: "arm64", + }, + "a1.large": { + InstanceType: "a1.large", + VCPU: 2, + MemoryMb: 4096, + GPU: 0, + Architecture: "arm64", + }, + "a1.medium": { + InstanceType: "a1.medium", + VCPU: 1, + MemoryMb: 2048, + GPU: 0, + Architecture: "arm64", + }, + "a1.metal": { + InstanceType: "a1.metal", + VCPU: 16, + MemoryMb: 32768, + GPU: 0, + Architecture: "arm64", + }, + "a1.xlarge": { + InstanceType: "a1.xlarge", + VCPU: 4, + MemoryMb: 8192, + GPU: 0, + Architecture: "arm64", + }, + "c1.medium": { + InstanceType: "c1.medium", + VCPU: 2, + MemoryMb: 1740, + GPU: 0, + Architecture: "amd64", + }, + "c1.xlarge": { + InstanceType: "c1.xlarge", + VCPU: 8, + MemoryMb: 7168, + GPU: 0, + Architecture: "amd64", + }, + "c3": { + InstanceType: "c3", + VCPU: 32, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "c3.2xlarge": { + InstanceType: "c3.2xlarge", + VCPU: 8, + MemoryMb: 15360, + GPU: 0, + Architecture: "amd64", + }, + "c3.4xlarge": { + InstanceType: "c3.4xlarge", + VCPU: 16, + MemoryMb: 30720, + GPU: 0, + Architecture: "amd64", + }, + "c3.8xlarge": { + InstanceType: "c3.8xlarge", + VCPU: 32, + MemoryMb: 61440, + GPU: 0, + Architecture: "amd64", + }, + "c3.large": { + InstanceType: "c3.large", + VCPU: 2, + MemoryMb: 3840, + GPU: 0, + Architecture: "amd64", + }, + "c3.xlarge": { + InstanceType: "c3.xlarge", + VCPU: 4, + MemoryMb: 7680, + GPU: 0, + Architecture: "amd64", + }, + "c4": { + InstanceType: "c4", + VCPU: 36, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "c4.2xlarge": { + InstanceType: "c4.2xlarge", + VCPU: 8, + MemoryMb: 15360, + GPU: 0, + Architecture: "amd64", + }, + "c4.4xlarge": { + InstanceType: "c4.4xlarge", + VCPU: 16, + MemoryMb: 30720, + GPU: 0, + Architecture: "amd64", + }, + "c4.8xlarge": { + InstanceType: "c4.8xlarge", + VCPU: 36, + MemoryMb: 61440, + GPU: 0, + Architecture: "amd64", + }, + "c4.large": { + InstanceType: "c4.large", + VCPU: 2, + MemoryMb: 3840, + GPU: 0, + Architecture: "amd64", + }, + "c4.xlarge": { + InstanceType: "c4.xlarge", + VCPU: 4, + MemoryMb: 7680, + GPU: 0, + Architecture: "amd64", + }, + "c5": { + InstanceType: "c5", + VCPU: 72, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "c5.12xlarge": { + InstanceType: "c5.12xlarge", + VCPU: 48, + MemoryMb: 98304, + GPU: 0, + Architecture: "amd64", + }, + "c5.18xlarge": { + InstanceType: "c5.18xlarge", + VCPU: 72, + MemoryMb: 147456, + GPU: 0, + Architecture: "amd64", + }, + "c5.24xlarge": { + InstanceType: "c5.24xlarge", + VCPU: 96, + MemoryMb: 196608, + GPU: 0, + Architecture: "amd64", + }, + "c5.2xlarge": { + InstanceType: "c5.2xlarge", + VCPU: 8, + MemoryMb: 16384, + GPU: 0, + Architecture: "amd64", + }, + "c5.4xlarge": { + InstanceType: "c5.4xlarge", + VCPU: 16, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, + "c5.9xlarge": { + InstanceType: "c5.9xlarge", + VCPU: 36, + MemoryMb: 73728, + GPU: 0, + Architecture: "amd64", + }, + "c5.large": { + InstanceType: "c5.large", + VCPU: 2, + MemoryMb: 4096, + GPU: 0, + Architecture: "amd64", + }, + "c5.metal": { + InstanceType: "c5.metal", + VCPU: 96, + MemoryMb: 196608, + GPU: 0, + Architecture: "amd64", + }, + "c5.xlarge": { + InstanceType: "c5.xlarge", + VCPU: 4, + MemoryMb: 8192, + GPU: 0, + Architecture: "amd64", + }, + "c5a.12xlarge": { + InstanceType: "c5a.12xlarge", + VCPU: 48, + MemoryMb: 98304, + GPU: 0, + Architecture: "amd64", + }, + "c5a.16xlarge": { + InstanceType: "c5a.16xlarge", + VCPU: 64, + MemoryMb: 131072, + GPU: 0, + Architecture: "amd64", + }, + "c5a.24xlarge": { + InstanceType: "c5a.24xlarge", + VCPU: 96, + MemoryMb: 196608, + GPU: 0, + Architecture: "amd64", + }, + "c5a.2xlarge": { + InstanceType: "c5a.2xlarge", + VCPU: 8, + MemoryMb: 16384, + GPU: 0, + Architecture: "amd64", + }, + "c5a.4xlarge": { + InstanceType: "c5a.4xlarge", + VCPU: 16, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, + "c5a.8xlarge": { + InstanceType: "c5a.8xlarge", + VCPU: 32, + MemoryMb: 65536, + GPU: 0, + Architecture: "amd64", + }, + "c5a.large": { + InstanceType: "c5a.large", + VCPU: 2, + MemoryMb: 4096, + GPU: 0, + Architecture: "amd64", + }, + "c5a.xlarge": { + InstanceType: "c5a.xlarge", + VCPU: 4, + MemoryMb: 8192, + GPU: 0, + Architecture: "amd64", + }, + "c5ad.12xlarge": { + InstanceType: "c5ad.12xlarge", + VCPU: 48, + MemoryMb: 98304, + GPU: 0, + Architecture: "amd64", + }, + "c5ad.16xlarge": { + InstanceType: "c5ad.16xlarge", + VCPU: 64, + MemoryMb: 131072, + GPU: 0, + Architecture: "amd64", + }, + "c5ad.24xlarge": { + InstanceType: "c5ad.24xlarge", + VCPU: 96, + MemoryMb: 196608, + GPU: 0, + Architecture: "amd64", + }, + "c5ad.2xlarge": { + InstanceType: "c5ad.2xlarge", + VCPU: 8, + MemoryMb: 16384, + GPU: 0, + Architecture: "amd64", + }, + "c5ad.4xlarge": { + InstanceType: "c5ad.4xlarge", + VCPU: 16, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, + "c5ad.8xlarge": { + InstanceType: "c5ad.8xlarge", + VCPU: 32, + MemoryMb: 65536, + GPU: 0, + Architecture: "amd64", + }, + "c5ad.large": { + InstanceType: "c5ad.large", + VCPU: 2, + MemoryMb: 4096, + GPU: 0, + Architecture: "amd64", + }, + "c5ad.xlarge": { + InstanceType: "c5ad.xlarge", + VCPU: 4, + MemoryMb: 8192, + GPU: 0, + Architecture: "amd64", + }, + "c5d": { + InstanceType: "c5d", + VCPU: 72, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "c5d.12xlarge": { + InstanceType: "c5d.12xlarge", + VCPU: 48, + MemoryMb: 98304, + GPU: 0, + Architecture: "amd64", + }, + "c5d.18xlarge": { + InstanceType: "c5d.18xlarge", + VCPU: 72, + MemoryMb: 147456, + GPU: 0, + Architecture: "amd64", + }, + "c5d.24xlarge": { + InstanceType: "c5d.24xlarge", + VCPU: 96, + MemoryMb: 196608, + GPU: 0, + Architecture: "amd64", + }, + "c5d.2xlarge": { + InstanceType: "c5d.2xlarge", + VCPU: 8, + MemoryMb: 16384, + GPU: 0, + Architecture: "amd64", + }, + "c5d.4xlarge": { + InstanceType: "c5d.4xlarge", + VCPU: 16, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, + "c5d.9xlarge": { + InstanceType: "c5d.9xlarge", + VCPU: 36, + MemoryMb: 73728, + GPU: 0, + Architecture: "amd64", + }, + "c5d.large": { + InstanceType: "c5d.large", + VCPU: 2, + MemoryMb: 4096, + GPU: 0, + Architecture: "amd64", + }, + "c5d.metal": { + InstanceType: "c5d.metal", + VCPU: 96, + MemoryMb: 196608, + GPU: 0, + Architecture: "amd64", + }, + "c5d.xlarge": { + InstanceType: "c5d.xlarge", + VCPU: 4, + MemoryMb: 8192, + GPU: 0, + Architecture: "amd64", + }, + "c5n": { + InstanceType: "c5n", + VCPU: 72, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "c5n.18xlarge": { + InstanceType: "c5n.18xlarge", + VCPU: 72, + MemoryMb: 196608, + GPU: 0, + Architecture: "amd64", + }, + "c5n.2xlarge": { + InstanceType: "c5n.2xlarge", + VCPU: 8, + MemoryMb: 21504, + GPU: 0, + Architecture: "amd64", + }, + "c5n.4xlarge": { + InstanceType: "c5n.4xlarge", + VCPU: 16, + MemoryMb: 43008, + GPU: 0, + Architecture: "amd64", + }, + "c5n.9xlarge": { + InstanceType: "c5n.9xlarge", + VCPU: 36, + MemoryMb: 98304, + GPU: 0, + Architecture: "amd64", + }, + "c5n.large": { + InstanceType: "c5n.large", + VCPU: 2, + MemoryMb: 5376, + GPU: 0, + Architecture: "amd64", + }, + "c5n.metal": { + InstanceType: "c5n.metal", + VCPU: 72, + MemoryMb: 196608, + GPU: 0, + Architecture: "amd64", + }, + "c5n.xlarge": { + InstanceType: "c5n.xlarge", + VCPU: 4, + MemoryMb: 10752, + GPU: 0, + Architecture: "amd64", + }, + "c6a": { + InstanceType: "c6a", + VCPU: 192, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "c6a.12xlarge": { + InstanceType: "c6a.12xlarge", + VCPU: 48, + MemoryMb: 98304, + GPU: 0, + Architecture: "amd64", + }, + "c6a.16xlarge": { + InstanceType: "c6a.16xlarge", + VCPU: 64, + MemoryMb: 131072, + GPU: 0, + Architecture: "amd64", + }, + "c6a.24xlarge": { + InstanceType: "c6a.24xlarge", + VCPU: 96, + MemoryMb: 196608, + GPU: 0, + Architecture: "amd64", + }, + "c6a.2xlarge": { + InstanceType: "c6a.2xlarge", + VCPU: 8, + MemoryMb: 16384, + GPU: 0, + Architecture: "amd64", + }, + "c6a.32xlarge": { + InstanceType: "c6a.32xlarge", + VCPU: 128, + MemoryMb: 262144, + GPU: 0, + Architecture: "amd64", + }, + "c6a.48xlarge": { + InstanceType: "c6a.48xlarge", + VCPU: 192, + MemoryMb: 393216, + GPU: 0, + Architecture: "amd64", + }, + "c6a.4xlarge": { + InstanceType: "c6a.4xlarge", + VCPU: 16, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, + "c6a.8xlarge": { + InstanceType: "c6a.8xlarge", + VCPU: 32, + MemoryMb: 65536, + GPU: 0, + Architecture: "amd64", + }, + "c6a.large": { + InstanceType: "c6a.large", + VCPU: 2, + MemoryMb: 4096, + GPU: 0, + Architecture: "amd64", + }, + "c6a.metal": { + InstanceType: "c6a.metal", + VCPU: 192, + MemoryMb: 393216, + GPU: 0, + Architecture: "amd64", + }, + "c6a.xlarge": { + InstanceType: "c6a.xlarge", + VCPU: 4, + MemoryMb: 8192, + GPU: 0, + Architecture: "amd64", + }, + "c6g": { + InstanceType: "c6g", + VCPU: 64, + MemoryMb: 0, + GPU: 0, + Architecture: "arm64", + }, + "c6g.12xlarge": { + InstanceType: "c6g.12xlarge", + VCPU: 48, + MemoryMb: 98304, + GPU: 0, + Architecture: "arm64", + }, + "c6g.16xlarge": { + InstanceType: "c6g.16xlarge", + VCPU: 64, + MemoryMb: 131072, + GPU: 0, + Architecture: "arm64", + }, + "c6g.2xlarge": { + InstanceType: "c6g.2xlarge", + VCPU: 8, + MemoryMb: 16384, + GPU: 0, + Architecture: "arm64", + }, + "c6g.4xlarge": { + InstanceType: "c6g.4xlarge", + VCPU: 16, + MemoryMb: 32768, + GPU: 0, + Architecture: "arm64", + }, + "c6g.8xlarge": { + InstanceType: "c6g.8xlarge", + VCPU: 32, + MemoryMb: 65536, + GPU: 0, + Architecture: "arm64", + }, + "c6g.large": { + InstanceType: "c6g.large", + VCPU: 2, + MemoryMb: 4096, + GPU: 0, + Architecture: "arm64", + }, + "c6g.medium": { + InstanceType: "c6g.medium", + VCPU: 1, + MemoryMb: 2048, + GPU: 0, + Architecture: "arm64", + }, + "c6g.metal": { + InstanceType: "c6g.metal", + VCPU: 64, + MemoryMb: 131072, + GPU: 0, + Architecture: "arm64", + }, + "c6g.xlarge": { + InstanceType: "c6g.xlarge", + VCPU: 4, + MemoryMb: 8192, + GPU: 0, + Architecture: "arm64", + }, + "c6gd": { + InstanceType: "c6gd", + VCPU: 64, + MemoryMb: 0, + GPU: 0, + Architecture: "arm64", + }, + "c6gd.12xlarge": { + InstanceType: "c6gd.12xlarge", + VCPU: 48, + MemoryMb: 98304, + GPU: 0, + Architecture: "arm64", + }, + "c6gd.16xlarge": { + InstanceType: "c6gd.16xlarge", + VCPU: 64, + MemoryMb: 131072, + GPU: 0, + Architecture: "arm64", + }, + "c6gd.2xlarge": { + InstanceType: "c6gd.2xlarge", + VCPU: 8, + MemoryMb: 16384, + GPU: 0, + Architecture: "arm64", + }, + "c6gd.4xlarge": { + InstanceType: "c6gd.4xlarge", + VCPU: 16, + MemoryMb: 32768, + GPU: 0, + Architecture: "arm64", + }, + "c6gd.8xlarge": { + InstanceType: "c6gd.8xlarge", + VCPU: 32, + MemoryMb: 65536, + GPU: 0, + Architecture: "arm64", + }, + "c6gd.large": { + InstanceType: "c6gd.large", + VCPU: 2, + MemoryMb: 4096, + GPU: 0, + Architecture: "arm64", + }, + "c6gd.medium": { + InstanceType: "c6gd.medium", + VCPU: 1, + MemoryMb: 2048, + GPU: 0, + Architecture: "arm64", + }, + "c6gd.metal": { + InstanceType: "c6gd.metal", + VCPU: 64, + MemoryMb: 131072, + GPU: 0, + Architecture: "arm64", + }, + "c6gd.xlarge": { + InstanceType: "c6gd.xlarge", + VCPU: 4, + MemoryMb: 8192, + GPU: 0, + Architecture: "arm64", + }, + "c6gn": { + InstanceType: "c6gn", + VCPU: 64, + MemoryMb: 0, + GPU: 0, + Architecture: "arm64", + }, + "c6gn.12xlarge": { + InstanceType: "c6gn.12xlarge", + VCPU: 48, + MemoryMb: 98304, + GPU: 0, + Architecture: "arm64", + }, + "c6gn.16xlarge": { + InstanceType: "c6gn.16xlarge", + VCPU: 64, + MemoryMb: 131072, + GPU: 0, + Architecture: "arm64", + }, + "c6gn.2xlarge": { + InstanceType: "c6gn.2xlarge", + VCPU: 8, + MemoryMb: 16384, + GPU: 0, + Architecture: "arm64", + }, + "c6gn.4xlarge": { + InstanceType: "c6gn.4xlarge", + VCPU: 16, + MemoryMb: 32768, + GPU: 0, + Architecture: "arm64", + }, + "c6gn.8xlarge": { + InstanceType: "c6gn.8xlarge", + VCPU: 32, + MemoryMb: 65536, + GPU: 0, + Architecture: "arm64", + }, + "c6gn.large": { + InstanceType: "c6gn.large", + VCPU: 2, + MemoryMb: 4096, + GPU: 0, + Architecture: "arm64", + }, + "c6gn.medium": { + InstanceType: "c6gn.medium", + VCPU: 1, + MemoryMb: 2048, + GPU: 0, + Architecture: "arm64", + }, + "c6gn.metal": { + InstanceType: "c6gn.metal", + VCPU: 64, + MemoryMb: 131072, + GPU: 0, + Architecture: "arm64", + }, + "c6gn.xlarge": { + InstanceType: "c6gn.xlarge", + VCPU: 4, + MemoryMb: 8192, + GPU: 0, + Architecture: "arm64", + }, + "c6i": { + InstanceType: "c6i", + VCPU: 128, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "c6i.12xlarge": { + InstanceType: "c6i.12xlarge", + VCPU: 48, + MemoryMb: 98304, + GPU: 0, + Architecture: "amd64", + }, + "c6i.16xlarge": { + InstanceType: "c6i.16xlarge", + VCPU: 64, + MemoryMb: 131072, + GPU: 0, + Architecture: "amd64", + }, + "c6i.24xlarge": { + InstanceType: "c6i.24xlarge", + VCPU: 96, + MemoryMb: 196608, + GPU: 0, + Architecture: "amd64", + }, + "c6i.2xlarge": { + InstanceType: "c6i.2xlarge", + VCPU: 8, + MemoryMb: 16384, + GPU: 0, + Architecture: "amd64", + }, + "c6i.32xlarge": { + InstanceType: "c6i.32xlarge", + VCPU: 128, + MemoryMb: 262144, + GPU: 0, + Architecture: "amd64", + }, + "c6i.4xlarge": { + InstanceType: "c6i.4xlarge", + VCPU: 16, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, + "c6i.8xlarge": { + InstanceType: "c6i.8xlarge", + VCPU: 32, + MemoryMb: 65536, + GPU: 0, + Architecture: "amd64", + }, + "c6i.large": { + InstanceType: "c6i.large", + VCPU: 2, + MemoryMb: 4096, + GPU: 0, + Architecture: "amd64", + }, + "c6i.metal": { + InstanceType: "c6i.metal", + VCPU: 128, + MemoryMb: 262144, + GPU: 0, + Architecture: "amd64", + }, + "c6i.xlarge": { + InstanceType: "c6i.xlarge", + VCPU: 4, + MemoryMb: 8192, + GPU: 0, + Architecture: "amd64", + }, + "c6id": { + InstanceType: "c6id", + VCPU: 128, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "c6id.12xlarge": { + InstanceType: "c6id.12xlarge", + VCPU: 48, + MemoryMb: 98304, + GPU: 0, + Architecture: "amd64", + }, + "c6id.16xlarge": { + InstanceType: "c6id.16xlarge", + VCPU: 64, + MemoryMb: 131072, + GPU: 0, + Architecture: "amd64", + }, + "c6id.24xlarge": { + InstanceType: "c6id.24xlarge", + VCPU: 96, + MemoryMb: 196608, + GPU: 0, + Architecture: "amd64", + }, + "c6id.2xlarge": { + InstanceType: "c6id.2xlarge", + VCPU: 8, + MemoryMb: 16384, + GPU: 0, + Architecture: "amd64", + }, + "c6id.32xlarge": { + InstanceType: "c6id.32xlarge", + VCPU: 128, + MemoryMb: 262144, + GPU: 0, + Architecture: "amd64", + }, + "c6id.4xlarge": { + InstanceType: "c6id.4xlarge", + VCPU: 16, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, + "c6id.8xlarge": { + InstanceType: "c6id.8xlarge", + VCPU: 32, + MemoryMb: 65536, + GPU: 0, + Architecture: "amd64", + }, + "c6id.large": { + InstanceType: "c6id.large", + VCPU: 2, + MemoryMb: 4096, + GPU: 0, + Architecture: "amd64", + }, + "c6id.metal": { + InstanceType: "c6id.metal", + VCPU: 128, + MemoryMb: 262144, + GPU: 0, + Architecture: "amd64", + }, + "c6id.xlarge": { + InstanceType: "c6id.xlarge", + VCPU: 4, + MemoryMb: 8192, + GPU: 0, + Architecture: "amd64", + }, + "c7g": { + InstanceType: "c7g", + VCPU: 64, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "c7g.12xlarge": { + InstanceType: "c7g.12xlarge", + VCPU: 48, + MemoryMb: 98304, + GPU: 0, + Architecture: "amd64", + }, + "c7g.16xlarge": { + InstanceType: "c7g.16xlarge", + VCPU: 64, + MemoryMb: 131072, + GPU: 0, + Architecture: "amd64", + }, + "c7g.2xlarge": { + InstanceType: "c7g.2xlarge", + VCPU: 8, + MemoryMb: 16384, + GPU: 0, + Architecture: "amd64", + }, + "c7g.4xlarge": { + InstanceType: "c7g.4xlarge", + VCPU: 16, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, + "c7g.8xlarge": { + InstanceType: "c7g.8xlarge", + VCPU: 32, + MemoryMb: 65536, + GPU: 0, + Architecture: "amd64", + }, + "c7g.large": { + InstanceType: "c7g.large", + VCPU: 2, + MemoryMb: 4096, + GPU: 0, + Architecture: "amd64", + }, + "c7g.medium": { + InstanceType: "c7g.medium", + VCPU: 1, + MemoryMb: 2048, + GPU: 0, + Architecture: "amd64", + }, + "c7g.xlarge": { + InstanceType: "c7g.xlarge", + VCPU: 4, + MemoryMb: 8192, + GPU: 0, + Architecture: "amd64", + }, + "cc2.8xlarge": { + InstanceType: "cc2.8xlarge", + VCPU: 32, + MemoryMb: 61952, + GPU: 0, + Architecture: "amd64", + }, + "cr1.8xlarge": { + InstanceType: "cr1.8xlarge", + VCPU: 32, + MemoryMb: 249856, + GPU: 0, + Architecture: "amd64", + }, + "d2": { + InstanceType: "d2", + VCPU: 36, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "d2.2xlarge": { + InstanceType: "d2.2xlarge", + VCPU: 8, + MemoryMb: 62464, + GPU: 0, + Architecture: "amd64", + }, + "d2.4xlarge": { + InstanceType: "d2.4xlarge", + VCPU: 16, + MemoryMb: 124928, + GPU: 0, + Architecture: "amd64", + }, + "d2.8xlarge": { + InstanceType: "d2.8xlarge", + VCPU: 36, + MemoryMb: 249856, + GPU: 0, + Architecture: "amd64", + }, + "d2.xlarge": { + InstanceType: "d2.xlarge", + VCPU: 4, + MemoryMb: 31232, + GPU: 0, + Architecture: "amd64", + }, + "d3.2xlarge": { + InstanceType: "d3.2xlarge", + VCPU: 8, + MemoryMb: 65536, + GPU: 0, + Architecture: "amd64", + }, + "d3.4xlarge": { + InstanceType: "d3.4xlarge", + VCPU: 16, + MemoryMb: 131072, + GPU: 0, + Architecture: "amd64", + }, + "d3.8xlarge": { + InstanceType: "d3.8xlarge", + VCPU: 32, + MemoryMb: 262144, + GPU: 0, + Architecture: "amd64", + }, + "d3.xlarge": { + InstanceType: "d3.xlarge", + VCPU: 4, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, + "d3en.12xlarge": { + InstanceType: "d3en.12xlarge", + VCPU: 48, + MemoryMb: 196608, + GPU: 0, + Architecture: "amd64", + }, + "d3en.2xlarge": { + InstanceType: "d3en.2xlarge", + VCPU: 8, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, + "d3en.4xlarge": { + InstanceType: "d3en.4xlarge", + VCPU: 16, + MemoryMb: 65536, + GPU: 0, + Architecture: "amd64", + }, + "d3en.6xlarge": { + InstanceType: "d3en.6xlarge", + VCPU: 24, + MemoryMb: 98304, + GPU: 0, + Architecture: "amd64", + }, + "d3en.8xlarge": { + InstanceType: "d3en.8xlarge", + VCPU: 32, + MemoryMb: 131072, + GPU: 0, + Architecture: "amd64", + }, + "d3en.xlarge": { + InstanceType: "d3en.xlarge", + VCPU: 4, + MemoryMb: 16384, + GPU: 0, + Architecture: "amd64", + }, + "dl1": { + InstanceType: "dl1", + VCPU: 96, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "dl1.24xlarge": { + InstanceType: "dl1.24xlarge", + VCPU: 96, + MemoryMb: 786432, + GPU: 0, + Architecture: "amd64", + }, + "f1": { + InstanceType: "f1", + VCPU: 64, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "f1.16xlarge": { + InstanceType: "f1.16xlarge", + VCPU: 64, + MemoryMb: 999424, + GPU: 0, + Architecture: "amd64", + }, + "f1.2xlarge": { + InstanceType: "f1.2xlarge", + VCPU: 8, + MemoryMb: 124928, + GPU: 0, + Architecture: "amd64", + }, + "f1.4xlarge": { + InstanceType: "f1.4xlarge", + VCPU: 16, + MemoryMb: 249856, + GPU: 0, + Architecture: "amd64", + }, + "g2": { + InstanceType: "g2", + VCPU: 32, + MemoryMb: 0, + GPU: 4, + Architecture: "amd64", + }, + "g2.2xlarge": { + InstanceType: "g2.2xlarge", + VCPU: 8, + MemoryMb: 15360, + GPU: 1, + Architecture: "amd64", + }, + "g2.8xlarge": { + InstanceType: "g2.8xlarge", + VCPU: 32, + MemoryMb: 61440, + GPU: 4, + Architecture: "amd64", + }, + "g3": { + InstanceType: "g3", + VCPU: 64, + MemoryMb: 0, + GPU: 4, + Architecture: "amd64", + }, + "g3.16xlarge": { + InstanceType: "g3.16xlarge", + VCPU: 64, + MemoryMb: 499712, + GPU: 4, + Architecture: "amd64", + }, + "g3.4xlarge": { + InstanceType: "g3.4xlarge", + VCPU: 16, + MemoryMb: 124928, + GPU: 1, + Architecture: "amd64", + }, + "g3.8xlarge": { + InstanceType: "g3.8xlarge", + VCPU: 32, + MemoryMb: 249856, + GPU: 2, + Architecture: "amd64", + }, + "g3s.xlarge": { + InstanceType: "g3s.xlarge", + VCPU: 4, + MemoryMb: 31232, + GPU: 1, + Architecture: "amd64", + }, + "g4ad": { + InstanceType: "g4ad", + VCPU: 192, + MemoryMb: 0, + GPU: 2, + Architecture: "amd64", + }, + "g4ad.16xlarge": { + InstanceType: "g4ad.16xlarge", + VCPU: 64, + MemoryMb: 262144, + GPU: 4, + Architecture: "amd64", + }, + "g4ad.2xlarge": { + InstanceType: "g4ad.2xlarge", + VCPU: 8, + MemoryMb: 32768, + GPU: 1, + Architecture: "amd64", + }, + "g4ad.4xlarge": { + InstanceType: "g4ad.4xlarge", + VCPU: 16, + MemoryMb: 65536, + GPU: 1, + Architecture: "amd64", + }, + "g4ad.8xlarge": { + InstanceType: "g4ad.8xlarge", + VCPU: 32, + MemoryMb: 131072, + GPU: 2, + Architecture: "amd64", + }, + "g4ad.xlarge": { + InstanceType: "g4ad.xlarge", + VCPU: 4, + MemoryMb: 16384, + GPU: 1, + Architecture: "amd64", + }, + "g4dn": { + InstanceType: "g4dn", + VCPU: 96, + MemoryMb: 0, + GPU: 8, + Architecture: "amd64", + }, + "g4dn.12xlarge": { + InstanceType: "g4dn.12xlarge", + VCPU: 48, + MemoryMb: 196608, + GPU: 4, + Architecture: "amd64", + }, + "g4dn.16xlarge": { + InstanceType: "g4dn.16xlarge", + VCPU: 64, + MemoryMb: 262144, + GPU: 1, + Architecture: "amd64", + GPUMemory: 15842934784, + MPSContext: 32, + }, + "g4dn.2xlarge": { + InstanceType: "g4dn.2xlarge", + VCPU: 8, + MemoryMb: 32768, + GPU: 1, + Architecture: "amd64", + GPUMemory: 15842934784, + MPSContext: 32, + }, + "g4dn.4xlarge": { + InstanceType: "g4dn.4xlarge", + VCPU: 16, + MemoryMb: 65536, + GPU: 1, + Architecture: "amd64", + GPUMemory: 15842934784, + MPSContext: 32, + }, + "g4dn.8xlarge": { + InstanceType: "g4dn.8xlarge", + VCPU: 32, + MemoryMb: 131072, + GPU: 1, + Architecture: "amd64", + GPUMemory: 15842934784, + MPSContext: 32, + }, + "g4dn.metal": { + InstanceType: "g4dn.metal", + VCPU: 96, + MemoryMb: 393216, + GPU: 8, + Architecture: "amd64", + }, + "g4dn.xlarge": { + InstanceType: "g4dn.xlarge", + VCPU: 4, + MemoryMb: 16384, + GPU: 1, + Architecture: "amd64", + GPUMemory: 15842934784, + MPSContext: 32, + }, + "g5": { + InstanceType: "g5", + VCPU: 192, + MemoryMb: 0, + GPU: 8, + Architecture: "amd64", + }, + "g5.12xlarge": { + InstanceType: "g5.12xlarge", + VCPU: 48, + MemoryMb: 196608, + GPU: 4, + Architecture: "amd64", + }, + "g5.16xlarge": { + InstanceType: "g5.16xlarge", + VCPU: 64, + MemoryMb: 262144, + GPU: 1, + Architecture: "amd64", + }, + "g5.24xlarge": { + InstanceType: "g5.24xlarge", + VCPU: 96, + MemoryMb: 393216, + GPU: 4, + Architecture: "amd64", + }, + "g5.2xlarge": { + InstanceType: "g5.2xlarge", + VCPU: 8, + MemoryMb: 32768, + GPU: 1, + Architecture: "amd64", + }, + "g5.48xlarge": { + InstanceType: "g5.48xlarge", + VCPU: 192, + MemoryMb: 786432, + GPU: 8, + Architecture: "amd64", + }, + "g5.4xlarge": { + InstanceType: "g5.4xlarge", + VCPU: 16, + MemoryMb: 65536, + GPU: 1, + Architecture: "amd64", + }, + "g5.8xlarge": { + InstanceType: "g5.8xlarge", + VCPU: 32, + MemoryMb: 131072, + GPU: 1, + Architecture: "amd64", + }, + "g5.xlarge": { + InstanceType: "g5.xlarge", + VCPU: 4, + MemoryMb: 16384, + GPU: 1, + Architecture: "amd64", + }, + "g5g": { + InstanceType: "g5g", + VCPU: 64, + MemoryMb: 0, + GPU: 2, + Architecture: "arm64", + }, + "g5g.16xlarge": { + InstanceType: "g5g.16xlarge", + VCPU: 64, + MemoryMb: 131072, + GPU: 2, + Architecture: "arm64", + }, + "g5g.2xlarge": { + InstanceType: "g5g.2xlarge", + VCPU: 8, + MemoryMb: 16384, + GPU: 1, + Architecture: "arm64", + }, + "g5g.4xlarge": { + InstanceType: "g5g.4xlarge", + VCPU: 16, + MemoryMb: 32768, + GPU: 1, + Architecture: "arm64", + }, + "g5g.8xlarge": { + InstanceType: "g5g.8xlarge", + VCPU: 32, + MemoryMb: 65536, + GPU: 1, + Architecture: "arm64", + }, + "g5g.metal": { + InstanceType: "g5g.metal", + VCPU: 64, + MemoryMb: 131072, + GPU: 2, + Architecture: "arm64", + }, + "g5g.xlarge": { + InstanceType: "g5g.xlarge", + VCPU: 4, + MemoryMb: 8192, + GPU: 1, + Architecture: "arm64", + }, + "h1": { + InstanceType: "h1", + VCPU: 64, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "h1.16xlarge": { + InstanceType: "h1.16xlarge", + VCPU: 64, + MemoryMb: 262144, + GPU: 0, + Architecture: "amd64", + }, + "h1.2xlarge": { + InstanceType: "h1.2xlarge", + VCPU: 8, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, + "h1.4xlarge": { + InstanceType: "h1.4xlarge", + VCPU: 16, + MemoryMb: 65536, + GPU: 0, + Architecture: "amd64", + }, + "h1.8xlarge": { + InstanceType: "h1.8xlarge", + VCPU: 32, + MemoryMb: 131072, + GPU: 0, + Architecture: "amd64", + }, + "hpc6a.48xlarge": { + InstanceType: "hpc6a.48xlarge", + VCPU: 96, + MemoryMb: 393216, + GPU: 0, + Architecture: "amd64", + }, + "hs1.8xlarge": { + InstanceType: "hs1.8xlarge", + VCPU: 16, + MemoryMb: 119808, + GPU: 0, + Architecture: "amd64", + }, + "i2": { + InstanceType: "i2", + VCPU: 32, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "i2.2xlarge": { + InstanceType: "i2.2xlarge", + VCPU: 8, + MemoryMb: 62464, + GPU: 0, + Architecture: "amd64", + }, + "i2.4xlarge": { + InstanceType: "i2.4xlarge", + VCPU: 16, + MemoryMb: 124928, + GPU: 0, + Architecture: "amd64", + }, + "i2.8xlarge": { + InstanceType: "i2.8xlarge", + VCPU: 32, + MemoryMb: 249856, + GPU: 0, + Architecture: "amd64", + }, + "i2.large": { + InstanceType: "i2.large", + VCPU: 2, + MemoryMb: 15360, + GPU: 0, + Architecture: "amd64", + }, + "i2.xlarge": { + InstanceType: "i2.xlarge", + VCPU: 4, + MemoryMb: 31232, + GPU: 0, + Architecture: "amd64", + }, + "i3": { + InstanceType: "i3", + VCPU: 64, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "i3.16xlarge": { + InstanceType: "i3.16xlarge", + VCPU: 64, + MemoryMb: 499712, + GPU: 0, + Architecture: "amd64", + }, + "i3.2xlarge": { + InstanceType: "i3.2xlarge", + VCPU: 8, + MemoryMb: 62464, + GPU: 0, + Architecture: "amd64", + }, + "i3.4xlarge": { + InstanceType: "i3.4xlarge", + VCPU: 16, + MemoryMb: 124928, + GPU: 0, + Architecture: "amd64", + }, + "i3.8xlarge": { + InstanceType: "i3.8xlarge", + VCPU: 32, + MemoryMb: 249856, + GPU: 0, + Architecture: "amd64", + }, + "i3.large": { + InstanceType: "i3.large", + VCPU: 2, + MemoryMb: 15616, + GPU: 0, + Architecture: "amd64", + }, + "i3.metal": { + InstanceType: "i3.metal", + VCPU: 64, + MemoryMb: 524288, + GPU: 0, + Architecture: "amd64", + }, + "i3.xlarge": { + InstanceType: "i3.xlarge", + VCPU: 4, + MemoryMb: 31232, + GPU: 0, + Architecture: "amd64", + }, + "i3en": { + InstanceType: "i3en", + VCPU: 96, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "i3en.12xlarge": { + InstanceType: "i3en.12xlarge", + VCPU: 48, + MemoryMb: 393216, + GPU: 0, + Architecture: "amd64", + }, + "i3en.24xlarge": { + InstanceType: "i3en.24xlarge", + VCPU: 96, + MemoryMb: 786432, + GPU: 0, + Architecture: "amd64", + }, + "i3en.2xlarge": { + InstanceType: "i3en.2xlarge", + VCPU: 8, + MemoryMb: 65536, + GPU: 0, + Architecture: "amd64", + }, + "i3en.3xlarge": { + InstanceType: "i3en.3xlarge", + VCPU: 12, + MemoryMb: 98304, + GPU: 0, + Architecture: "amd64", + }, + "i3en.6xlarge": { + InstanceType: "i3en.6xlarge", + VCPU: 24, + MemoryMb: 196608, + GPU: 0, + Architecture: "amd64", + }, + "i3en.large": { + InstanceType: "i3en.large", + VCPU: 2, + MemoryMb: 16384, + GPU: 0, + Architecture: "amd64", + }, + "i3en.metal": { + InstanceType: "i3en.metal", + VCPU: 96, + MemoryMb: 786432, + GPU: 0, + Architecture: "amd64", + }, + "i3en.xlarge": { + InstanceType: "i3en.xlarge", + VCPU: 4, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, + "i3p.16xlarge": { + InstanceType: "i3p.16xlarge", + VCPU: 64, + MemoryMb: 499712, + GPU: 0, + Architecture: "amd64", + }, + "i4i": { + InstanceType: "i4i", + VCPU: 128, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "i4i.16xlarge": { + InstanceType: "i4i.16xlarge", + VCPU: 64, + MemoryMb: 524288, + GPU: 0, + Architecture: "amd64", + }, + "i4i.2xlarge": { + InstanceType: "i4i.2xlarge", + VCPU: 8, + MemoryMb: 65536, + GPU: 0, + Architecture: "amd64", + }, + "i4i.32xlarge": { + InstanceType: "i4i.32xlarge", + VCPU: 128, + MemoryMb: 1048576, + GPU: 0, + Architecture: "amd64", + }, + "i4i.4xlarge": { + InstanceType: "i4i.4xlarge", + VCPU: 16, + MemoryMb: 131072, + GPU: 0, + Architecture: "amd64", + }, + "i4i.8xlarge": { + InstanceType: "i4i.8xlarge", + VCPU: 32, + MemoryMb: 262144, + GPU: 0, + Architecture: "amd64", + }, + "i4i.large": { + InstanceType: "i4i.large", + VCPU: 2, + MemoryMb: 16384, + GPU: 0, + Architecture: "amd64", + }, + "i4i.metal": { + InstanceType: "i4i.metal", + VCPU: 128, + MemoryMb: 1048576, + GPU: 0, + Architecture: "amd64", + }, + "i4i.xlarge": { + InstanceType: "i4i.xlarge", + VCPU: 4, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, + "im4gn": { + InstanceType: "im4gn", + VCPU: 64, + MemoryMb: 0, + GPU: 0, + Architecture: "arm64", + }, + "im4gn.16xlarge": { + InstanceType: "im4gn.16xlarge", + VCPU: 64, + MemoryMb: 262144, + GPU: 0, + Architecture: "arm64", + }, + "im4gn.2xlarge": { + InstanceType: "im4gn.2xlarge", + VCPU: 8, + MemoryMb: 32768, + GPU: 0, + Architecture: "arm64", + }, + "im4gn.4xlarge": { + InstanceType: "im4gn.4xlarge", + VCPU: 16, + MemoryMb: 65536, + GPU: 0, + Architecture: "arm64", + }, + "im4gn.8xlarge": { + InstanceType: "im4gn.8xlarge", + VCPU: 32, + MemoryMb: 131072, + GPU: 0, + Architecture: "arm64", + }, + "im4gn.large": { + InstanceType: "im4gn.large", + VCPU: 2, + MemoryMb: 8192, + GPU: 0, + Architecture: "arm64", + }, + "im4gn.xlarge": { + InstanceType: "im4gn.xlarge", + VCPU: 4, + MemoryMb: 16384, + GPU: 0, + Architecture: "arm64", + }, + "inf1": { + InstanceType: "inf1", + VCPU: 96, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "inf1.24xlarge": { + InstanceType: "inf1.24xlarge", + VCPU: 96, + MemoryMb: 196608, + GPU: 0, + Architecture: "amd64", + }, + "inf1.2xlarge": { + InstanceType: "inf1.2xlarge", + VCPU: 8, + MemoryMb: 16384, + GPU: 0, + Architecture: "amd64", + }, + "inf1.6xlarge": { + InstanceType: "inf1.6xlarge", + VCPU: 24, + MemoryMb: 49152, + GPU: 0, + Architecture: "amd64", + }, + "inf1.xlarge": { + InstanceType: "inf1.xlarge", + VCPU: 4, + MemoryMb: 8192, + GPU: 0, + Architecture: "amd64", + }, + "is4gen.2xlarge": { + InstanceType: "is4gen.2xlarge", + VCPU: 8, + MemoryMb: 49152, + GPU: 0, + Architecture: "arm64", + }, + "is4gen.4xlarge": { + InstanceType: "is4gen.4xlarge", + VCPU: 16, + MemoryMb: 98304, + GPU: 0, + Architecture: "arm64", + }, + "is4gen.8xlarge": { + InstanceType: "is4gen.8xlarge", + VCPU: 32, + MemoryMb: 196608, + GPU: 0, + Architecture: "arm64", + }, + "is4gen.large": { + InstanceType: "is4gen.large", + VCPU: 2, + MemoryMb: 12288, + GPU: 0, + Architecture: "arm64", + }, + "is4gen.medium": { + InstanceType: "is4gen.medium", + VCPU: 1, + MemoryMb: 6144, + GPU: 0, + Architecture: "arm64", + }, + "is4gen.xlarge": { + InstanceType: "is4gen.xlarge", + VCPU: 4, + MemoryMb: 24576, + GPU: 0, + Architecture: "arm64", + }, + "m1.large": { + InstanceType: "m1.large", + VCPU: 2, + MemoryMb: 7680, + GPU: 0, + Architecture: "amd64", + }, + "m1.medium": { + InstanceType: "m1.medium", + VCPU: 1, + MemoryMb: 3840, + GPU: 0, + Architecture: "amd64", + }, + "m1.small": { + InstanceType: "m1.small", + VCPU: 1, + MemoryMb: 1740, + GPU: 0, + Architecture: "amd64", + }, + "m1.xlarge": { + InstanceType: "m1.xlarge", + VCPU: 4, + MemoryMb: 15360, + GPU: 0, + Architecture: "amd64", + }, + "m2.2xlarge": { + InstanceType: "m2.2xlarge", + VCPU: 4, + MemoryMb: 35020, + GPU: 0, + Architecture: "amd64", + }, + "m2.4xlarge": { + InstanceType: "m2.4xlarge", + VCPU: 8, + MemoryMb: 70041, + GPU: 0, + Architecture: "amd64", + }, + "m2.xlarge": { + InstanceType: "m2.xlarge", + VCPU: 2, + MemoryMb: 17510, + GPU: 0, + Architecture: "amd64", + }, + "m3": { + InstanceType: "m3", + VCPU: 8, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "m3.2xlarge": { + InstanceType: "m3.2xlarge", + VCPU: 8, + MemoryMb: 30720, + GPU: 0, + Architecture: "amd64", + }, + "m3.large": { + InstanceType: "m3.large", + VCPU: 2, + MemoryMb: 7680, + GPU: 0, + Architecture: "amd64", + }, + "m3.medium": { + InstanceType: "m3.medium", + VCPU: 1, + MemoryMb: 3840, + GPU: 0, + Architecture: "amd64", + }, + "m3.xlarge": { + InstanceType: "m3.xlarge", + VCPU: 4, + MemoryMb: 15360, + GPU: 0, + Architecture: "amd64", + }, + "m4": { + InstanceType: "m4", + VCPU: 40, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "m4.10xlarge": { + InstanceType: "m4.10xlarge", + VCPU: 40, + MemoryMb: 163840, + GPU: 0, + Architecture: "amd64", + }, + "m4.16xlarge": { + InstanceType: "m4.16xlarge", + VCPU: 64, + MemoryMb: 262144, + GPU: 0, + Architecture: "amd64", + }, + "m4.2xlarge": { + InstanceType: "m4.2xlarge", + VCPU: 8, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, + "m4.4xlarge": { + InstanceType: "m4.4xlarge", + VCPU: 16, + MemoryMb: 65536, + GPU: 0, + Architecture: "amd64", + }, + "m4.large": { + InstanceType: "m4.large", + VCPU: 2, + MemoryMb: 8192, + GPU: 0, + Architecture: "amd64", + }, + "m4.xlarge": { + InstanceType: "m4.xlarge", + VCPU: 4, + MemoryMb: 16384, + GPU: 0, + Architecture: "amd64", + }, + "m5": { + InstanceType: "m5", + VCPU: 96, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "m5.12xlarge": { + InstanceType: "m5.12xlarge", + VCPU: 48, + MemoryMb: 196608, + GPU: 0, + Architecture: "amd64", + }, + "m5.16xlarge": { + InstanceType: "m5.16xlarge", + VCPU: 64, + MemoryMb: 262144, + GPU: 0, + Architecture: "amd64", + }, + "m5.24xlarge": { + InstanceType: "m5.24xlarge", + VCPU: 96, + MemoryMb: 393216, + GPU: 0, + Architecture: "amd64", + }, + "m5.2xlarge": { + InstanceType: "m5.2xlarge", + VCPU: 8, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, + "m5.4xlarge": { + InstanceType: "m5.4xlarge", + VCPU: 16, + MemoryMb: 65536, + GPU: 0, + Architecture: "amd64", + }, + "m5.8xlarge": { + InstanceType: "m5.8xlarge", + VCPU: 32, + MemoryMb: 131072, + GPU: 0, + Architecture: "amd64", + }, + "m5.large": { + InstanceType: "m5.large", + VCPU: 2, + MemoryMb: 8192, + GPU: 0, + Architecture: "amd64", + }, + "m5.metal": { + InstanceType: "m5.metal", + VCPU: 96, + MemoryMb: 393216, + GPU: 0, + Architecture: "amd64", + }, + "m5.xlarge": { + InstanceType: "m5.xlarge", + VCPU: 4, + MemoryMb: 16384, + GPU: 0, + Architecture: "amd64", + }, + "m5a.12xlarge": { + InstanceType: "m5a.12xlarge", + VCPU: 48, + MemoryMb: 196608, + GPU: 0, + Architecture: "amd64", + }, + "m5a.16xlarge": { + InstanceType: "m5a.16xlarge", + VCPU: 64, + MemoryMb: 262144, + GPU: 0, + Architecture: "amd64", + }, + "m5a.24xlarge": { + InstanceType: "m5a.24xlarge", + VCPU: 96, + MemoryMb: 393216, + GPU: 0, + Architecture: "amd64", + }, + "m5a.2xlarge": { + InstanceType: "m5a.2xlarge", + VCPU: 8, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, + "m5a.4xlarge": { + InstanceType: "m5a.4xlarge", + VCPU: 16, + MemoryMb: 65536, + GPU: 0, + Architecture: "amd64", + }, + "m5a.8xlarge": { + InstanceType: "m5a.8xlarge", + VCPU: 32, + MemoryMb: 131072, + GPU: 0, + Architecture: "amd64", + }, + "m5a.large": { + InstanceType: "m5a.large", + VCPU: 2, + MemoryMb: 8192, + GPU: 0, + Architecture: "amd64", + }, + "m5a.xlarge": { + InstanceType: "m5a.xlarge", + VCPU: 4, + MemoryMb: 16384, + GPU: 0, + Architecture: "amd64", + }, + "m5ad.12xlarge": { + InstanceType: "m5ad.12xlarge", + VCPU: 48, + MemoryMb: 196608, + GPU: 0, + Architecture: "amd64", + }, + "m5ad.16xlarge": { + InstanceType: "m5ad.16xlarge", + VCPU: 64, + MemoryMb: 262144, + GPU: 0, + Architecture: "amd64", + }, + "m5ad.24xlarge": { + InstanceType: "m5ad.24xlarge", + VCPU: 96, + MemoryMb: 393216, + GPU: 0, + Architecture: "amd64", + }, + "m5ad.2xlarge": { + InstanceType: "m5ad.2xlarge", + VCPU: 8, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, + "m5ad.4xlarge": { + InstanceType: "m5ad.4xlarge", + VCPU: 16, + MemoryMb: 65536, + GPU: 0, + Architecture: "amd64", + }, + "m5ad.8xlarge": { + InstanceType: "m5ad.8xlarge", + VCPU: 32, + MemoryMb: 131072, + GPU: 0, + Architecture: "amd64", + }, + "m5ad.large": { + InstanceType: "m5ad.large", + VCPU: 2, + MemoryMb: 8192, + GPU: 0, + Architecture: "amd64", + }, + "m5ad.xlarge": { + InstanceType: "m5ad.xlarge", + VCPU: 4, + MemoryMb: 16384, + GPU: 0, + Architecture: "amd64", + }, + "m5d": { + InstanceType: "m5d", + VCPU: 96, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "m5d.12xlarge": { + InstanceType: "m5d.12xlarge", + VCPU: 48, + MemoryMb: 196608, + GPU: 0, + Architecture: "amd64", + }, + "m5d.16xlarge": { + InstanceType: "m5d.16xlarge", + VCPU: 64, + MemoryMb: 262144, + GPU: 0, + Architecture: "amd64", + }, + "m5d.24xlarge": { + InstanceType: "m5d.24xlarge", + VCPU: 96, + MemoryMb: 393216, + GPU: 0, + Architecture: "amd64", + }, + "m5d.2xlarge": { + InstanceType: "m5d.2xlarge", + VCPU: 8, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, + "m5d.4xlarge": { + InstanceType: "m5d.4xlarge", + VCPU: 16, + MemoryMb: 65536, + GPU: 0, + Architecture: "amd64", + }, + "m5d.8xlarge": { + InstanceType: "m5d.8xlarge", + VCPU: 32, + MemoryMb: 131072, + GPU: 0, + Architecture: "amd64", + }, + "m5d.large": { + InstanceType: "m5d.large", + VCPU: 2, + MemoryMb: 8192, + GPU: 0, + Architecture: "amd64", + }, + "m5d.metal": { + InstanceType: "m5d.metal", + VCPU: 96, + MemoryMb: 393216, + GPU: 0, + Architecture: "amd64", + }, + "m5d.xlarge": { + InstanceType: "m5d.xlarge", + VCPU: 4, + MemoryMb: 16384, + GPU: 0, + Architecture: "amd64", + }, + "m5dn": { + InstanceType: "m5dn", + VCPU: 96, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "m5dn.12xlarge": { + InstanceType: "m5dn.12xlarge", + VCPU: 48, + MemoryMb: 196608, + GPU: 0, + Architecture: "amd64", + }, + "m5dn.16xlarge": { + InstanceType: "m5dn.16xlarge", + VCPU: 64, + MemoryMb: 262144, + GPU: 0, + Architecture: "amd64", + }, + "m5dn.24xlarge": { + InstanceType: "m5dn.24xlarge", + VCPU: 96, + MemoryMb: 393216, + GPU: 0, + Architecture: "amd64", + }, + "m5dn.2xlarge": { + InstanceType: "m5dn.2xlarge", + VCPU: 8, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, + "m5dn.4xlarge": { + InstanceType: "m5dn.4xlarge", + VCPU: 16, + MemoryMb: 65536, + GPU: 0, + Architecture: "amd64", + }, + "m5dn.8xlarge": { + InstanceType: "m5dn.8xlarge", + VCPU: 32, + MemoryMb: 131072, + GPU: 0, + Architecture: "amd64", + }, + "m5dn.large": { + InstanceType: "m5dn.large", + VCPU: 2, + MemoryMb: 8192, + GPU: 0, + Architecture: "amd64", + }, + "m5dn.metal": { + InstanceType: "m5dn.metal", + VCPU: 96, + MemoryMb: 393216, + GPU: 0, + Architecture: "amd64", + }, + "m5dn.xlarge": { + InstanceType: "m5dn.xlarge", + VCPU: 4, + MemoryMb: 16384, + GPU: 0, + Architecture: "amd64", + }, + "m5n": { + InstanceType: "m5n", + VCPU: 96, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "m5n.12xlarge": { + InstanceType: "m5n.12xlarge", + VCPU: 48, + MemoryMb: 196608, + GPU: 0, + Architecture: "amd64", + }, + "m5n.16xlarge": { + InstanceType: "m5n.16xlarge", + VCPU: 64, + MemoryMb: 262144, + GPU: 0, + Architecture: "amd64", + }, + "m5n.24xlarge": { + InstanceType: "m5n.24xlarge", + VCPU: 96, + MemoryMb: 393216, + GPU: 0, + Architecture: "amd64", + }, + "m5n.2xlarge": { + InstanceType: "m5n.2xlarge", + VCPU: 8, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, + "m5n.4xlarge": { + InstanceType: "m5n.4xlarge", + VCPU: 16, + MemoryMb: 65536, + GPU: 0, + Architecture: "amd64", + }, + "m5n.8xlarge": { + InstanceType: "m5n.8xlarge", + VCPU: 32, + MemoryMb: 131072, + GPU: 0, + Architecture: "amd64", + }, + "m5n.large": { + InstanceType: "m5n.large", + VCPU: 2, + MemoryMb: 8192, + GPU: 0, + Architecture: "amd64", + }, + "m5n.metal": { + InstanceType: "m5n.metal", + VCPU: 96, + MemoryMb: 393216, + GPU: 0, + Architecture: "amd64", + }, + "m5n.xlarge": { + InstanceType: "m5n.xlarge", + VCPU: 4, + MemoryMb: 16384, + GPU: 0, + Architecture: "amd64", + }, + "m5zn": { + InstanceType: "m5zn", + VCPU: 48, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "m5zn.12xlarge": { + InstanceType: "m5zn.12xlarge", + VCPU: 48, + MemoryMb: 196608, + GPU: 0, + Architecture: "amd64", + }, + "m5zn.2xlarge": { + InstanceType: "m5zn.2xlarge", + VCPU: 8, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, + "m5zn.3xlarge": { + InstanceType: "m5zn.3xlarge", + VCPU: 12, + MemoryMb: 49152, + GPU: 0, + Architecture: "amd64", + }, + "m5zn.6xlarge": { + InstanceType: "m5zn.6xlarge", + VCPU: 24, + MemoryMb: 98304, + GPU: 0, + Architecture: "amd64", + }, + "m5zn.large": { + InstanceType: "m5zn.large", + VCPU: 2, + MemoryMb: 8192, + GPU: 0, + Architecture: "amd64", + }, + "m5zn.metal": { + InstanceType: "m5zn.metal", + VCPU: 48, + MemoryMb: 196608, + GPU: 0, + Architecture: "amd64", + }, + "m5zn.xlarge": { + InstanceType: "m5zn.xlarge", + VCPU: 4, + MemoryMb: 16384, + GPU: 0, + Architecture: "amd64", + }, + "m6a": { + InstanceType: "m6a", + VCPU: 192, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "m6a.12xlarge": { + InstanceType: "m6a.12xlarge", + VCPU: 48, + MemoryMb: 196608, + GPU: 0, + Architecture: "amd64", + }, + "m6a.16xlarge": { + InstanceType: "m6a.16xlarge", + VCPU: 64, + MemoryMb: 262144, + GPU: 0, + Architecture: "amd64", + }, + "m6a.24xlarge": { + InstanceType: "m6a.24xlarge", + VCPU: 96, + MemoryMb: 393216, + GPU: 0, + Architecture: "amd64", + }, + "m6a.2xlarge": { + InstanceType: "m6a.2xlarge", + VCPU: 8, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, + "m6a.32xlarge": { + InstanceType: "m6a.32xlarge", + VCPU: 128, + MemoryMb: 524288, + GPU: 0, + Architecture: "amd64", + }, + "m6a.48xlarge": { + InstanceType: "m6a.48xlarge", + VCPU: 192, + MemoryMb: 786432, + GPU: 0, + Architecture: "amd64", + }, + "m6a.4xlarge": { + InstanceType: "m6a.4xlarge", + VCPU: 16, + MemoryMb: 65536, + GPU: 0, + Architecture: "amd64", + }, + "m6a.8xlarge": { + InstanceType: "m6a.8xlarge", + VCPU: 32, + MemoryMb: 131072, + GPU: 0, + Architecture: "amd64", + }, + "m6a.large": { + InstanceType: "m6a.large", + VCPU: 2, + MemoryMb: 8192, + GPU: 0, + Architecture: "amd64", + }, + "m6a.metal": { + InstanceType: "m6a.metal", + VCPU: 192, + MemoryMb: 786432, + GPU: 0, + Architecture: "amd64", + }, + "m6a.xlarge": { + InstanceType: "m6a.xlarge", + VCPU: 4, + MemoryMb: 16384, + GPU: 0, + Architecture: "amd64", + }, + "m6g": { + InstanceType: "m6g", + VCPU: 64, + MemoryMb: 0, + GPU: 0, + Architecture: "arm64", + }, + "m6g.12xlarge": { + InstanceType: "m6g.12xlarge", + VCPU: 48, + MemoryMb: 196608, + GPU: 0, + Architecture: "arm64", + }, + "m6g.16xlarge": { + InstanceType: "m6g.16xlarge", + VCPU: 64, + MemoryMb: 262144, + GPU: 0, + Architecture: "arm64", + }, + "m6g.2xlarge": { + InstanceType: "m6g.2xlarge", + VCPU: 8, + MemoryMb: 32768, + GPU: 0, + Architecture: "arm64", + }, + "m6g.4xlarge": { + InstanceType: "m6g.4xlarge", + VCPU: 16, + MemoryMb: 65536, + GPU: 0, + Architecture: "arm64", + }, + "m6g.8xlarge": { + InstanceType: "m6g.8xlarge", + VCPU: 32, + MemoryMb: 131072, + GPU: 0, + Architecture: "arm64", + }, + "m6g.large": { + InstanceType: "m6g.large", + VCPU: 2, + MemoryMb: 8192, + GPU: 0, + Architecture: "arm64", + }, + "m6g.medium": { + InstanceType: "m6g.medium", + VCPU: 1, + MemoryMb: 4096, + GPU: 0, + Architecture: "arm64", + }, + "m6g.metal": { + InstanceType: "m6g.metal", + VCPU: 64, + MemoryMb: 262144, + GPU: 0, + Architecture: "arm64", + }, + "m6g.xlarge": { + InstanceType: "m6g.xlarge", + VCPU: 4, + MemoryMb: 16384, + GPU: 0, + Architecture: "arm64", + }, + "m6gd": { + InstanceType: "m6gd", + VCPU: 64, + MemoryMb: 0, + GPU: 0, + Architecture: "arm64", + }, + "m6gd.12xlarge": { + InstanceType: "m6gd.12xlarge", + VCPU: 48, + MemoryMb: 196608, + GPU: 0, + Architecture: "arm64", + }, + "m6gd.16xlarge": { + InstanceType: "m6gd.16xlarge", + VCPU: 64, + MemoryMb: 262144, + GPU: 0, + Architecture: "arm64", + }, + "m6gd.2xlarge": { + InstanceType: "m6gd.2xlarge", + VCPU: 8, + MemoryMb: 32768, + GPU: 0, + Architecture: "arm64", + }, + "m6gd.4xlarge": { + InstanceType: "m6gd.4xlarge", + VCPU: 16, + MemoryMb: 65536, + GPU: 0, + Architecture: "arm64", + }, + "m6gd.8xlarge": { + InstanceType: "m6gd.8xlarge", + VCPU: 32, + MemoryMb: 131072, + GPU: 0, + Architecture: "arm64", + }, + "m6gd.large": { + InstanceType: "m6gd.large", + VCPU: 2, + MemoryMb: 8192, + GPU: 0, + Architecture: "arm64", + }, + "m6gd.medium": { + InstanceType: "m6gd.medium", + VCPU: 1, + MemoryMb: 4096, + GPU: 0, + Architecture: "arm64", + }, + "m6gd.metal": { + InstanceType: "m6gd.metal", + VCPU: 64, + MemoryMb: 262144, + GPU: 0, + Architecture: "arm64", + }, + "m6gd.xlarge": { + InstanceType: "m6gd.xlarge", + VCPU: 4, + MemoryMb: 16384, + GPU: 0, + Architecture: "arm64", + }, + "m6i": { + InstanceType: "m6i", + VCPU: 128, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "m6i.12xlarge": { + InstanceType: "m6i.12xlarge", + VCPU: 48, + MemoryMb: 196608, + GPU: 0, + Architecture: "amd64", + }, + "m6i.16xlarge": { + InstanceType: "m6i.16xlarge", + VCPU: 64, + MemoryMb: 262144, + GPU: 0, + Architecture: "amd64", + }, + "m6i.24xlarge": { + InstanceType: "m6i.24xlarge", + VCPU: 96, + MemoryMb: 393216, + GPU: 0, + Architecture: "amd64", + }, + "m6i.2xlarge": { + InstanceType: "m6i.2xlarge", + VCPU: 8, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, + "m6i.32xlarge": { + InstanceType: "m6i.32xlarge", + VCPU: 128, + MemoryMb: 524288, + GPU: 0, + Architecture: "amd64", + }, + "m6i.4xlarge": { + InstanceType: "m6i.4xlarge", + VCPU: 16, + MemoryMb: 65536, + GPU: 0, + Architecture: "amd64", + }, + "m6i.8xlarge": { + InstanceType: "m6i.8xlarge", + VCPU: 32, + MemoryMb: 131072, + GPU: 0, + Architecture: "amd64", + }, + "m6i.large": { + InstanceType: "m6i.large", + VCPU: 2, + MemoryMb: 8192, + GPU: 0, + Architecture: "amd64", + }, + "m6i.metal": { + InstanceType: "m6i.metal", + VCPU: 128, + MemoryMb: 524288, + GPU: 0, + Architecture: "amd64", + }, + "m6i.xlarge": { + InstanceType: "m6i.xlarge", + VCPU: 4, + MemoryMb: 16384, + GPU: 0, + Architecture: "amd64", + }, + "m6id": { + InstanceType: "m6id", + VCPU: 128, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "m6id.12xlarge": { + InstanceType: "m6id.12xlarge", + VCPU: 48, + MemoryMb: 196608, + GPU: 0, + Architecture: "amd64", + }, + "m6id.16xlarge": { + InstanceType: "m6id.16xlarge", + VCPU: 64, + MemoryMb: 262144, + GPU: 0, + Architecture: "amd64", + }, + "m6id.24xlarge": { + InstanceType: "m6id.24xlarge", + VCPU: 96, + MemoryMb: 393216, + GPU: 0, + Architecture: "amd64", + }, + "m6id.2xlarge": { + InstanceType: "m6id.2xlarge", + VCPU: 8, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, + "m6id.32xlarge": { + InstanceType: "m6id.32xlarge", + VCPU: 128, + MemoryMb: 524288, + GPU: 0, + Architecture: "amd64", + }, + "m6id.4xlarge": { + InstanceType: "m6id.4xlarge", + VCPU: 16, + MemoryMb: 65536, + GPU: 0, + Architecture: "amd64", + }, + "m6id.8xlarge": { + InstanceType: "m6id.8xlarge", + VCPU: 32, + MemoryMb: 131072, + GPU: 0, + Architecture: "amd64", + }, + "m6id.large": { + InstanceType: "m6id.large", + VCPU: 2, + MemoryMb: 8192, + GPU: 0, + Architecture: "amd64", + }, + "m6id.metal": { + InstanceType: "m6id.metal", + VCPU: 128, + MemoryMb: 524288, + GPU: 0, + Architecture: "amd64", + }, + "m6id.xlarge": { + InstanceType: "m6id.xlarge", + VCPU: 4, + MemoryMb: 16384, + GPU: 0, + Architecture: "amd64", + }, + "mac1": { + InstanceType: "mac1", + VCPU: 12, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "mac1.metal": { + InstanceType: "mac1.metal", + VCPU: 12, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, + "mac2": { + InstanceType: "mac2", + VCPU: 12, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "mac2.metal": { + InstanceType: "mac2.metal", + VCPU: 12, + MemoryMb: 16384, + GPU: 0, + Architecture: "amd64", + }, + "p2": { + InstanceType: "p2", + VCPU: 64, + MemoryMb: 0, + GPU: 16, + Architecture: "amd64", + }, + "p2.16xlarge": { + InstanceType: "p2.16xlarge", + VCPU: 64, + MemoryMb: 749568, + GPU: 16, + Architecture: "amd64", + }, + "p2.8xlarge": { + InstanceType: "p2.8xlarge", + VCPU: 32, + MemoryMb: 499712, + GPU: 8, + Architecture: "amd64", + }, + "p2.xlarge": { + InstanceType: "p2.xlarge", + VCPU: 4, + MemoryMb: 62464, + GPU: 1, + Architecture: "amd64", + GPUMemory: 12000000000, // Rough estimate of 12 GB + MPSContext: 16, + }, + "p3": { + InstanceType: "p3", + VCPU: 64, + MemoryMb: 0, + GPU: 8, + Architecture: "amd64", + }, + "p3.16xlarge": { + InstanceType: "p3.16xlarge", + VCPU: 64, + MemoryMb: 499712, + GPU: 8, + Architecture: "amd64", + }, + "p3.2xlarge": { + InstanceType: "p3.2xlarge", + VCPU: 8, + MemoryMb: 62464, + GPU: 1, + Architecture: "amd64", + GPUMemory: 16000000000, // Rough estimate of 16 GB + MPSContext: 32, + }, + "p3.8xlarge": { + InstanceType: "p3.8xlarge", + VCPU: 32, + MemoryMb: 249856, + GPU: 4, + Architecture: "amd64", + }, + "p3dn": { + InstanceType: "p3dn", + VCPU: 96, + MemoryMb: 0, + GPU: 8, + Architecture: "amd64", + }, + "p3dn.24xlarge": { + InstanceType: "p3dn.24xlarge", + VCPU: 96, + MemoryMb: 786432, + GPU: 8, + Architecture: "amd64", + }, + "p4d": { + InstanceType: "p4d", + VCPU: 96, + MemoryMb: 0, + GPU: 8, + Architecture: "amd64", + }, + "p4d.24xlarge": { + InstanceType: "p4d.24xlarge", + VCPU: 96, + MemoryMb: 1179648, + GPU: 8, + Architecture: "amd64", + }, + "p4de": { + InstanceType: "p4de", + VCPU: 96, + MemoryMb: 0, + GPU: 8, + Architecture: "amd64", + }, + "p4de.24xlarge": { + InstanceType: "p4de.24xlarge", + VCPU: 96, + MemoryMb: 1179648, + GPU: 8, + Architecture: "amd64", + }, + "r3": { + InstanceType: "r3", + VCPU: 32, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "r3.2xlarge": { + InstanceType: "r3.2xlarge", + VCPU: 8, + MemoryMb: 62464, + GPU: 0, + Architecture: "amd64", + }, + "r3.4xlarge": { + InstanceType: "r3.4xlarge", + VCPU: 16, + MemoryMb: 124928, + GPU: 0, + Architecture: "amd64", + }, + "r3.8xlarge": { + InstanceType: "r3.8xlarge", + VCPU: 32, + MemoryMb: 249856, + GPU: 0, + Architecture: "amd64", + }, + "r3.large": { + InstanceType: "r3.large", + VCPU: 2, + MemoryMb: 15616, + GPU: 0, + Architecture: "amd64", + }, + "r3.xlarge": { + InstanceType: "r3.xlarge", + VCPU: 4, + MemoryMb: 31232, + GPU: 0, + Architecture: "amd64", + }, + "r4": { + InstanceType: "r4", + VCPU: 64, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "r4.16xlarge": { + InstanceType: "r4.16xlarge", + VCPU: 64, + MemoryMb: 499712, + GPU: 0, + Architecture: "amd64", + }, + "r4.2xlarge": { + InstanceType: "r4.2xlarge", + VCPU: 8, + MemoryMb: 62464, + GPU: 0, + Architecture: "amd64", + }, + "r4.4xlarge": { + InstanceType: "r4.4xlarge", + VCPU: 16, + MemoryMb: 124928, + GPU: 0, + Architecture: "amd64", + }, + "r4.8xlarge": { + InstanceType: "r4.8xlarge", + VCPU: 32, + MemoryMb: 249856, + GPU: 0, + Architecture: "amd64", + }, + "r4.large": { + InstanceType: "r4.large", + VCPU: 2, + MemoryMb: 15616, + GPU: 0, + Architecture: "amd64", + }, + "r4.xlarge": { + InstanceType: "r4.xlarge", + VCPU: 4, + MemoryMb: 31232, + GPU: 0, + Architecture: "amd64", + }, + "r5": { + InstanceType: "r5", + VCPU: 96, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "r5.12xlarge": { + InstanceType: "r5.12xlarge", + VCPU: 48, + MemoryMb: 393216, + GPU: 0, + Architecture: "amd64", + }, + "r5.16xlarge": { + InstanceType: "r5.16xlarge", + VCPU: 64, + MemoryMb: 524288, + GPU: 0, + Architecture: "amd64", + }, + "r5.24xlarge": { + InstanceType: "r5.24xlarge", + VCPU: 96, + MemoryMb: 786432, + GPU: 0, + Architecture: "amd64", + }, + "r5.2xlarge": { + InstanceType: "r5.2xlarge", + VCPU: 8, + MemoryMb: 65536, + GPU: 0, + Architecture: "amd64", + }, + "r5.4xlarge": { + InstanceType: "r5.4xlarge", + VCPU: 16, + MemoryMb: 131072, + GPU: 0, + Architecture: "amd64", + }, + "r5.8xlarge": { + InstanceType: "r5.8xlarge", + VCPU: 32, + MemoryMb: 262144, + GPU: 0, + Architecture: "amd64", + }, + "r5.large": { + InstanceType: "r5.large", + VCPU: 2, + MemoryMb: 16384, + GPU: 0, + Architecture: "amd64", + }, + "r5.metal": { + InstanceType: "r5.metal", + VCPU: 96, + MemoryMb: 786432, + GPU: 0, + Architecture: "amd64", + }, + "r5.xlarge": { + InstanceType: "r5.xlarge", + VCPU: 4, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, + "r5a.12xlarge": { + InstanceType: "r5a.12xlarge", + VCPU: 48, + MemoryMb: 393216, + GPU: 0, + Architecture: "amd64", + }, + "r5a.16xlarge": { + InstanceType: "r5a.16xlarge", + VCPU: 64, + MemoryMb: 524288, + GPU: 0, + Architecture: "amd64", + }, + "r5a.24xlarge": { + InstanceType: "r5a.24xlarge", + VCPU: 96, + MemoryMb: 786432, + GPU: 0, + Architecture: "amd64", + }, + "r5a.2xlarge": { + InstanceType: "r5a.2xlarge", + VCPU: 8, + MemoryMb: 65536, + GPU: 0, + Architecture: "amd64", + }, + "r5a.4xlarge": { + InstanceType: "r5a.4xlarge", + VCPU: 16, + MemoryMb: 131072, + GPU: 0, + Architecture: "amd64", + }, + "r5a.8xlarge": { + InstanceType: "r5a.8xlarge", + VCPU: 32, + MemoryMb: 262144, + GPU: 0, + Architecture: "amd64", + }, + "r5a.large": { + InstanceType: "r5a.large", + VCPU: 2, + MemoryMb: 16384, + GPU: 0, + Architecture: "amd64", + }, + "r5a.xlarge": { + InstanceType: "r5a.xlarge", + VCPU: 4, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, + "r5ad.12xlarge": { + InstanceType: "r5ad.12xlarge", + VCPU: 48, + MemoryMb: 393216, + GPU: 0, + Architecture: "amd64", + }, + "r5ad.16xlarge": { + InstanceType: "r5ad.16xlarge", + VCPU: 64, + MemoryMb: 524288, + GPU: 0, + Architecture: "amd64", + }, + "r5ad.24xlarge": { + InstanceType: "r5ad.24xlarge", + VCPU: 96, + MemoryMb: 786432, + GPU: 0, + Architecture: "amd64", + }, + "r5ad.2xlarge": { + InstanceType: "r5ad.2xlarge", + VCPU: 8, + MemoryMb: 65536, + GPU: 0, + Architecture: "amd64", + }, + "r5ad.4xlarge": { + InstanceType: "r5ad.4xlarge", + VCPU: 16, + MemoryMb: 131072, + GPU: 0, + Architecture: "amd64", + }, + "r5ad.8xlarge": { + InstanceType: "r5ad.8xlarge", + VCPU: 32, + MemoryMb: 262144, + GPU: 0, + Architecture: "amd64", + }, + "r5ad.large": { + InstanceType: "r5ad.large", + VCPU: 2, + MemoryMb: 16384, + GPU: 0, + Architecture: "amd64", + }, + "r5ad.xlarge": { + InstanceType: "r5ad.xlarge", + VCPU: 4, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, + "r5b": { + InstanceType: "r5b", + VCPU: 96, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "r5b.12xlarge": { + InstanceType: "r5b.12xlarge", + VCPU: 48, + MemoryMb: 393216, + GPU: 0, + Architecture: "amd64", + }, + "r5b.16xlarge": { + InstanceType: "r5b.16xlarge", + VCPU: 64, + MemoryMb: 524288, + GPU: 0, + Architecture: "amd64", + }, + "r5b.24xlarge": { + InstanceType: "r5b.24xlarge", + VCPU: 96, + MemoryMb: 786432, + GPU: 0, + Architecture: "amd64", + }, + "r5b.2xlarge": { + InstanceType: "r5b.2xlarge", + VCPU: 8, + MemoryMb: 65536, + GPU: 0, + Architecture: "amd64", + }, + "r5b.4xlarge": { + InstanceType: "r5b.4xlarge", + VCPU: 16, + MemoryMb: 131072, + GPU: 0, + Architecture: "amd64", + }, + "r5b.8xlarge": { + InstanceType: "r5b.8xlarge", + VCPU: 32, + MemoryMb: 262144, + GPU: 0, + Architecture: "amd64", + }, + "r5b.large": { + InstanceType: "r5b.large", + VCPU: 2, + MemoryMb: 16384, + GPU: 0, + Architecture: "amd64", + }, + "r5b.metal": { + InstanceType: "r5b.metal", + VCPU: 96, + MemoryMb: 786432, + GPU: 0, + Architecture: "amd64", + }, + "r5b.xlarge": { + InstanceType: "r5b.xlarge", + VCPU: 4, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, + "r5d": { + InstanceType: "r5d", + VCPU: 96, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "r5d.12xlarge": { + InstanceType: "r5d.12xlarge", + VCPU: 48, + MemoryMb: 393216, + GPU: 0, + Architecture: "amd64", + }, + "r5d.16xlarge": { + InstanceType: "r5d.16xlarge", + VCPU: 64, + MemoryMb: 524288, + GPU: 0, + Architecture: "amd64", + }, + "r5d.24xlarge": { + InstanceType: "r5d.24xlarge", + VCPU: 96, + MemoryMb: 786432, + GPU: 0, + Architecture: "amd64", + }, + "r5d.2xlarge": { + InstanceType: "r5d.2xlarge", + VCPU: 8, + MemoryMb: 65536, + GPU: 0, + Architecture: "amd64", + }, + "r5d.4xlarge": { + InstanceType: "r5d.4xlarge", + VCPU: 16, + MemoryMb: 131072, + GPU: 0, + Architecture: "amd64", + }, + "r5d.8xlarge": { + InstanceType: "r5d.8xlarge", + VCPU: 32, + MemoryMb: 262144, + GPU: 0, + Architecture: "amd64", + }, + "r5d.large": { + InstanceType: "r5d.large", + VCPU: 2, + MemoryMb: 16384, + GPU: 0, + Architecture: "amd64", + }, + "r5d.metal": { + InstanceType: "r5d.metal", + VCPU: 96, + MemoryMb: 786432, + GPU: 0, + Architecture: "amd64", + }, + "r5d.xlarge": { + InstanceType: "r5d.xlarge", + VCPU: 4, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, + "r5dn": { + InstanceType: "r5dn", + VCPU: 96, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "r5dn.12xlarge": { + InstanceType: "r5dn.12xlarge", + VCPU: 48, + MemoryMb: 393216, + GPU: 0, + Architecture: "amd64", + }, + "r5dn.16xlarge": { + InstanceType: "r5dn.16xlarge", + VCPU: 64, + MemoryMb: 524288, + GPU: 0, + Architecture: "amd64", + }, + "r5dn.24xlarge": { + InstanceType: "r5dn.24xlarge", + VCPU: 96, + MemoryMb: 786432, + GPU: 0, + Architecture: "amd64", + }, + "r5dn.2xlarge": { + InstanceType: "r5dn.2xlarge", + VCPU: 8, + MemoryMb: 65536, + GPU: 0, + Architecture: "amd64", + }, + "r5dn.4xlarge": { + InstanceType: "r5dn.4xlarge", + VCPU: 16, + MemoryMb: 131072, + GPU: 0, + Architecture: "amd64", + }, + "r5dn.8xlarge": { + InstanceType: "r5dn.8xlarge", + VCPU: 32, + MemoryMb: 262144, + GPU: 0, + Architecture: "amd64", + }, + "r5dn.large": { + InstanceType: "r5dn.large", + VCPU: 2, + MemoryMb: 16384, + GPU: 0, + Architecture: "amd64", + }, + "r5dn.metal": { + InstanceType: "r5dn.metal", + VCPU: 96, + MemoryMb: 786432, + GPU: 0, + Architecture: "amd64", + }, + "r5dn.xlarge": { + InstanceType: "r5dn.xlarge", + VCPU: 4, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, + "r5n": { + InstanceType: "r5n", + VCPU: 96, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "r5n.12xlarge": { + InstanceType: "r5n.12xlarge", + VCPU: 48, + MemoryMb: 393216, + GPU: 0, + Architecture: "amd64", + }, + "r5n.16xlarge": { + InstanceType: "r5n.16xlarge", + VCPU: 64, + MemoryMb: 524288, + GPU: 0, + Architecture: "amd64", + }, + "r5n.24xlarge": { + InstanceType: "r5n.24xlarge", + VCPU: 96, + MemoryMb: 786432, + GPU: 0, + Architecture: "amd64", + }, + "r5n.2xlarge": { + InstanceType: "r5n.2xlarge", + VCPU: 8, + MemoryMb: 65536, + GPU: 0, + Architecture: "amd64", + }, + "r5n.4xlarge": { + InstanceType: "r5n.4xlarge", + VCPU: 16, + MemoryMb: 131072, + GPU: 0, + Architecture: "amd64", + }, + "r5n.8xlarge": { + InstanceType: "r5n.8xlarge", + VCPU: 32, + MemoryMb: 262144, + GPU: 0, + Architecture: "amd64", + }, + "r5n.large": { + InstanceType: "r5n.large", + VCPU: 2, + MemoryMb: 16384, + GPU: 0, + Architecture: "amd64", + }, + "r5n.metal": { + InstanceType: "r5n.metal", + VCPU: 96, + MemoryMb: 786432, + GPU: 0, + Architecture: "amd64", + }, + "r5n.xlarge": { + InstanceType: "r5n.xlarge", + VCPU: 4, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, + "r6g": { + InstanceType: "r6g", + VCPU: 64, + MemoryMb: 0, + GPU: 0, + Architecture: "arm64", + }, + "r6g.12xlarge": { + InstanceType: "r6g.12xlarge", + VCPU: 48, + MemoryMb: 393216, + GPU: 0, + Architecture: "arm64", + }, + "r6g.16xlarge": { + InstanceType: "r6g.16xlarge", + VCPU: 64, + MemoryMb: 524288, + GPU: 0, + Architecture: "arm64", + }, + "r6g.2xlarge": { + InstanceType: "r6g.2xlarge", + VCPU: 8, + MemoryMb: 65536, + GPU: 0, + Architecture: "arm64", + }, + "r6g.4xlarge": { + InstanceType: "r6g.4xlarge", + VCPU: 16, + MemoryMb: 131072, + GPU: 0, + Architecture: "arm64", + }, + "r6g.8xlarge": { + InstanceType: "r6g.8xlarge", + VCPU: 32, + MemoryMb: 262144, + GPU: 0, + Architecture: "arm64", + }, + "r6g.large": { + InstanceType: "r6g.large", + VCPU: 2, + MemoryMb: 16384, + GPU: 0, + Architecture: "arm64", + }, + "r6g.medium": { + InstanceType: "r6g.medium", + VCPU: 1, + MemoryMb: 8192, + GPU: 0, + Architecture: "arm64", + }, + "r6g.metal": { + InstanceType: "r6g.metal", + VCPU: 64, + MemoryMb: 524288, + GPU: 0, + Architecture: "arm64", + }, + "r6g.xlarge": { + InstanceType: "r6g.xlarge", + VCPU: 4, + MemoryMb: 32768, + GPU: 0, + Architecture: "arm64", + }, + "r6gd": { + InstanceType: "r6gd", + VCPU: 64, + MemoryMb: 0, + GPU: 0, + Architecture: "arm64", + }, + "r6gd.12xlarge": { + InstanceType: "r6gd.12xlarge", + VCPU: 48, + MemoryMb: 393216, + GPU: 0, + Architecture: "arm64", + }, + "r6gd.16xlarge": { + InstanceType: "r6gd.16xlarge", + VCPU: 64, + MemoryMb: 524288, + GPU: 0, + Architecture: "arm64", + }, + "r6gd.2xlarge": { + InstanceType: "r6gd.2xlarge", + VCPU: 8, + MemoryMb: 65536, + GPU: 0, + Architecture: "arm64", + }, + "r6gd.4xlarge": { + InstanceType: "r6gd.4xlarge", + VCPU: 16, + MemoryMb: 131072, + GPU: 0, + Architecture: "arm64", + }, + "r6gd.8xlarge": { + InstanceType: "r6gd.8xlarge", + VCPU: 32, + MemoryMb: 262144, + GPU: 0, + Architecture: "arm64", + }, + "r6gd.large": { + InstanceType: "r6gd.large", + VCPU: 2, + MemoryMb: 16384, + GPU: 0, + Architecture: "arm64", + }, + "r6gd.medium": { + InstanceType: "r6gd.medium", + VCPU: 1, + MemoryMb: 8192, + GPU: 0, + Architecture: "arm64", + }, + "r6gd.metal": { + InstanceType: "r6gd.metal", + VCPU: 64, + MemoryMb: 524288, + GPU: 0, + Architecture: "arm64", + }, + "r6gd.xlarge": { + InstanceType: "r6gd.xlarge", + VCPU: 4, + MemoryMb: 32768, + GPU: 0, + Architecture: "arm64", + }, + "r6i": { + InstanceType: "r6i", + VCPU: 128, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "r6i.12xlarge": { + InstanceType: "r6i.12xlarge", + VCPU: 48, + MemoryMb: 393216, + GPU: 0, + Architecture: "amd64", + }, + "r6i.16xlarge": { + InstanceType: "r6i.16xlarge", + VCPU: 64, + MemoryMb: 524288, + GPU: 0, + Architecture: "amd64", + }, + "r6i.24xlarge": { + InstanceType: "r6i.24xlarge", + VCPU: 96, + MemoryMb: 786432, + GPU: 0, + Architecture: "amd64", + }, + "r6i.2xlarge": { + InstanceType: "r6i.2xlarge", + VCPU: 8, + MemoryMb: 65536, + GPU: 0, + Architecture: "amd64", + }, + "r6i.32xlarge": { + InstanceType: "r6i.32xlarge", + VCPU: 128, + MemoryMb: 1048576, + GPU: 0, + Architecture: "amd64", + }, + "r6i.4xlarge": { + InstanceType: "r6i.4xlarge", + VCPU: 16, + MemoryMb: 131072, + GPU: 0, + Architecture: "amd64", + }, + "r6i.8xlarge": { + InstanceType: "r6i.8xlarge", + VCPU: 32, + MemoryMb: 262144, + GPU: 0, + Architecture: "amd64", + }, + "r6i.large": { + InstanceType: "r6i.large", + VCPU: 2, + MemoryMb: 16384, + GPU: 0, + Architecture: "amd64", + }, + "r6i.metal": { + InstanceType: "r6i.metal", + VCPU: 128, + MemoryMb: 1048576, + GPU: 0, + Architecture: "amd64", + }, + "r6i.xlarge": { + InstanceType: "r6i.xlarge", + VCPU: 4, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, + "t1.micro": { + InstanceType: "t1.micro", + VCPU: 1, + MemoryMb: 627, + GPU: 0, + Architecture: "amd64", + }, + "t2.2xlarge": { + InstanceType: "t2.2xlarge", + VCPU: 8, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, + "t2.large": { + InstanceType: "t2.large", + VCPU: 2, + MemoryMb: 8192, + GPU: 0, + Architecture: "amd64", + }, + "t2.medium": { + InstanceType: "t2.medium", + VCPU: 2, + MemoryMb: 4096, + GPU: 0, + Architecture: "amd64", + }, + "t2.micro": { + InstanceType: "t2.micro", + VCPU: 1, + MemoryMb: 1024, + GPU: 0, + Architecture: "amd64", + }, + "t2.nano": { + InstanceType: "t2.nano", + VCPU: 1, + MemoryMb: 512, + GPU: 0, + Architecture: "amd64", + }, + "t2.small": { + InstanceType: "t2.small", + VCPU: 1, + MemoryMb: 2048, + GPU: 0, + Architecture: "amd64", + }, + "t2.xlarge": { + InstanceType: "t2.xlarge", + VCPU: 4, + MemoryMb: 16384, + GPU: 0, + Architecture: "amd64", + }, + "t3": { + InstanceType: "t3", + VCPU: 8, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "t3.2xlarge": { + InstanceType: "t3.2xlarge", + VCPU: 8, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, + "t3.large": { + InstanceType: "t3.large", + VCPU: 2, + MemoryMb: 8192, + GPU: 0, + Architecture: "amd64", + }, + "t3.medium": { + InstanceType: "t3.medium", + VCPU: 2, + MemoryMb: 4096, + GPU: 0, + Architecture: "amd64", + }, + "t3.micro": { + InstanceType: "t3.micro", + VCPU: 2, + MemoryMb: 1024, + GPU: 0, + Architecture: "amd64", + }, + "t3.nano": { + InstanceType: "t3.nano", + VCPU: 2, + MemoryMb: 512, + GPU: 0, + Architecture: "amd64", + }, + "t3.small": { + InstanceType: "t3.small", + VCPU: 2, + MemoryMb: 2048, + GPU: 0, + Architecture: "amd64", + }, + "t3.xlarge": { + InstanceType: "t3.xlarge", + VCPU: 4, + MemoryMb: 16384, + GPU: 0, + Architecture: "amd64", + }, + "t3a.2xlarge": { + InstanceType: "t3a.2xlarge", + VCPU: 8, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, + "t3a.large": { + InstanceType: "t3a.large", + VCPU: 2, + MemoryMb: 8192, + GPU: 0, + Architecture: "amd64", + }, + "t3a.medium": { + InstanceType: "t3a.medium", + VCPU: 2, + MemoryMb: 4096, + GPU: 0, + Architecture: "amd64", + }, + "t3a.micro": { + InstanceType: "t3a.micro", + VCPU: 2, + MemoryMb: 1024, + GPU: 0, + Architecture: "amd64", + }, + "t3a.nano": { + InstanceType: "t3a.nano", + VCPU: 2, + MemoryMb: 512, + GPU: 0, + Architecture: "amd64", + }, + "t3a.small": { + InstanceType: "t3a.small", + VCPU: 2, + MemoryMb: 2048, + GPU: 0, + Architecture: "amd64", + }, + "t3a.xlarge": { + InstanceType: "t3a.xlarge", + VCPU: 4, + MemoryMb: 16384, + GPU: 0, + Architecture: "amd64", + }, + "t4g.2xlarge": { + InstanceType: "t4g.2xlarge", + VCPU: 8, + MemoryMb: 32768, + GPU: 0, + Architecture: "arm64", + }, + "t4g.large": { + InstanceType: "t4g.large", + VCPU: 2, + MemoryMb: 8192, + GPU: 0, + Architecture: "arm64", + }, + "t4g.medium": { + InstanceType: "t4g.medium", + VCPU: 2, + MemoryMb: 4096, + GPU: 0, + Architecture: "arm64", + }, + "t4g.micro": { + InstanceType: "t4g.micro", + VCPU: 2, + MemoryMb: 1024, + GPU: 0, + Architecture: "arm64", + }, + "t4g.nano": { + InstanceType: "t4g.nano", + VCPU: 2, + MemoryMb: 512, + GPU: 0, + Architecture: "arm64", + }, + "t4g.small": { + InstanceType: "t4g.small", + VCPU: 2, + MemoryMb: 2048, + GPU: 0, + Architecture: "arm64", + }, + "t4g.xlarge": { + InstanceType: "t4g.xlarge", + VCPU: 4, + MemoryMb: 16384, + GPU: 0, + Architecture: "arm64", + }, + "u-12tb1": { + InstanceType: "u-12tb1", + VCPU: 448, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "u-12tb1.112xlarge": { + InstanceType: "u-12tb1.112xlarge", + VCPU: 448, + MemoryMb: 12582912, + GPU: 0, + Architecture: "amd64", + }, + "u-12tb1.metal": { + InstanceType: "u-12tb1.metal", + VCPU: 448, + MemoryMb: 12582912, + GPU: 0, + Architecture: "amd64", + }, + "u-18tb1": { + InstanceType: "u-18tb1", + VCPU: 448, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "u-18tb1.metal": { + InstanceType: "u-18tb1.metal", + VCPU: 448, + MemoryMb: 18874368, + GPU: 0, + Architecture: "amd64", + }, + "u-24tb1": { + InstanceType: "u-24tb1", + VCPU: 448, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "u-24tb1.metal": { + InstanceType: "u-24tb1.metal", + VCPU: 448, + MemoryMb: 25165824, + GPU: 0, + Architecture: "amd64", + }, + "u-3tb1.56xlarge": { + InstanceType: "u-3tb1.56xlarge", + VCPU: 224, + MemoryMb: 3145728, + GPU: 0, + Architecture: "amd64", + }, + "u-6tb1": { + InstanceType: "u-6tb1", + VCPU: 448, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "u-6tb1.112xlarge": { + InstanceType: "u-6tb1.112xlarge", + VCPU: 448, + MemoryMb: 6291456, + GPU: 0, + Architecture: "amd64", + }, + "u-6tb1.56xlarge": { + InstanceType: "u-6tb1.56xlarge", + VCPU: 224, + MemoryMb: 6291456, + GPU: 0, + Architecture: "amd64", + }, + "u-6tb1.metal": { + InstanceType: "u-6tb1.metal", + VCPU: 448, + MemoryMb: 6291456, + GPU: 0, + Architecture: "amd64", + }, + "u-9tb1": { + InstanceType: "u-9tb1", + VCPU: 448, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "u-9tb1.112xlarge": { + InstanceType: "u-9tb1.112xlarge", + VCPU: 448, + MemoryMb: 9437184, + GPU: 0, + Architecture: "amd64", + }, + "u-9tb1.metal": { + InstanceType: "u-9tb1.metal", + VCPU: 448, + MemoryMb: 9437184, + GPU: 0, + Architecture: "amd64", + }, + "vt1": { + InstanceType: "vt1", + VCPU: 96, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "vt1.24xlarge": { + InstanceType: "vt1.24xlarge", + VCPU: 96, + MemoryMb: 196608, + GPU: 0, + Architecture: "amd64", + }, + "vt1.3xlarge": { + InstanceType: "vt1.3xlarge", + VCPU: 12, + MemoryMb: 24576, + GPU: 0, + Architecture: "amd64", + }, + "vt1.6xlarge": { + InstanceType: "vt1.6xlarge", + VCPU: 24, + MemoryMb: 49152, + GPU: 0, + Architecture: "amd64", + }, + "x1": { + InstanceType: "x1", + VCPU: 128, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "x1.16xlarge": { + InstanceType: "x1.16xlarge", + VCPU: 64, + MemoryMb: 999424, + GPU: 0, + Architecture: "amd64", + }, + "x1.32xlarge": { + InstanceType: "x1.32xlarge", + VCPU: 128, + MemoryMb: 1998848, + GPU: 0, + Architecture: "amd64", + }, + "x1e": { + InstanceType: "x1e", + VCPU: 128, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "x1e.16xlarge": { + InstanceType: "x1e.16xlarge", + VCPU: 64, + MemoryMb: 1998848, + GPU: 0, + Architecture: "amd64", + }, + "x1e.2xlarge": { + InstanceType: "x1e.2xlarge", + VCPU: 8, + MemoryMb: 249856, + GPU: 0, + Architecture: "amd64", + }, + "x1e.32xlarge": { + InstanceType: "x1e.32xlarge", + VCPU: 128, + MemoryMb: 3997696, + GPU: 0, + Architecture: "amd64", + }, + "x1e.4xlarge": { + InstanceType: "x1e.4xlarge", + VCPU: 16, + MemoryMb: 499712, + GPU: 0, + Architecture: "amd64", + }, + "x1e.8xlarge": { + InstanceType: "x1e.8xlarge", + VCPU: 32, + MemoryMb: 999424, + GPU: 0, + Architecture: "amd64", + }, + "x1e.xlarge": { + InstanceType: "x1e.xlarge", + VCPU: 4, + MemoryMb: 124928, + GPU: 0, + Architecture: "amd64", + }, + "x2gd": { + InstanceType: "x2gd", + VCPU: 64, + MemoryMb: 0, + GPU: 0, + Architecture: "arm64", + }, + "x2gd.12xlarge": { + InstanceType: "x2gd.12xlarge", + VCPU: 48, + MemoryMb: 786432, + GPU: 0, + Architecture: "arm64", + }, + "x2gd.16xlarge": { + InstanceType: "x2gd.16xlarge", + VCPU: 64, + MemoryMb: 1048576, + GPU: 0, + Architecture: "arm64", + }, + "x2gd.2xlarge": { + InstanceType: "x2gd.2xlarge", + VCPU: 8, + MemoryMb: 131072, + GPU: 0, + Architecture: "arm64", + }, + "x2gd.4xlarge": { + InstanceType: "x2gd.4xlarge", + VCPU: 16, + MemoryMb: 262144, + GPU: 0, + Architecture: "arm64", + }, + "x2gd.8xlarge": { + InstanceType: "x2gd.8xlarge", + VCPU: 32, + MemoryMb: 524288, + GPU: 0, + Architecture: "arm64", + }, + "x2gd.large": { + InstanceType: "x2gd.large", + VCPU: 2, + MemoryMb: 32768, + GPU: 0, + Architecture: "arm64", + }, + "x2gd.medium": { + InstanceType: "x2gd.medium", + VCPU: 1, + MemoryMb: 16384, + GPU: 0, + Architecture: "arm64", + }, + "x2gd.metal": { + InstanceType: "x2gd.metal", + VCPU: 64, + MemoryMb: 1048576, + GPU: 0, + Architecture: "arm64", + }, + "x2gd.xlarge": { + InstanceType: "x2gd.xlarge", + VCPU: 4, + MemoryMb: 65536, + GPU: 0, + Architecture: "arm64", + }, + "x2idn": { + InstanceType: "x2idn", + VCPU: 128, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "x2idn.16xlarge": { + InstanceType: "x2idn.16xlarge", + VCPU: 64, + MemoryMb: 1048576, + GPU: 0, + Architecture: "amd64", + }, + "x2idn.24xlarge": { + InstanceType: "x2idn.24xlarge", + VCPU: 96, + MemoryMb: 1572864, + GPU: 0, + Architecture: "amd64", + }, + "x2idn.32xlarge": { + InstanceType: "x2idn.32xlarge", + VCPU: 128, + MemoryMb: 2097152, + GPU: 0, + Architecture: "amd64", + }, + "x2idn.metal": { + InstanceType: "x2idn.metal", + VCPU: 128, + MemoryMb: 2097152, + GPU: 0, + Architecture: "amd64", + }, + "x2iedn": { + InstanceType: "x2iedn", + VCPU: 128, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "x2iedn.16xlarge": { + InstanceType: "x2iedn.16xlarge", + VCPU: 64, + MemoryMb: 2097152, + GPU: 0, + Architecture: "amd64", + }, + "x2iedn.24xlarge": { + InstanceType: "x2iedn.24xlarge", + VCPU: 96, + MemoryMb: 3145728, + GPU: 0, + Architecture: "amd64", + }, + "x2iedn.2xlarge": { + InstanceType: "x2iedn.2xlarge", + VCPU: 8, + MemoryMb: 262144, + GPU: 0, + Architecture: "amd64", + }, + "x2iedn.32xlarge": { + InstanceType: "x2iedn.32xlarge", + VCPU: 128, + MemoryMb: 4194304, + GPU: 0, + Architecture: "amd64", + }, + "x2iedn.4xlarge": { + InstanceType: "x2iedn.4xlarge", + VCPU: 16, + MemoryMb: 524288, + GPU: 0, + Architecture: "amd64", + }, + "x2iedn.8xlarge": { + InstanceType: "x2iedn.8xlarge", + VCPU: 32, + MemoryMb: 1048576, + GPU: 0, + Architecture: "amd64", + }, + "x2iedn.metal": { + InstanceType: "x2iedn.metal", + VCPU: 128, + MemoryMb: 4194304, + GPU: 0, + Architecture: "amd64", + }, + "x2iedn.xlarge": { + InstanceType: "x2iedn.xlarge", + VCPU: 4, + MemoryMb: 131072, + GPU: 0, + Architecture: "amd64", + }, + "x2iezn": { + InstanceType: "x2iezn", + VCPU: 48, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "x2iezn.12xlarge": { + InstanceType: "x2iezn.12xlarge", + VCPU: 48, + MemoryMb: 1572864, + GPU: 0, + Architecture: "amd64", + }, + "x2iezn.2xlarge": { + InstanceType: "x2iezn.2xlarge", + VCPU: 8, + MemoryMb: 262144, + GPU: 0, + Architecture: "amd64", + }, + "x2iezn.4xlarge": { + InstanceType: "x2iezn.4xlarge", + VCPU: 16, + MemoryMb: 524288, + GPU: 0, + Architecture: "amd64", + }, + "x2iezn.6xlarge": { + InstanceType: "x2iezn.6xlarge", + VCPU: 24, + MemoryMb: 786432, + GPU: 0, + Architecture: "amd64", + }, + "x2iezn.8xlarge": { + InstanceType: "x2iezn.8xlarge", + VCPU: 32, + MemoryMb: 1048576, + GPU: 0, + Architecture: "amd64", + }, + "x2iezn.metal": { + InstanceType: "x2iezn.metal", + VCPU: 48, + MemoryMb: 1572864, + GPU: 0, + Architecture: "amd64", + }, + "z1d": { + InstanceType: "z1d", + VCPU: 48, + MemoryMb: 0, + GPU: 0, + Architecture: "amd64", + }, + "z1d.12xlarge": { + InstanceType: "z1d.12xlarge", + VCPU: 48, + MemoryMb: 393216, + GPU: 0, + Architecture: "amd64", + }, + "z1d.2xlarge": { + InstanceType: "z1d.2xlarge", + VCPU: 8, + MemoryMb: 65536, + GPU: 0, + Architecture: "amd64", + }, + "z1d.3xlarge": { + InstanceType: "z1d.3xlarge", + VCPU: 12, + MemoryMb: 98304, + GPU: 0, + Architecture: "amd64", + }, + "z1d.6xlarge": { + InstanceType: "z1d.6xlarge", + VCPU: 24, + MemoryMb: 196608, + GPU: 0, + Architecture: "amd64", + }, + "z1d.large": { + InstanceType: "z1d.large", + VCPU: 2, + MemoryMb: 16384, + GPU: 0, + Architecture: "amd64", + }, + "z1d.metal": { + InstanceType: "z1d.metal", + VCPU: 48, + MemoryMb: 393216, + GPU: 0, + Architecture: "amd64", + }, + "z1d.xlarge": { + InstanceType: "z1d.xlarge", + VCPU: 4, + MemoryMb: 32768, + GPU: 0, + Architecture: "amd64", + }, +} diff --git a/cluster-autoscaler/cloudprovider/spotinst/spotinst_cloud_provider.go b/cluster-autoscaler/cloudprovider/spotinst/spotinst_cloud_provider.go new file mode 100644 index 000000000000..2e6c2c05c90b --- /dev/null +++ b/cluster-autoscaler/cloudprovider/spotinst/spotinst_cloud_provider.go @@ -0,0 +1,155 @@ +/* +Copyright 2016 The Kubernetes Authors. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package spotinst + +import ( + "io" + apiv1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + "k8s.io/autoscaler/cluster-autoscaler/cloudprovider" + "k8s.io/autoscaler/cluster-autoscaler/config" + "k8s.io/autoscaler/cluster-autoscaler/utils/errors" + "k8s.io/klog/v2" + "os" +) + +const ( + // ProviderName is the provide name of spotinst + ProviderName = "spotinst" + + // GPULabel is the label added to nodes with GPU resource. + GPULabel = "k8s.amazonaws.com/accelerator" +) + +// CloudProvider implements CloudProvider interface. +type CloudProvider struct { + manager *CloudManager + resourceLimiter *cloudprovider.ResourceLimiter +} + +var ( + availableGPUTypes = map[string]struct{}{ + "nvidia-tesla-k80": {}, + "nvidia-tesla-p100": {}, + "nvidia-tesla-v100": {}, + } +) + +// NewCloudProvider returns CloudProvider implementation for Spotinst. +func NewCloudProvider(manager *CloudManager, resourceLimiter *cloudprovider.ResourceLimiter) (*CloudProvider, error) { + klog.Info("Building Spotinst cloud provider") + cloud := &CloudProvider{ + manager: manager, + resourceLimiter: resourceLimiter, + } + + return cloud, nil +} + +// Name returns name of the cloud c. +func (c *CloudProvider) Name() string { + return ProviderName +} + +// NodeGroups returns all node groups configured for this cloud c. +func (c *CloudProvider) NodeGroups() []cloudprovider.NodeGroup { + out := make([]cloudprovider.NodeGroup, len(c.manager.groups)) + for i, group := range c.manager.groups { + out[i] = group + } + return out +} + +// NodeGroupForNode returns the node group for the given node. +func (c *CloudProvider) NodeGroupForNode(node *apiv1.Node) (cloudprovider.NodeGroup, error) { + instanceID, err := extractInstanceId(node.Spec.ProviderID) + if err != nil { + return nil, err + } + return c.manager.GetGroupForInstance(instanceID) +} + +// Pricing returns pricing model for this cloud provider or error if not available. +func (c *CloudProvider) Pricing() (cloudprovider.PricingModel, errors.AutoscalerError) { + return nil, cloudprovider.ErrNotImplemented +} + +// GetAvailableMachineTypes get all machine types that can be requested from the cloud provider. +// Implementation optional. +func (c *CloudProvider) GetAvailableMachineTypes() ([]string, error) { + return []string{}, nil +} + +// NewNodeGroup builds a theoretical node group based on the node definition provided. +func (c *CloudProvider) NewNodeGroup(machineType string, labels map[string]string, systemLabels map[string]string, + taints []apiv1.Taint, extraResources map[string]resource.Quantity) (cloudprovider.NodeGroup, error) { + return nil, cloudprovider.ErrNotImplemented +} + +// GetResourceLimiter returns struct containing limits (max, min) for resources (cores, memory etc.). +func (c *CloudProvider) GetResourceLimiter() (*cloudprovider.ResourceLimiter, error) { + return c.resourceLimiter, nil +} + +// Cleanup cleans up open resources before the cloud provider is destroyed, i.e. go routines etc. +func (c *CloudProvider) Cleanup() error { + return c.manager.Cleanup() +} + +// Refresh is called before every main loop and can be used to dynamically update cloud provider state. +// In particular the list of node groups returned by NodeGroups can change as a result of CloudProvider.Refresh(). +func (c *CloudProvider) Refresh() error { + return c.manager.Refresh() +} + +// GetInstanceID gets the instance ID for the specified node. +func (c *CloudProvider) GetInstanceID(node *apiv1.Node) string { + return node.Spec.ProviderID +} + +// GPULabel returns the label added to nodes with GPU resource. +func (c *CloudProvider) GPULabel() string { + return GPULabel +} + +// GetAvailableGPUTypes return all available GPU types cloud provider supports +func (c *CloudProvider) GetAvailableGPUTypes() map[string]struct{} { + return availableGPUTypes +} + + +// BuildSpotinst return the spotinst provider +func BuildSpotinst(opts config.AutoscalingOptions, do cloudprovider.NodeGroupDiscoveryOptions, rl *cloudprovider.ResourceLimiter) cloudprovider.CloudProvider { + var config io.ReadCloser + if opts.CloudConfig != "" { + var err error + config, err = os.Open(opts.CloudConfig) + if err != nil { + klog.Fatalf("Couldn't open cloud provider configuration %s: %#v", opts.CloudConfig, err) + } + defer config.Close() + } + + manager, err := NewCloudManager(config, do) + if err != nil { + klog.Fatalf("Failed to create Spotinst manager: %v", err) + } + + provider, err := NewCloudProvider(manager, rl) + if err != nil { + klog.Fatalf("Failed to create Spotinst cloud provider: %v", err) + } + + return provider +} \ No newline at end of file diff --git a/cluster-autoscaler/cloudprovider/spotinst/spotinst_cloud_provider_test.go b/cluster-autoscaler/cloudprovider/spotinst/spotinst_cloud_provider_test.go new file mode 100644 index 000000000000..7dd1da692705 --- /dev/null +++ b/cluster-autoscaler/cloudprovider/spotinst/spotinst_cloud_provider_test.go @@ -0,0 +1,416 @@ +/* +Copyright 2016 The Kubernetes Authors. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package spotinst + +import ( + "context" + "testing" + "time" + + "github.com/spotinst/spotinst-sdk-go/service/elastigroup/providers/aws" + "github.com/spotinst/spotinst-sdk-go/service/elastigroup/providers/azure" + azurev3 "github.com/spotinst/spotinst-sdk-go/service/elastigroup/providers/azure/v3" + "github.com/spotinst/spotinst-sdk-go/service/elastigroup/providers/gcp" + "github.com/spotinst/spotinst-sdk-go/spotinst" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + apiv1 "k8s.io/api/core/v1" + "k8s.io/autoscaler/cluster-autoscaler/cloudprovider" +) + +type groupServiceMock struct { + mock.Mock + providerAWS *awsServiceMock +} + +func (s *groupServiceMock) CloudProviderAWS() aws.Service { + return s.providerAWS +} + +func (s *groupServiceMock) CloudProviderGCP() gcp.Service { + return nil // not implemented +} + +func (s *groupServiceMock) CloudProviderAzure() azure.Service { + return nil // not implemented +} + +func (s *groupServiceMock) CloudProviderAzureV3() azurev3.Service { + return nil // not implemented +} + +type awsServiceMock struct { + mock.Mock +} + +func (s *awsServiceMock) List(ctx context.Context, input *aws.ListGroupsInput) (*aws.ListGroupsOutput, error) { + return nil, nil +} + +func (s *awsServiceMock) Create(ctx context.Context, input *aws.CreateGroupInput) (*aws.CreateGroupOutput, error) { + return nil, nil +} + +func (s *awsServiceMock) DeploymentStatusECS(context.Context, *aws.DeploymentStatusInput) (*aws.RollGroupOutput, error) { + return nil, nil +} + +func (s *awsServiceMock) DeploymentStatus(context.Context, *aws.DeploymentStatusInput) (*aws.RollGroupOutput, error) { + return nil, nil +} + +func (s *awsServiceMock) RollECS(context.Context, *aws.RollECSGroupInput) (*aws.RollGroupOutput, error) { + return nil, nil +} + +func (s *awsServiceMock) Scale(context.Context, *aws.ScaleGroupInput) (*aws.ScaleGroupOutput, error) { + return nil, nil +} + +func (s *awsServiceMock) FinishBeanstalkMaintenance(context.Context, *aws.BeanstalkMaintenanceInput) (*aws.BeanstalkMaintenanceOutput, error) { + return nil, nil +} + +func (s *awsServiceMock) GetBeanstalkMaintenanceStatus(context.Context, *aws.BeanstalkMaintenanceInput) (*string, error) { + return nil, nil +} + +func (s *awsServiceMock) GetGroupEvents(context.Context, *aws.GetGroupEventsInput) (*aws.GetGroupEventsOutput, error) { + return nil, nil +} + +func (s *awsServiceMock) StartBeanstalkMaintenance(context.Context, *aws.BeanstalkMaintenanceInput) (*aws.BeanstalkMaintenanceOutput, error) { + return nil, nil +} + +func (s *awsServiceMock) Read(ctx context.Context, input *aws.ReadGroupInput) (*aws.ReadGroupOutput, error) { + out := &aws.ReadGroupOutput{ + Group: &aws.Group{ + Capacity: &aws.Capacity{ + Target: spotinst.Int(2), + }, + }, + } + return out, nil +} + +func (s *awsServiceMock) GetInstanceHealthiness(context.Context, *aws.GetInstanceHealthinessInput) (*aws.GetInstanceHealthinessOutput, error) { + return nil, nil +} + +func (s *awsServiceMock) ImportBeanstalkEnv(context.Context, *aws.ImportBeanstalkInput) (*aws.ImportBeanstalkOutput, error) { + return nil, nil +} + +func (s *awsServiceMock) StopDeployment(context.Context, *aws.StopDeploymentInput) (*aws.StopDeploymentOutput, error) { + return nil, nil +} + +func (s *awsServiceMock) Update(ctx context.Context, input *aws.UpdateGroupInput) (*aws.UpdateGroupOutput, error) { + args := s.Called(ctx, input) + return args.Get(0).(*aws.UpdateGroupOutput), nil +} + +func (s *awsServiceMock) Delete(ctx context.Context, input *aws.DeleteGroupInput) (*aws.DeleteGroupOutput, error) { + return nil, nil +} + +func (s *awsServiceMock) Status(ctx context.Context, input *aws.StatusGroupInput) (*aws.StatusGroupOutput, error) { + out := &aws.StatusGroupOutput{ + Instances: []*aws.Instance{ + { + ID: spotinst.String("test-instance-id"), + }, + { + ID: spotinst.String("second-test-instance-id"), + }, + }, + } + return out, nil +} + +func (s *awsServiceMock) Detach(ctx context.Context, input *aws.DetachGroupInput) (*aws.DetachGroupOutput, error) { + args := s.Called(ctx, input) + return args.Get(0).(*aws.DetachGroupOutput), nil +} + +func (s *awsServiceMock) Roll(ctx context.Context, input *aws.RollGroupInput) (*aws.RollGroupOutput, error) { + return nil, nil +} + +func (s *awsServiceMock) CreateSuspensions(ctx context.Context, input *aws.CreateSuspensionsInput) (*aws.CreateSuspensionsOutput, error) { + return nil, nil +} + +func (s *awsServiceMock) ListSuspensions(context.Context, *aws.ListSuspensionsInput) (*aws.ListSuspensionsOutput, error) { + return nil, nil +} +func (s *awsServiceMock) DeleteSuspensions(context.Context, *aws.DeleteSuspensionsInput) (*aws.DeleteSuspensionsOutput, error) { + return nil, nil +} + +func (s *awsServiceMock) ListStatefulInstances(context.Context, *aws.ListStatefulInstancesInput) (*aws.ListStatefulInstancesOutput, error) { + return nil, nil +} +func (s *awsServiceMock) PauseStatefulInstance(context.Context, *aws.PauseStatefulInstanceInput) (*aws.PauseStatefulInstanceOutput, error) { + return nil, nil +} +func (s *awsServiceMock) ResumeStatefulInstance(context.Context, *aws.ResumeStatefulInstanceInput) (*aws.ResumeStatefulInstanceOutput, error) { + return nil, nil +} +func (s *awsServiceMock) RecycleStatefulInstance(context.Context, *aws.RecycleStatefulInstanceInput) (*aws.RecycleStatefulInstanceOutput, error) { + return nil, nil +} +func (s *awsServiceMock) DeallocateStatefulInstance(context.Context, *aws.DeallocateStatefulInstanceInput) (*aws.DeallocateStatefulInstanceOutput, error) { + return nil, nil +} + +func testCloudManager(t *testing.T) *CloudManager { + return &CloudManager{ + groupService: &groupServiceMock{ + providerAWS: new(awsServiceMock), + }, + groups: make([]*Group, 0), + cache: make(map[string]*Group), + interruptCh: make(chan struct{}), + refreshInterval: time.Minute, + } +} + +func testCloudProvider(t *testing.T, m *CloudManager) *CloudProvider { + resourceLimiter := cloudprovider.NewResourceLimiter( + map[string]int64{cloudprovider.ResourceNameCores: 1, cloudprovider.ResourceNameMemory: 10000000}, + map[string]int64{cloudprovider.ResourceNameCores: 10, cloudprovider.ResourceNameMemory: 100000000}) + + cloud, err := NewCloudProvider(m, resourceLimiter) + assert.NoError(t, err) + return cloud +} + +func TestNewCloudProvider(t *testing.T) { + testCloudProvider(t, testCloudManager(t)) +} + +func TestAddNodeGroup(t *testing.T) { + provider := testCloudProvider(t, testCloudManager(t)) + err := provider.manager.addNodeGroup("bad spec") + assert.Error(t, err) + assert.Equal(t, len(provider.manager.groups), 0) + + err = provider.manager.addNodeGroup("1:5:sig-test") + assert.NoError(t, err) + assert.Equal(t, len(provider.manager.groups), 1) +} + +func TestName(t *testing.T) { + provider := testCloudProvider(t, testCloudManager(t)) + assert.Equal(t, provider.Name(), "spotinst") +} + +func TestNodeGroups(t *testing.T) { + provider := testCloudProvider(t, testCloudManager(t)) + assert.Equal(t, len(provider.NodeGroups()), 0) + err := provider.manager.addNodeGroup("1:5:sig-test") + assert.NoError(t, err) + assert.Equal(t, len(provider.NodeGroups()), 1) +} + +func TestNodeGroupForNode(t *testing.T) { + node := &apiv1.Node{ + Spec: apiv1.NodeSpec{ + ProviderID: "aws:///us-east-1a/test-instance-id", + }, + } + provider := testCloudProvider(t, testCloudManager(t)) + err := provider.manager.addNodeGroup("1:5:sig-test") + assert.NoError(t, err) + + provider.Refresh() + + group, err := provider.NodeGroupForNode(node) + + assert.NoError(t, err) + assert.Equal(t, group.Id(), "sig-test") + assert.Equal(t, group.MinSize(), 1) + assert.Equal(t, group.MaxSize(), 5) + + // test node in cluster that is not in a group managed by cluster autoscaler + nodeNotInGroup := &apiv1.Node{ + Spec: apiv1.NodeSpec{ + ProviderID: "aws:///us-east-1a/test-instance-id-not-in-group", + }, + } + + group, err = provider.NodeGroupForNode(nodeNotInGroup) + assert.NoError(t, err) + assert.Nil(t, group) +} + +func TestExtractInstanceId(t *testing.T) { + _, err := extractInstanceId("bad spec") + assert.Error(t, err) + + instanceID, err := extractInstanceId("aws:///us-east-1a/i-260942b3") + assert.NoError(t, err) + assert.Equal(t, instanceID, "i-260942b3") +} + +func TestMaxSize(t *testing.T) { + provider := testCloudProvider(t, testCloudManager(t)) + err := provider.manager.addNodeGroup("1:5:sig-test") + assert.NoError(t, err) + assert.Equal(t, len(provider.manager.groups), 1) + assert.Equal(t, provider.manager.groups[0].MaxSize(), 5) +} + +func TestMinSize(t *testing.T) { + provider := testCloudProvider(t, testCloudManager(t)) + err := provider.manager.addNodeGroup("1:5:sig-test") + assert.NoError(t, err) + assert.Equal(t, len(provider.manager.groups), 1) + assert.Equal(t, provider.manager.groups[0].MinSize(), 1) +} + +func TestTargetSize(t *testing.T) { + provider := testCloudProvider(t, testCloudManager(t)) + err := provider.manager.addNodeGroup("1:5:sig-test") + assert.NoError(t, err) + targetSize, err := provider.manager.groups[0].TargetSize() + assert.Equal(t, targetSize, 2) + assert.NoError(t, err) +} + +func TestIncreaseSize(t *testing.T) { + provider := testCloudProvider(t, testCloudManager(t)) + err := provider.manager.addNodeGroup("1:5:sig-test") + assert.NoError(t, err) + assert.Equal(t, len(provider.manager.groups), 1) + + cloud := provider.manager.groupService.CloudProviderAWS().(*awsServiceMock) + cloud.On("Update", context.Background(), &aws.UpdateGroupInput{ + Group: &aws.Group{ + ID: spotinst.String(provider.manager.groups[0].Id()), + Capacity: &aws.Capacity{ + Target: spotinst.Int(3), + Minimum: spotinst.Int(provider.manager.groups[0].minSize), + Maximum: spotinst.Int(provider.manager.groups[0].maxSize), + }, + }, + }).Return(&aws.UpdateGroupOutput{}) + + err = provider.manager.groups[0].IncreaseSize(1) + assert.NoError(t, err) + cloud.AssertExpectations(t) +} + +func TestBelongs(t *testing.T) { + provider := testCloudProvider(t, testCloudManager(t)) + err := provider.manager.addNodeGroup("1:5:sig-test") + assert.NoError(t, err) + + provider.Refresh() + + invalidNode := &apiv1.Node{ + Spec: apiv1.NodeSpec{ + ProviderID: "aws:///us-east-1a/invalid-instance-id", + }, + } + _, err = provider.manager.groups[0].Belongs(invalidNode) + assert.Error(t, err) + + validNode := &apiv1.Node{ + Spec: apiv1.NodeSpec{ + ProviderID: "aws:///us-east-1a/test-instance-id", + }, + } + belongs, err := provider.manager.groups[0].Belongs(validNode) + assert.Equal(t, belongs, true) + assert.NoError(t, err) +} + +func TestDeleteNodes(t *testing.T) { + provider := testCloudProvider(t, testCloudManager(t)) + err := provider.manager.addNodeGroup("1:5:sig-test") + assert.NoError(t, err) + assert.Equal(t, len(provider.manager.groups), 1) + + provider.Refresh() + + cloud := provider.manager.groupService.CloudProviderAWS().(*awsServiceMock) + cloud.On("Detach", context.Background(), &aws.DetachGroupInput{ + GroupID: spotinst.String(provider.manager.groups[0].Id()), + InstanceIDs: []string{"test-instance-id"}, + ShouldDecrementTargetCapacity: spotinst.Bool(true), + ShouldTerminateInstances: spotinst.Bool(true), + }).Return(&aws.DetachGroupOutput{}) + + node := &apiv1.Node{ + Spec: apiv1.NodeSpec{ + ProviderID: "aws:///us-east-1a/test-instance-id", + }, + } + + err = provider.manager.groups[0].DeleteNodes([]*apiv1.Node{node}) + assert.NoError(t, err) + cloud.AssertExpectations(t) +} + +func TestId(t *testing.T) { + provider := testCloudProvider(t, testCloudManager(t)) + err := provider.manager.addNodeGroup("1:5:sig-test") + assert.NoError(t, err) + assert.Equal(t, len(provider.manager.groups), 1) + assert.Equal(t, provider.manager.groups[0].Id(), "sig-test") +} + +func TestDebug(t *testing.T) { + grp := Group{ + manager: testCloudManager(t), + minSize: 5, + maxSize: 55, + } + grp.groupID = "sig-test" + assert.Equal(t, grp.Debug(), "sig-test (5:55)") +} + +func TestBuildGroup(t *testing.T) { + provider := testCloudProvider(t, testCloudManager(t)) + + _, err := provider.manager.buildGroupFromSpec("a") + assert.Error(t, err) + _, err = provider.manager.buildGroupFromSpec("a:b:c") + assert.Error(t, err) + _, err = provider.manager.buildGroupFromSpec("1:") + assert.Error(t, err) + _, err = provider.manager.buildGroupFromSpec("1:2:") + assert.Error(t, err) + + grp, err := provider.manager.buildGroupFromSpec("111:222:sig-test") + assert.NoError(t, err) + assert.Equal(t, 111, grp.MinSize()) + assert.Equal(t, 222, grp.MaxSize()) + assert.Equal(t, "sig-test", grp.Id()) +} + +func TestGetResourceLimiter(t *testing.T) { + provider := testCloudProvider(t, testCloudManager(t)) + _, err := provider.GetResourceLimiter() + assert.NoError(t, err) +} + +func TestCleanup(t *testing.T) { + provider := testCloudProvider(t, testCloudManager(t)) + err := provider.Cleanup() + assert.NoError(t, err) +} \ No newline at end of file diff --git a/cluster-autoscaler/cloudprovider/spotinst/spotinst_manager.go b/cluster-autoscaler/cloudprovider/spotinst/spotinst_manager.go new file mode 100644 index 000000000000..c5505f360ef5 --- /dev/null +++ b/cluster-autoscaler/cloudprovider/spotinst/spotinst_manager.go @@ -0,0 +1,503 @@ +/* +Copyright 2016 The Kubernetes Authors. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package spotinst + +import ( + "context" + "errors" + "fmt" + "io" + "math/rand" + "strconv" + "strings" + "sync" + "time" + + "k8s.io/autoscaler/cluster-autoscaler/utils/gpu" + "k8s.io/klog/v2" + + "k8s.io/autoscaler/cluster-autoscaler/utils/mpscontext" + + "github.com/spotinst/spotinst-sdk-go/service/elastigroup" + "github.com/spotinst/spotinst-sdk-go/service/elastigroup/providers/aws" + "github.com/spotinst/spotinst-sdk-go/spotinst" + "github.com/spotinst/spotinst-sdk-go/spotinst/log" + "github.com/spotinst/spotinst-sdk-go/spotinst/session" + "github.com/spotinst/spotinst-sdk-go/spotinst/util/stringutil" + gcfg "gopkg.in/gcfg.v1" + apiv1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/autoscaler/cluster-autoscaler/cloudprovider" + "k8s.io/autoscaler/cluster-autoscaler/config/dynamic" + "k8s.io/autoscaler/cluster-autoscaler/utils/gpumemory" + kubeletapis "k8s.io/kubelet/pkg/apis" +) + +// CloudManager holds the config and client. +type CloudManager struct { + groupService elastigroup.Service + groups []*Group + refreshedAt time.Time + refreshInterval time.Duration + interruptCh chan struct{} + cacheMu sync.Mutex + cache map[string]*Group // k: InstanceID, v: Group +} + +// CloudConfig holds the configuration parsed from the --cloud-config flag. +// All fields are required unless otherwise specified. +type CloudConfig struct { + Global struct{} +} + +// NewCloudManager constructs manager object. +func NewCloudManager(config io.Reader, discoveryOpts cloudprovider.NodeGroupDiscoveryOptions) (*CloudManager, error) { + klog.Info("Building Spotinst cloud manager") + + cfg, err := readCloudConfig(config) + if err != nil { + return nil, err + } + + svc, err := newService(cfg) + if err != nil { + return nil, err + } + + manager := &CloudManager{ + groupService: svc, + refreshInterval: time.Minute, + interruptCh: make(chan struct{}), + groups: make([]*Group, 0), + cache: make(map[string]*Group), + } + + if err := manager.addNodeGroups(discoveryOpts.NodeGroupSpecs); err != nil { + return nil, err + } + + go wait.Until(func() { + manager.cacheMu.Lock() + defer manager.cacheMu.Unlock() + + if err := manager.forceRefresh(); err != nil { + klog.Errorf("Error while refreshing cache: %v", err) + } + }, time.Hour, manager.interruptCh) + + return manager, nil +} + +// newService returns a new instance of Spotinst Service. +func newService(cloudConfig *CloudConfig) (elastigroup.Service, error) { + // Create a new config. + config := spotinst.DefaultConfig() + config.WithLogger(newStdLogger()) + config.WithUserAgent("Kubernetes-ClusterAutoscaler") + + // Create a new session. + sess := session.New(config) + + // Create a new service. + svc := elastigroup.New(sess) + + return svc, nil +} + +func newStdLogger() log.Logger { + return log.LoggerFunc(func(format string, args ...interface{}) { + klog.V(4).Infof(format, args...) + }) +} + +// readCloudConfig reads an instance of Config from config reader. +func readCloudConfig(config io.Reader) (*CloudConfig, error) { + var cfg CloudConfig + + if config != nil { + if err := gcfg.ReadInto(&cfg, config); err != nil { + return nil, fmt.Errorf("couldn't read Spotinst config: %v", err) + } + } + + return &cfg, nil +} + +func (mgr *CloudManager) addNodeGroups(specs []string) error { + klog.Info("Attempting to add node groups") + + for _, spec := range specs { + if err := mgr.addNodeGroup(spec); err != nil { + return fmt.Errorf("could not register group with spec %s: %v", spec, err) + } + } + + return nil +} + +func (mgr *CloudManager) addNodeGroup(spec string) error { + klog.Infof("Attempting to add node group: %s", spec) + + group, err := mgr.buildGroupFromSpec(spec) + if err != nil { + return fmt.Errorf("could not parse spec for node group: %v", err) + } + err = mgr.RegisterGroup(group) + if err != nil { + return fmt.Errorf("could not register the group(%s): %v", group.Id(), err) + } + + klog.Infof("Node group added: %s", group.groupID) + return nil +} + +func (mgr *CloudManager) buildGroupFromSpec(value string) (*Group, error) { + spec, err := dynamic.SpecFromString(value, true) + if err != nil { + return nil, fmt.Errorf("failed to parse node group spec: %v", err) + } + group := &Group{ + manager: mgr, + groupID: spec.Name, + minSize: spec.MinSize, + maxSize: spec.MaxSize, + } + return group, nil +} + +// RegisterGroup registers a resource group in Spotinst Manager. +func (mgr *CloudManager) RegisterGroup(grp *Group) error { + mgr.cacheMu.Lock() + defer mgr.cacheMu.Unlock() + + group, err := mgr.getResourceForGroup(grp.Id()) + if err != nil { + return err + } + grp.group = group + + mgr.groups = append(mgr.groups, grp) + return nil +} + +// GetGroupSize gets the current size of the group. +func (mgr *CloudManager) GetGroupSize(grp *Group) (int64, error) { + group, err := mgr.getResourceForGroup(grp.Id()) + if err != nil { + return -1, err + } + size := spotinst.IntValue(group.Capacity.Target) + return int64(size), nil +} + +// SetGroupSize sets the instances count in a Group by updating a +// predefined Spotinst stack parameter (specified by the user). +func (mgr *CloudManager) SetGroupSize(grp *Group, size int64) error { + in := &aws.UpdateGroupInput{ + Group: &aws.Group{ + ID: spotinst.String(grp.Id()), + Capacity: &aws.Capacity{ + Target: spotinst.Int(int(size)), + Minimum: spotinst.Int(grp.minSize), + Maximum: spotinst.Int(grp.maxSize), + }, + }, + } + _, err := mgr.groupService.CloudProviderAWS().Update(context.Background(), in) + if err != nil { + return err + } + return nil +} + +// GetGroupForInstance retrieves the resource group that contains +// a given instance. +func (mgr *CloudManager) GetGroupForInstance(instanceID string) (*Group, error) { + mgr.cacheMu.Lock() + defer mgr.cacheMu.Unlock() + + if group, ok := mgr.cache[instanceID]; ok { + return group, nil + } + + klog.V(8).Infof("Instance `%s` does not belong to any managed group", instanceID) + return nil, nil +} + +// DeleteInstances deletes the specified instances from the +// OpenStack resource group +func (mgr *CloudManager) DeleteInstances(instanceIDs []string) error { + if len(instanceIDs) == 0 { + return nil + } + commonGroup, err := mgr.GetGroupForInstance(instanceIDs[0]) + if err != nil { + return err + } + for _, instanceID := range instanceIDs { + instanceGroup, err := mgr.GetGroupForInstance(instanceID) + if err != nil { + return err + } + if instanceGroup.groupID != commonGroup.groupID { + return errors.New("connot delete instances which don't belong to the same group") + } + } + in := &aws.DetachGroupInput{ + GroupID: spotinst.String(commonGroup.groupID), + InstanceIDs: instanceIDs, + ShouldDecrementTargetCapacity: spotinst.Bool(true), + ShouldTerminateInstances: spotinst.Bool(true), + } + if _, err := mgr.groupService.CloudProviderAWS().Detach(context.Background(), in); err != nil { + return fmt.Errorf("failed to detach instances from group %s: %v", commonGroup.groupID, err) + } + return nil +} + +func (mgr *CloudManager) getResourceForGroup(groupID string) (*aws.Group, error) { + in := &aws.ReadGroupInput{ + GroupID: spotinst.String(groupID), + } + out, err := mgr.groupService.CloudProviderAWS().Read(context.Background(), in) + if err != nil { + return nil, err + } + if out.Group == nil { + return nil, fmt.Errorf("failed to get group %s", groupID) + } + return out.Group, nil +} + +// Cleanup cleans up open resources before the cloud provider is destroyed, i.e. go routines etc. +func (mgr *CloudManager) Cleanup() error { + close(mgr.interruptCh) + return nil +} + +// Refresh is called before every main loop and can be used to dynamically update cloud provider state. +// In particular the list of node groups returned by NodeGroups can change as a result of CloudProvider.Refresh(). +func (mgr *CloudManager) Refresh() error { + mgr.cacheMu.Lock() + defer mgr.cacheMu.Unlock() + + if mgr.refreshedAt.Add(mgr.refreshInterval).After(time.Now()) { + return nil + } + return mgr.forceRefresh() +} + +func (mgr *CloudManager) forceRefresh() error { + mgr.regenerateCache() + mgr.refreshedAt = time.Now() + klog.V(2).Infof("Refreshed, next refresh after %v", mgr.refreshedAt.Add(mgr.refreshInterval)) + return nil +} + +func (mgr *CloudManager) regenerateCache() { + mgr.cache = make(map[string]*Group) + for _, group := range mgr.groups { + klog.V(4).Infof("Regenerating resource group information for %s", group.groupID) + if err := mgr.refreshGroupNodes(group); err != nil { + klog.Warningf("Could not retrieve nodes for group %s: %v", group.groupID, err) + } + } +} + +func (mgr *CloudManager) refreshGroupNodes(grp *Group) error { + in := &aws.StatusGroupInput{ + GroupID: spotinst.String(grp.Id()), + } + status, err := mgr.groupService.CloudProviderAWS().Status(context.Background(), in) + if err != nil { + return err + } + for _, instance := range status.Instances { + if instance.ID != nil { + instanceID := spotinst.StringValue(instance.ID) + klog.V(8).Infof("Managing AWS instance with ID %s in group %s", instanceID, grp.Id()) + mgr.cache[instanceID] = grp + } + } + return nil +} + +type groupTemplate struct { + InstanceType *instanceType + Region string + Zone string + Tags []*aws.Tag +} + +func (mgr *CloudManager) inferInstanceType(instanceTypeName string) *instanceType { + ret := &instanceType{ + InstanceType: instanceTypeName, + VCPU: 1, + MemoryMb: 1024, // 1GB + GPU: 0, + } + size := 1 + if strings.HasSuffix(instanceTypeName, ".medium") || strings.HasSuffix(instanceTypeName, ".large") { + size = 1 + } else if strings.HasSuffix(instanceTypeName, ".xlarge") { + size = 2 + } else { + elems := strings.Split(instanceTypeName, ".") + if len(elems) > 1 { + nums := strings.Split(elems[1], "xlarge") + if len(nums) > 0 { + if num, err := strconv.Atoi(nums[0]); err == nil { + size = num * 2 + } + } + } + } + ret.VCPU = 2 * int64(size) + ret.MemoryMb = 1024 * 2 * ret.VCPU + if strings.HasPrefix(instanceTypeName, "g") || strings.HasPrefix(instanceTypeName, "p") { + ret.GPU = int64(size / 4) + if ret.GPU <= 0 { + ret.GPU = 1 + } + } + return ret +} + +func (mgr *CloudManager) buildGroupTemplate(groupID string) (*groupTemplate, error) { + klog.Infof("Building template for group %s", groupID) + + group, err := mgr.getResourceForGroup(groupID) + if err != nil { + return nil, err + } + + if len(group.Compute.AvailabilityZones) < 1 { + return nil, fmt.Errorf("unable to get first AvailabilityZone for %s", groupID) + } + + zone := spotinst.StringValue(group.Compute.AvailabilityZones[0].Name) + region := zone[0 : len(zone)-1] + + if len(group.Compute.AvailabilityZones) > 1 { + klog.Warningf("Found multiple availability zones, using %s", zone) + } + + instanceTypeName := spotinst.StringValue(group.Compute.InstanceTypes.OnDemand) + foundInstanceType := InstanceTypes[instanceTypeName] + if foundInstanceType == nil { + klog.Warningf("Unable to get node template info for instance type %s", instanceTypeName) + foundInstanceType = mgr.inferInstanceType(instanceTypeName) + } + + tmpl := &groupTemplate{ + InstanceType: foundInstanceType, + Region: region, + Zone: zone, + Tags: group.Compute.LaunchSpecification.Tags, + } + + return tmpl, nil +} + +func (mgr *CloudManager) buildNodeFromTemplate(group *Group, template *groupTemplate) (*apiv1.Node, error) { + klog.Infof("Building node from template of group %s", group.Id()) + + node := apiv1.Node{} + nodeName := fmt.Sprintf("%s-group-%d", group.groupID, rand.Int63()) + + node.ObjectMeta = metav1.ObjectMeta{ + Name: nodeName, + SelfLink: fmt.Sprintf("/api/v1/nodes/%s", nodeName), + Labels: map[string]string{}, + } + + node.Status = apiv1.NodeStatus{ + Capacity: apiv1.ResourceList{}, + } + + node.Status.Capacity[apiv1.ResourcePods] = *resource.NewQuantity(110, resource.DecimalSI) + node.Status.Capacity[apiv1.ResourceCPU] = *resource.NewQuantity(template.InstanceType.VCPU, resource.DecimalSI) + node.Status.Capacity[apiv1.ResourceMemory] = *resource.NewQuantity(template.InstanceType.MemoryMb*1024*1024, resource.DecimalSI) + node.Status.Capacity[gpu.ResourceNvidiaGPU] = *resource.NewQuantity(template.InstanceType.GPU, resource.DecimalSI) + node.Status.Capacity[gpumemory.ResourceVisenzeGPUMemory] = *resource.NewQuantity(template.InstanceType.GPUMemory, resource.DecimalSI) + node.Status.Capacity[mpscontext.ResourceVisenzeMPSContext] = *resource.NewQuantity(template.InstanceType.MPSContext, resource.DecimalSI) + node.Status.Allocatable = node.Status.Capacity + + // NodeLabels + node.Labels = cloudprovider.JoinStringMaps(node.Labels, extractLabelsFromGroup(template.Tags)) + + // GenericLabels + node.Labels = cloudprovider.JoinStringMaps(node.Labels, buildGenericLabels(template, nodeName)) + + node.Spec.Taints = extractTaintsFromGroup(template.Tags) + node.Status.Conditions = cloudprovider.BuildReadyConditions() + + klog.V(4).Infof("Node `%s` labels: %s", nodeName, stringutil.Stringify(node.Labels)) + klog.V(4).Infof("Node `%s` taints: %s", nodeName, stringutil.Stringify(node.Spec.Taints)) + + return &node, nil +} + +func buildGenericLabels(template *groupTemplate, nodeName string) map[string]string { + result := make(map[string]string) + + result[kubeletapis.LabelArch] = cloudprovider.DefaultArch + result[kubeletapis.LabelOS] = cloudprovider.DefaultOS + result[apiv1.LabelInstanceType] = template.InstanceType.InstanceType + result[apiv1.LabelZoneRegion] = template.Region + result[apiv1.LabelZoneFailureDomain] = template.Zone + result[apiv1.LabelHostname] = nodeName + + return result +} + +func extractLabelsFromGroup(tags []*aws.Tag) map[string]string { + result := make(map[string]string) + + for _, tag := range tags { + k := *tag.Key + v := *tag.Value + splits := strings.Split(k, "k8s.io/cluster-autoscaler/node-template/label/") + if len(splits) > 1 { + label := splits[1] + if label != "" { + result[label] = v + } + } + } + + return result +} + +func extractTaintsFromGroup(tags []*aws.Tag) []apiv1.Taint { + taints := make([]apiv1.Taint, 0) + + for _, tag := range tags { + k := *tag.Key + v := *tag.Value + splits := strings.Split(k, "k8s.io/cluster-autoscaler/node-template/taint/") + if len(splits) > 1 { + values := strings.SplitN(v, ":", 2) + taints = append(taints, apiv1.Taint{ + Key: splits[1], + Value: values[0], + Effect: apiv1.TaintEffect(values[1]), + }) + } + } + + return taints +} \ No newline at end of file diff --git a/cluster-autoscaler/cloudprovider/spotinst/spotinst_node_group.go b/cluster-autoscaler/cloudprovider/spotinst/spotinst_node_group.go new file mode 100644 index 000000000000..8eb1efd0f464 --- /dev/null +++ b/cluster-autoscaler/cloudprovider/spotinst/spotinst_node_group.go @@ -0,0 +1,232 @@ +/* +Copyright 2016 The Kubernetes Authors. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package spotinst + +import ( + "context" + "errors" + "fmt" + "regexp" + "strings" + + "k8s.io/klog/v2" + + "github.com/spotinst/spotinst-sdk-go/service/elastigroup/providers/aws" + "github.com/spotinst/spotinst-sdk-go/spotinst" + apiv1 "k8s.io/api/core/v1" + "k8s.io/autoscaler/cluster-autoscaler/cloudprovider" + "k8s.io/autoscaler/cluster-autoscaler/config" + schedulerframework "k8s.io/kubernetes/pkg/scheduler/framework" +) + +// Group declaration of spotinst nodegroup +type Group struct { + manager *CloudManager + group *aws.Group + groupID string + minSize int + maxSize int +} + +// MaxSize returns maximum size of the node group. +func (grp *Group) MaxSize() int { + return grp.maxSize +} + +// MinSize returns minimum size of the node group. +func (grp *Group) MinSize() int { + return grp.minSize +} + +// TargetSize returns the current target size of the node group. +func (grp *Group) TargetSize() (int, error) { + size, err := grp.manager.GetGroupSize(grp) + return int(size), err +} + +// IncreaseSize increases the size of the node group. +func (grp *Group) IncreaseSize(delta int) error { + if delta <= 0 { + return errors.New("size increase must be positive") + } + size, err := grp.manager.GetGroupSize(grp) + if err != nil { + return err + } + if int(size)+delta > grp.MaxSize() { + return fmt.Errorf("size increase too large - desired:%d max:%d", int(size)+delta, grp.MaxSize()) + } + return grp.manager.SetGroupSize(grp, size+int64(delta)) +} + +// DeleteNodes deletes nodes from this node group. +func (grp *Group) DeleteNodes(nodes []*apiv1.Node) error { + size, err := grp.manager.GetGroupSize(grp) + if err != nil { + return fmt.Errorf("error when deleting nodes, retrieving size of group %s failed: %v", grp.Id(), err) + } + if int(size) <= grp.MinSize() { + return errors.New("min size reached, nodes will not be deleted") + } + toBeDeleted := make([]string, 0) + for _, node := range nodes { + belongs, err := grp.Belongs(node) + if err != nil { + return fmt.Errorf("failed to check membership of node %s in group %s: %v", node.Name, grp.Id(), err) + } + if !belongs { + return fmt.Errorf("%s belongs to a different group than %s", node.Name, grp.Id()) + } + instanceID, err := extractInstanceId(node.Spec.ProviderID) + if err != nil { + return fmt.Errorf("node %s's cloud provider ID is malformed: %v", node.Name, err) + } + toBeDeleted = append(toBeDeleted, instanceID) + } + return grp.manager.DeleteInstances(toBeDeleted) +} + +// DecreaseTargetSize decreases the target size of the node group. +func (grp *Group) DecreaseTargetSize(delta int) error { + if delta >= 0 { + return errors.New("size decrease size must be negative") + } + size, err := grp.manager.GetGroupSize(grp) + if err != nil { + return err + } + nodes, err := grp.Nodes() + if err != nil { + return err + } + if int(size)+delta < len(nodes) { + return fmt.Errorf("size decrease too large - desired:%d existing:%d", int(size)+delta, len(nodes)) + } + return grp.manager.SetGroupSize(grp, size+int64(delta)) +} + +// Id returns an unique identifier of the node group. +func (grp *Group) Id() string { + return grp.groupID +} + +// Debug returns a string containing all information regarding this node group. +func (grp *Group) Debug() string { + return fmt.Sprintf("%s (%d:%d)", grp.Id(), grp.MinSize(), grp.MaxSize()) +} + +// Nodes returns a list of all nodes that belong to this node group. +func (grp *Group) Nodes() ([]cloudprovider.Instance, error) { + in := &aws.StatusGroupInput{ + GroupID: spotinst.String(grp.Id()), + } + status, err := grp.manager.groupService.CloudProviderAWS().Status(context.Background(), in) + if err != nil { + return []cloudprovider.Instance{}, err + } + out := make([]cloudprovider.Instance, 0) + for _, instance := range status.Instances { + if instance.ID != nil && instance.AvailabilityZone != nil { + out = append(out, cloudprovider.Instance{Id: fmt.Sprintf("aws:///%s/%s", *instance.AvailabilityZone, *instance.ID)}) + } + } + return out, nil +} + +// TemplateNodeInfo returns a node template for this node group. +func (grp *Group) TemplateNodeInfo() (*schedulerframework.NodeInfo, error) { + klog.Infof("No working nodes in node group %s, trying to generate from template", grp.Id()) + + template, err := grp.manager.buildGroupTemplate(grp.Id()) + if err != nil { + return nil, err + } + + node, err := grp.manager.buildNodeFromTemplate(grp, template) + if err != nil { + return nil, err + } + + nodeInfo := schedulerframework.NewNodeInfo(cloudprovider.BuildKubeProxy(grp.Id())) + nodeInfo.SetNode(node) + return nodeInfo, nil +} + +// Belongs returns true if the given node belongs to the NodeGroup. +func (grp *Group) Belongs(node *apiv1.Node) (bool, error) { + instanceID, err := extractInstanceId(node.Spec.ProviderID) + if err != nil { + return false, err + } + group, err := grp.manager.GetGroupForInstance(instanceID) + if err != nil { + return false, err + } + if group == nil { + return false, fmt.Errorf("%s does not belong to a known group", node.Name) + } + return true, nil +} + +// Exist checks if the node group really exists on the cloud provider side. +func (grp *Group) Exist() bool { + return true +} + +// Create creates the node group on the cloud provider side. +func (grp *Group) Create() (cloudprovider.NodeGroup, error) { + return nil, cloudprovider.ErrAlreadyExist +} + +// Delete deletes the node group on the cloud provider side. +func (grp *Group) Delete() error { + return cloudprovider.ErrNotImplemented +} + +// Autoprovisioned returns true if the node group is autoprovisioned. +func (grp *Group) Autoprovisioned() bool { + return false +} + +func (grp *Group) GetOptions(defaults config.NodeGroupAutoscalingOptions) (*config.NodeGroupAutoscalingOptions, error) { + return nil, cloudprovider.ErrNotImplemented +} + +var ( + spotinstProviderRE = regexp.MustCompile(`^spotinst\:\/\/\/[-0-9a-z]*\/[-0-9a-z]*$`) + awsProviderRE = regexp.MustCompile(`^aws\:\/\/\/[-0-9a-z]*\/[-0-9a-z]*$`) +) + +func extractInstanceId(providerID string) (string, error) { + var prefix string + + if spotinstProviderRE.FindStringSubmatch(providerID) != nil { + prefix = "spotinst:///" + } + + if awsProviderRE.FindStringSubmatch(providerID) != nil { + prefix = "aws:///" + } + + if prefix == "" { + return "", fmt.Errorf("expected node provider ID to be one of the "+ + "forms `spotinst:////` or `aws:////`, got `%s`", providerID) + } + + parts := strings.Split(providerID[len(prefix):], "/") + instanceID := parts[1] + + klog.V(8).Infof("Instance ID `%s` extracted from provider `%s`", instanceID, providerID) + return instanceID, nil +} \ No newline at end of file diff --git a/cluster-autoscaler/utils/gpumemory/gpumemory.go b/cluster-autoscaler/utils/gpumemory/gpumemory.go new file mode 100644 index 000000000000..7d357c10c579 --- /dev/null +++ b/cluster-autoscaler/utils/gpumemory/gpumemory.go @@ -0,0 +1,41 @@ +package gpumemory + +import ( + apiv1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" +) + +const ( + // ResourceVisenzeGPUMemory is the name of the GPU Memory resource + ResourceVisenzeGPUMemory = "visenze.com/nvidia-gpu-memory" + // GPULabel is the label added to nodes with GPU resource by Visenze. + // If you're not scaling - this is probably the problem! + GPULabel = "accelerator" +) + +// NodeHasGpuMemory returns true if a given node has GPU hardware +func NodeHasGpuMemory(node *apiv1.Node) bool { + _, hasGpuLabel := node.Labels[GPULabel] + gpuAllocatable, hasGpuAllocatable := node.Status.Allocatable[ResourceVisenzeGPUMemory] + return hasGpuLabel || (hasGpuAllocatable && !gpuAllocatable.IsZero()) +} + +// PodRequestsGpuMemory returns true if a given pod has GPU Memory request +func PodRequestsGpuMemory(pod *apiv1.Pod) bool { + for _, container := range pod.Spec.Containers { + if container.Resources.Requests != nil { + _, gpuMemoryFound := container.Resources.Requests[ResourceVisenzeGPUMemory] + if gpuMemoryFound { + return true + } + } + } + return false +} + +// RequestInfo gives some information about hwo much GPU memory is needed +type RequestInfo struct { + MaximumMemory resource.Quantity + TotalMemory resource.Quantity + Pods []*apiv1.Pod +} \ No newline at end of file diff --git a/cluster-autoscaler/utils/gpumemory/gpumemory_test.go b/cluster-autoscaler/utils/gpumemory/gpumemory_test.go new file mode 100644 index 000000000000..14507cf51cbb --- /dev/null +++ b/cluster-autoscaler/utils/gpumemory/gpumemory_test.go @@ -0,0 +1,83 @@ +package gpumemory + +import ( + "testing" + + "github.com/stretchr/testify/assert" + apiv1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestNodeHasGpuMemory(t *testing.T) { + gpuLabels := map[string]string{ + GPULabel: "nvidia-tesla-k80", + } + nodeGpuReady := &apiv1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "nodeGpuReady", + Labels: gpuLabels, + }, + Status: apiv1.NodeStatus{ + Capacity: apiv1.ResourceList{}, + Allocatable: apiv1.ResourceList{}, + }, + } + nodeGpuReady.Status.Allocatable[ResourceVisenzeGPUMemory] = *resource.NewQuantity(8e9, resource.DecimalSI) + nodeGpuReady.Status.Capacity[ResourceVisenzeGPUMemory] = *resource.NewQuantity(8e9, resource.DecimalSI) + assert.True(t, NodeHasGpuMemory(nodeGpuReady)) + + nodeGpuUnready := &apiv1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "nodeGpuUnready", + Labels: gpuLabels, + }, + Status: apiv1.NodeStatus{ + Capacity: apiv1.ResourceList{}, + Allocatable: apiv1.ResourceList{}, + }, + } + assert.True(t, NodeHasGpuMemory(nodeGpuUnready)) + + nodeNoGpu := &apiv1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "nodeNoGpu", + Labels: map[string]string{}, + }, + Status: apiv1.NodeStatus{ + Capacity: apiv1.ResourceList{}, + Allocatable: apiv1.ResourceList{}, + }, + } + assert.False(t, NodeHasGpuMemory(nodeNoGpu)) +} + +func TestPodRequestsGpuMemory(t *testing.T) { + podNoGpu := &apiv1.Pod{ + Spec: apiv1.PodSpec{ + Containers: []apiv1.Container{ + apiv1.Container{ + Resources: apiv1.ResourceRequirements{ + Requests: apiv1.ResourceList{ + apiv1.ResourceCPU: *resource.NewQuantity(1, resource.DecimalSI), + }, + }, + }, + }, + }, + } + podWithGpu := &apiv1.Pod{Spec: apiv1.PodSpec{Containers: []apiv1.Container{ + apiv1.Container{ + Resources: apiv1.ResourceRequirements{ + Requests: apiv1.ResourceList{ + apiv1.ResourceCPU: *resource.NewQuantity(1, resource.DecimalSI), + ResourceVisenzeGPUMemory: *resource.NewQuantity(1, resource.DecimalSI), + }, + }, + }, + }}} + podWithGpu.Spec.Containers[0].Resources.Requests[ResourceVisenzeGPUMemory] = *resource.NewQuantity(1, resource.DecimalSI) + + assert.False(t, PodRequestsGpuMemory(podNoGpu)) + assert.True(t, PodRequestsGpuMemory(podWithGpu)) +} \ No newline at end of file diff --git a/cluster-autoscaler/utils/mpscontext/mpscontext.go b/cluster-autoscaler/utils/mpscontext/mpscontext.go new file mode 100644 index 000000000000..22d9a66687dc --- /dev/null +++ b/cluster-autoscaler/utils/mpscontext/mpscontext.go @@ -0,0 +1,6 @@ +package mpscontext + +// Custom resource for NVIDIA MPS context +const ( + ResourceVisenzeMPSContext = "visenze.com/nvidia-mps-context" +) \ No newline at end of file diff --git a/cluster-autoscaler/visenze.md b/cluster-autoscaler/visenze.md new file mode 100644 index 000000000000..a756fb8ae987 --- /dev/null +++ b/cluster-autoscaler/visenze.md @@ -0,0 +1,46 @@ +#Upgrade workflow +Suppose that we want to upgrade from 1.17 to 1.18 +1. Pull the latest cost from the open source repository +1. Create a new branch `release-1.18-eks` based on the open source branch `cluster-autoscaler-release-1.18` +1. Find the patch file `patch/1.17.patch` in the branch `release-1.17-eks`, try to use it apply to the current branch +1. After modifications, push the code to our repository. Then it will trigger the build https://jenkins.visenze.com/job/kubernetes-cluster-autoscaler/ +1. Then we can test it in staging environment. + + +#How to test the cluster autoscaler work +1. Test if gpu related resources can trigger the scaling up and scaling down with this pod definition. + +``` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: gpu-pod + labels: + app: gpu-pod +spec: + replicas: 0 + selector: + matchLabels: + app: gpu-pod + template: + metadata: + labels: + app: gpu-pod + spec: + nodeSelector: + visenze.component: search + visenze.gpu: "true" + containers: + - name: digits-container + image: nvcr.io/nvidia/digits:20.12-tensorflow-py3 + #image: banst/awscli + resources: + limits: + visenze.com/nvidia-gpu-memory: 8988051968 + # visenze.com/nvidia-mps-context: 20 + # nvidia.com/gpu: 1 +``` + +#Note +* If it can work, then generate and commit a new patch for the next version upgrade. The command to generate the patch: + `git diff [commit that before applying the patch] ':(exclude)cluster-autoscaler/go.mod' ':(exclude)cluster-autoscaler/go.sum' > patch/1.18.patch`