Tutorial: usar o AWS SDK para .NET para gerenciar instâncias spot do Amazon EC2 - AWS Lambda

Tutorial: usar o AWS SDK para .NET para gerenciar instâncias spot do Amazon EC2

Você pode usar o AWS SDK para .NET para gerenciar instâncias spot Amazon EC2 com código C#. O SDK permite que você use a API do Amazon EC2 para criar solicitações de instância spot, determinar quando a solicitação é atendida, excluir solicitações e identificar as instâncias criadas.

Este tutorial fornece código que executa essas tarefas e um aplicativo de exemplo que você pode executar localmente ou na AWS. Ele inclui um projeto de exemplo que você pode implantar no tempo de execução do .NET Core 2.1 do AWS Lambda.


      Uma função do Lambda que gerencia solicitações spot e instâncias do Amazon EC2.

Para obter mais informações sobre o uso de instâncias spot e as práticas recomendadas, consulte Instâncias spot no guia do usuário do Amazon EC2.

Pré-requisitos

Para seguir os procedimentos neste manual, você precisa de um terminal de linha de comando ou de um shell para executar os comandos. Nas listagens, os comandos são mostrados precedidos por um símbolo de prompt ($) e pelo nome do diretório atual, quando apropriado:

~/lambda-project$ this is a command this is output

Para comandos longos, um caractere de escape (\) é usado para dividir um comando em várias linhas.

No Linux e no macOS, use seu gerenciador preferido de pacotes e de shell. No Windows 10, você pode instalar o Subsistema Windows para Linux para obter uma versão do Ubuntu integrada com o Windows e o Bash.

Este tutorial usa o código do repositório GitHub do guia do desenvolvedor. O repositório também contém scripts auxiliares e arquivos de configuração que são necessários para seguir seus procedimentos. Clone o repositório em github.com/awsdocs/aws-lambda-developer-guide.

Para usar o código de exemplo, você precisa das seguintes ferramentas:

  • AWS CLI – para implantar o aplicativo de exemplo na AWS, instale a AWS CLI. A AWS CLI também fornece credenciais para o código de exemplo quando você o executa localmente.

  • CLI do .NET Core – para executar e testar o código localmente, instale o .NET Core SDK 2.1.

  • Ferramenta global do .NET Core do Lambda – para criar o pacote de implantação para o Lambda, instale a ferramenta global do .NET Core com a CLI .NET Core.

    $ dotnet tool install -g Amazon.Lambda.Tools

O código neste tutorial gerencia solicitações spot que executam instâncias do Amazon EC2. Para executar o código localmente, você precisa de credenciais de SDK com permissão para usar as seguintes APIs.

  • ec2:RequestSpotInstance

  • ec2:GetSpotRequestState

  • ec2:CancelSpotRequest

  • ec2:TerminateInstances

Para executar o aplicativo de exemplo na AWS, você precisa de permissão para usar o Lambda e os seguintes serviços.

Aplicam-se taxas padrão para cada serviço.

Revisar o código

Localize o projeto de amostra no repositório guia em sample-apps/ec2-spot. Este diretório contém código de função do Lambda, testes, arquivos de projeto, scripts e um modelo do AWS CloudFormation.

A classe Function inclui um método FunctionHandler que chama outros métodos para criar solicitações spot, verificar seu status e limpar. Ele cria um cliente do Amazon EC2 com o AWS SDK para .NET em um construtor estático para permitir que ele seja usado em toda a classe.

exemplo Function.cs – FunctionHandler

using Amazon.EC2; ... public class Function { private static AmazonEC2Client ec2Client; static Function() { AWSSDKHandler.RegisterXRayForAllServices(); ec2Client = new AmazonEC2Client(); } public async Task<string> FunctionHandler(Dictionary<string, string> input, ILambdaContext context) { // More AMI IDs: aws.amazon.com/amazon-linux-2/release-notes/ // us-east-2 HVM EBS-Backed 64-bit Amazon Linux 2 string ami = "ami-09d9edae5eb90d556"; string sg = "default"; InstanceType type = InstanceType.T3aNano; string price = "0.003"; int count = 1; var requestSpotInstances = await RequestSpotInstance(ami, sg, type, price, count); var spotRequestId = requestSpotInstances.SpotInstanceRequests[0].SpotInstanceRequestId;

O método RequestSpotInstance cria uma solicitação de instância spot.

exemplo Function.cs – RequestSpotInstance

using Amazon; using Amazon.Util; using Amazon.EC2; using Amazon.EC2.Model; ... public async Task<RequestSpotInstancesResponse> RequestSpotInstance( string amiId, string securityGroupName, InstanceType instanceType, string spotPrice, int instanceCount) { var request = new RequestSpotInstancesRequest(); var launchSpecification = new LaunchSpecification(); launchSpecification.ImageId = amiId; launchSpecification.InstanceType = instanceType; launchSpecification.SecurityGroups.Add(securityGroupName); request.SpotPrice = spotPrice; request.InstanceCount = instanceCount; request.LaunchSpecification = launchSpecification; RequestSpotInstancesResponse response = await ec2Client.RequestSpotInstancesAsync(request); return response; } ...

Em seguida, é preciso esperar até que a solicitação spot alcance o estado Active antes de continuar para a última etapa. Para determinar o estado da solicitação spot, use o método DescribeSpotInstanceRequests para obter o estado do ID da solicitação spot a ser monitorado.

public async Task<SpotInstanceRequest> GetSpotRequest(string spotRequestId) { var request = new DescribeSpotInstanceRequestsRequest(); request.SpotInstanceRequestIds.Add(spotRequestId); var describeResponse = await ec2Client.DescribeSpotInstanceRequestsAsync(request); return describeResponse.SpotInstanceRequests[0]; }

A etapa final é limpar suas solicitações e instâncias. É importante cancelar todas as solicitações pendentes e encerrar as instâncias. Simplesmente cancelar as solicitações não encerrará as instâncias, o que significa que você continuará a ser cobrado por elas. Se você encerrar suas instâncias suas solicitações spot poderão ser canceladas, mas há algumas situações, por exemplo, se você usar solicitações persistentes, nas quais encerrar suas instâncias não basta para impedir que a solicitação seja atendida novamente. Portanto, é uma prática recomendada cancelar todas as solicitações ativas e encerrar as instâncias em execução.

Para cancelar uma solicitação spot, você usa o método CancelSpotInstanceRequests. O exemplo a seguir demonstra como cancelar uma solicitação spot.

public async Task CancelSpotRequest(string spotRequestId) { Console.WriteLine("Canceling request " + spotRequestId); var cancelRequest = new CancelSpotInstanceRequestsRequest(); cancelRequest.SpotInstanceRequestIds.Add(spotRequestId); await ec2Client.CancelSpotInstanceRequestsAsync(cancelRequest); }

Para encerrar uma instância, você usa o método TerminateInstances.

public async Task TerminateSpotInstance(string instanceId) { Console.WriteLine("Terminating instance " + instanceId); var terminateRequest = new TerminateInstancesRequest(); terminateRequest.InstanceIds = new List<string>() { instanceId }; try { var terminateResponse = await ec2Client.TerminateInstancesAsync(terminateRequest); } catch (AmazonEC2Exception ex) { // Check the ErrorCode to see if the instance does not exist. if ("InvalidInstanceID.NotFound" == ex.ErrorCode) { Console.WriteLine("Instance {0} does not exist.", instanceId); } else { // The exception was thrown for another reason, so re-throw the exception. throw; } } }

Executar o código localmente

Execute o código em sua máquina local para criar uma solicitação de instância spot. Depois que a solicitação é atendida, o código exclui a solicitação e encerra a instância.

Para executar o código do aplicativo

  1. Navegue até o diretório ec2Spot.Tests.

    $ cd test/ec2Spot.Tests
  2. Use a CLI .NET para executar os testes de unidade do projeto.

    test/ec2Spot.Tests$ dotnet test Starting test execution, please wait... sir-x5tgs5ij open open open open open active Canceling request sir-x5tgs5ij Terminating instance i-0b3fdff0e12e0897e Complete Test Run Successful. Total tests: 1 Passed: 1 Total time: 7.6060 Seconds

O teste de unidade chama o método FunctionHandler para criar uma solicitação de instância spot, monitorá-la e limpar. Ele é implementado na estrutura de teste xUnit.net.

Implantar o aplicativo

Execute o código no Lambda como um ponto de partida para criar um aplicativo sem servidor.

Para implantar e testar o aplicativo

  1. Defina sua região como us-east-2.

    $ export AWS_DEFAULT_REGION=us-east-2
  2. Crie um bucket para artefatos de implantação.

    $ ./create-bucket.sh make_bucket: lambda-artifacts-63d5cbbf18fa5ecc
  3. Crie um pacote de implantação e implante o aplicativo.

    $ ./deploy.sh Amazon Lambda Tools for .NET Core applications (3.3.0) Project Home: https://github.com/aws/aws-extensions-for-dotnet-cli, https://github.com/aws/aws-lambda-dotnet Executing publish command ... Created publish archive (ec2spot.zip) Lambda project successfully packaged: ec2spot.zip Uploading to ebd38e401cedd7d676d05d22b76f0209 1305107 / 1305107.0 (100.00%) Successfully packaged artifacts and wrote output template to file out.yaml. Execute the following command to deploy the packaged template aws cloudformation deploy --template-file out.yaml --stack-name <YOUR STACK NAME> Waiting for changeset to be created.. Waiting for stack create/update to complete Successfully created/updated stack - ec2-spot
  4. Abra a página Aplicativos do console do Lambda.

    
            O aplicativo de exemplo no console do Lambda.
  5. Em Resources (Recursos), escolha function (função).

  6. Escolha Test (Testar) e crie um evento de teste a partir do modelo padrão.

  7. Escolha Test (Testar) novamente para invocar a função.

Exiba os logs e informações de rastreamento para ver o ID de solicitação spot e a sequência de chamadas para Amazon EC2.

Para exibir o mapa de serviço, abra a página Mapa de serviço no console do X-Ray.


        O mapa de serviço do X-Ray para o aplicativo de exemplo.

Escolha um nó no mapa de serviço e escolha View traces (Visualizar rastreamentos) para ver uma lista de rastreamentos. Escolha um rastreamento na lista para ver a linha do tempo das chamadas feitas pela função para o Amazon EC2.


        A linha do tempo do X-Ray para o aplicativo de exemplo.

Limpar

O código fornecido neste tutorial foi projetado para criar e excluir solicitações de instância spot e para encerrar as instâncias executadas. No entanto, se ocorrer um erro, as solicitações e instâncias podem não ser limpas automaticamente. Exiba as solicitações spot e as instâncias no console do Amazon EC2.

Para confirmar que os recursos do Amazon EC2 são limpos

  1. Abra a página Solicitações spot no console do Amazon EC2.

  2. Verifique se o estado das solicitações é Cancelled (Cancelado).

  3. Escolha o ID da instância na coluna Capacity (Capacidade) para exibir a instância.

  4. Verifique se o estado das instâncias éTerminated (Encerrado) ou Shutting down (Desligando).

Para limpar a função de exemplo e os recursos de suporte, exclua a pilha do AWS CloudFormation e o bucket de artefatos que você criou.

$ ./cleanup.sh Delete deployment artifacts and bucket (lambda-artifacts-63d5cbbf18fa5ecc)?y delete: s3://lambda-artifacts-63d5cbbf18fa5ecc/ebd38e401cedd7d676d05d22b76f0209 remove_bucket: lambda-artifacts-63d5cbbf18fa5ecc

O grupo de log da função não é excluído automaticamente. Você pode excluí-lo no console do CloudWatch Logs. Rastreamentos em X-Ray expiram após algumas semanas e são excluídos automaticamente.