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


90

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


2
Что происходит с данными вашего инстанса EC2, когда он выключен? Он сохраняется или вам придется его восстанавливать заново?
Мэтью Лок

Автоматический запуск и завершение инстанса с использованием Amazon API может привести к потере данных при этом событии. Я бы рекомендовал действия по остановке и восстановлению с использованием предупреждений AWS CloudWatch
Четабахана

Вместо Amazon API я бы предложил запланировать запуск / остановку EC2 с помощью AWS Lambda , в вашем случае это стоит менее 0,0004 долларов США в месяц.
Chetabahana

Ответы:


102

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

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


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

@KiranK. Означает ли это, что новый экземпляр не подключен к используемому в данный момент тому EBS? что ты использовал?
Соломенная шляпа

26

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

Вы можете сначала протестировать команду вручную, а затем, когда все будет работать нормально, настроить Unix crontab или запланированные задачи в Windows. Вы можете найти приведенный ниже пример для файла Linux / etc / crontab (не забывайте, что все упомянутые выше переменные среды должны присутствовать для пользователя your-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.

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


2
Для этого еще нужен другой экземпляр. Потому что проблема не в выключении, а в запуске. Crone или что-то еще не будет работать на мертвом компьютере после его выключения.
Upul Doluweera

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

17

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

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


16

Для этого я написал код на 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])

1
Возможно ли это и для сред Elastic Beanstalk?
Амол Чакане

5

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

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


5

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

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

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


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 для загрузки и выполнения в качестве предварительного условия в вашей корзине S3

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

При активации и запуске конвейера в выходные дни на консоли AWS Pipeline Health Status отображается вводящая в заблуждение «ERROR». Сценарий bash возвращает ошибку (выход 1), и EC2 не запускается. В дни с 1 по 5 статус «ЗДОРОВЫЙ».

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


1

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

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


1

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

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

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

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

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

Но если вы не можете прекратить работу своих экземпляров и использовать новые, например, если у вас есть эластичные IP-адреса, связанные с и т. Д.

Вы можете создать сценарий Ruby для запуска и остановки ваших экземпляров в зависимости от диапазона дат и времени.

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


1

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


1

Да, это можно сделать с помощью 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 и выполнив следующий Баш скрипт, чтобы остановить 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и ваш идентификатор запущенного экземпляра должен быть в выводе. Вот пример вывода

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

Следующий сценарий Баш находится 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и убедитесь, что он возвращает правильный идентификатор экземпляра, который был помечен.

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

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

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


0

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


-8

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.