Автоматическое выключение и запуск инстанса Amazon EC2

87

Можно ли автоматически запускать и завершать экземпляр Amazon с помощью API Amazon? Не могли бы вы описать, как это можно сделать? Мне в идеале нужно запустить экземпляр и останавливать экземпляр с заданными временными интервалами каждый день.

  • 2
    Что происходит с данными вашего экземпляра EC2, когда он выключен? Это сохраняется или вам нужно восстановить его снова?
  • 0
    Автоматический запуск и остановка экземпляра с помощью Amazon API может привести к потере данных в этом событии. Я бы порекомендовал остановить и восстановить действия, используя сигналы тревоги AWS CloudWatch.
Показать ещё 1 комментарий
Теги:
amazon-web-services
amazon-ec2

14 ответов

100
Лучший ответ

На всякий случай кто-то наткнется на этот старый вопрос, в настоящее время вы можете добиться того же, добавив расписание в группу автоматического масштабирования: увеличьте количество экземпляров в группе автоматического масштабирования до 1 в определенное время и уменьшите ее до 0 после.

И так как этот ответ получает много просмотров, я думал связать с очень полезным руководством об этом: Запуск экземпляров EC2 в повторяющемся расписании с автоматическим масштабированием

  • 3
    Лучший новичок здесь.
  • 6
    Я попробовал метод, описанный в ссылке, и он действительно запускает / останавливает экземпляры в моменты времени, указанные в руководстве. Однако в веб-консоли AWS я заметил, что, когда экземпляр запускается этим методом, он не запускается с ключом (таким, что вы можете использовать в нем ssh), и, похоже, он не имеет того же материала, что и я. установлен на моем микроэкземпляре, который я использую в качестве теста (я не эксперт по облачным вычислениям, но я думаю, это означает, что этот новый запущенный экземпляр не подключен к EBS?) Есть ли способ автоматического запуска и остановить тот же экземпляр по расписанию?
Показать ещё 1 комментарий
27

Вы можете напрямую использовать инструменты API Amazon EC2. Есть вам нужны только две команды: ec2-start-экземпляры и ec2-stop-экземпляры. Убедитесь, что переменные среды, такие как EC2_HOME, AWS_CREDENTIAL_FILE, EC2_CERT, EC2_PRIVATE_KEY и т.д. настроенные и все учетные данные AWS, файлы сертификатов и закрытых ключей находятся в правильном месте - вы можете найти дополнительную информацию в API AWS EC2 документации по инструментам.

Сначала вы можете проверить команду вручную, а затем, когда все будет хорошо, настроить Unix crontab или запланированные задачи в Windows. Вы можете найти пример ниже для файла Linux/etc/crontab (не забывайте, что все эти упомянутые выше переменные среды должны присутствовать пользователь вашей учетной записи.

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

Я разработчик проекта BitNami Cloud, где мы упаковываем Инструменты AWS (включая те, о которых я упоминал) в бесплатной, простой в использовании который вы можете попробовать: BitNami CloudTools pack стек

  • 2
    Для этого еще нужно иметь другой экземпляр. Потому что закрытие не проблема, а запуск. Crone или что-либо еще не будет работать на мертвом компьютере после его выключения.
  • 0
    Я выполнил следующие действия, чтобы настроить AWS CLI Tools на моем экземпляре AMazon Linux. Остановка экземпляра работает нормально. Но запуск уже остановленного экземпляра выдает ошибку 400, идентификатор экземпляра не найден. Как я могу запустить уже остановленный экземпляр?
17

Я рекомендую вам взглянуть на Руководство по началу работы с EC2, в котором показано, как делать то, что вам нужно, используя инструменты командной строки EC2, Вы можете легко script выполнить это задание cron (в Linux/UNIX) или запланированное задание в Windows, чтобы вызвать команды запуска и остановки в заданное время.

Если вы хотите сделать это из своего собственного кода, вы можете использовать API SOAP или REST; Подробнее см. Руководство разработчика.

15

Я написал код на Python, используя библиотеку Boto, чтобы сделать это. Вы можете настроить это для собственного использования. Обязательно запустите это как часть задания cron, а затем вы сможете запустить или отключить столько случаев, сколько вам нужно во время выполнения заданий 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])
  • 0
    Возможно ли это и для среды Elastic Beanstalk?
5

В компании, в которой я работаю, клиенты регулярно спрашивали об этом, поэтому мы написали бесплатное приложение для планирования EC2, доступное здесь:

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

Он работает на Windows и Mac, позволяет создавать несколько ежедневных/еженедельных/ежемесячных расписаний и позволяет использовать соответствующие фильтры для включения большого количества экземпляров легко или включает в себя те, которые вы добавляете в будущем.

3

Если это не критически важно - проще всего планировать командный файл для запуска "SHUTDOWN" (окна) в 3 часа ночи каждый день. Тогда, по крайней мере, вы не рискуете случайно покинуть нежелательный экземпляр, работающий на неопределенный срок.

Очевидно, что это только половина истории!

2

AWS Data Pipeline работает нормально. https://aws.amazon.com/premiumsupport/knowledge-center/stop-start-ec2-instances/

Если вы хотите исключить дни с начала (например, выходные), добавьте объект ShellCommandPrecondition.

В AWS Console/Data Pipeline создайте новый конвейер. Легче редактировать/импортировать определение (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"
}
}

Поместите Bash script, чтобы загрузить и выполнить как предварительное условие в вашем ведре S3

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

При активации и запуске конвейера в выходные дни, состояние здоровья трубопровода AWS сообщает об ошибке "ОШИБКА". Bash script возвращает ошибку (выход 1), а EC2 не запускается. В дни с 1 по 5 статус "ЗДОРОВЫЙ".

Чтобы остановить EC2 автоматически при закрытии офисного времени, ежедневно используйте команду AWS CLI с предварительным условием.

1

Несмотря на то, что есть способы достичь этого с помощью автоматического масштабирования, он может не подходить для всех случаев, поскольку он завершает экземпляры. Задачи Cron никогда не будут работать для одного экземпляра (хотя он отлично может использоваться для ситуаций, таких как остановка одного экземпляра и планирование других экземпляров при запуске многих экземпляров). Вы можете использовать вызовы API, такие как StartInstancesRequest, и StopInstancesRequest для достижения того же, но снова вам нужно полагаться на третий ресурс. Существует множество приложений для планирования экземпляров AWS со многими функциями, но для простого решения я бы рекомендовал бесплатное приложение, например snapleaf.io

1

ИМХО Добавление расписания в группу автоматического масштабирования - лучший подход к "облачным", как упоминалось ранее.

Но в случае, если вы не можете прервать свои экземпляры и использовать новые, например, если у вас есть Elastic IPs, связанные с ним.

Вы можете создать Ruby script, чтобы запустить и остановить свои экземпляры на основе диапазона дат.

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

Посмотрите amazon_start_stop, чтобы бесплатно создать планировщик, используя Планировщик Heroku.

1

AutoScaling ограничивается завершающими экземплярами. Если вы хотите остановить экземпляр и сохранить состояние сервера, лучшим вариантом будет внешний script.

Вы можете сделать это, запустив задание в другом экземпляре, который работает 24/7, или вы можете использовать стороннюю службу, такую ​​как Ylastic (упомянутый выше) или Ракетный пик.

Например, в С# код для остановки сервера довольно прост:

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

Вы можете посмотреть Ylastic для этого. Кажется, что у альтернативы есть одна машина, которая выключает/запускает другие экземпляры, используя задание cron или запланированную задачу.

Очевидно, что если вам нужен только один экземпляр, это дорогостоящее решение, так как одна машина всегда должна работать, а оплата ~ 80 долларов в месяц для одной машины для запуска заданий cron не является экономически эффективной.

0

Да, вы можете сделать это с помощью AWS Lambda. Вы можете выбрать триггер в Cloudwatch, который запускается в выражениях Cron в UTC.

Вот связанная ссылка https://aws.amazon.com/premiumsupport/knowledge-center/start-stop-lambda-cloudwatch/

Другой альтернативой является использование awscli доступного из pip, apt-get, yum или brew, а затем запуск aws configure с вашими учетными данными, экспортированными из IAM, и выполнение следующего скрипта bash, чтобы остановить EC2, помеченный с помощью Name: Appname и Value: Appname Prod. Вы можете использовать awscli чтобы пометить свои экземпляры или пометить их вручную с консоли AWS. aws ec2 stop-instances остановит экземпляр, а jq используется для фильтрации запроса json и получения правильного идентификатора экземпляра с использованием тегов из aws ec2 describe-instances.

Чтобы убедиться, что aws configure была успешной и возвращает вывод json, запустите aws ec2 describe-instances и в выводе должен быть aws ec2 describe-instances идентификатор вашего работающего экземпляра. Вот пример вывода

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

Следующий скрипт bash - это stop-ec2.sh в /home/centos/cron-scripts/ вдохновленный этим постом 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} )

Запустите файл, используя sh/home/centos/cron-scripts/stop-ec2.sh и убедитесь, что экземпляр EC2 остановлен. Для отладки запустите 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 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 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 и убедитесь, что он возвращает правильный идентификатор экземпляра, который был помечен.

Затем в crontab -e можно добавить следующую строку

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

который будет записывать вывод в /tmp/stop. 30 14 * * * - это выражение cron UTC, которое вы можете проверить в https://crontab.guru/. Аналогично замена на aws ec2 start-instances может запустить экземпляр.

0

Я считаю, что первоначальный вопрос был немного запутанным. Это зависит от того, что нужно макаронам: 1.launch/terminate (хранилище экземпляров) - автоматическое масштабирование - правильное решение (Nakedible answer) 2.start/stop EBS boot instance - автоматическое масштабирование не поможет, я использую удаленные запланированные сценарии (например, ec2 CLI).

-9

Вы не можете делать это автоматически или, по крайней мере, не без программирования и манипулирования API в файлах script. Если вы хотите найти надежное решение для остановки, перезагрузки и управления вашими изображениями (предположительно для контроля затрат в вашей среде), вы можете посмотреть LabSlice. Отказ от ответственности: я работаю в этой компании.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню