Tutorial de Amazon EC2 Spot Instance - AWS SDK for .NET

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

Tutorial de Amazon EC2 Spot Instance

En este tutorial, se muestra cómo utilizarla AWS SDK for .NET para gestionar Amazon EC2 Spot Instances.

Información general

Las instancias puntuales le permiten solicitar EC2 capacidad de Amazon no utilizada por un precio inferior al precio bajo demanda. Esto puede reducir considerablemente EC2 los costes de las aplicaciones que pueden interrumpirse.

Este es un resumen general de cómo solicitar y utilizar instancias de spot.

  1. Cree una solicitud de instancia de spot, especificando el precio máximo que está dispuesto a pagar.

  2. Cuando se complete la solicitud, ejecuta la instancia como lo harías con cualquier otra EC2 instancia de Amazon.

  3. Ejecute la instancia todo el tiempo que desee y, a continuación, termínela, a menos que el precio de instancia spot cambie y la instancia termine automáticamente.

  4. Limpie la solicitud de instancia de spot cuando ya no la necesite para que no se creen más instancias de spot.

Esta descripción general de las instancias de spot es muy genérica. Para comprender mejor las instancias puntuales, consulte las instancias puntuales en la Guía del EC2 usuario de Amazon.

Acerca de este tutorial

A medida que siga este tutorial, utilizará el AWS SDK for .NET para hacer lo siguiente:

  • Creación de una solicitud de instancia de spot

  • Determinar cuándo se ha atendido la solicitud de instancia de spot

  • Cancelar la solicitud de instancia de spot

  • Terminar las instancias asociadas

En las siguientes secciones se proporcionan fragmentos de código y otra información de este ejemplo. Después de los fragmentos de código se muestra el código completo del ejemplo, que se puede compilar y ejecutar tal cual.

Requisitos previos

Para obtener información sobre los requisitos APIs y requisitos previos, consulte la sección principal (Trabajando con Amazon EC2).

Reunir todo lo necesario

Para crear una solicitud de instancia de spot, necesitará varias cosas.

  • El precio máximo que está dispuesto a pagar por hora de instancia. Puedes ver los precios de todos los tipos de instancias (tanto de las instancias bajo demanda como de las instancias puntuales) en la página de EC2 precios de Amazon. El precio predeterminado de este tutorial se explica más adelante.

Hay muchas formas de abordar la solicitud de instancias de spot. Estas son algunas estrategias comunes:

  • Realizar solicitudes que seguro que van a costar menos que el precio bajo demanda

  • Realizar solicitudes según en el valor del cálculo resultante

  • Realizar solicitudes adquirir capacidad informática lo más rápidamente posible

Las siguientes explicaciones hacen referencia al historial de precios de Spot Instance en la Guía del EC2 usuario de Amazon.

Tiene una tarea de procesamiento por lotes que tardará en ejecutarse una cantidad determinada de horas o días. Sin embargo, es flexible con respecto a cuándo comienza y finaliza. Desea ver si puede completarla por menos del valor del costo de las instancias bajo demanda.

Para examinar el historial de precios al contado, por ejemplo, puede utilizar la EC2 consola de Amazon o Amazon EC2API. Una vez que haya analizado el historial de precios para su tipo de instancia deseado en una zona de disponibilidad especificada, tendrá dos enfoques alternativos para su solicitud:

  • Especificar una solicitud en el extremo superior del rango de precios de instancias de spot, que aún son inferiores al precio bajo demanda, contando con que lo más probable es que su solicitud de instancia de spot puntual se atienda y se ejecute durante un tiempo de computación consecutivo suficiente para completar la tarea.

  • Especificar una solicitud en el extremo inferior del rango de precios y tener previsto combinar muchas instancias lanzadas con el tiempo a través de una solicitud persistente. Las instancias se ejecutarían el tiempo suficiente, combinadas, para completar la tarea con un costo total aún más reducido

Tiene una tarea de procesamiento de datos para ejecutar. Conoce las ventajas de los resultados de la tarea lo suficientemente bien como para saber lo valiosos que son en términos de costos de computación.

Una vez que analizado el historial de precios de instancias de spot del tipo de instancia, elige un precio en el que el costo del tiempo de computación no es superior al valor de los resultados de la tarea. Crea una solicitud persistente y deja que se ejecute intermitentemente a medida que el precio de instancia de spot fluctúa en torno a su solicitud o por debajo de esta.

Tiene una necesidad a corto plazo no anticipada de capacidad adicional que no está disponible a través de las instancias bajo demanda. Una vez analizado el historial de precios de instancia de spot del tipo de instancia, elige un precio por encima del precio histórico para mejorar significativamente la probabilidad de que la solicitud se atienda con rapidez y continúe computándose hasta completarse.

Tras reunir todo lo necesario y elegir una estrategia, está listo para solicitar una instancia de spot. En este tutorial, el precio máximo de instancias de spot predeterminado se establece que sea el mismo que el precio bajo demanda (que es 0,003 USD para este tutorial). Establecer el precio de esta manera maximiza las posibilidades de que se cumpla la solicitud.

Creación de una solicitud de instancia de spot

En el siguiente fragmento de código se muestra cómo crear una solicitud de instancia de spot con los elementos que ha reunido anteriormente.

El ejemplo que aparece al final de este tema muestra este fragmento de código en 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]; }

El valor importante que devuelve este método es el identificador de solicitud de la instancia puntual, que se encuentra en el SpotInstanceRequestId elemento del SpotInstanceRequestobjeto devuelto.

nota

Se le cobrará por cualquier instancia de spot que se lance. Para evitar costos innecesarios, asegúrese de cancelar todas las solicitudes y de terminar cualquier instancia.

Determinación del estado de la solicitud de instancia de spot

En el siguiente fragmento de código se muestra cómo obtener información sobre la solicitud de instancia de spot. Puede utilizar esa información para tomar algunas decisiones relativas a su código, por ejemplo, si debe seguir esperando a que se atienda una solicitud de instancia de spot.

El ejemplo que aparece al final de este tema muestra este fragmento de código en 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]; }

El método devuelve información sobre la solicitud de instancia de spot, como el ID de la instancia, su estado y el código de estado. Para obtener más información sobre los códigos de estado de las solicitudes de instancias puntuales, consulte el estado de las solicitudes puntuales en la Guía del EC2 usuario de Amazon.

Limpieza de las solicitudes de instancia de spot

Cuando ya no necesite solicitar instancias de spot, es importante cancelar las solicitudes pendientes para evitar que se vuelvan a atenderse. En el siguiente fragmento de código se muestra cómo cancelar una solicitud de instancia de spot.

El ejemplo que aparece al final de este tema muestra este fragmento de código en 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); }

Limpieza de las instancias de spot

Para no incurrir en costos innecesarios, es importante terminar cualquier instancia que se haya iniciado a partir de solicitudes de instancia de spot; las instancias no terminarán si solamente se cancelan, lo que significa que se le seguirá cobrando por ellas. En el siguiente fragmento de código se muestra cómo terminar una instancia después de obtener el identificador de instancia de una instancia de spot activa.

El ejemplo que aparece al final de este tema muestra este fragmento de código en 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

En el siguiente ejemplo de código se utilizan los métodos descritos anteriormente para crear y cancelar una solicitud de instancia de spot y terminar una instancia de spot.

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"); } } } } }

Consideraciones adicionales