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


90

Чи можу я автоматично запускати та припиняти свій екземпляр Amazon за допомогою API Amazon? Чи можете ви описати, як це можна зробити? Мені в ідеалі потрібно запускати екземпляр і зупиняти екземпляр через визначені інтервали часу щодня.


2
Що відбувається з даними вашого екземпляра EC2, коли його вимкнено? Це зберігається чи вам доведеться його перебудовувати заново?
Matthew Lock

Автоматичний запуск і завершення екземпляра за допомогою API Amazon може спричинити втрату даних у цій події. Я б порекомендував зупинити та відновити дії за допомогою AWS CloudWatch Alarms
Chetabahana

Замість Amazon API, я б запропонував запланувати EC2 Start / Stop з використанням AWS Lambda , у вашому випадку це коштує вам менше $ 0,0004 USD / місяць.
Четабахана,

Відповіді:


102

Про всяк випадок, якщо хтось натрапить на це старе питання, сьогодні ви можете досягти того самого, додавши розклад до групи автоматичного масштабування: збільште кількість випадків у групі автоматичного масштабування до 1 у певний час і зменшіть її назад до 0 згодом .

І оскільки ця відповідь отримує багато переглядів, я подумав зробити посилання на дуже корисний посібник з цього приводу: Запуск екземплярів EC2 за періодичним розкладом з автоматичним масштабуванням


6
Я спробував метод, описаний у посиланні, і він дійсно запускає / зупиняє екземпляри в той час, як зазначено в навчальному посібнику. Однак я помітив у веб-консолі AWS, що коли екземпляр запускається цим методом, він не запускається з ключем (таким, що ви можете в нього ssh), і, схоже, у нього немає того самого, що я встановлений на моєму мікро-екземплярі, який я використовую в якості тесту (я не експерт у хмарі, але, думаю, це означає, що цей новий екземпляр, який закручений, не підключений до EBS?) Чи є спосіб для автоматичного запуску та зупинити той самий екземпляр за графіком?
Кіран К.

@KiranK. чи означає це, що новий екземпляр не приєднаний до обсягу EBS, що використовується зараз? чим ти користувався?
Солом'яний капелюх

26

Ви можете спробувати скористатися інструментами Amazon EC2 API безпосередньо. Насправді вам потрібні лише дві команди: ec2-start-instances та ec2-stop-instances. Переконайтесь, що змінні середовища, такі як 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


2
Для цього все-таки потрібно мати інший екземпляр. Тому що вимкнення - це не проблема, а запуск. Crone або щось інше не буде працювати в мертвому комп'ютері після його вимкнення.
Упул Долувеера,

Я виконав ці кроки, щоб налаштувати AWS CLI Tools на своєму екземплярі AMazon Linux. Зупинка екземпляра працює нормально. Але запуск уже зупиненого екземпляра видає 400 помилок, екземпляра Id не знайдено. Як запустити вже зупинений екземпляр?
Amol Chakane

17

Я рекомендую вам поглянути на Посібник із початку роботи EC2 , де показано, як зробити те, що потрібно, за допомогою інструментів командного рядка EC2. Ви можете легко скриптувати це у завдання 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])

1
Чи можливо це також для середовищ Elastic Beanstalk?
Амол Чакане

5

Якщо це не критично важливо - спростити, що потрібно зробити, це запланувати пакетний файл для запуску "ВИМКНЕННЯ" (windows) о 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-instance/

Якщо ви хочете виключити дні з початку (наприклад, вихідні), додайте об'єкт 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 Status відображається оманливе повідомлення "ПОМИЛКА". Скрипт bash повертає помилку (вихід 1) і EC2 не запускається. З 1 по 5 день статус "ЗДОРОВИЙ".

Щоб автоматично зупинити EC2 під час закриття офісу, використовуйте команду AWS CLI щодня без попередньої умови.


1

Ви можете подивитися на Ylastic, щоб зробити це. Здається, альтернативою є одна запущена машина, яка вимикає / запускає інші екземпляри за допомогою завдання cron або запланованого завдання.

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


1

Автомасштабування обмежується завершенням екземплярів. Якщо ви хочете зупинити екземпляр і зберегти стан сервера, найкращим підходом є зовнішній сценарій.

Ви можете зробити це, запустивши завдання в іншому екземплярі, який працює цілодобово та без вихідних, або скористатися сторонньою службою, такою як 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

Додавання розкладу до групи автоматичного масштабування IMHO - найкращий підхід, схожий на хмару, як згадувалося раніше.

Але на випадок, якщо ви не можете завершити роботу своїх екземплярів і використовувати нові, наприклад, якщо у вас є еластичні 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, такі як StartInsngthRequest та StopInsngthRequest, щоб досягти того ж, але знову ж таки вам доведеться покладатися на третій ресурс. Є багато програм для планування екземплярів 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 , що ви можете перевірити https://crontab.guru/. Подібним чином заміна на aws ec2 start-instancesможе запустити екземпляр.


0

Я вважаю, що початкове запитання було трохи заплутаним. Це залежить від того, що потрібно макаронам: 1.запуск / завершення (зберігання екземплярів) - автоматичне масштабування є правильним рішенням (відповідь Nakedible) 2.запуск / зупинка екземпляра завантаження EBS - автоматичне масштабування не допоможе, я використовую віддалені заплановані сценарії (тобто , ec2 CLI).


-8

Ви не можете зробити це автоматично або, принаймні, без певного програмування та маніпулювання API у файлах сценаріїв. Якщо ви хочете отримати надійне рішення, щоб зупинити, перезапустити та керувати своїми зображеннями (імовірно, щоб контролювати витрати у вашому середовищі), тоді ви можете переглянути LabSlice . Застереження: я працюю в цій компанії.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.