Automatyczne wyłączanie i uruchamianie instancji Amazon EC2

90

Czy mogę automatycznie uruchamiać i zamykać moją instancję Amazon za pomocą Amazon API? Czy możesz opisać, jak można to zrobić? Najlepiej byłoby uruchamiać instancję i zatrzymywać ją w określonych odstępach czasu każdego dnia.

Makaron
źródło
2
Co dzieje się z danymi Twojej instancji EC2, gdy jest ona wyłączona? Czy utrzymuje się, czy musisz go ponownie odbudować?
Matthew Lock
Automatyczne uruchamianie i zamykanie instancji za pomocą Amazon API może spowodować utratę danych w tym zdarzeniu. Poleciłbym
Chetabahana
Zamiast Amazon API sugerowałbym zaplanowanie EC2 Start / Stop przy użyciu AWS Lambda , w twoim przypadku kosztuje to mniej niż 0,0004 USD / miesiąc.
Chetabahana

Odpowiedzi:

102

Na wypadek, gdyby ktoś natknął się na to stare pytanie, obecnie możesz osiągnąć to samo, dodając harmonogram do grupy z automatycznym skalowaniem: zwiększ liczbę wystąpień w grupie z automatycznym skalowaniem do 1 w określonych momentach, a potem zmniejsz ją z powrotem do 0 .

Ponieważ ta odpowiedź ma wiele wyświetleń, pomyślałem, że zamieściłem link do bardzo pomocnego przewodnika na ten temat: Uruchamianie instancji EC2 w cyklicznym harmonogramie z automatycznym skalowaniem

Naga
źródło
6
Wypróbowałem metodę opisaną w linku i rzeczywiście uruchamia / zatrzymuje instancje w czasie określonym w samouczku. Jednak zauważyłem w konsoli internetowej AWS, że gdy instancja jest uruchamiana tą metodą, nie uruchamia się z kluczem (takim, że można do niej ssh), a także nie wydaje się mieć tych samych rzeczy, które ja zainstalowany na mojej mikro-instancji, której używam jako testu (nie jestem ekspertem w chmurze, ale myślę, że oznacza to, że ta nowa uruchomiona instancja nie jest podłączona do EBS?) Czy istnieje sposób na automatyczne uruchomienie i zatrzymać to samo wystąpienie w harmonogramie?
Kiran K.
@KiranK. czy to oznacza, że ​​nowa instancja nie jest dołączona do aktualnie używanego woluminu EBS? czego użyłeś?
Słomkowy kapelusz,
26

Możesz spróbować bezpośrednio skorzystać z narzędzi API Amazon EC2. Potrzebujesz tylko dwóch poleceń: ec2-start-instances i ec2-stop-instances. Upewnij się, że zmienne środowiskowe, takie jak EC2_HOME, AWS_CREDENTIAL_FILE, EC2_CERT, EC2_PRIVATE_KEY, itp. Są odpowiednio skonfigurowane, a wszystkie poświadczenia AWS, pliki certyfikatów i kluczy prywatnych znajdują się we właściwej lokalizacji - więcej informacji znajdziesz w dokumentacji narzędzi AWS EC2 API.

Możesz najpierw przetestować polecenie ręcznie, a gdy wszystko działa dobrze, skonfigurować Unix crontab lub Scheduled Tasks w systemie Windows. Możesz znaleźć poniższy przykład dla pliku Linux / etc / crontab (nie zapominaj, że wszystkie wymienione powyżej zmienne środowiskowe muszą być obecne dla użytkownika „twoje konto”.

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

Jestem programistą projektu BitNami Cloud, w którym pakujemy narzędzia AWS (w tym te, o których wspomniałem) w darmowym, łatwym w użyciu instalatorze, który możesz wypróbować: stos pakietów BitNami CloudTools

danoo
źródło
2
W tym celu nadal potrzebujesz innej instancji. Ponieważ zamknięcie nie jest problemem, ale uruchomieniem. Crone ani nic nie będzie działać na martwym komputerze po jego zamknięciu.
Upul Doluweera
Śledziłem kroki Aby skonfigurować AWS CLI narzędzi na moim Amazon Linux Instancji. Zatrzymanie instancji działa poprawnie. Ale uruchomienie już zatrzymanej instancji powoduje błąd 400, nie znaleziono identyfikatora instancji. Jak mogę uruchomić już zatrzymaną instancję?
Amol Chakane
17

Zalecam zapoznanie się z Przewodnikiem Pierwsze kroki EC2 , który pokazuje, jak zrobić to, czego potrzebujesz, używając narzędzi wiersza poleceń EC2. Możesz łatwo zapisać to w zadaniu cron (w systemie Linux / UNIX) lub zaplanowanym zadaniu w systemie Windows, aby wywołać polecenia uruchamiania i zatrzymywania w określonym czasie.

Jeśli chcesz to zrobić z własnego kodu, możesz użyć API SOAP lub REST; szczegółowe informacje można znaleźć w Podręczniku programisty .

gareth_bowles
źródło
16

Aby to zrobić, napisałem kod w Pythonie, korzystając z biblioteki Boto. Możesz to dostosować do własnego użytku. Upewnij się, że uruchamiasz to jako część zadania cron, a wtedy będziesz mógł uruchomić lub zamknąć tyle instancji, ile potrzebujesz podczas wykonywania zadań cron.

#!/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
źródło
1
Czy jest to możliwe również w przypadku środowisk Elastic Beanstalk?
Amol Chakane
5

Jeśli nie jest to krytyczne dla misji - prostą rzeczą jest zaplanowanie uruchamiania pliku wsadowego „SHUTDOWN” (Windows) o 3 nad ranem każdego dnia. Wtedy przynajmniej nie ryzykujesz przypadkowego pozostawienia niechcianej instancji działającej w nieskończoność.

Oczywiście to tylko połowa historii!

AndyM
źródło
5

Firma, dla której pracuję, miała klientów regularnie pytających o to, dlatego napisaliśmy bezpłatną aplikację do planowania EC2 dostępną tutaj:

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

Działa w systemach Windows i Mac, umożliwia tworzenie wielu dziennych / tygodniowych / miesięcznych harmonogramów i pozwala używać pasujących filtrów w celu łatwego dołączania dużej liczby instancji lub zawiera te, które dodasz w przyszłości.

Antonim
źródło
2

Potok danych AWS działa dobrze. https://aws.amazon.com/premiumsupport/knowledge-center/stop-start-ec2-instances/

Jeśli chcesz wykluczyć dni od rozpoczęcia (np. Weekend), dodaj obiekt ShellCommandPrecondition.

W konsoli AWS / potoku danych utwórz nowy potok. Łatwiej jest edytować / importować definicję (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"
}
}

Umieść skrypt Bash do pobrania i wykonania jako warunek wstępny w swoim segmencie S3

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

Podczas aktywacji i uruchamiania potoku w dni weekendowe stan kondycji rurociągu konsoli AWS wyświetla wprowadzający w błąd „BŁĄD”. Skrypt bash zwraca błąd (wyjście 1), a EC2 nie jest uruchamiany. W dniach od 1 do 5 stan jest „ZDROWY”.

Aby automatycznie zatrzymać EC2 po zamknięciu biura, używaj komendy AWS CLI codziennie bez warunku wstępnego.

user3526918
źródło
1

Aby to zrobić, możesz spojrzeć na Ylastic . Wydaje się, że alternatywą jest uruchomienie jednej maszyny, która zamyka / uruchamia inne wystąpienia przy użyciu zadania cron lub zaplanowanego zadania.

Oczywiście, jeśli potrzebujesz tylko jednej instancji, jest to drogie rozwiązanie, ponieważ jedna maszyna musi zawsze działać, a płacenie ~ 80 USD miesięcznie za jedną maszynę do wykonywania zadań cron nie jest opłacalne.

Chris S.
źródło
1

Automatyczne skalowanie jest ograniczone do przerywania wystąpień. Jeśli chcesz zatrzymać instancję i zachować stan serwera, najlepszym rozwiązaniem jest zewnętrzny skrypt.

Możesz to zrobić, uruchamiając zadanie w innej instancji, która działa 24 godziny na dobę, 7 dni w tygodniu lub możesz skorzystać z usługi innej firmy, takiej jak Ylastic (wspomniana powyżej) lub Rocket Peak .

Na przykład w C # kod zatrzymujący serwer jest całkiem prosty:

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
źródło
1

IMHO dodawanie harmonogramu do grupy z automatycznym skalowaniem jest najlepszym podejściem podobnym do chmury, jak wspomniano wcześniej.

Ale jeśli nie możesz zamknąć swoich instancji i użyć nowych, na przykład jeśli masz powiązane elastyczne adresy IP itp.

Możesz utworzyć skrypt Ruby, aby uruchamiać i zatrzymywać instancje na podstawie zakresu dat i godzin.

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

Zajrzyj na amazon_start_stop, aby za darmo utworzyć harmonogram za pomocą Heroku Scheduler .

Pablo Cantero
źródło
1

Mimo że istnieją sposoby na osiągnięcie tego za pomocą automatycznego skalowania, może to nie być odpowiednie we wszystkich przypadkach, ponieważ powoduje zakończenie instancji. Zadania Cron nigdy nie będą działać dla pojedynczej instancji (chociaż można go doskonale wykorzystać w sytuacjach takich jak zatrzymanie pojedynczej instancji i planowanie innych instancji podczas uruchamiania wielu instancji). Możesz użyć wywołań interfejsu API, takich jak StartInstancesRequest i StopInstancesRequest, aby osiągnąć to samo, ale ponownie musisz polegać na trzecim zasobie. Istnieje wiele aplikacji do planowania wystąpień AWS z wieloma funkcjami, ale dla prostego rozwiązania polecam bezpłatną aplikację, taką jak snapleaf.io

Upul Doluweera
źródło
1

Tak, możesz to zrobić za pomocą AWS Lambda. Możesz wybrać wyzwalacz w Cloudwatch, który działa na wyrażeniach Cron w UTC.

Oto powiązany link https://aws.amazon.com/premiumsupport/knowledge-center/start-stop-lambda-cloudwatch/

Inną alternatywą jest do użytku awscli, który jest dostępny z pip, apt-get, yumlub brew, a następnie działa aws configurez poświadczeniami eksportowanych z IAM i wykonując następujący skrypt bash, aby zatrzymać EC2 który został oznaczony z Name: Appnamei Value: Appname Prod. Możesz użyć awsclido otagowania swoich instancji lub otagowania ich ręcznie z konsoli AWS. aws ec2 stop-instanceszatrzyma instancję i jqjest używany do filtrowania zapytania json i pobierania prawidłowego identyfikatora instancji przy użyciu tagów z aws ec2 describe-instances.

Aby sprawdzić, czy się aws configurepowiodło i zwraca wynik json, uruchom, aws ec2 describe-instancesa identyfikator działającej instancji powinien znajdować się w danych wyjściowych. Oto przykładowe dane wyjściowe

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

Poniższy skrypt bash stop-ec2.shw /home/centos/cron-scripts/którym jest inspirowana z tym SO postu

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

Uruchom plik za pomocą sh /home/centos/cron-scripts/stop-ec2.shi sprawdź, czy instancja EC2 została zatrzymana. Aby debugować, uruchom 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 .[].InstanceIdi sprawdź, czy zwraca poprawny identyfikator instancji, który został oznaczony.

Następnie crontab -emożna dodać następujący wiersz

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

który będzie rejestrował dane wyjściowe /tmp/stop. To 30 14 * * *jest wyrażenie cron UTC, które możesz sprawdzić https://crontab.guru/. Podobnie zamiana na aws ec2 start-instancesmoże rozpocząć instancję.

devssh
źródło
0

Uważam, że pierwsze pytanie było trochę zagmatwane. Zależy to od tego, czego potrzebuje Pasta: 1. uruchom / zakończ (magazyn instancji) - Automatyczne skalowanie to właściwe rozwiązanie (odpowiedź Nakedible) 2. uruchom / zatrzymaj instancję rozruchową EBS - automatyczne skalowanie nie pomoże, używam zdalnych zaplanowanych skryptów (tj. , ec2 CLI).

lk7777
źródło
-8

Nie możesz tego zrobić automatycznie, a przynajmniej nie bez programowania i manipulacji API w plikach skryptów. Jeśli chcesz mieć niezawodne rozwiązanie do zatrzymywania, ponownego uruchamiania i zarządzania obrazami (prawdopodobnie w celu kontrolowania kosztów w Twoim środowisku), możesz spojrzeć na LabSlice . Zastrzeżenie: pracuję dla tej firmy.

Simon w LabSlice-com
źródło