As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.
Tutorial de instância Amazon EC2 Spot
Este tutorial mostra como usar o AWS SDK for .NET para gerenciar instâncias EC2 spot da Amazon.
Visão geral
As instâncias spot permitem que você solicite EC2 capacidade não utilizada da Amazon por menos do que o preço sob demanda. Isso pode reduzir significativamente os EC2 custos de aplicativos que podem ser interrompidos.
O resumo a seguir detalha como as instâncias spot são solicitadas e usadas.
-
Criação uma solicitação de instância spot, especificando o preço máximo que está disposto a pagar.
-
Quando a solicitação for atendida, execute a instância como você faria com qualquer outra EC2 instância da Amazon.
-
Execute a instância por quanto tempo quiser e, em seguida, encerre-a, a menos que o preço de spot mude de maneira que a instância fique encerrada para você.
-
Limpe a solicitação da Instância Spot quando não for mais necessária, para que as Instâncias Spot não sejam mais criadas.
Essa tem sido uma visão geral de alto nível das Instâncias Spot. Para obter uma melhor compreensão das Instâncias Spot, consulte Instâncias Spot no Guia EC2 do Usuário da Amazon.
Sobre este tutorial
Ao seguir este tutorial, você usa o AWS SDK for .NET para fazer o seguinte:
-
Criar uma solicitação de instância spot
-
Determinar quando a solicitação de instância spot é atendida
-
Cancelar a solicitação de instância spot
-
Encerrar as instâncias associadas
As seções a seguir fornecem snippets e outras informações para este exemplo. O código completo do exemplo é mostrado após os snippets e pode ser criado e executado como está.
Tópicos
Pré-requisitos
Para obter informações sobre os pré-requisitos APIs e, consulte a seção principal (). Trabalhando com a Amazon EC2
Colete o que você precisa
Para criar uma solicitação de instância spot, você precisará de várias coisas.
-
O número da instância e o seu tipo. Há vários tipos de instância para escolher. Para obter mais informações, consulte os tipos de EC2 instância da Amazon no Guia EC2 do usuário da Amazon. Consulte também Detalhes do tipo de instância
e Explorador de tipos de instância . Para número padrão para este tutorial é o 1.
-
A Amazon Machine Image (AMI) que será usada para criar a instância. Para obter informações sobreAMIs, consulte Amazon Machine Images (AMIs) no Guia EC2 do usuário da Amazon. Em particular, consulte Find an AMI and Shared AMIs.
-
O preço máximo que você está disposto a pagar por hora por instância. Você pode ver os preços de todos os tipos de instância (tanto para instâncias sob demanda quanto para instâncias spot) na página de EC2 preços da Amazon
. O preço padrão deste tutorial será explicado posteriormente.
-
Se você quiser se conectar remotamente a uma instância, a um grupo de segurança com a configuração e os recursos adequados. Isso está descrito em Trabalhando com grupos de segurança na Amazon EC2 e as informações sobre como coletar o que você precisa e conectar-se a uma instância em Lançamento de uma EC2 instância da Amazon. Para simplificar, este tutorial usa o grupo de segurança chamado padrão, que todas as contas AWS mais recentes possuem.
Há muitas maneiras de abordar a solicitação de instâncias spot. Estas são estratégias comuns:
-
Faça solicitações que certamente custarão menos que os preços sob demanda.
-
Solicitar com base no valor da computação resultante.
-
Solicitar para adquirir capacidade de computação o mais rápido possível.
As explicações a seguir se referem ao histórico de preços de instâncias spot no Guia do EC2 usuário da Amazon.
Você tem um job de processamento em lote que modera determinado número de horas ou dias para ser executado. Contudo, você tem flexibilidade em relação ao início e ao fim. Você quer ver se pode o concluído por um custo inferior ao das instâncias sob demanda.
Você examina o histórico de preços à vista para tipos de instância usando o EC2 console da Amazon ou a Amazon EC2API. Depois de analisar o histórico de preços do tipo de instância desejado em determinada zona de disponibilidade, há duas abordagens alternativas para sua solicitação:
-
Especificar uma solicitação na extremidade superior do intervalo de preços spot que ainda estão abaixo do preço sob demanda, prevendo que sua solicitação instância spot única seria provavelmente cumprida e executada pelo tempo de computação consecutivo suficiente para concluir o trabalho.
-
Especificar uma solicitação na extremidade inferior do intervalo de preço e planejar a combinação de várias instâncias executadas ao longo do tempo por meio de uma requisição persistente. As instâncias seriam executadas por tempo suficiente, ao todo, para concluir o trabalho com um custo total ainda inferior.
Você tem um job de processamento de dados para ser executado. Você entende o valor dos resultados do trabalho bem o suficiente para saber o quanto valem em termos de custos computação.
Após analisar o histórico de preços spot para seu tipo de instância, escolha o preço de lance no qual o custo do tempo computacional não é mais que o valor dos resultados do job. Você cria uma requisição persistente e a deixa ser executada de forma intermitente, à medida que o preço spot flutua acima ou abaixo da sua solicitação.
Você tem uma necessidade imprevista e de curto prazo para capacidade adicional indisponível pelas instâncias sob demanda. Depois de analisar o histórico de preços spot para seu tipo de instância, você escolhe um preço acima do preço histórico mais alto para aumentar significativamente a probabilidade de sua solicitação ser atendida com rapidez e continuar a computação até a conclusão.
Depois de coletar o que precisa e escolher uma estratégia, você está pronto para solicitar uma Instância Spot. Para este tutorial, o preço máximo da instância spot padrão está definido para ser o mesmo que o preço da instância sob demanda (que é 0,003 USD para este tutorial). Definir o preço desta forma maximiza as chances de que o pedido seja atendido.
Como criar uma solicitação de instância spot
O snippet a seguir mostra como criar uma solicitação de instância spot com os elementos coletados anteriormente.
O exemplo no final deste tópico mostra o snippet em uso.
// // Method to create a Spot Instance request private static async Task<SpotInstanceRequest> CreateSpotInstanceRequest( IAmazonEC2 ec2Client, string amiId, string securityGroupName, InstanceType instanceType, string spotPrice, int instanceCount) { var launchSpecification = new LaunchSpecification{ ImageId = amiId, InstanceType = instanceType }; launchSpecification.SecurityGroups.Add(securityGroupName); var request = new RequestSpotInstancesRequest{ SpotPrice = spotPrice, InstanceCount = instanceCount, LaunchSpecification = launchSpecification }; RequestSpotInstancesResponse result = await ec2Client.RequestSpotInstancesAsync(request); return result.SpotInstanceRequests[0]; }
O valor importante retornado desse método é o ID da solicitação da Instância Spot, que está contido no SpotInstanceRequestId
membro do SpotInstanceRequestobjeto retornado.
nota
Você será cobrado por todas as instâncias spot que forem iniciadas. Para evitar custos desnecessários, certifique-se de cancelar todas as solicitações e encerrar todas as instâncias.
Determinar o estado da solicitação de instância spot
O snippet a seguir mostra como obter informações sobre sua solicitação de instância spot. Você pode usar essas informações para tomar certas decisões em seu código, como decidir continuar esperando o atendimento de uma solicitação de instância spot.
O exemplo no final deste tópico mostra o snippet em uso.
// // Method to get information about a Spot Instance request, including the status, // instance ID, etc. // It gets the information for a specific request (as opposed to all requests). private static async Task<SpotInstanceRequest> GetSpotInstanceRequestInfo( IAmazonEC2 ec2Client, string requestId) { var describeRequest = new DescribeSpotInstanceRequestsRequest(); describeRequest.SpotInstanceRequestIds.Add(requestId); DescribeSpotInstanceRequestsResponse describeResponse = await ec2Client.DescribeSpotInstanceRequestsAsync(describeRequest); return describeResponse.SpotInstanceRequests[0]; }
O método retorna informações sobre a solicitação da instância spot, como o ID da instância, seu estado e o código de status. Para obter mais informações sobre os códigos de status das solicitações de Instância Spot, consulte Status da solicitação spot no Guia EC2 do usuário da Amazon.
Limpar suas solicitações de instância spot
Quando você não precisar mais solicitar instâncias spot, é importante cancelar todas as solicitações pendentes para evitar que essas solicitações sejam atendidas novamente. O snippet a seguir mostra como cancelar uma solicitação de instância spot.
O exemplo no final deste tópico mostra o snippet em uso.
// // Method to cancel a Spot Instance request private static async Task CancelSpotInstanceRequest( IAmazonEC2 ec2Client, string requestId) { var cancelRequest = new CancelSpotInstanceRequestsRequest(); cancelRequest.SpotInstanceRequestIds.Add(requestId); await ec2Client.CancelSpotInstanceRequestsAsync(cancelRequest); }
Limpar as instâncias spot
Para evitar custos desnecessários, é importante que você encerre todas as instâncias que foram iniciadas a partir de solicitações de instância spot. Apenas cancelar a solicitação de instância spot não encerrará as instâncias, o que significa que você continuará a ser cobrado por elas. O snippet a seguir mostra como encerrar uma instância depois de obter o identificador da instância para uma instância spot ativa.
O exemplo no final deste tópico mostra o snippet em uso.
// // Method to terminate a Spot Instance private static async Task TerminateSpotInstance( IAmazonEC2 ec2Client, string requestId) { var describeRequest = new DescribeSpotInstanceRequestsRequest(); describeRequest.SpotInstanceRequestIds.Add(requestId); // Retrieve the Spot Instance request to check for running instances. DescribeSpotInstanceRequestsResponse describeResponse = await ec2Client.DescribeSpotInstanceRequestsAsync(describeRequest); // If there are any running instances, terminate them if( (describeResponse.SpotInstanceRequests[0].Status.Code == "request-canceled-and-instance-running") || (describeResponse.SpotInstanceRequests[0].State == SpotInstanceState.Active)) { TerminateInstancesResponse response = await ec2Client.TerminateInstancesAsync(new TerminateInstancesRequest{ InstanceIds = new List<string>(){ describeResponse.SpotInstanceRequests[0].InstanceId } }); foreach (InstanceStateChange item in response.TerminatingInstances) { Console.WriteLine($"\n Terminated instance: {item.InstanceId}"); Console.WriteLine($" Instance state: {item.CurrentState.Name}\n"); } } }
Código completo
O exemplo de código a seguir chama os métodos descritos anteriormente para criar e cancelar uma solicitação de instância spot e encerrar uma instância spot.
NuGet pacotes:
Elementos de programação:
-
Classe Amazon EC2Client
Classe InstanceType
-
Classe CancelSpotInstanceRequestsRequest
Classe DescribeSpotInstanceRequestsRequest
Classe DescribeSpotInstanceRequestsResponse
Classe InstanceStateChange
Classe LaunchSpecification
Classe RequestSpotInstancesRequest
Classe RequestSpotInstancesResponse
Classe SpotInstanceRequest
Classe TerminateInstancesRequest
Classe TerminateInstancesResponse
using System; using System.Threading; using System.Threading.Tasks; using System.Collections.Generic; using Amazon.EC2; using Amazon.EC2.Model; namespace EC2SpotInstanceRequests { class Program { static async Task Main(string[] args) { // Some default values. // These could be made into command-line arguments instead. var instanceType = InstanceType.T1Micro; string securityGroupName = "default"; string spotPrice = "0.003"; int instanceCount = 1; // Parse the command line arguments if((args.Length != 1) || (!args[0].StartsWith("ami-"))) { Console.WriteLine("\nUsage: EC2SpotInstanceRequests ami"); Console.WriteLine(" ami: the Amazon Machine Image to use for the Spot Instances."); return; } // Create the Amazon EC2 client. var ec2Client = new AmazonEC2Client(); // Create the Spot Instance request and record its ID Console.WriteLine("\nCreating spot instance request..."); var req = await CreateSpotInstanceRequest( ec2Client, args[0], securityGroupName, instanceType, spotPrice, instanceCount); string requestId = req.SpotInstanceRequestId; // Wait for an EC2 Spot Instance to become active Console.WriteLine( $"Waiting for Spot Instance request with ID {requestId} to become active..."); int wait = 1; var start = DateTime.Now; while(true) { Console.Write("."); // Get and check the status to see if the request has been fulfilled. var requestInfo = await GetSpotInstanceRequestInfo(ec2Client, requestId); if(requestInfo.Status.Code == "fulfilled") { Console.WriteLine($"\nSpot Instance request {requestId} " + $"has been fulfilled by instance {requestInfo.InstanceId}.\n"); break; } // Wait a bit and try again, longer each time (1, 2, 4, ...) Thread.Sleep(wait); wait = wait * 2; } // Show the user how long it took to fulfill the Spot Instance request. TimeSpan span = DateTime.Now.Subtract(start); Console.WriteLine($"That took {span.TotalMilliseconds} milliseconds"); // Perform actions here as needed. // For this example, simply wait for the user to hit a key. // That gives them a chance to look at the EC2 console to see // the running instance if they want to. Console.WriteLine("Press any key to start the cleanup..."); Console.ReadKey(true); // Cancel the request. // Do this first to make sure that the request can't be re-fulfilled // once the Spot Instance has been terminated. Console.WriteLine("Canceling Spot Instance request..."); await CancelSpotInstanceRequest(ec2Client, requestId); // Terminate the Spot Instance that's running. Console.WriteLine("Terminating the running Spot Instance..."); await TerminateSpotInstance(ec2Client, requestId); Console.WriteLine("Done. Press any key to exit..."); Console.ReadKey(true); } // // Method to create a Spot Instance request private static async Task<SpotInstanceRequest> CreateSpotInstanceRequest( IAmazonEC2 ec2Client, string amiId, string securityGroupName, InstanceType instanceType, string spotPrice, int instanceCount) { var launchSpecification = new LaunchSpecification{ ImageId = amiId, InstanceType = instanceType }; launchSpecification.SecurityGroups.Add(securityGroupName); var request = new RequestSpotInstancesRequest{ SpotPrice = spotPrice, InstanceCount = instanceCount, LaunchSpecification = launchSpecification }; RequestSpotInstancesResponse result = await ec2Client.RequestSpotInstancesAsync(request); return result.SpotInstanceRequests[0]; } // // Method to get information about a Spot Instance request, including the status, // instance ID, etc. // It gets the information for a specific request (as opposed to all requests). private static async Task<SpotInstanceRequest> GetSpotInstanceRequestInfo( IAmazonEC2 ec2Client, string requestId) { var describeRequest = new DescribeSpotInstanceRequestsRequest(); describeRequest.SpotInstanceRequestIds.Add(requestId); DescribeSpotInstanceRequestsResponse describeResponse = await ec2Client.DescribeSpotInstanceRequestsAsync(describeRequest); return describeResponse.SpotInstanceRequests[0]; } // // Method to cancel a Spot Instance request private static async Task CancelSpotInstanceRequest( IAmazonEC2 ec2Client, string requestId) { var cancelRequest = new CancelSpotInstanceRequestsRequest(); cancelRequest.SpotInstanceRequestIds.Add(requestId); await ec2Client.CancelSpotInstanceRequestsAsync(cancelRequest); } // // Method to terminate a Spot Instance private static async Task TerminateSpotInstance( IAmazonEC2 ec2Client, string requestId) { var describeRequest = new DescribeSpotInstanceRequestsRequest(); describeRequest.SpotInstanceRequestIds.Add(requestId); // Retrieve the Spot Instance request to check for running instances. DescribeSpotInstanceRequestsResponse describeResponse = await ec2Client.DescribeSpotInstanceRequestsAsync(describeRequest); // If there are any running instances, terminate them if( (describeResponse.SpotInstanceRequests[0].Status.Code == "request-canceled-and-instance-running") || (describeResponse.SpotInstanceRequests[0].State == SpotInstanceState.Active)) { TerminateInstancesResponse response = await ec2Client.TerminateInstancesAsync(new TerminateInstancesRequest{ InstanceIds = new List<string>(){ describeResponse.SpotInstanceRequests[0].InstanceId } }); foreach (InstanceStateChange item in response.TerminatingInstances) { Console.WriteLine($"\n Terminated instance: {item.InstanceId}"); Console.WriteLine($" Instance state: {item.CurrentState.Name}\n"); } } } } }
Considerações adicionais
-
Depois de executar o tutorial, é uma boa ideia fazer login no EC2console da Amazon
para verificar se a solicitação da Instância Spot foi cancelada e se a Instância Spot foi encerrada.