Arresto automatico e avvio dell'istanza Amazon EC2


90

Posso avviare e terminare automaticamente la mia istanza Amazon utilizzando Amazon API? Puoi descrivere come si può fare? Idealmente ho bisogno di avviare l'istanza e arrestare l'istanza a intervalli di tempo specificati ogni giorno.


2
Cosa succede ai dati della tua istanza EC2 quando viene arrestata? Persiste o devi ricostruirlo di nuovo?
Matthew Lock

Avviare e terminare automaticamente l'istanza utilizzando Amazon API potrebbe causare perdite di dati su quell'evento. Consiglierei le azioni Stop & Recover utilizzando AWS CloudWatch Alarms
Chetabahana

Prima dell'API di Amazon, suggerirei di pianificare l'avvio / arresto di EC2 utilizzando AWS Lambda , nel tuo caso ti costa meno di $ 0,0004 USD / mese.
Chetabahana

Risposte:


102

Nel caso in cui qualcuno inciampi su questa vecchia domanda, al giorno d'oggi puoi ottenere la stessa cosa aggiungendo una pianificazione a un gruppo di ridimensionamento automatico: aumentare la quantità di istanze in un gruppo di ridimensionamento automatico a 1 in determinati momenti e ridurlo a 0 in seguito .

E poiché questa risposta sta ottenendo molte visualizzazioni, ho pensato di collegarmi a una guida molto utile su questo: Esecuzione di istanze EC2 su una pianificazione ricorrente con Auto Scaling


6
Ho provato il metodo descritto nel collegamento e in effetti avvia / arresta le istanze negli orari specificati dal tutorial. Tuttavia, ho notato nella console Web AWS che quando un'istanza viene avviata con questo metodo, non viene avviata con una chiave (in modo tale da poterla inserire tramite ssh) e inoltre non sembra avere le stesse cose che ho installato sulla mia microistanza che uso come test (non sono un esperto di cloud, ma penso che questo significhi che questa nuova istanza che è stata attivata non è collegata a EBS?) C'è un modo per avviare automaticamente e interrompere la stessa istanza in base a una pianificazione temporale?
Kiran K.

@KiranK. significa che la nuova istanza non è collegata al volume EBS attualmente utilizzato? cosa hai usato?
Cappello di paglia

26

Puoi provare a utilizzare direttamente gli strumenti API di Amazon EC2. Ci sono davvero solo due comandi di cui hai bisogno: ec2-start-instances ed ec2-stop-istanze. Assicurati che le variabili di ambiente come EC2_HOME, AWS_CREDENTIAL_FILE, EC2_CERT, EC2_PRIVATE_KEY e così via siano configurate correttamente e che tutte le credenziali AWS, i certificati e i file della chiave privata siano nella posizione corretta: puoi trovare ulteriori informazioni nella documentazione degli strumenti API di AWS EC2.

Puoi prima testare il comando manualmente e poi, quando tutto funziona correttamente, configurare Unix crontab o Scheduled Tasks su Windows. Di seguito è possibile trovare l'esempio per il file Linux / etc / crontab (non dimenticare che tutte le variabili di ambiente menzionate sopra devono essere presenti per l'utente "tuo account".

/etc/crontab
0 8     * * *   your-account ec2-start-instances <your_instance_id>
0 16    * * *   your-account ec2-stop-instances <your_instance_id>
# Your instance will be started at 8am and shutdown at 4pm.

Sono uno sviluppatore per il progetto BitNami Cloud, dove impacchettiamo gli strumenti AWS (compresi quelli che ho citato) in un programma di installazione gratuito e facile da usare che potresti voler provare: BitNami CloudTools pack stack


2
Per questo ancora è necessario disporre di un'altra istanza. Perché lo spegnimento non è il problema ma l'avvio. Crone o altro non funzionerà in un computer morto dopo che è stato spento.
Upul Doluweera

Ho seguito questi passaggi per configurare gli strumenti AWS CLI sulla mia istanza Linux di AMazon. L'arresto dell'istanza funziona correttamente. Ma l'avvio di un'istanza già arrestata restituisce un errore 400, ID istanza non trovato. Come posso avviare un'istanza già interrotta?
Amol Chakane

17

Ti consiglio di dare un'occhiata alla Guida introduttiva di EC2 , che ti mostra come fare ciò di cui hai bisogno utilizzando gli strumenti della riga di comando di EC2. Puoi facilmente inserire questo script in un cron job (su Linux / UNIX) o in un job pianificato su Windows per chiamare i comandi di avvio e arresto in un dato momento.

Se vuoi farlo dal tuo codice, puoi usare le API SOAP o REST; vedere il Guida per sviluppatori per i dettagli.


15

Ho scritto codice in Python, usando la libreria Boto, per farlo. Puoi regolarlo per il tuo uso personale. Assicurati di eseguirlo come parte di un cron job, quindi sarai in grado di avviare o arrestare tutte le istanze di cui hai bisogno durante l'esecuzione dei cron job.

#!/usr/bin/python
#
# Auto-start and stop EC2 instances
#
import boto, datetime, sys
from time import gmtime, strftime, sleep

# AWS credentials
aws_key = "AKIAxxx"
aws_secret = "abcd"

# The instances that we want to auto-start/stop
instances = [
    # You can have tuples in this format:
    # [instance-id, name/description, startHour, stopHour, ipAddress]
    ["i-12345678", "Description", "00", "12", "1.2.3.4"]
]

# --------------------------------------------

# If its the weekend, then quit
# If you don't care about the weekend, remove these three 
# lines of code below.
weekday = datetime.datetime.today().weekday()
if (weekday == 5) or (weekday == 6):
    sys.exit()

# Connect to EC2
conn = boto.connect_ec2(aws_key, aws_secret)

# Get current hour
hh = strftime("%H", gmtime())

# For each instance
for (instance, description, start, stop, ip) in instances:
    # If this is the hour of starting it...
    if (hh == start):
        # Start the instance
        conn.start_instances(instance_ids=[instance])
        # Sleep for a few seconds to ensure starting
        sleep(10)
        # Associate the Elastic IP with instance
        if ip:
            conn.associate_address(instance, ip)
    # If this is the hour of stopping it...
    if (hh == stop):
        # Stop the instance
        conn.stop_instances(instance_ids=[instance])

1
È possibile anche per gli ambienti Elastic Beanstalk?
Amol Chakane

5

Se non è mission critical - Una cosa semplicistica da fare è programmare il file batch per eseguire "SHUTDOWN" (Windows) alle 3 del mattino ogni giorno. Quindi almeno non corri il rischio di lasciare accidentalmente un'istanza indesiderata in esecuzione indefinitamente.

Ovviamente questa è solo metà della storia!


5

L'azienda per cui lavoro aveva clienti che lo chiedevano regolarmente, quindi abbiamo scritto un'app di pianificazione EC2 freeware disponibile qui:

http://blog.simple-help.com/2012/03/free-ec2-scheduler/

Funziona su Windows e Mac, ti consente di creare più pianificazioni giornaliere / settimanali / mensili e ti consente di utilizzare filtri di corrispondenza per includere facilmente un gran numero di istanze o include quelle che aggiungi in futuro.


2

AWS Data Pipeline funziona correttamente. https://aws.amazon.com/premiumsupport/knowledge-center/stop-start-ec2-instances/

Se desideri escludere i giorni dall'inizio (es. Weekend) aggiungi un oggetto ShellCommandPrecondition.

Nella Console AWS / Data Pipeline, crea una nuova pipeline. È più facile modificare / importare una definizione (JSON)

    {
"objects": [
{
  "failureAndRerunMode": "CASCADE",
  "schedule": {
    "ref": "DefaultSchedule"
  },
  "resourceRole": "DataPipelineDefaultResourceRole",
  "role": "DataPipelineDefaultRole",
  "pipelineLogUri": "s3://MY_BUCKET/log/",
  "scheduleType": "cron",
  "name": "Default",
  "id": "Default"
},
{
  "name": "CliActivity",
  "id": "CliActivity",
  "runsOn": {
    "ref": "Ec2Instance"
  },
  "precondition": {
    "ref": "PreconditionDow"
  },
  "type": "ShellCommandActivity",
  "command": "(sudo yum -y update aws-cli) && (#{myAWSCLICmd})"
},
{
  "period": "1 days",
  "startDateTime": "2015-10-27T13:00:00",
  "name": "Every 1 day",
  "id": "DefaultSchedule",
  "type": "Schedule"
},
{
  "scriptUri": "s3://MY_BUCKET/script/dow.sh",
  "name": "DayOfWeekPrecondition",
  "id": "PreconditionDow",
  "type": "ShellCommandPrecondition"
},
{
  "instanceType": "t1.micro",
  "name": "Ec2Instance",
  "id": "Ec2Instance",
  "type": "Ec2Resource",
  "terminateAfter": "50 Minutes"
}
],
"parameters": [
{
  "watermark": "aws [options] <command> <subcommand> [parameters]",
  "description": "AWS CLI command",
  "id": "myAWSCLICmd",
  "type": "String"
}
 ],
"values": {
"myAWSCLICmd": "aws ec2 start-instances --instance-ids i-12345678 --region eu-west-1"
}
}

Metti lo script Bash da scaricare ed eseguire come precondizione nel tuo bucket S3

#!/bin/sh
if [ "$(date +%u)" -lt 6 ]
then exit 0
else exit 1
fi

All'attivazione e all'esecuzione della pipeline nei giorni del fine settimana, lo stato di integrità della pipeline della console AWS legge un "ERRORE" fuorviante. Lo script bash restituisce un errore (uscita 1) e EC2 non viene avviato. Nei giorni da 1 a 5, lo stato è "SANO".

Per interrompere automaticamente EC2 alla chiusura dell'ufficio, utilizza il comando AWS CLI ogni giorno senza precondizioni.


1

Potresti guardare Ylastic per farlo. L'alternativa sembra avere una macchina in esecuzione che arresta / avvia altre istanze utilizzando un cron job o un'attività pianificata.

Ovviamente se vuoi solo un'istanza questa è una soluzione costosa, poiché una macchina deve essere sempre in esecuzione e pagare ~ $ 80 al mese per una macchina per eseguire cron job non è conveniente.


1

La scalabilità automatica è limitata alla terminazione delle istanze. Se si desidera arrestare un'istanza e mantenere lo stato del server, l'approccio migliore è uno script esterno.

Puoi farlo eseguendo un lavoro su un'altra istanza in esecuzione 24 ore su 24, 7 giorni su 7 oppure puoi utilizzare un servizio di terze parti come Ylastic (menzionato sopra) o Rocket Peak .

Ad esempio in C # il codice per arrestare un server è abbastanza semplice:

public void stopInstance(string instance_id, string AWSRegion)
        {
            RegionEndpoint myAWSRegion = RegionEndpoint.GetBySystemName(AWSRegion);
            AmazonEC2 ec2 = AWSClientFactory.CreateAmazonEC2Client(AWSAccessKey, AWSSecretKey, myAWSRegion);
            ec2.StopInstances(new StopInstancesRequest().WithInstanceId(instance_id));
        }

1

IMHO l'aggiunta di una pianificazione a un gruppo di ridimensionamento automatico è il miglior approccio "simile a una nuvola" come menzionato prima.

Ma nel caso in cui non sia possibile terminare le istanze e utilizzarne di nuove, ad esempio se sono associati IP elastici ecc.

Puoi creare uno script Ruby per avviare e arrestare le istanze in base a un intervallo di date.

#!/usr/bin/env ruby

# based on https://github.com/phstc/amazon_start_stop

require 'fog'
require 'tzinfo'

START_HOUR = 6 # Start 6AM
STOP_HOUR  = 0 # Stop  0AM (midnight)

conn = Fog::Compute::AWS.new(aws_access_key_id:     ENV['AWS_ACCESS_KEY_ID'],
                             aws_secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'])

server = conn.servers.get('instance-id')

tz = TZInfo::Timezone.get('America/Sao_Paulo')

now = tz.now

stopped_range = (now.hour >= STOP_HOUR && now.hour < START_HOUR)
running_range = !stopped_range

if stopped_range && server.state != 'stopped'
  server.stop
end

if running_range && server.state != 'running'
  server.start

  # if you need an Elastic IP
  # (everytime you stop an instance Amazon dissociates Elastic IPs)
  #
  # server.wait_for { state == 'running' }
  # conn.associate_address server.id, 127.0.0.0
end

Dai un'occhiata ad amazon_start_stop per creare uno scheduler gratuitamente utilizzando Heroku Scheduler .


1

Anche se ci sono modi per ottenere ciò utilizzando il ridimensionamento automatico, potrebbe non essere adatto a tutte le occasioni in quanto termina le istanze. I cron job non funzioneranno mai per una singola istanza (sebbene possano essere perfettamente utilizzati per situazioni come l'arresto di una singola istanza e la pianificazione di altre istanze durante l'esecuzione di molte istanze). Puoi utilizzare chiamate API come StartInstancesRequest e StopInstancesRequest per ottenere lo stesso risultato, ma ancora una volta devi fare affidamento su una terza risorsa. Esistono molte applicazioni per pianificare istanze AWS con molte funzionalità, ma per una soluzione semplice consiglierei un'app gratuita come snapleaf.io


1

Sì, puoi farlo utilizzando AWS Lambda. Puoi selezionare il trigger in Cloudwatch che viene eseguito su espressioni Cron su UTC.

Ecco un link correlato https://aws.amazon.com/premiumsupport/knowledge-center/start-stop-lambda-cloudwatch/

Un'altra alternativa è quella di utilizzare awscliche è disponibile da pip, apt-get, yumo brew, e quindi eseguire aws configurecon le credenziali esportati da IAM ed eseguendo il seguente script bash, per fermare un EC2 che è stato etichettato con Name: Appnamee Value: Appname Prod. Puoi utilizzare awscliper taggare le tue istanze o taggarle manualmente dalla console AWS. aws ec2 stop-instancesinterromperà l'istanza e jqviene utilizzato per filtrare la query json e recuperare l'id dell'istanza corretto utilizzando i tag daaws ec2 describe-instances .

Per verificare che sia aws configureandato a buon fine e restituisca l'output json, esegui aws ec2 describe-instancese l'ID dell'istanza in esecuzione dovrebbe essere presente nell'output. Ecco un esempio di output

{
    "Reservations": [
        {
            "Instances": [
                {
                    "Monitoring": {
                        "State": "disabled"
                    },
                    "PublicDnsName": "ec2-xxx.ap-south-1.compute.amazonaws.com",
                    "State": {
                        "Code": xx,
                        "Name": "running"
                    },
                    "EbsOptimized": false,
                    "LaunchTime": "20xx-xx-xxTxx:16:xx.000Z",
                    "PublicIpAddress": "xx.127.24.xxx",
                    "PrivateIpAddress": "xxx.31.3.xxx",
                    "ProductCodes": [],
                    "VpcId": "vpc-aaxxxxx",
                    "StateTransitionReason": "",
                    "InstanceId": "i-xxxxxxxx",
                    "ImageId": "ami-xxxxxxx",
                    "PrivateDnsName": "ip-xxxx.ap-south-1.compute.internal",
                    "KeyName": "node",
                    "SecurityGroups": [
                        {
                            "GroupName": "xxxxxx",
                            "GroupId": "sg-xxxx"
                        }
                    ],
                    "ClientToken": "",
                    "SubnetId": "subnet-xxxx",
                    "InstanceType": "t2.xxxxx",
                    "NetworkInterfaces": [
                        {
                            "Status": "in-use",
                            "MacAddress": "0x:xx:xx:xx:xx:xx",
                            "SourceDestCheck": true,
                            "VpcId": "vpc-xxxxxx",
                            "Description": "",
                            "NetworkInterfaceId": "eni-xxxx",
                            "PrivateIpAddresses": [
                                {
                                    "PrivateDnsName": "ip-xx.ap-south-1.compute.internal",
                                    "PrivateIpAddress": "xx.31.3.xxx",
                                    "Primary": true,
                                    "Association": {
                                        "PublicIp": "xx.127.24.xxx",
                                        "PublicDnsName": "ec2-xx.ap-south-1.compute.amazonaws.com",
                                        "IpOwnerId": "xxxxx"
                                    }
                                }
                            ],
                            "PrivateDnsName": "ip-xxx-31-3-xxx.ap-south-1.compute.internal",
                            "Attachment": {
                                "Status": "attached",
                                "DeviceIndex": 0,
                                "DeleteOnTermination": true,
                                "AttachmentId": "xxx",
                                "AttachTime": "20xx-xx-30Txx:16:xx.000Z"
                            },
                            "Groups": [
                                {
                                    "GroupName": "xxxx",
                                    "GroupId": "sg-xxxxx"
                                }
                            ],
                            "Ipv6Addresses": [],
                            "OwnerId": "xxxx",
                            "PrivateIpAddress": "xx.xx.xx.xxx",
                            "SubnetId": "subnet-xx",
                            "Association": {
                                "PublicIp": "xx.xx.xx.xxx",
                                "PublicDnsName": "ec2-xx.ap-south-1.compute.amazonaws.com",
                                "IpOwnerId": "xxxx"
                            }
                        }
                    ],
                    "SourceDestCheck": true,
                    "Placement": {
                        "Tenancy": "default",
                        "GroupName": "",
                        "AvailabilityZone": "xx"
                    },
                    "Hypervisor": "xxx",
                    "BlockDeviceMappings": [
                        {
                            "DeviceName": "/dev/xxx",
                            "Ebs": {
                                "Status": "attached",
                                "DeleteOnTermination": true,
                                "VolumeId": "vol-xxx",
                                "AttachTime": "20xxx-xx-xxTxx:16:xx.000Z"
                            }
                        }
                    ],
                    "Architecture": "x86_64",
                    "RootDeviceType": "ebs",
                    "RootDeviceName": "/dev/xxx",
                    "VirtualizationType": "xxx",
                    "Tags": [
                        {
                            "Value": "xxxx centxx",
                            "Key": "Name"
                        }
                    ],
                    "AmiLaunchIndex": 0
                }
            ],
            "ReservationId": "r-xxxx",
            "Groups": [],
            "OwnerId": "xxxxx"
        }
    ]
}

Il seguente script bash è stop-ec2.shin /home/centos/cron-scripts/cui è ispirato da questo post SO

(instance=$(aws ec2 describe-instances | jq '.Reservations[].Instances | select(.[].Tags[].Value | startswith("Appname Prod") ) |  select(.[].Tags[].Key == "Appname") |  {InstanceId: .[].InstanceId, PublicDnsName: .[].PublicDnsName, State: .[].State, LaunchTime: .[].LaunchTime, Tags: .[].Tags}  | [.]' | jq -r .[].InstanceId) && aws ec2 stop-instances --instance-ids ${instance} )

Esegui il file utilizzando sh /home/centos/cron-scripts/stop-ec2.she verifica che l'istanza EC2 venga arrestata. Per eseguire il debug, eseguiaws ec2 describe-instances | jq '.Reservations[].Instances | select(.[].Tags[].Value | startswith("Appname Prod") ) | select(.[].Tags[].Key == "Appname") | {InstanceId: .[].InstanceId, PublicDnsName: .[].PublicDnsName, State: .[].State, LaunchTime: .[].LaunchTime, Tags: .[].Tags} | [.]' | jq -r .[].InstanceId e verifica che restituisca l'ID istanza corretto che è stato taggato.

Quindi nella crontab -eriga seguente può essere aggiunto

30 14 * * * sh /home/centos/cron-scripts/stop-ec2.sh >> /tmp/stop

che registrerà l'output in /tmp/stop. Il 30 14 * * *è l'espressione cron UTC che è possibile controllare in https://crontab.guru/. Allo stesso modo, la sostituzione con aws ec2 start-instancespuò avviare un'istanza.


0

Credo che la domanda iniziale fosse un po 'confusa. Dipende da ciò di cui Pasta ha bisogno: 1.launch / terminate (instance store) - Auto Scaling è la soluzione giusta (risposta di Nakedible) 2.start / stop istanza di avvio EBS - Auto Scaling non aiuta, io uso script programmati remoti (es. , ec2 CLI).


-8

Non è possibile farlo automaticamente, o almeno non senza un po 'di programmazione e manipolazione API nei file di script. Se desideri una soluzione affidabile per arrestare, riavviare e gestire le tue immagini (presumibilmente per controllare i costi nel tuo ambiente), allora potresti voler dare un'occhiata a LabSlice . Disclaimer: lavoro per questa azienda.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.