Didacticiel : Amazon EC2 Spot instances - AWS SDK for Java 1. x

La AWS SDK for Java version 1.x est entrée en mode maintenance le 31 juillet 2024 et atteindra end-of-supportle 31 décembre 2025. Nous vous recommandons de migrer vers le pour continuer AWS SDK for Java 2.xà bénéficier des nouvelles fonctionnalités, des améliorations de disponibilité et des mises à jour de sécurité.

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.

Didacticiel : Amazon EC2 Spot instances

Présentation

Les instances Spot vous permettent de placer une offre sur des capacités Amazon Elastic Compute Cloud (Amazon EC2) inutilisées d’une valeur égale à 90 % au maximum du prix d’une instance à la demande et d'exécuter les instances acquises aussi longtemps que votre offre dépasse le prix Spot actuel. Amazon EC2 modifie régulièrement le prix Spot en fonction de l'offre et de la demande, et les clients dont les offres sont égales ou supérieures à ce prix ont accès aux instances Spot disponibles. Tout comme les instances à la demande et les instances réservées, les instances Spot vous offrent une autre possibilité d'obtenir des capacités de calcul supplémentaires.

Les instances Spot peuvent faire baisser de manière significative vos coûts Amazon EC2 pour les traitements par lot, la recherche scientifique, le traitement des images, l'encodage vidéo, l'indexation des données et des sites web, les analyses financières et les tests. De plus, les instances Spot vous donnent accès à de grandes quantités de capacité supplémentaire lorsque le besoin de capacité n'est pas urgent.

Pour utiliser des instances Spot, créez une demande d'instance Spot indiquant le prix maximum que vous êtes prêt à payer par heure d'instance. Cette valeur constitue votre offre. Si votre offre est supérieure au prix Spot actuel, votre demande est satisfaite et vos instances s'exécutent jusqu'à ce que vous décidiez de les résilier ou jusqu'à ce que le prix Spot devienne supérieur à votre offre, selon la première échéance.

Veuillez noter les points importants suivants :

  • Vous payez souvent un tarif par heure inférieur à celui de votre offre. Amazon EC2 ajuste régulièrement le prix Spot au fur et à mesure que les demandes arrivent et que les offres disponibles changent. Chacun paie le même prix Spot pour cette période, même si l'offre soumise était supérieure. Par conséquent, vous pouvez payer moins que votre offre, mais vous ne paierez jamais plus que votre offre.

  • Si vous exécutez des instances Spot et que votre offre n'est plus égale au prix Spot actuel ou ne le dépasse plus, vos instances sont résiliées. Cela signifie que vous devez vous assurer que vos charges de travail et applications sont suffisamment flexibles pour tirer parti de cette capacité opportuniste.

Les instances Spot fonctionnent exactement comme les autres instances Amazon EC2 et, tout comme les autres instances Amazon EC2, elles peuvent être résiliées lorsque vous n'en avez plus besoin. Si vous résiliez votre instance, vous êtes facturé pour toute heure d'utilisation partielle (comme c'est le cas pour les instances à la demande et les instances réservées). Toutefois, si le prix Spot devient supérieur à votre offre et qu'Amazon EC2 résilie votre instance, vous n'êtes pas facturé pour l'heure d'utilisation partielle.

Ce didacticiel explique comment utiliser le kit AWS SDK for Java pour effectuer les tâches suivantes :

  • Soumettre une demande Spot

  • Déterminer à quel moment la demande Spot est satisfaite

  • Annuler la demande Spot

  • Résilier les instances associées

Prérequis

Pour utiliser ce didacticiel, vous devez avoir le kit AWS SDK for Java installé, ainsi que satisfaire à ses conditions d'installation prérequises de base. VoirConfiguration de l'AWS SDK for Javapour plus d'informations, consultez.

Étape 1 : Définition de vos informations d'identification

Pour utiliser cet exemple de code, vous devez configurerAWSInformations d'identification . VoirConfigurationAWSInformations d'identification et région pour le développementpour obtenir des instructions sur la façon d'effectuer cette opération.

Note

Nous vous recommandons d'utiliser les informations d'identification d'un utilisateur IAM pour fournir ces valeurs. Pour de plus amples informations, veuillez consulterS'inscrire àAWSet Créer un utilisateur IAM.

Maintenant que vous avez configuré vos paramètres, vous pouvez commencer à utiliser le code de l'exemple.

Étape 2 : Configuration d'un groupe de sécurité

Un groupe de sécurité fonctionne comme un pare-feu qui contrôle le trafic autorisé en entrée et en sortie d'un groupe d'instances. Par défaut, une instance est lancée sans aucun groupe de sécurité, ce qui signifie que l'ensemble du trafic IP entrant, sur n'importe quel port TCP, est refusé. Par conséquent, avant de soumettre notre demande Spot, nous allons configurer un groupe de sécurité qui permet le trafic réseau nécessaire. Dans le cadre de ce didacticiel, nous allons créer un groupe de sécurité appelé « GettingStarted », qui autorise le trafic SSH (Secure Shell) depuis l'adresse IP à partir de laquelle vous exécutez votre application. Pour configurer un nouveau groupe de sécurité, vous devez inclure ou exécuter l'exemple de code suivant qui configure le groupe de sécurité par programmation.

Après avoir créé un objet client AmazonEC2, nous créons un objet CreateSecurityGroupRequest avec le nom « GettingStarted » et une description du groupe de sécurité. Ensuite, nous appelons l'API ec2.createSecurityGroup pour créer le groupe.

Pour permettre l'accès au groupe, nous créons un objet ipPermission avec la plage d'adresses IP définie sur la représentation CIDR du sous-réseau de l'ordinateur local ; le suffixe « /10 » de l'adresse IP indique le sous-réseau de l'adresse IP spécifiée. Nous configurons également l'objet ipPermission avec le protocole TCP et le port 22 (SSH). La dernière étape consiste à appeler ec2.authorizeSecurityGroupIngress avec le nom de notre groupe de sécurité et l'objet ipPermission.

// Create the AmazonEC2 client so we can call various APIs. AmazonEC2 ec2 = AmazonEC2ClientBuilder.defaultClient(); // Create a new security group. try { CreateSecurityGroupRequest securityGroupRequest = new CreateSecurityGroupRequest("GettingStartedGroup", "Getting Started Security Group"); ec2.createSecurityGroup(securityGroupRequest); } catch (AmazonServiceException ase) { // Likely this means that the group is already created, so ignore. System.out.println(ase.getMessage()); } String ipAddr = "0.0.0.0/0"; // Get the IP of the current host, so that we can limit the Security // Group by default to the ip range associated with your subnet. try { InetAddress addr = InetAddress.getLocalHost(); // Get IP Address ipAddr = addr.getHostAddress()+"/10"; } catch (UnknownHostException e) { } // Create a range that you would like to populate. ArrayList<String> ipRanges = new ArrayList<String>(); ipRanges.add(ipAddr); // Open up port 22 for TCP traffic to the associated IP // from above (e.g. ssh traffic). ArrayList<IpPermission> ipPermissions = new ArrayList<IpPermission> (); IpPermission ipPermission = new IpPermission(); ipPermission.setIpProtocol("tcp"); ipPermission.setFromPort(new Integer(22)); ipPermission.setToPort(new Integer(22)); ipPermission.setIpRanges(ipRanges); ipPermissions.add(ipPermission); try { // Authorize the ports to the used. AuthorizeSecurityGroupIngressRequest ingressRequest = new AuthorizeSecurityGroupIngressRequest("GettingStartedGroup",ipPermissions); ec2.authorizeSecurityGroupIngress(ingressRequest); } catch (AmazonServiceException ase) { // Ignore because this likely means the zone has // already been authorized. System.out.println(ase.getMessage()); }

Notez que vous avez uniquement besoin d'exécuter cette application une seule fois pour créer un nouveau groupe de sécurité.

Vous pouvez aussi créer le groupe de sécurité avec AWS Toolkit for Eclipse. VoirGestion des groupes de sécurité à partirAWS Cost Explorerpour plus d'informations, consultez.

Étape 3 : Soumission de votre demande Spot

Pour soumettre une demande Spot, vous devez d'abord déterminer le type d'instance, l'AMI (Amazon Machine Image) et le prix maximum de l'offre à utiliser. Vous devez également inclure le groupe de sécurité configuré précédemment, afin de pouvoir vous connecter à l'instance, le cas échéant.

Il existe plusieurs types d'instances au choix.Amazon EC2Types d'instances pour obtenir la liste complète. Dans le cadre de ce didacticiel, nous allons utiliser t1.micro, le type d'instance le moins cher disponible. Ensuite, nous allons déterminer le type d'AMI à utiliser. Nous allons utiliser ami-a9d09ed1, l'AMI Amazon Linux la plus récente disponible au moment de la rédaction de ce didacticiel. L'AMI la plus récente peut changer au fil du temps, mais vous pouvez déterminer la dernière version de l'AMI en procédant comme suit :

  1. Ouvrez la console Amazon EC2.

  2. Choisissez le bouton Lancer une instance.

  3. La première fenêtre affiche les AMI disponibles. L'ID de l'AMI est répertorié en regard de chaque titre d'AMI. Vous pouvez aussi utiliser l'API DescribeImages, mais l'exploitation de cette commande n'entre pas dans le cadre de ce didacticiel.

Il existe de nombreuses façons d'aborder les offres relatives aux instances Spot. Pour obtenir une vue d'ensemble des diverses approches possibles, regardez la vidéo présentant les offres relatives aux instances Spot. Toutefois, pour commencer, nous allons décrire trois stratégies courantes : offre garantissant un coût inférieur à la tarification à la demande, offre basée sur la valeur du calcul résultant et offre visant à acquérir une capacité de calcul aussi vite que possible.

  • Réduction du coût sous la tarification à la demande 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 obtenu avec les instances à la demande. Vous examinez l'historique des prix Spot pour les types d'instances à l'aide de la AWS Management Console ou de l'API Amazon EC2. Pour plus d'informations, consultez Historique de tarification des instance Spots. 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 :

    • Vous pouvez faire une offre à la limite supérieure de la plage de prix Spot (qui sont toujours inférieurs au prix à la demande), en anticipant que votre demande d'instance Spot sera très probablement satisfaite et que vous aurez suffisamment de temps de calcul consécutifs pour terminer la tâche.

    • Vous pouvez également spécifier le montant que vous êtes disposé à payer pour les instances Spot sous forme de % du prix des instances à la demande et prévoir de combiner de nombreuses instances lancées au fil du temps via une demande persistante. Si le prix spécifié est dépassé, l'instance Spot est résiliée. (Nous vous expliquerons comment automatiser cette tâche plus tard dans ce didacticiel.)

  • Paiement égal ou inférieur à la valeur du résultat Vous avez une tâche de traitement de données à exécuter. Vous connaissez la valeur des résultats de la tâche suffisamment bien pour savoir qu'ils représentent un réel intérêt en termes de coûts informatiques. Une fois que vous avez analysé l'historique des prix Spot pour votre type d'instance, vous choisissez un prix d'offre pour lequel le coût du temps de calcul n'est pas supérieur à la valeur des résultats de la tâche. Vous créez une offre 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 offre.

  • Acquisition rapide de capacité de calcul Vous avez un besoin de capacité supplémentaire imprévu, à court terme, que les instances à la demande ne peuvent pas satisfaire. Une fois que vous avez analysé l'historique des prix Spot pour votre type d'instance, vous effectuez une offre supérieure au prix historique le plus élevé afin d'être quasiment sûr que votre demande sera satisfaite rapidement et que vous pourrez poursuivre les calculs jusqu'à ce qu'elle soit terminée.

Une fois que vous avez choisi votre prix d'offre, vous êtes prêt à demander une instance Spot. Dans le cadre de ce didacticiel, nous allons faire une offre au prix à la demande (0,03 USD) afin de maximiser les chances que votre offre soit satisfaite. Vous pouvez déterminer les types d'instances disponibles et les prix à la demande des instances en accédant à laAmazon EC2Page de tarification. Vous payez le prix Spot en vigueur pendant la durée d'exécution de vos instances Spot. Les prix Spot sont définis par Amazon EC2 et ajustés graduellement en fonction des tendances à long terme en matière d'offre et de demande de capacité d'instance Spot. Vous pouvez également spécifier le montant que vous êtes disposé à payer pour une instance Spot sous forme de % du prix d'une instance à la demande. Pour demander une instance Spot, il vous suffit de créer votre demande avec les paramètres que vous avez choisis précédemment. Nous allons commencer par créer un objet RequestSpotInstanceRequest. L'objet de la demande nécessite le nombre d'instances que vous voulez démarrer et le prix de l'offre. De plus, vous devez définir l'élément LaunchSpecification pour la demande, qui comprend le type d'instance, l'ID d'AMI et le groupe de sécurité que vous souhaitez utiliser. Une fois la demande remplie, vous appelez la méthode requestSpotInstances sur l'objet AmazonEC2Client. L'exemple suivant indique comment demander une instance Spot.

// Create the AmazonEC2 client so we can call various APIs. AmazonEC2 ec2 = AmazonEC2ClientBuilder.defaultClient(); // Initializes a Spot Instance Request RequestSpotInstancesRequest requestRequest = new RequestSpotInstancesRequest(); // Request 1 x t1.micro instance with a bid price of $0.03. requestRequest.setSpotPrice("0.03"); requestRequest.setInstanceCount(Integer.valueOf(1)); // Setup the specifications of the launch. This includes the // instance type (e.g. t1.micro) and the latest Amazon Linux // AMI id available. Note, you should always use the latest // Amazon Linux AMI id or another of your choosing. LaunchSpecification launchSpecification = new LaunchSpecification(); launchSpecification.setImageId("ami-a9d09ed1"); launchSpecification.setInstanceType(InstanceType.T1Micro); // Add the security group to the request. ArrayList<String> securityGroups = new ArrayList<String>(); securityGroups.add("GettingStartedGroup"); launchSpecification.setSecurityGroups(securityGroups); // Add the launch specifications to the request. requestRequest.setLaunchSpecification(launchSpecification); // Call the RequestSpotInstance API. RequestSpotInstancesResult requestResult = ec2.requestSpotInstances(requestRequest);

L'exécution de ce code lance une nouvelle demande d'instance Spot. Il existe d'autres options que vous pouvez utiliser pour configurer vos demandes Spot. Pour en savoir plus, rendez-vous surDidacticiel : Advanced (Avancé)Amazon EC2Gestion des demandes Spotou leRequestSpotInstancesdans la classeAWS SDK for JavaRéférence API.

Note

Vous serez facturé pour toute instance Spot réellement lancée. Veillez donc à annuler toute demande inutile et à résilier toutes les instances que vous lancez afin de réduire les frais associés.

Étape 4 : Détermination de l'état de votre demande Spot

Nous voulons créer le code en attendant que la demande Spot atteigne le statut « actif » avant de passer à la dernière étape. Pour déterminer l'état de la requête Spot, nous interrogeons la méthode describeSpotInstanceRequests concernant l'état de l'ID de la requête Spot qui nous intéresse.

L'ID de demande créé à l'étape 2 est intégré dans la réponse à notre demande requestSpotInstances. L'exemple de code suivant montre comment collecter des ID de demande à partir de la réponse requestSpotInstances et les utiliser pour remplir une ArrayList.

// Call the RequestSpotInstance API. RequestSpotInstancesResult requestResult = ec2.requestSpotInstances(requestRequest); List<SpotInstanceRequest> requestResponses = requestResult.getSpotInstanceRequests(); // Setup an arraylist to collect all of the request ids we want to // watch hit the running state. ArrayList<String> spotInstanceRequestIds = new ArrayList<String>(); // Add all of the request ids to the hashset, so we can determine when they hit the // active state. for (SpotInstanceRequest requestResponse : requestResponses) { System.out.println("Created Spot Request: "+requestResponse.getSpotInstanceRequestId()); spotInstanceRequestIds.add(requestResponse.getSpotInstanceRequestId()); }

Pour surveiller votre ID de demande, appelez la méthode describeSpotInstanceRequests pour déterminer l'état de la demande. Ensuite, poursuivez la boucle jusqu'à ce que la demande ne soit plus à l'état « ouvert ». Notez que nous recherchons un état autre qu'« ouvert », par exemple « actif », car la demande peut passer directement à l'état « fermé » s'il y a un problème au niveau des arguments de la demande. L'exemple de code suivant décrit comment accomplir cette tâche.

// Create a variable that will track whether there are any // requests still in the open state. boolean anyOpen; do { // Create the describeRequest object with all of the request ids // to monitor (e.g. that we started). DescribeSpotInstanceRequestsRequest describeRequest = new DescribeSpotInstanceRequestsRequest(); describeRequest.setSpotInstanceRequestIds(spotInstanceRequestIds); // Initialize the anyOpen variable to false - which assumes there // are no requests open unless we find one that is still open. anyOpen=false; try { // Retrieve all of the requests we want to monitor. DescribeSpotInstanceRequestsResult describeResult = ec2.describeSpotInstanceRequests(describeRequest); List<SpotInstanceRequest> describeResponses = describeResult.getSpotInstanceRequests(); // Look through each request and determine if they are all in // the active state. for (SpotInstanceRequest describeResponse : describeResponses) { // If the state is open, it hasn't changed since we attempted // to request it. There is the potential for it to transition // almost immediately to closed or cancelled so we compare // against open instead of active. if (describeResponse.getState().equals("open")) { anyOpen = true; break; } } } catch (AmazonServiceException e) { // If we have an exception, ensure we don't break out of // the loop. This prevents the scenario where there was // blip on the wire. anyOpen = true; } try { // Sleep for 60 seconds. Thread.sleep(60*1000); } catch (Exception e) { // Do nothing because it woke up early. } } while (anyOpen);

Une fois ce code exécuté, votre demande d'instance Spot est terminée ou a échoué avec une erreur qui s'affiche à l'écran. Dans les deux cas, nous pouvons passer à l'étape suivante pour nettoyer les demandes actives et résilier toutes les instances en cours d'exécution.

Étape 5 : Nettoyage de vos demandes et instances Spot

Nous devons nettoyer nos demandes et instances. Il est important à la fois d'annuler toutes les demandes en cours et de résilier toutes les instances. Si vous annulez simplement vos demandes, cela ne résiliera pas vos instances, ce qui signifie que vous continuerez à payer pour elles. Lorsque vous résiliez vos instances, les demandes Spot peuvent être annulées, mais dans certains cas, par exemple si vous utilisez les offres persistantes, la résiliation de vos instances ne sera pas suffisante pour empêcher votre demande d'être à nouveau satisfaite. Par conséquent, annuler les offres actives et résilier en même temps toutes les instances en cours d'exécution constitue une bonne pratique.

Le code suivant montre comment annuler vos demandes.

try { // Cancel requests. CancelSpotInstanceRequestsRequest cancelRequest = new CancelSpotInstanceRequestsRequest(spotInstanceRequestIds); ec2.cancelSpotInstanceRequests(cancelRequest); } catch (AmazonServiceException e) { // Write out any exceptions that may have occurred. System.out.println("Error cancelling instances"); System.out.println("Caught Exception: " + e.getMessage()); System.out.println("Reponse Status Code: " + e.getStatusCode()); System.out.println("Error Code: " + e.getErrorCode()); System.out.println("Request ID: " + e.getRequestId()); }

Pour résilier les instances en attente, vous avez besoin de l'ID d'instance associé à la demande qui les a démarrées. L'exemple de code suivant utilise notre code d'origine pour surveiller les instances et ajoute un élément ArrayList dans lequel nous stockons l'ID d'instance associé à la réponse describeInstance.

// Create a variable that will track whether there are any requests // still in the open state. boolean anyOpen; // Initialize variables. ArrayList<String> instanceIds = new ArrayList<String>(); do { // Create the describeRequest with all of the request ids to // monitor (e.g. that we started). DescribeSpotInstanceRequestsRequest describeRequest = new DescribeSpotInstanceRequestsRequest(); describeRequest.setSpotInstanceRequestIds(spotInstanceRequestIds); // Initialize the anyOpen variable to false, which assumes there // are no requests open unless we find one that is still open. anyOpen = false; try { // Retrieve all of the requests we want to monitor. DescribeSpotInstanceRequestsResult describeResult = ec2.describeSpotInstanceRequests(describeRequest); List<SpotInstanceRequest> describeResponses = describeResult.getSpotInstanceRequests(); // Look through each request and determine if they are all // in the active state. for (SpotInstanceRequest describeResponse : describeResponses) { // If the state is open, it hasn't changed since we // attempted to request it. There is the potential for // it to transition almost immediately to closed or // cancelled so we compare against open instead of active. if (describeResponse.getState().equals("open")) { anyOpen = true; break; } // Add the instance id to the list we will // eventually terminate. instanceIds.add(describeResponse.getInstanceId()); } } catch (AmazonServiceException e) { // If we have an exception, ensure we don't break out // of the loop. This prevents the scenario where there // was blip on the wire. anyOpen = true; } try { // Sleep for 60 seconds. Thread.sleep(60*1000); } catch (Exception e) { // Do nothing because it woke up early. } } while (anyOpen);

Grâce aux ID d'instance stockés dans l'élément ArrayList, vous pouvez résilier toutes les instances en cours d'exécution en utilisant l'extrait de code suivant.

try { // Terminate instances. TerminateInstancesRequest terminateRequest = new TerminateInstancesRequest(instanceIds); ec2.terminateInstances(terminateRequest); } catch (AmazonServiceException e) { // Write out any exceptions that may have occurred. System.out.println("Error terminating instances"); System.out.println("Caught Exception: " + e.getMessage()); System.out.println("Reponse Status Code: " + e.getStatusCode()); System.out.println("Error Code: " + e.getErrorCode()); System.out.println("Request ID: " + e.getRequestId()); }

Synthèse

Pour résumer, nous fournissons une approche plus orientée objet qui associe les étapes précédemment présentées : initialiser le client EC2, soumettre la demande Spot, déterminer le moment où les demandes Spot ne sont plus à l'état ouvert et nettoyer les demandes Spot persistantes et les instances associées. Nous créons une classe appelée Requests qui effectue toutes ces actions.

Nous créons aussi une classe GettingStartedApp qui comporte une méthode principale au niveau de laquelle nous effectuons les appels de fonction de haut niveau. Nous initialisons en particulier l'objet Requests décrit précédemment. Nous soumettons la demande d'instance Spot. Nous attendons ensuite que l'état de la demande Spot soit « Actif ». Enfin, nous nettoyons les demandes et les instances.

Consultez ou téléchargez le code source complet de cet exemple à partir de GitHub.

Félicitations ! Vous venez de terminer le didacticiel de mise en route permettant de développer le logiciel d'instances Spot avec le kit AWS SDK for Java.

Étapes suivantes

Procédez avecDidacticiel : Advanced (Avancé)Amazon EC2Gestion des demandes Spot.