Automatisches Herunterfahren und Starten der Amazon EC2-Instanz

90

Kann ich meine Amazon-Instanz mithilfe der Amazon-API automatisch starten und beenden? Können Sie bitte beschreiben, wie dies getan werden kann? Idealerweise muss ich die Instanz jeden Tag in festgelegten Zeitintervallen starten und stoppen.

Pasta
quelle
2
Was passiert mit den Daten Ihrer EC2-Instanz, wenn diese heruntergefahren wird? Bleibt es bestehen oder müssen Sie es erneut erstellen?
Matthew Lock
Das automatische Starten und Beenden der Instanz mithilfe der Amazon-API kann zu Datenverlusten bei diesem Ereignis führen. Ich würde die Stop & Recover-Aktionen mit AWS CloudWatch Alarms
Chetabahana
Anstelle der Amazon-API würde ich empfehlen, den Start / Stopp von EC2 mit AWS Lambda zu planen. In Ihrem Fall kostet dies weniger als 0,0004 USD / Monat.
Chetabahana

Antworten:

102

Nur für den Fall, dass jemand über diese alte Frage stolpert, können Sie heutzutage dasselbe erreichen, indem Sie einer automatischen Skalierungsgruppe einen Zeitplan hinzufügen: Erhöhen Sie die Anzahl der Instanzen in einer automatischen Skalierungsgruppe zu bestimmten Zeiten auf 1 und verringern Sie sie anschließend wieder auf 0 .

Und da diese Antwort viele Aufrufe erhält, habe ich mir überlegt, auf eine sehr hilfreiche Anleitung zu diesem Thema zu verweisen : Ausführen von EC2-Instanzen nach einem wiederkehrenden Zeitplan mit automatischer Skalierung

Nakedible
quelle
6
Ich habe die im Link beschriebene Methode ausprobiert und sie startet / stoppt tatsächlich Instanzen zu den im Lernprogramm angegebenen Zeiten. In der AWS-Webkonsole habe ich jedoch festgestellt, dass eine Instanz, die mit dieser Methode gestartet wird, nicht mit einem Schlüssel gestartet wird (so dass Sie in sie eindringen können), und dass sie auch nicht das gleiche Material zu haben scheint wie ich auf meiner Mikroinstanz installiert, die ich als Test verwende (ich bin kein Cloud-Experte, aber ich denke, dies bedeutet, dass diese neue Instanz, die hochgefahren wird, nicht mit dem EBS verbunden ist?) Gibt es eine Möglichkeit, automatisch zu starten und die gleiche Instanz nach einem Zeitplan stoppen ?
Kiran K.
@ KiranK. Bedeutet dies, dass keine neue Instanz an das aktuell verwendete EBS-Volume angehängt ist? was hast du benutzt
Strohhut
26

Sie können versuchen, die Amazon EC2-API-Tools direkt zu verwenden. Es gibt wirklich nur zwei Befehle, die Sie benötigen: ec2-start-Instanzen und ec2-stop-Instanzen. Stellen Sie sicher, dass Umgebungsvariablen wie EC2_HOME, AWS_CREDENTIAL_FILE, EC2_CERT, EC2_PRIVATE_KEY usw. ordnungsgemäß konfiguriert sind und sich alle AWS-Anmeldeinformationen, Zertifikate und privaten Schlüsseldateien am richtigen Speicherort befinden. Weitere Informationen finden Sie in der Dokumentation zu den AWS EC2-API-Tools.

Sie können den Befehl zuerst von Hand testen und dann, wenn alles einwandfrei funktioniert, Unix crontab oder Scheduled Tasks unter Windows konfigurieren. Im Folgenden finden Sie ein Beispiel für die Linux / etc / crontab-Datei (vergessen Sie nicht, dass alle oben genannten Umgebungsvariablen für den Benutzer "Ihr Konto" vorhanden sein müssen.

/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.

Ich bin Entwickler für das BitNami Cloud-Projekt, in dem wir die AWS-Tools (einschließlich der von mir erwähnten) in einem kostenlosen, benutzerfreundlichen Installationsprogramm verpacken , das Sie möglicherweise ausprobieren möchten: BitNami CloudTools Pack Stack

danoo
quelle
2
Dazu benötigen Sie noch eine andere Instanz. Denn Herunterfahren ist nicht das Problem, sondern das Starten. Crone oder etwas anderes läuft auf einem toten Computer nach dem Herunterfahren nicht mehr.
Upul Doluweera
Ich habe diese Schritte ausgeführt, um AWS CLI Tools auf meiner AMazon Linux-Instanz einzurichten. Das Stoppen der Instanz funktioniert einwandfrei. Das Starten einer bereits gestoppten Instanz führt jedoch zu einem Fehler von 400, die Instanz-ID wurde nicht gefunden. Wie kann ich eine bereits gestoppte Instanz starten?
Amol Chakane
17

Ich empfehle Ihnen, einen Blick auf das EC2-Handbuch Erste Schritte zu werfen , das Ihnen zeigt, wie Sie mit den EC2-Befehlszeilentools das tun, was Sie benötigen. Sie können dies einfach in einen Cron-Job (unter Linux / UNIX) oder einen geplanten Job unter Windows schreiben, um die Start- und Stoppbefehle zu einem bestimmten Zeitpunkt aufzurufen.

Wenn Sie dies aus Ihrem eigenen Code heraus tun möchten, können Sie die SOAP- oder REST-APIs verwenden. Weitere Informationen finden Sie im Entwicklerhandbuch .

gareth_bowles
quelle
15

Ich habe dazu Code in Python unter Verwendung der Boto-Bibliothek geschrieben. Sie können dies für Ihren eigenen Gebrauch anpassen. Stellen Sie sicher, dass Sie dies als Teil eines Cron-Jobs ausführen. Anschließend können Sie so viele Instanzen starten oder herunterfahren, wie Sie während der Ausführung von Cron-Jobs benötigen.

#!/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])
Suman
quelle
1
Ist dies auch für Elastic Beanstalk-Umgebungen möglich?
Amol Chakane
5

Wenn es nicht geschäftskritisch ist - Eine vereinfachende Aufgabe besteht darin, die Batch-Datei so zu planen, dass 'SHUTDOWN' (Windows) jeden Tag um 3 Uhr morgens ausgeführt wird. Dann laufen Sie zumindest nicht Gefahr, versehentlich eine unerwünschte Instanz auf unbestimmte Zeit laufen zu lassen.

Offensichtlich ist dies nur die halbe Wahrheit!

AndyM
quelle
5

In der Firma, für die ich arbeite, haben Kunden regelmäßig danach gefragt. Deshalb haben wir hier eine Freeware-EC2-Planungs-App geschrieben:

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

Es funktioniert unter Windows und Mac, ermöglicht das Erstellen mehrerer Tages-, Wochen- und Monatspläne und das Verwenden von passenden Filtern, um eine große Anzahl von Instanzen einfach einzuschließen, oder solche, die Sie in Zukunft hinzufügen.

Antonym
quelle
2

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

Wenn Sie Tage vom Start ausschließen möchten (z. B. Wochenende), fügen Sie ein ShellCommandPrecondition-Objekt hinzu.

Erstellen Sie in AWS Console / Data Pipeline eine neue Pipeline. Es ist einfacher, eine Definition (JSON) zu bearbeiten / importieren.

    {
"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"
}
}

Legen Sie das herunterzuladende und auszuführende Bash-Skript als Voraussetzung in Ihren S3-Bucket

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

Beim Aktivieren und Ausführen der Pipeline an Wochenendtagen liest der Pipeline-Integritätsstatus der AWS-Konsole einen irreführenden "FEHLER". Das Bash-Skript gibt einen Fehler zurück (Exit 1) und EC2 wird nicht gestartet. An den Tagen 1 bis 5 lautet der Status "GESUND".

Verwenden Sie den täglichen AWS CLI-Befehl ohne Vorbedingung, um EC2 zum Schließen der Bürozeit automatisch zu stoppen.

user3526918
quelle
1

Sie könnten sich Ylastic ansehen, um dies zu tun. Die Alternative scheint darin zu bestehen, dass ein Computer ausgeführt wird, der andere Instanzen mithilfe eines Cron-Jobs oder einer geplanten Aufgabe herunterfährt / startet.

Wenn Sie nur eine Instanz möchten, ist dies natürlich eine teure Lösung, da immer ein Computer ausgeführt werden muss und es nicht kosteneffektiv ist, etwa 80 US-Dollar pro Monat für einen Computer zu zahlen, um Cron-Jobs auszuführen.

Chris S.
quelle
1

AutoScaling ist auf das Beenden von Instanzen beschränkt. Wenn Sie eine Instanz stoppen und den Serverstatus beibehalten möchten, ist ein externes Skript der beste Ansatz.

Sie können dies tun, indem Sie einen Job auf einer anderen Instanz ausführen, die rund um die Uhr ausgeführt wird, oder Sie können einen Drittanbieter-Service wie Ylastic (oben erwähnt) oder Rocket Peak verwenden .

In C # ist der Code zum Stoppen eines Servers beispielsweise recht einfach:

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));
        }
MrGreggs
quelle
1

IMHO ist das Hinzufügen eines Zeitplans zu einer automatischen Skalierungsgruppe der beste "Cloud-ähnliche" Ansatz, wie bereits erwähnt.

Falls Sie Ihre Instanzen jedoch nicht beenden und neue verwenden können, z. B. wenn Sie mit elastischen IPs usw. verknüpft sind.

Sie können ein Ruby-Skript erstellen, um Ihre Instanzen basierend auf einem Datums- und Zeitbereich zu starten und zu stoppen.

#!/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

Schauen Sie sich amazon_start_stop an, um mit Heroku Scheduler kostenlos einen Scheduler zu erstellen .

Pablo Cantero
quelle
1

Obwohl es Möglichkeiten gibt, dies mithilfe der automatischen Skalierung zu erreichen, ist es möglicherweise nicht für alle Fälle geeignet, da die Instanzen beendet werden. Cron-Jobs funktionieren niemals für eine einzelne Instanz (obwohl sie perfekt für Situationen wie das Stoppen einer einzelnen Instanz und das Planen anderer Instanzen beim Ausführen vieler Instanzen verwendet werden können). Sie können API-Aufrufe wie StartInstancesRequest und StopInstancesRequest verwenden , um dasselbe zu erreichen, aber Sie müssen sich erneut auf eine dritte Ressource verlassen. Es gibt viele Anwendungen zum Planen von AWS-Instanzen mit vielen Funktionen, aber für eine einfache Lösung würde ich eine kostenlose App wie snapleaf.io empfehlen

Upul Doluweera
quelle
1

Ja, das können Sie mit AWS Lambda tun. Sie können den Auslöser in Cloudwatch auswählen, der auf Cron-Ausdrücken unter UTC ausgeführt wird.

Hier ist ein verwandter Link https://aws.amazon.com/premiumsupport/knowledge-center/start-stop-lambda-cloudwatch/

Eine andere Alternative besteht darin, zu verwenden, awscliwas von pip, oder verfügbar ist apt-get, und dann mit Ihren aus IAM exportierten Anmeldeinformationen auszuführen und das folgende Bash-Skript auszuführen, um eine EC2 zu stoppen, die mit und gekennzeichnet wurde . Sie können Ihre Instanzen mit Tags versehen oder manuell über die AWS-Konsole markieren. stoppt die Instanz und wird verwendet, um die JSON-Abfrage zu filtern und die richtige Instanz-ID mithilfe der Tags von abzurufen .yumbrewaws configureName: AppnameValue: Appname Prodawscliaws ec2 stop-instancesjqaws ec2 describe-instances

Um zu überprüfen, ob dies aws configureerfolgreich war und json-Ausgabe zurückgibt, aws ec2 describe-instancessollte Ihre laufende Instanz-ID in der Ausgabe vorhanden sein. Hier ist eine Beispielausgabe

{
    "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"
        }
    ]
}

Der folgende Bash - Skript wird stop-ec2.shin /home/centos/cron-scripts/dem von inspiriert diese SO Post

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

Führen Sie die Datei mit aus sh /home/centos/cron-scripts/stop-ec2.shund stellen Sie sicher, dass die EC2-Instanz gestoppt wird. Zum Debuggen führen Sie aus 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 .[].InstanceIdund stellen Sie sicher, dass die korrekte Instanz-ID zurückgegeben wird, die mit Tags versehen wurde.

Dann kann in crontab -eder folgenden Zeile hinzugefügt werden

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

Dadurch wird die Ausgabe protokolliert /tmp/stop. Das 30 14 * * *ist der UTC Cron - Ausdruck , dass Sie einchecken können https://crontab.guru/. Ebenso kann das Ersetzen durch aws ec2 start-instanceseine Instanz starten.

devssh
quelle
0

Ich glaube, dass die anfängliche Frage etwas verwirrend war. Es hängt davon ab, was Pasta benötigt: 1. Starten / Beenden (Instanzspeicher) - Automatische Skalierung ist die richtige Lösung (Nakedibles Antwort) 2. Starten / Stoppen der EBS-Startinstanz - Automatische Skalierung hilft nicht, ich verwende geplante Remote-Skripte (z , ec2 CLI).

lk7777
quelle
-8

Sie können dies nicht automatisch oder zumindest nicht ohne Programmierung und API-Manipulation in Skriptdateien tun. Wenn Sie eine zuverlässige Lösung zum Stoppen, Neustarten und Verwalten Ihrer Bilder suchen (vermutlich um die Kosten in Ihrer Umgebung zu kontrollieren), sollten Sie sich LabSlice ansehen . Haftungsausschluss: Ich arbeite für diese Firma.

Simon bei LabSlice-com
quelle