it-swarm.com.ru

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

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

88
Pasta

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

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

100
Nakedible

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

Сначала вы можете проверить команду вручную, а затем, когда все будет работать, Настроить 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 stack

26
danoo

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

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

17
gareth_bowles

Я написал код на 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])
15
Suman

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

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

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

5
AntonyM

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

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

3
AndyM

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

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

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

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

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

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

2
user3526918

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

Вы можете сделать это, запустив задание в другом экземпляре, который работает 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
MrGreggs

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

Но если вы не можете закрыть свои экземпляры и использовать новые, например, если у вас есть Elastic 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
Pablo Cantero

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

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

Затем в 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 может запустить экземпляр.

1
devssh

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

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

1
Chris S

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

1
Upul Doluweera

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

0
lk7777