Tự động tắt máy và khởi động phiên bản Amazon EC2


90

Tôi có thể tự động bắt đầu và kết thúc phiên bản Amazon của mình bằng API Amazon không? Bạn có thể vui lòng mô tả làm thế nào điều này có thể được thực hiện? Lý tưởng nhất là tôi cần bắt đầu phiên bản và dừng phiên bản vào những khoảng thời gian được chỉ định mỗi ngày.


2
Điều gì xảy ra với dữ liệu của phiên bản EC2 của bạn khi nó bị tắt? Nó có tồn tại hay bạn phải xây dựng lại nó một lần nữa?
Matthew Lock

Tự động bắt đầu và kết thúc phiên bản bằng Amazon API có thể gây ra mất mát dữ liệu về sự kiện đó. Tôi khuyên bạn nên dừng và khôi phục các hành động bằng AWS CloudWatch Alarms
Chetabahana

Thay vì Amazon API, tôi khuyên bạn nên Lập lịch Khởi động / Ngừng EC2 bằng AWS Lambda , trong trường hợp của bạn, bạn phải trả ít hơn $ 0,0004 USD / tháng.
Chetabahana

Câu trả lời:


102

Đề phòng trường hợp ai đó vấp phải câu hỏi cũ này của bạn, ngày nay bạn có thể đạt được điều tương tự bằng cách thêm lịch trình vào nhóm chia tỷ lệ tự động: tăng số lượng phiên bản trong nhóm chia tỷ lệ tự động lên 1 tại một số thời điểm nhất định và giảm về 0 sau đó .

Và vì câu trả lời này đang nhận được rất nhiều lượt xem, tôi nghĩ liên kết đến một hướng dẫn rất hữu ích về điều này: Chạy Phiên bản EC2 theo lịch trình định kỳ với Tự động mở rộng quy mô


6
Tôi đã thử phương pháp được mô tả trong liên kết và nó thực sự bắt đầu / dừng các phiên bản vào những thời điểm được chỉ định bởi hướng dẫn. Tuy nhiên, tôi nhận thấy trong bảng điều khiển web AWS rằng khi một phiên bản được khởi động bằng phương pháp này, nó không bắt đầu bằng một khóa (để bạn có thể ssh vào đó) và dường như nó cũng không có cùng thứ mà tôi được cài đặt trên phiên bản vi mô của tôi mà tôi sử dụng làm thử nghiệm (Tôi không phải là chuyên gia về đám mây, nhưng tôi nghĩ điều này có nghĩa là phiên bản mới này được tạo ra không được kết nối với EBS?) Có cách nào để tự động khởi động và dừng cùng một phiên bản trên một lịch trình thời gian?
Kiran K.

@KiranK. điều đó có nghĩa là phiên bản mới đó không được đính kèm với ổ đĩa EBS hiện đang được sử dụng? bạn đã dùng gì
Mũ Rơm

26

Bạn có thể thử sử dụng trực tiếp các công cụ API Amazon EC2. Thực sự chỉ có hai lệnh bạn cần: ec2-start-instance và ec2-stop-instance. Đảm bảo rằng các biến môi trường như EC2_HOME, AWS_CREDENTIAL_FILE, EC2_CERT, EC2_PRIVATE_KEY, v.v. được định cấu hình đúng cách và tất cả thông tin đăng nhập AWS, chứng chỉ và tệp khóa cá nhân đều ở vị trí thích hợp - bạn có thể tìm thêm thông tin trong tài liệu công cụ AWS EC2 API.

Bạn có thể kiểm tra lệnh bằng tay trước và sau đó, khi mọi thứ hoạt động tốt, hãy định cấu hình Unix crontab hoặc Tác vụ đã lên lịch trên Windows. Bạn có thể tìm thấy ví dụ bên dưới cho tệp Linux / etc / crontab (đừng quên rằng tất cả các biến môi trường được đề cập ở trên cần phải có cho người dùng 'tài khoản của bạn'.

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

Tôi là nhà phát triển cho dự án BitNami Cloud, nơi chúng tôi đóng gói các công cụ AWS (bao gồm cả những công cụ tôi đã đề cập) trong một trình cài đặt miễn phí, dễ sử dụng mà bạn có thể muốn thử: BitNami CloudTools pack stack


2
Đối với điều này, bạn cần phải có một trường hợp khác. Bởi vì tắt không phải là vấn đề mà là khởi động. Crone hoặc bất cứ thứ gì sẽ không chạy trong một máy tính đã chết sau khi nó đã được tắt.
Upul Doluweera,

Tôi đã làm theo các bước sau để thiết lập Công cụ AWS CLI trên Phiên bản Linux AMazon của mình. Phiên bản dừng hoạt động tốt. Nhưng việc bắt đầu một phiên bản đã dừng lại gây ra lỗi 400, không tìm thấy Id phiên bản. Làm cách nào để bắt đầu phiên bản đã dừng?
Amol Chakane

17

Tôi khuyên bạn nên xem Hướng dẫn Bắt đầu EC2 , hướng dẫn này chỉ cho bạn cách thực hiện những gì bạn cần bằng cách sử dụng các công cụ dòng lệnh EC2. Bạn có thể dễ dàng viết kịch bản này thành công việc cron (trên Linux / UNIX) hoặc công việc đã lên lịch trên Windows để gọi lệnh bắt đầu và dừng tại một thời điểm nhất định.

Nếu bạn muốn làm điều này từ mã của riêng mình, bạn có thể sử dụng API SOAP hoặc REST; xem Hướng dẫn dành cho nhà phát triển để biết chi tiết.


15

Tôi đã viết mã bằng Python, sử dụng thư viện Boto, để thực hiện việc này. Bạn có thể điều chỉnh điều này để sử dụng của riêng bạn. Đảm bảo chạy điều này như một phần của công việc cron, và sau đó bạn sẽ có thể khởi động hoặc tắt bao nhiêu phiên bản bạn cần trong quá trình chạy công việc 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
Điều này có khả thi cho môi trường Elastic Beanstalk không?
Amol Chakane

5

Nếu đó không phải là nhiệm vụ quan trọng - Một việc đơn giản cần làm là lên lịch cho tệp hàng loạt chạy 'SHUTDOWN' (cửa sổ) lúc 3 giờ sáng hàng ngày. Sau đó, ít nhất bạn không gặp rủi ro vô tình để một phiên bản không mong muốn chạy vô thời hạn.

Rõ ràng đây chỉ là một nửa câu chuyện!


5

Công ty tôi làm việc có khách hàng thường xuyên hỏi về điều này, vì vậy chúng tôi đã viết một ứng dụng lập lịch EC2 miễn phí có sẵn tại đây:

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

Nó hoạt động trên Windows và Mac, cho phép bạn tạo nhiều lịch biểu hàng ngày / hàng tuần / hàng tháng và cho phép bạn sử dụng các bộ lọc phù hợp để bao gồm số lượng lớn các phiên bản một cách dễ dàng hoặc bao gồm những phiên bản mà bạn thêm vào trong tương lai.


2

Đường ống dữ liệu AWS đang hoạt động tốt. https://aws.amazon.com/premiumsupport/knowledge-center/stop-start-ec2-instances/

Nếu bạn muốn loại trừ ngày bắt đầu (ví dụ: cuối tuần), hãy thêm một đối tượng ShellCommandPrecondition.

Trong Bảng điều khiển AWS / Đường ống dữ liệu, hãy tạo một đường dẫn mới. Việc chỉnh sửa / nhập định nghĩa (JSON) dễ dàng hơn

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

Đặt tập lệnh Bash được tải xuống và thực thi như điều kiện tiên quyết trong nhóm S3 của bạn

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

Khi kích hoạt và chạy đường ống vào các ngày cuối tuần, Trạng thái sức khỏe đường ống của bảng điều khiển AWS đọc "ERROR" gây hiểu lầm. Tập lệnh bash trả về lỗi (thoát 1) và EC2 không được khởi động. Vào ngày 1 đến ngày 5, trạng thái là "KHỎE MẠNH".

Để tự động dừng EC2 vào giờ đóng cửa văn phòng, hãy sử dụng lệnh AWS CLI điều kiện tiên quyết hàng ngày.


1

Bạn có thể nhìn vào Ylastic để làm điều này. Giải pháp thay thế dường như có một máy đang chạy tắt / khởi động các trường hợp khác bằng cách sử dụng công việc cron hoặc tác vụ đã lên lịch.

Rõ ràng nếu bạn chỉ muốn một phiên bản thì đây là một giải pháp đắt tiền, vì một máy phải luôn chạy và việc trả ~ 80 đô la một tháng cho một máy để chạy các công việc cron là không hiệu quả.


1

AutoScaling được giới hạn cho các phiên bản kết thúc. Nếu bạn muốn dừng một phiên bản và giữ lại trạng thái máy chủ thì một tập lệnh bên ngoài là cách tốt nhất.

Bạn có thể thực hiện việc này bằng cách chạy một công việc trên một phiên bản khác đang chạy 24/7 hoặc bạn có thể sử dụng dịch vụ của bên thứ 3 như Ylastic (đã đề cập ở trên) hoặc Rocket Peak .

Ví dụ trong C #, mã dừng máy chủ khá đơn giản:

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 thêm lịch biểu vào nhóm chia tỷ lệ tự động là cách tiếp cận "giống như đám mây" tốt nhất như đã đề cập trước đây.

Nhưng trong trường hợp bạn không thể kết thúc phiên bản của mình và sử dụng phiên bản mới, ví dụ: nếu bạn có IP đàn hồi được liên kết với v.v.

Bạn có thể tạo một tập lệnh Ruby để bắt đầu và dừng các phiên bản của mình dựa trên phạm vi thời gian ngày.

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

Hãy xem amazon_start_stop để tạo bộ lập lịch miễn phí bằng Heroku Scheduler .


1

Mặc dù có nhiều cách để đạt được điều này bằng cách sử dụng tính năng tự động mở rộng quy mô, nhưng nó có thể không phù hợp cho tất cả các trường hợp vì nó kết thúc các phiên bản. Các công việc Cron sẽ không bao giờ hoạt động cho một phiên bản (mặc dù nó hoàn toàn có thể được sử dụng cho các trường hợp như dừng một phiên bản đơn lẻ và lên lịch cho các phiên bản khác khi chạy nhiều phiên bản). Bạn có thể sử dụng các cuộc gọi API như StartInstancesRequest , và StopInstancesRequest để đạt được tương tự, nhưng một lần nữa bạn phải dựa vào một nguồn lực thứ ba. Có rất nhiều ứng dụng để lên lịch cho các phiên bản AWS với nhiều tính năng nhưng để có một giải pháp đơn giản, tôi muốn giới thiệu một ứng dụng miễn phí như snapleaf.io


1

Có, bạn có thể làm điều đó bằng AWS Lambda. Bạn có thể chọn trình kích hoạt trong Cloudwatch chạy trên biểu thức Cron trên UTC.

Đây là liên kết liên quan https://aws.amazon.com/premiumsupport/knowledge-center/start-stop-lambda-cloudwatch/

Một lựa chọn khác là sử dụng awsclitrong đó có sẵn từ pip, apt-get, yumhay brew, và sau đó chạy aws configurevới các thông tin của bạn xuất khẩu từ IAM và thực hiện kịch bản bash sau, để ngăn chặn một EC2 đã được gắn thẻ với Name: AppnameValue: Appname Prod. Bạn có thể sử dụng awscliđể gắn thẻ các phiên bản của mình hoặc gắn thẻ thủ công từ bảng điều khiển AWS. aws ec2 stop-instancessẽ dừng phiên bản và jqđược sử dụng để lọc truy vấn json và tìm nạp id phiên bản chính xác bằng cách sử dụng các thẻ từ aws ec2 describe-instances.

Để xác minh điều đó aws configuređã thành công và trả về chạy đầu ra json aws ec2 describe-instancesvà id phiên bản đang chạy của bạn sẽ ở đó trong đầu ra. Đây là đầu ra mẫu

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

Các kịch bản bash Sau đây là stop-ec2.sh/home/centos/cron-scripts/đó được lấy cảm hứng từ bài này 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} )

Chạy tệp bằng cách sử dụng sh /home/centos/cron-scripts/stop-ec2.shvà xác minh rằng phiên bản EC2 bị dừng. Để gỡ lỗi, hãy chạy 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 .[].InstanceIdvà thấy rằng nó trả về ID phiên bản chính xác đã được gắn thẻ.

Sau đó, trong crontab -edòng sau có thể được thêm

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

sẽ ghi đầu ra vào /tmp/stop. Đây 30 14 * * *là biểu thức cron UTC mà bạn có thể kiểm tra https://crontab.guru/. Tương tự thay thế bằng aws ec2 start-instancescó thể bắt đầu một thể hiện.


0

Tôi tin rằng câu hỏi ban đầu hơi khó hiểu. Nó phụ thuộc vào những gì Pasta cần: 1. khởi chạy / kết thúc (cửa hàng phiên bản) - Tự động mở rộng quy mô là giải pháp phù hợp (câu trả lời của Nakedible) 2. bắt đầu / dừng phiên bản khởi động EBS - Tự động mở rộng quy mô sẽ không hữu ích, tôi sử dụng các tập lệnh được lập lịch từ xa (tức là , ec2 CLI).


-8

Bạn không thể thực hiện việc này một cách tự động, hoặc ít nhất là không có một số thao tác lập trình và API trong các tệp tập lệnh. Nếu bạn muốn có một giải pháp đáng tin cậy để dừng, khởi động lại và quản lý hình ảnh của mình (có lẽ là để kiểm soát chi phí trong môi trường của bạn) thì bạn có thể muốn xem LabSlice . Tuyên bố từ chối trách nhiệm: Tôi làm việc cho công ty này.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.