Автоматическое отключение и запуск инстанса Amazon EC2 - PullRequest
88 голосов
/ 10 марта 2010

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

Ответы [ 14 ]

100 голосов
/ 27 марта 2012

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

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

26 голосов
/ 05 августа 2011

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

/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 стек

17 голосов
/ 10 марта 2010

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

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

15 голосов
/ 11 августа 2012

Я написал код на 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])
5 голосов
/ 23 марта 2012

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

http://blog.simple -help.com / 2012/03 / свободный ec2-планировщик /

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

4 голосов
/ 01 августа 2011

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

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

2 голосов
/ 29 октября 2015

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

#!/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 без предварительных условий.

1 голос
/ 11 декабря 2018

Да, вы можете сделать это с помощью 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 голос
/ 19 марта 2014

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

1 голос
/ 04 января 2014

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...