web-dev-qa-db-ja.com

Amazon EC2インスタンスの自動シャットダウンと起動

Amazon APIを使用してAmazonインスタンスを自動的に開始および終了できますか?これをどのように行うことができるか説明していただけますか?理想的には、毎日指定された時間間隔でインスタンスを開始し、インスタンスを停止する必要があります。

88
Pasta

誰かがこの昔の質問に出くわした場合に備えて、最近では自動スケーリンググループにスケジュールを追加することで同じことを実現できます。特定の時間に自動スケーリンググループのインスタンスの量を1に増やし、その後0に戻します。

そして、この回答には多くの意見が寄せられているため、これに関する非常に役立つガイドにリンクすることを考えました: Auto Scaling

101
Nakedible

Amazon EC2 APIツールを直接使用してみてください。実際に必要なコマンドは、ec2-start-instancesとec2-stop-instancesの2つだけです。 EC2_HOME、AWS_CREDENTIAL_FILE、EC2_CERT、EC2_PRIVATE_KEYなどの環境変数が適切に設定され、すべてのAWS認証情報、証明書、プライベートキーファイルが適切な場所にあることを確認してください-AWS EC2 APIツールのドキュメントで詳細を確認できます。

最初に手動でコマンドをテストしてから、すべてが正常に機能するようになったら、WindowsでUnix crontabまたはスケジュールされたタスクを構成します。 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 pack stack

26
danoo

EC2入門ガイド をご覧になることをお勧めします。これは、EC2コマンドラインツールを使用して必要なことを行う方法を示しています。これをcronジョブ(Linux/UNIXの場合)またはWindowsのスケジュールされたジョブに簡単にスクリプト化して、特定の時間に開始および停止コマンドを呼び出すことができます。

独自のコードからこれを行うには、SOAPまたはREST API; 開発者ガイド を参照してください。詳細。

17
gareth_bowles

これを行うために、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])
15
Suman

私が働いている会社には、これについて顧客から定期的に尋ねられるものがあったため、ここで利用可能なフリーウェアEC2スケジューリングアプリを作成しました。

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

WindowsおよびMacで動作し、複数の毎日/毎週/毎月のスケジュールを作成し、マッチングフィルターを使用して多数のインスタンスを簡単に含めるか、将来追加するインスタンスを含めることができます。

5
AntonyM

ミッションクリティカルでない場合-単純化することは、毎日午前3時に「シャットダウン」(ウィンドウ)を実行するようにバッチファイルをスケジュールすることです。そうすれば、少なくとも、不要なインスタンスを無期限に実行したままにしてしまうリスクを負うことはありません。

明らかにこれは物語の半分にすぎません!

4
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バケットの前提条件として実行します

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

週末にパイプラインをアクティブにして実行すると、AWSコンソールのパイプラインヘルスステータスに誤解を招く「エラー」が表示されます。 bashスクリプトはエラー(終了1)を返し、EC2は開始されません。 1日目から5日目までのステータスは「健康」です。

オフィスの閉店時間にEC2を自動的に停止するには、AWS CLIコマンドを前提条件なしで毎日使用します。

2
user3526918

AutoScalingは、インスタンスの終了に制限されています。インスタンスを停止してサーバーの状態を保持する場合は、外部スクリプトが最適なアプローチです。

これを行うには、24時間年中無休で実行されている別のインスタンスでジョブを実行するか、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

IMHOが自動スケーリンググループにスケジュールを追加することは、前述のように最適な「クラウドのような」アプローチです。

ただし、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を使用してそれを行うことができます。 UTCのCron式で実行されるCloudwatchでトリガーを選択できます。

関連リンクはこちら https://aws.Amazon.com/premiumsupport/knowledge-center/start-stop-lambda-cloudwatch/

別の方法として、awscli、_apt-get_、pip、またはyumから利用可能なbrewを使用し、_aws configure_を実行する方法があります。 IAMからエクスポートされた資格情報で次のbashスクリプトを実行し、_Name: Appname_および_Value: Appname Prod_でタグ付けされたEC2を停止します。 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スクリプトは、 this SO post に触発された_stop-ec2.sh_の_/home/centos/cron-scripts/_です。

_(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を実行し、タグ付けされた正しいインスタンスIDを返すことを確認します。

その後、_crontab -e_に次の行を追加できます

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

出力を_/tmp/stop_に記録します。 _30 14 * * *_は、_https://crontab.guru/_でチェックインできるUTC cron式です。同様に、_aws ec2 start-instances_と置き換えると、インスタンスを開始できます。

1
devssh

これを行うには Ylastic を見ることができます。代替案は、cronジョブまたはスケジュールされたタスクを使用して他のインスタンスをシャットダウン/開始する1台のマシンを実行しているようです。

明らかに、1つのインスタンスのみが必要な場合、これは高価なソリューションです。1台のマシンを常に実行する必要があり、1台のマシンでcronジョブを実行するために月に80ドルを支払うことは費用効果がありません。

1
Chris S

自動スケーリングを使用してこれを実現する方法はありますが、インスタンスを終了するため、すべての状況に適しているとは限りません。 Cronジョブは単一のインスタンスでは機能しません(ただし、単一のインスタンスを停止したり、多数のインスタンスを実行しているときに他のインスタンスをスケジュールしたりする場合に完全に使用できます)。 StartInstancesRequestStopInstancesRequest などのAPI呼び出しを使用して同じことを実現できますが、やはり3番目のリソースに依存する必要があります。多くの機能を備えたAWSインスタンスをスケジュールする多くのアプリケーションがありますが、単純なソリューションのために snapleaf.io のような無料アプリをお勧めします

1
Upul Doluweera

最初の質問は少しわかりにくいと思います。パスタのニーズによって異なります:1.起動/終了(インスタンスストア)-Auto Scalingが適切なソリューションです(Nakedibleの答え)2. EBSブートインスタンスを開始/停止します-Auto Scalingは役に立たないので、リモートスケジュールスクリプトを使用します(つまり、 、ec2 CLI)。

0
lk7777