Tutoriel sur les instances Spot Amazon EC2 - AWS SDK for .NET

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

Tutoriel sur les instances Spot Amazon EC2

Ce didacticiel explique comment utiliser le AWS SDK for .NET pour gérer les instances Spot Amazon EC2.

Présentation

Les instances Spot vous permettent de demander de la capacité Amazon EC2 inutilisée à un prix inférieur au prix à la demande. Cela peut réduire considérablement vos coûts EC2 pour les applications susceptibles d'être interrompues.

Vous trouverez ci-dessous un résumé détaillé de la manière dont les instances Spot sont demandées et utilisées.

  1. Créez une demande d'instance Spot en spécifiant le prix maximum que vous êtes prêt à payer.

  2. Lorsque la demande est satisfaite, exécutez l'instance comme n'importe quelle autre instance Amazon EC2.

  3. Exécutez l'instance aussi longtemps que vous le souhaitez, puis mettez-la hors service, sauf si le prix au comptant change de telle sorte que l'instance soit résiliée pour vous.

  4. Nettoyez la demande d'instance Spot lorsque vous n'en avez plus besoin afin que les instances Spot ne soient plus créées.

Il s'agit d'un aperçu de très haut niveau des instances Spot. Pour mieux comprendre les instances Spot, consultez la section Instances Spot dans le guide de l'utilisateur Amazon EC2.

À propos de ce didacticiel

Au fur et à mesure que vous suivez ce didacticiel, vous utilisez le AWS SDK for .NET pour effectuer les opérations suivantes :

  • Créer une demande d’instance Spot

  • Déterminez quand la demande d'instance Spot a été satisfaite

  • Annuler la demande d'instance Spot

  • Résilier les instances associées

Les sections suivantes fournissent des extraits et d'autres informations pour cet exemple. Le code complet de l'exemple est affiché après les extraits et peut être créé et exécuté tel quel.

Prérequis

Pour plus d'informations sur les API et les prérequis, consultez la section parent (Utilisation avec Amazon EC2).

Rassemblez ce dont vous avez besoin

Pour créer une demande d'instance Spot, vous aurez besoin de plusieurs éléments.

  • Le prix maximum que vous êtes prêt à payer par heure d'instance. Vous pouvez consulter les prix de tous les types d'instances (pour les instances à la demande et les instances ponctuelles) sur la page de tarification d'Amazon EC2. Le prix par défaut de ce didacticiel est expliqué plus loin.

Il existe de nombreuses façons d'aborder la demande d'instances Spot. Les stratégies les plus courantes sont les suivantes :

  • Faites des demandes qui coûteront certainement moins cher que la tarification à la demande.

  • Effectuez des demandes en fonction de la valeur du calcul obtenu.

  • Faites des demandes afin d'acquérir une capacité de calcul le plus rapidement possible.

Les explications suivantes font référence à l'historique des tarifs des instances Spot dans le guide de l'utilisateur Amazon EC2.

Vous avez une tâche de traitement par lot dont l'exécution prendra un certain nombre d'heures ou de jours. Toutefois, vous êtes flexible quant aux dates et heures de début et de fin de la tâche. Vous voulez savoir si vous pouvez exécuter cette tâche à un coût inférieur à celui des instances à la demande.

Vous examinez l'historique des prix au comptant pour les types d'instances à l'aide de la console Amazon EC2 ou de l'API Amazon EC2. Une fois que vous avez analysé l'historique des prix pour le type d'instance souhaité dans une zone de disponibilité donnée, deux approches sont possibles pour votre demande :

  • Spécifiez une demande se situant dans la partie supérieure de la fourchette des prix ponctuels, qui sont toujours inférieurs au prix à la demande, en anticipant que votre demande d'instance ponctuelle unique sera probablement satisfaite et exécutée pendant une durée de calcul consécutive suffisante pour terminer le travail.

  • Spécifiez une demande à la limite inférieure de la plage de prix et envisagez de combiner plusieurs instances lancées au fil du temps via une demande persistante. Les instances vont s'exécuter suffisamment longtemps, au total, pour terminer la tâche avec un coût total plus faible.

Vous avez une tâche de traitement de données à exécuter. Vous comprenez suffisamment la valeur des résultats du travail pour savoir combien ils valent en termes de coûts informatiques.

Après avoir analysé l'historique des prix au comptant pour votre type d'instance, vous choisissez un prix dont le coût du temps de calcul ne dépasse pas la valeur des résultats de la tâche. Vous créez une demande persistante et faites en sorte qu'elle s'exécute de façon intermittente selon que le prix Spot est égal ou inférieur à votre demande.

Vous avez un besoin imprévu à court terme de capacité supplémentaire qui n'est pas disponible via les instances à la demande. Après avoir analysé l'historique des prix au comptant pour votre type d'instance, vous choisissez un prix supérieur au prix historique le plus élevé afin d'améliorer considérablement les chances que votre demande soit traitée rapidement et vous poursuivez le calcul jusqu'à ce qu'elle soit complète.

Une fois que vous avez rassemblé ce dont vous avez besoin et que vous avez choisi une stratégie, vous êtes prêt à demander une instance Spot. Pour ce didacticiel, le prix maximal d'instance spot par défaut est défini pour être le même que celui à la demande (qui est de 0,003 $pour ce didacticiel). Fixer le prix de cette manière maximise les chances de satisfaire la demande.

Création d'une demande d'instance Spot

L'extrait suivant explique comment créer une demande d'instance Spot avec les éléments que vous avez collectés précédemment.

L'exemple à la fin de cette rubrique montre cet extrait en cours d'utilisation.

// // 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]; }

La valeur importante renvoyée par cette méthode est l'ID de demande d'instance Spot, qui est contenu dans le SpotInstanceRequestId membre de l'SpotInstanceRequestobjet renvoyé.

Note

Toutes les instances Spot lancées vous seront facturées. Pour éviter des coûts inutiles, veillez à annuler toutes les demandes et à mettre fin à toutes les instances.

Déterminez l'état de votre demande d'instance Spot

L'extrait suivant vous montre comment obtenir des informations sur votre demande d'instance Spot. Vous pouvez utiliser ces informations pour prendre certaines décisions dans votre code, par exemple si vous souhaitez continuer à attendre qu'une demande d'instance Spot soit traitée.

L'exemple à la fin de cette rubrique montre cet extrait en cours d'utilisation.

// // 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]; }

La méthode renvoie des informations sur la demande d'instance Spot, telles que l'ID de l'instance, son état et son code d'état. Pour plus d'informations sur les codes de statut des demandes d'instance Spot, consultez la section État des demandes Spot dans le guide de l'utilisateur Amazon EC2.

Nettoyez vos demandes d'instance Spot

Lorsque vous n'avez plus besoin de demander des instances ponctuelles, il est important d'annuler toutes les demandes en suspens afin d'éviter qu'elles ne soient traitées à nouveau. L'extrait suivant explique comment annuler une demande d'instance Spot.

L'exemple à la fin de cette rubrique montre cet extrait en cours d'utilisation.

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

Nettoyez vos instances Spot

Pour éviter des coûts inutiles, il est important de résilier toutes les instances créées à partir de demandes d'instances Spot ; le simple fait d'annuler les demandes d'instance Spot ne mettra pas fin à vos instances, ce qui signifie qu'elles continueront à vous être facturées. L'extrait suivant explique comment mettre fin à une instance après avoir obtenu l'identifiant d'instance d'une instance Spot active.

L'exemple à la fin de cette rubrique montre cet extrait en cours d'utilisation.

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

Code complet

L'exemple de code suivant appelle les méthodes décrites précédemment pour créer et annuler une demande d'instance Spot et mettre fin à une instance 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"); } } } } }

Considérations supplémentaires