Tutorial sull'istanza Spot di Amazon EC2 - AWS SDK for .NET

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

Tutorial sull'istanza Spot di Amazon EC2

Questo tutorial mostra come utilizzarlo per AWS SDK for .NET gestire le istanze Spot di Amazon EC2.

Panoramica

Le istanze Spot consentono di richiedere capacità Amazon EC2 inutilizzata a un prezzo inferiore al prezzo On-Demand. Ciò può ridurre in modo significativo i costi EC2 per le applicazioni che possono essere interrotte.

Di seguito è riportato un riepilogo di alto livello di come le istanze Spot vengono richieste e utilizzate.

  1. Crea una richiesta di istanza Spot, specificando il prezzo massimo che sei disposto a pagare.

  2. Una volta soddisfatta la richiesta, esegui l'istanza come faresti con qualsiasi altra istanza Amazon EC2.

  3. Esegui l'istanza per tutto il tempo che desideri e poi chiudila, a meno che il prezzo Spot non cambi in modo tale che l'istanza venga interrotta per te.

  4. Pulisci la richiesta dell'istanza Spot quando non è più necessaria, in modo che le istanze Spot non vengano più create.

Questa è stata una panoramica di altissimo livello sulle istanze Spot. Per comprendere meglio le istanze Spot, consulta la Amazon EC2 User Guide for Linux Instances o la Amazon EC2 User Guide for Windows Instances.

Informazioni sul tutorial

Mentre segui questo tutorial, usi il per fare quanto segue AWS SDK for .NET :

  • Creare una richiesta di istanza spot

  • Determina quando la richiesta di istanza Spot è stata soddisfatta

  • Annulla la richiesta di istanza Spot

  • Terminare le istanze associate

Le sezioni seguenti forniscono frammenti e altre informazioni per questo esempio. Il codice completo dell'esempio viene mostrato dopo gli snippet e può essere creato ed eseguito così com'è.

Prerequisiti

Per informazioni sulle API e sui prerequisiti, consultate la sezione principale (). Utilizzo di Amazon EC2

Raccogli ciò di cui hai bisogno

Per creare una richiesta di istanza Spot, avrai bisogno di diversi elementi.

  • L'Amazon Machine Image (AMI) che verrà utilizzata per creare l'istanza. Consulta le informazioni sulle AMI nella Amazon EC2 User Guide for Linux Instances o nella Amazon EC2 User Guide for Windows Instances. Ad esempio, leggi le AMI condivise nella Amazon EC2 User Guide for Linux Instances o nella Amazon EC2 User Guide for Windows Instances.

  • Il prezzo massimo che sei disposto a pagare per ora di istanza. Puoi vedere i prezzi per tutti i tipi di istanze (sia per le istanze On-Demand che per le istanze Spot) nella pagina dei prezzi di Amazon EC2. Il prezzo predefinito per questo tutorial viene spiegato più avanti.

Esistono molti approcci per proporre delle richieste per le istanze Spot. Le seguenti sono strategie comuni:

  • Effettua richieste che sicuramente costeranno meno dei prezzi su richiesta.

  • Effettua richieste in base al valore del calcolo risultante.

  • Effettua richieste in modo da acquisire capacità di calcolo il più rapidamente possibile.

Le seguenti spiegazioni si riferiscono alla cronologia dei prezzi Spot nella Amazon EC2 User Guide for Linux Instances o nella Amazon EC2 User Guide for Windows Instances.

Hai un processo di elaborazione in batch la cui esecuzione richiede diverse ore o giorni. Tuttavia, hai una certa flessibilità sui tempi di inizio e di fine. Vuoi vedere se riesci a completarlo a un costo inferiore a quello delle istanze on demand.

Puoi esaminare la cronologia dei prezzi Spot per i tipi di istanza utilizzando la console Amazon EC2 o l'API Amazon EC2. Dopo aver analizzato la cronologia dei prezzi per il tipo di istanza desiderato in una determinata zona di disponibilità, hai due alternative per la tua richiesta:

  • Specificate una richiesta all'estremità superiore della gamma di prezzi Spot, che sono ancora inferiori al prezzo on demand, prevedendo che la richiesta effettuata una sola volta sull'istanza Spot venga probabilmente soddisfatta ed eseguita per un tempo di calcolo consecutivo sufficiente a completare il lavoro.

  • Specifica una richiesta nella fascia bassa della gamma di prezzi, pianificando di combinare più istanze avviate in momenti diversi in un'unica richiesta persistente. Le istanze, in forma aggregata, verrebbero eseguite abbastanza a lungo da completare il processo a un costo totale persino inferiore.

Hai un processo di elaborazione dei dati da completare. Conosci abbastanza bene il valore dei risultati del lavoro da sapere quanto valgono in termini di costi di elaborazione.

Dopo aver analizzato la cronologia dei prezzi Spot per il tipo di istanza, scegli un prezzo al quale il costo del tempo di elaborazione non sia superiore al valore dei risultati del lavoro. Crea una richiesta persistente e impostane l'esecuzione intermittente quando il prezzo Spot raggiunge o scende sotto la tua richiesta.

Hai un bisogno imprevisto, a breve termine, di capacità aggiuntiva che non è disponibile tramite le istanze on demand. Dopo aver analizzato la cronologia dei prezzi Spot per il tipo di istanza, scegli un prezzo superiore al prezzo storico più alto per aumentare notevolmente la probabilità che la tua richiesta venga soddisfatta rapidamente e continui a calcolare fino al completamento.

Dopo aver raccolto ciò di cui hai bisogno e scelto una strategia, sei pronto per richiedere un'istanza Spot. Per questa esercitazione il prezzo massimo di spot-instance predefinito è impostato per essere lo stesso del prezzo su richiesta (che è $0,003 per questo tutorial). Impostare il prezzo in questo modo massimizza le possibilità che la richiesta venga soddisfatta.

Creazione di una richiesta di istanza Spot

Il seguente frammento mostra come creare una richiesta di istanza Spot con gli elementi raccolti in precedenza.

L'esempio alla fine di questo argomento mostra questo frammento in 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]; }

Il valore importante restituito da questo metodo è l'ID della richiesta dell'istanza Spot, contenuto nel SpotInstanceRequestId membro dell'oggetto restituito SpotInstanceRequest.

Nota

Ti verranno addebitati i costi per ogni istanza Spot lanciata. Per evitare costi inutili, assicurati di annullare qualsiasi richiesta e terminare qualsiasi istanza.

Determina lo stato della tua richiesta di istanza Spot

Il seguente frammento mostra come ottenere informazioni sulla richiesta di istanza Spot. Puoi utilizzare queste informazioni per prendere determinate decisioni nel codice, ad esempio se continuare ad aspettare che venga soddisfatta una richiesta di istanza Spot.

L'esempio alla fine di questo argomento mostra questo frammento in 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]; }

Il metodo restituisce informazioni sulla richiesta dell'istanza Spot, come l'ID dell'istanza, lo stato e il codice di stato. Puoi visualizzare i codici di stato per le richieste di istanze Spot nella Amazon EC2 User Guide for Linux Instances o nella Amazon EC2 User Guide for Windows Instances.

Pulisci le tue richieste di istanze Spot

Quando non è più necessario richiedere istanze Spot, è importante annullare le richieste in sospeso per evitare che vengano soddisfatte nuovamente. Il seguente frammento mostra come annullare una richiesta di istanza Spot.

L'esempio alla fine di questo argomento mostra questo frammento in 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); }

Pulisci le tue istanze Spot

Per evitare costi inutili, è importante chiudere tutte le istanze avviate dalle richieste di istanze Spot; la semplice cancellazione delle richieste di istanze Spot non comporterà la chiusura delle istanze, il che significa che continueranno a ricevere i relativi costi. Il seguente frammento mostra come terminare un'istanza dopo aver ottenuto l'identificatore di istanza per un'istanza Spot attiva.

L'esempio alla fine di questo argomento mostra questo frammento in 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"); } } }

Codice completo

Il seguente esempio di codice richiama i metodi descritti in precedenza per creare e annullare una richiesta di istanza Spot e terminare un'istanza 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"); } } } } }

Ulteriori considerazioni