簡體   English   中英

自動關閉並啟動Amazon EC2實例

[英]Auto Shutdown and Start Amazon EC2 Instance

我可以使用Amazon API自動啟動和終止我的Amazon實例嗎? 你能描述一下如何做到這一點嗎? 理想情況下,我需要啟動實例並每天以指定的時間間隔停止實例。

為了防止有人在這個舊問題上遇到麻煩,現在你可以通過向自動縮放組添加一個時間表來實現同樣的目的:在某些時間將自動縮放組中的實例數量增加到1並在之后將其減少到0 。

由於這個答案得到了很多觀點,我想鏈接到一個非常有用的指南: 使用Auto Scaling在循環計划上運行EC2實例

您可以嘗試直接使用Amazon EC2 API工具。 實際上只需要兩個命令:ec2-start-instances和ec2-stop-instances。 確保正確配置了EC2_HOME,AWS_CREDENTIAL_FILE,EC2_CERT,EC2_PRIVATE_KEY等環境變量,並且所有AWS憑證,證書和私鑰文件都位於正確的位置 - 您可以在AWS EC2 API工具文檔中找到更多信息。

您可以先手動測試命令,然后在一切正常時,在Windows上配置Unix crontab或Scheduled Tasks。 您可以在下面找到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包堆棧

我建議您查看EC2入門指南 ,該指南向您展示如何使用EC2命令行工具執行所需操作。 您可以輕松地將此腳本編寫到cron作業(在Linux / UNIX上)或Windows上的預定作業,以在給定時間調用啟動和停止命令。

如果要從自己的代碼中執行此操作,可以使用SOAP或REST API; 請參閱開發者指南了解詳細信息

我使用Boto庫在Python中編寫代碼來執行此操作。 您可以根據自己的需要進行調整。 確保將其作為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])

我工作的公司讓客戶經常詢問這個,所以我們在這里寫了一個免費的EC2調度應用程序:

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

它適用於Windows和Mac,允許您創建多個每日/每周/每月計划,並允許您使用匹配篩選器輕松包含大量實例,或包括您將來添加的實例。

如果它不是關鍵任務 - 一個簡單的事情是安排批處理文件每天凌晨3點運行'SHUTDOWN'(窗口)。 那么至少你不會冒不小心讓無意義的實例無限期地運行的風險。

顯然這只是故事的一半!

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控制台管道運行狀況會讀取誤導性的“錯誤”。 bash腳本返回錯誤(退出1)並且未啟動EC2。 在第1天到第5天,狀態為“健康”。

要在關閉辦公時間自動停止EC2,請在每日前提條件下使用AWS CLI命令。

AutoScaling僅限於終止實例。 如果要停止實例並保留服務器狀態,則外部腳本是最佳方法。

您可以通過在另一個全天候運行的實例上運行作業來執行此操作,也可以使用第三方服務,例如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));
        }

恕我直言,如上所述,向自動縮放組添加時間表是最好的“雲狀”方法。

但是,如果您無法終止實例並使用新實例,例如,如果您有與之相關的彈性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免費創建一個調度程序

盡管有很多方法可以使用自動縮放來實現這一點,但它可能不適合所有場合,因為它會終止實例。 Cron作業永遠不會用於單個實例(盡管它可以完美地用於停止單個實例和在運行許多實例時調度其他實例的情況)。 您可以使用諸如StartInstancesRequestStopInstancesRequest之類的API調用來實現相同的功能,但您必須再次依賴第三個資源。 有許多應用程序可以調度具有許多功能的AWS實例,但對於一個簡單的解決方案,我建議使用像snapleaf.io這樣的免費應用程序

你可以看看Ylastic這樣做。 替代方案似乎是讓一台機器運行,使用cron作業或計划任務關閉/啟動其他實例。

顯然,如果你只想要一個實例,這是一個昂貴的解決方案,因為一台機器必須始終運行,並且每台為一台機器支付約80美元來運行cron作業是不划算的。

是的,您可以使用AWS Lambda執行此操作。 您可以在Cloudwatch中選擇在UTC上的Cron表達式上運行的觸發器。

這是一個相關的鏈接https://aws.amazon.com/premiumsupport/knowledge-center/start-stop-lambda-cloudwatch/

另一種方法是使用可從pipapt-getyumbrew apt-get awscli ,然后使用從IAM導出的憑據運行aws configure並執行以下bash腳本,以停止已使用Name: Appname標記的EC2 Name: AppnameValue: Appname Prod 您可以使用awscli標記實例或從AWS控制台手動標記它。 aws ec2 stop-instances將停止實例, jq用於過濾json查詢並使用aws ec2 describe-instances的標記獲取正確的實例id。

要驗證aws configure是否成功並返回json輸出,請運行aws ec2 describe-instances並且您的運行實例ID應該在輸出中。 這是一個示例輸出

{
    "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腳本是/home/centos/cron-scripts/ stop-ec2.sh ,靈感來自這篇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 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 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並看到它返回已標記的正確實例ID。

然后在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替換可以啟動一個實例。

我認為最初的問題有點令人困惑。 這取決於Pasta需要什么:1。啟動/終止(實例存儲) - Auto Scaling是正確的解決方案(Nakedible的答案)2。啟動/停止EBS啟動實例 - Auto Scaling無濟於事,我使用遠程調度腳本(即,ec2 CLI)。

您不能自動執行此操作,或者至少在腳本文件中沒有編程和API操作時也不能這樣做。 如果您想要一個可靠的解決方案來停止,重新啟動和管理您的圖像(可能是為了控制您環境中的成本),那么您可能需要查看LabSlice 免責聲明:我為這家公司工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM