Tutorial: Amazon EC2 Spot Instances - AWS SDK for Java 1. x

La AWS SDK for Java versione 1.x è entrata in modalità manutenzione il 31 luglio 2024 e sarà disponibile il 31 end-of-supportdicembre 2025. Ti consigliamo di eseguire la migrazione a per continuare AWS SDK for Java 2.xa ricevere nuove funzionalità, miglioramenti della disponibilità e aggiornamenti di sicurezza.

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: Amazon EC2 Spot Instances

Panoramica

Le istanze Spot ti consentono di fare offerte su inutilizzateAmazon Elastic Compute Cloud(Amazon EC2) capacità t fino al 90% rispetto al prezzo dell'istanza on-demand ed eseguire le istanze acquisite fino a quando l'offerta supera la correnteprezzo Spot.Amazon EC2cambia periodicamente il prezzo Spot in funzione della domanda e dell'offerta e i clienti che presentano offerte pari o superiori hanno diritto di accedere alle istanze Spot disponibili. Come le istanze on demand e le istanze riservate, le istanze Spot offrono un'altra opzione per ottenere una maggiore capacità di elaborazione.

Le istanze Spot possono ridurre significativamente il tuoAmazon EC2costi per l'elaborazione in batch, la ricerca scientifica, l'elaborazione delle immagini, la codifica video, la crawling di dati e Web, l'analisi finanziaria e i test. Inoltre, le istanze Spot consentono di accedere a grandi quantità di capacità aggiuntiva in situazioni in cui la necessità di tale capacità non è urgente.

Per utilizzare le istanze Spot, farne richiesta specificando il prezzo massimo che si desidera pagare per ora di istanza; questa sarà la tua offerta. Se la tua offerta supera il prezzo Spot corrente, la tua richiesta è soddisfatta e le tue istanze saranno eseguite finché non sceglierai di terminarle o finché il prezzo Spot non supererà nuovamente la tua offerta (a seconda di quale dei due si verifica prima).

È importante notare:

  • Spesso il prezzo che pagherai per ora sarà inferiore alla tua offerta. Amazon EC2 adegua il prezzo Spot periodicamente in base al variare delle richieste in entrata e alla fornitura disponibile. Tutti devono pagare lo stesso prezzo Spot per quel periodo, indipendentemente dal fatto che la loro offerta fosse più alta. Pertanto, potresti pagare meno, ma non pagherai mai di più rispetto alla tua offerta.

  • Se esegui le istanze Spot e la tua offerta non corrisponde più all'attuale prezzo Spot o lo supera, le istanze saranno terminate. Ciò significa che è necessario assicurarsi che i carichi di lavoro e le applicazioni siano sufficientemente flessibili da sfruttare questa capacità opportunistica.

Le istanze Spot offrono esattamente le stesse prestazioni di tutte le altre istanze Amazon EC2 durante l'esecuzione e, come tutte le altre istanze Amazon EC2 possono essere terminate quando non sono più necessarie. Se termini la tua istanza, paghi per la frazione di ora utilizzata (come faresti per le istanze On demand o Riservate). Tuttavia, se il prezzo Spot supera la tua offerta e la tua istanza viene terminata daAmazon EC2, non ti verrà addebitato alcun costo per un'ora parziale di utilizzo.

Questo tutorial mostra come utilizzareAWS SDK for Javaper eseguire le operazioni descritte di seguito.

  • Inviare una richiesta Spot

  • Stabilire quando la richiesta Spot viene soddisfatta

  • Annullare la richiesta Spot

  • Terminare le istanze associate

Prerequisiti

Per utilizzare questo tutorial, è necessario disporre dellaAWS SDK for Javainstallato, oltre ad aver soddisfatto i suoi prerequisiti di installazione di base. Consulta .Impostazione dell'interfacciaAWS SDK for Javaper ulteriori informazioni.

Fase 1: Configurazione delle credenziali

Per iniziare a utilizzare questo esempio di codice, è necessario configurareAWSCredenziali . Consulta .ConfigurazioneAWSCredenziali e regione per lo sviluppoper istruzioni su come eseguire questa operazione.

Nota

Si consiglia di utilizzare le credenziali di un utente IAM per fornire questi valori. Per ulteriori informazioni, consultaRegistrazione adAWSe Creare un utente IAM.

Dopo aver configurato le impostazioni, puoi iniziare a utilizzare il codice nell'esempio.

Fase 2: Configurazione di un gruppo di sicurezza

UNgruppo di sicurezzaFunziona come un firewall che controlla il traffico consentito in entrata e in uscita da un gruppo di istanze. Per impostazione predefinita, un'istanza viene avviata senza alcun gruppo di sicurezza, il che significa che tutto il traffico IP in entrata, su qualsiasi porta TCP, verrà negato. Quindi, prima di inviare la nostra richiesta Spot, creeremo un gruppo di sicurezza che consenta il traffico di rete necessario. Ai fini di questo tutorial, creeremo un nuovo gruppo di sicurezza chiamato «GettingStarted» che consente il traffico SSH (Secure Shell) dall'indirizzo IP da cui si sta eseguendo l'applicazione. Per configurare un nuovo gruppo di sicurezza, è necessario includere o eseguire il seguente esempio di codice che imposta il gruppo di sicurezza a livello di programmazione.

Dopo aver creato unAmazonEC2oggetto client, creiamo unCreateSecurityGroupRequestoggetto con il nome, «GettingStarted» e una descrizione per il gruppo di sicurezza. Poi chiamiamo ilec2.createSecurityGroupAPI per creare il gruppo.

Per abilitare l'accesso al gruppo, creiamo unipPermissionoggetto con l'intervallo di indirizzi IP impostato sulla rappresentazione CIDR della subnet per il computer locale; il suffisso «/10" sull'indirizzo IP indica la subnet per l'indirizzo IP specificato. Configuriamo anche ilipPermissioncon il protocollo TCP e la porta 22 (SSH). La fase finale prevede la chiamataec2.authorizeSecurityGroupIngresscon il nome del nostro gruppo di sicurezza eipPermissionoggetto.

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

Per creare un nuovo gruppo di sicurezza, è necessario eseguire questa applicazione una sola volta.

È inoltre possibile creare il gruppo di sicurezza tramiteAWS Toolkit for Eclipse. Consulta .Gestione di gruppi di sicurezza daAWS Cost Explorerper ulteriori informazioni.

Fase 3: Invio della richiesta Spot

Per inviare una richiesta Spot, devi prima determinare il tipo di istanza, l'Amazon Machine Image (AMI) e l'offerta massima da proporre. Devi anche includere il gruppo di sicurezza configurato in precedenza, in modo da poter accedere all'istanza se lo desideri.

Sono disponibili diversi tipi di istanza tra cui scegliere. Vai aAmazon EC2Tipi di istanza per un elenco completo. Per questo tutorial, useremo t1.micro, il tipo di istanza più economico disponibile. Successivamente, determineremo il tipo di AMI che vorremmo utilizzare. Quando abbiamo scritto questo tutorial, utilizzeremo ami-a9d09ed1, l'AMI Amazon Linux più aggiornata disponibile. L'AMI più recente potrebbe cambiare nel tempo, ma puoi sempre determinare l'AMI della versione più recente seguendo questi passaggi:

  1. Aprire la console Amazon EC2.

  2. SelezionaAvvia istanza.

  3. La prima finestra mostra le AMI disponibili. L'ID AMI è elencato accanto a ciascun titolo AMI. In alternativa, è possibile utilizzare laDescribeImagesL'API, ma l'utilizzo di questo comando non rientra nell'ambito di questo tutorial.

Ci sono molti modi per affrontare le offerte per le istanze Spot; per ottenere un'ampia panoramica dei vari approcci, è consigliabile guardare ilOfferta per istanze Spotvideo. Tuttavia, per iniziare, descriveremo tre strategie comuni: offerta per assicurarsi un costo inferiore al prezzo on demand; offerta in base al valore del calcolo risultante; offerta per acquisire capacità di elaborazione il più rapidamente possibile.

  • Ridurre i costi sotto i prezziHai un processo di elaborazione in batch la cui esecuzione richiede diverse ore o giorni. Tuttavia, hai una certa flessibilità sui tempi di avvio e di completamento. Vuoi vedere se riesci a completarlo a un costo inferiore rispetto alle istanze on demand. Analizzi la cronologia dei prezzi Spot per i tipi di istanza utilizzando la AWS Management Console o le API di Amazon EC2. Per ulteriori informazioni, vedi Visualizzazione della cronologia dei prezzi Spot. 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 offerta:

    • Puoi fare un'offerta nella fascia alta della gamma di prezzi Spot (ma comunque inferiore al prezzo on demand), prevedendo che la tua singola richiesta Spot sarà probabilmente soddisfatta ed eseguita per un tempo di elaborazione consecutivo sufficiente a completare il processo.

    • In alternativa, puoi specificare l'importo che desideri pagare per le istanze Spot come percentuale del prezzo dell'istanza on demand e pianificare di combinare più istanze avviate in momenti diversi in un'unica richiesta persistente. Se il prezzo specificato è superiore, l'istanza Spot viene terminata. (Più avanti nel tutorial spiegheremo come automatizzare questa operazione).

  • Non pagare più del valore del risultatoHai un processo di elaborazione dei dati da completare. Conosci abbastanza il valore dei risultati del processo per sapere quando valgono in termini di costi di elaborazione. Dopo aver analizzato la cronologia dei prezzi Spot per il tuo tipo di istanza, scegli un prezzo di offerta per cui il costo del tempo di elaborazione non sia superiore al valore dei risultati del processo. Crea un'offerta persistente e impostane l'esecuzione intermittente quando il prezzo Spot raggiunge o scende sotto la tua offerta.

  • Acquisire rapidamente le capacità di elaborazioneTi occorre una capacità aggiuntiva imprevista e a breve termine che non è disponibile con le istanze on demand. Dopo aver analizzato la cronologia dei prezzi Spot per il tuo tipo di istanza, fai un'offerta superiore al valore massimo dello storico dei prezzi per offrire un'alta probabilità che la tua richiesta sia soddisfatta in modo rapido e continuare l'elaborazione finché non viene completata.

Dopo aver scelto il prezzo di offerta, sei pronto a richiedere un'istanza Spot. Ai fini di questo tutorial, offriamo il prezzo on demand (0,03 USD) per aumentare al massimo la possibilità che l'offerta sia soddisfatta. Puoi determinare i tipi di istanze disponibili e i prezzi on demand per le istanze, vai aAmazon EC2Pagina dei prezzi. Mentre un'istanza Spot è in esecuzione, paghi il prezzo Spot in corso di validità durante l'esecuzione delle istanze. I prezzi delle istanze Spot sono stabiliti da Amazon EC2 e regolati in modo graduale in base ai trend a lungo termine di offerta e domanda di capacità delle istanze Spot. Puoi anche specificare l'importo che desideri pagare per un'istanza Spot come percentuale del prezzo dell'istanza on demand. Per richiedere un'istanza Spot, devi semplicemente creare la tua richiesta con i parametri scelti in precedenza. Iniziamo creando unRequestSpotInstanceRequestoggetto. L'oggetto della richiesta richiede il numero di istanze da avviare e il prezzo di offerta. Inoltre, è necessario impostare laLaunchSpecificationper la richiesta, che include il tipo di istanza, l'ID dell'AMI e il gruppo di sicurezza da utilizzare. Una volta compilata la richiesta, si chiama ilrequestSpotInstancessul metodo sulAmazonEC2Clientoggetto. L'esempio seguente mostra come richiedere un'istanza 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'esecuzione di questo codice avvierà una nuova richiesta dell'istanza Spot. Sono disponibili altre opzioni per configurare le tue richieste Spot. Per ulteriori informazioni, consulta la paginaTutorial: AvanzatoAmazon EC2Gestione delle richieste Spoto ilRequestSpotInstancesclasse nelAWS SDK for JavaInformazioni di riferimento sull'API.

Nota

Ti verrà addebitato il costo delle istanze Spot effettivamente avviate, quindi assicurati di annullare tutte le richieste e di terminare tutte le istanze avviate per ridurre i costi associati.

Fase 4: Verifica dello stato della richiesta Spot

Per poter procedere all'ultima fase, vogliamo creare un codice per attendere che la richiesta Spot raggiunga lo stato «attivo». Per determinare lo stato della nostra richiesta Spot, effettuiamo il sondaggiodescribeSpotInstanceRequestsMetodo per lo stato dell'ID della richiesta Spot da monitorare.

L'ID richiesta creato nel passaggio 2 è incorporato nella risposta al nostrorequestSpotInstances. Il codice di esempio seguente mostra come raccogliere gli ID della richiesta darequestSpotInstancesrisposta e usarli per popolare unArrayList.

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

Per monitorare il tuo ID richiesta, chiama ildescribeSpotInstanceRequestsper determinare lo stato di una richiesta. Quindi esegui il ciclo fino a quando la richiesta non è nello stato «aperto». Si noti che monitoriamo per uno stato non «aperto», piuttosto uno stato di, diciamo, «attivo», perché la richiesta può andare direttamente a «chiusa» se c'è un problema con gli argomenti della richiesta. L'esempio di codice seguente fornisce i dettagli su come eseguire questa operazione.

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

Dopo aver eseguito questo codice, la richiesta di istanza Spot sarà completata o non riuscita con un errore che verrà visualizzato sullo schermo. In entrambi i casi, possiamo procedere al passaggio successivo per ripulire tutte le richieste attive e terminare tutte le istanze in esecuzione.

Fase 5: Eliminazione delle richieste e delle istanze Spot

Infine, dobbiamo ripulire le nostre richieste e istanze. È importante annullare tutte le richieste in sospesoeTerminare tutte le istanze La semplice cancellazione delle richieste non termina le istanze, i cui costi continueranno a pagare. Quando termini le istanze, le richieste Spot in genere vengono annullate. Tuttavia, in alcuni scenari, ad esempio quando utilizzi le offerte persistenti, la terminazione delle istanze non è sufficiente a interrompere la rielaborazione della richiesta. Pertanto, è consigliabile sia annullare le offerte attive che terminare le istanze in esecuzione.

Il codice seguente mostra come annullare le tue richieste.

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

Per terminare eventuali istanze in sospeso, è necessario l'ID di istanza associato alla richiesta che le ha avviate. Il seguente esempio di codice prende il nostro codice originale per il monitoraggio delle istanze e aggiunge unArrayListin cui memorizziamo l'ID di istanza associato aldescribeInstancerisposta.

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

Utilizzo degli ID di istanza, memorizzati nelArrayList, terminare tutte le istanze in esecuzione utilizzando il seguente frammento di codice.

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

Mettere tutto insieme

Per riunire tutto questo, forniamo un approccio più orientato agli oggetti che combina i passaggi precedenti che abbiamo mostrato: inizializzazione del client EC2, invio della richiesta Spot, determinazione quando le Richieste Spot non sono più in stato aperto e pulizia di qualsiasi richiesta Spot persistente e istanze associate. Creiamo una classe chiamataRequestsche esegue queste operazioni.

Creiamo anche unGettingStartedAppclass, che ha un metodo principale in cui eseguiamo le chiamate di funzioni di alto livello. Nello specifico, inizializziamo ilRequestsoggetto descritto in precedenza. Inviare la richiesta dell'istanza Spot. Quindi aspettiamo che la richiesta Spot raggiunga lo stato «Attivo». Infine, puliamo le richieste e le istanze.

Il codice sorgente completo per questo esempio può essere visualizzato o scaricato all'indirizzoGitHub.

Complimenti! Hai appena completato il tutorial introduttivo per lo sviluppo del software Spot Instance conAWS SDK for Java.

Fasi successive

Continua con laTutorial: AvanzatoAmazon EC2Gestione delle richieste Spot.