ฉันจะเริ่มและยุติอินสแตนซ์ Amazon โดยอัตโนมัติโดยใช้ Amazon API ได้หรือไม่ คุณช่วยอธิบายวิธีการนี้ได้ไหม ฉันจำเป็นต้องเริ่มอินสแตนซ์และหยุดอินสแตนซ์ตามช่วงเวลาที่กำหนดทุกวัน
ฉันจะเริ่มและยุติอินสแตนซ์ Amazon โดยอัตโนมัติโดยใช้ Amazon API ได้หรือไม่ คุณช่วยอธิบายวิธีการนี้ได้ไหม ฉันจำเป็นต้องเริ่มอินสแตนซ์และหยุดอินสแตนซ์ตามช่วงเวลาที่กำหนดทุกวัน
คำตอบ:
ในกรณีที่มีคนสะดุดกับคำถามเก่า ๆ นี้ในปัจจุบันคุณสามารถบรรลุสิ่งเดียวกันได้โดยการเพิ่มตารางเวลาในกลุ่มการปรับขนาดอัตโนมัติ: เพิ่มจำนวนอินสแตนซ์ในกลุ่มการปรับขนาดอัตโนมัติเป็น 1 ในบางช่วงเวลาและลดกลับเป็น 0 หลังจากนั้น .
และเนื่องจากคำตอบนี้ได้รับการดูจำนวนมากฉันจึงคิดว่าจะเชื่อมโยงไปยังคำแนะนำที่เป็นประโยชน์มากเกี่ยวกับเรื่องนี้: การเรียกใช้อินสแตนซ์ EC2 ตามกำหนดการที่เกิดซ้ำด้วยการปรับขนาดอัตโนมัติ
คุณสามารถลองใช้เครื่องมือ Amazon EC2 API ได้โดยตรง มีเพียงสองคำสั่งที่คุณต้องการ: ec2-start-instances และ ec2-stop-instances ตรวจสอบให้แน่ใจว่าตัวแปรสภาพแวดล้อมเช่น EC2_HOME, AWS_CREDENTIAL_FILE, EC2_CERT, EC2_PRIVATE_KEY ฯลฯ ได้รับการกำหนดค่าอย่างเหมาะสมและข้อมูลรับรอง AWS ใบรับรองและไฟล์คีย์ส่วนตัวทั้งหมดอยู่ในตำแหน่งที่เหมาะสม - คุณสามารถค้นหาข้อมูลเพิ่มเติมได้ในเอกสารประกอบเครื่องมือ AWS EC2 API
คุณสามารถทดสอบคำสั่งด้วยตนเองก่อนจากนั้นเมื่อทุกอย่างทำงานได้ดีให้กำหนดค่า 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 stack
ขอแนะนำให้คุณดูคู่มือการเริ่มต้นใช้งาน EC2ซึ่งจะแสดงวิธีทำสิ่งที่คุณต้องการโดยใช้เครื่องมือบรรทัดคำสั่ง EC2 คุณสามารถเขียนสคริปต์นี้ลงในงาน cron (บน Linux / UNIX) หรืองานที่กำหนดเวลาไว้บน Windows เพื่อเรียกใช้คำสั่งเริ่มและหยุดในเวลาที่กำหนด
หากคุณต้องการดำเนินการจากโค้ดของคุณเองคุณสามารถใช้ SOAP หรือ REST API ดูรายละเอียดในคู่มือนักพัฒนาซอฟต์แวร์
ฉันเขียนโค้ดใน 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])
หากไม่ใช่ภารกิจสำคัญ - สิ่งที่ง่ายที่ต้องทำคือกำหนดเวลาแบตช์ไฟล์ให้เรียกใช้ 'SHUTDOWN' (windows) เวลา 03.00 น. ทุกวัน อย่างน้อยคุณก็ไม่เสี่ยงที่จะปล่อยให้อินสแตนซ์ที่ไม่ต้องการทำงานโดยไม่ได้ตั้งใจ
เห็นได้ชัดว่านี่เป็นเพียงครึ่งเรื่องเท่านั้น!
บริษัท ที่ฉันทำงานมีลูกค้าถามเกี่ยวกับเรื่องนี้เป็นประจำดังนั้นเราจึงได้เขียนแอปกำหนดเวลา EC2 แบบฟรีแวร์ไว้ที่นี่:
http://blog.simple-help.com/2012/03/free-ec2-scheduler/
ทำงานบน Windows และ Mac ช่วยให้คุณสร้างตารางเวลารายวัน / สัปดาห์ / เดือนได้หลายรายการและให้คุณใช้ตัวกรองที่ตรงกันเพื่อรวมอินสแตนซ์จำนวนมากได้อย่างง่ายดายหรือรวมถึงรายการที่คุณจะเพิ่มในอนาคต
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 Console Pipeline Health Status จะอ่าน "ERROR" ที่ทำให้เข้าใจผิด สคริปต์ทุบตีส่งกลับข้อผิดพลาด (ทางออก 1) และ EC2 ไม่เริ่มทำงาน ในวันที่ 1 ถึง 5 สถานะคือ "HEALTHY"
หากต้องการหยุด EC2 โดยอัตโนมัติเมื่อปิดเวลาสำนักงานให้ใช้คำสั่ง AWS CLI ทุกวันโดยไม่มีเงื่อนไขเบื้องต้น
คุณสามารถดูYlasticเพื่อทำสิ่งนี้ อีกทางเลือกหนึ่งดูเหมือนว่าจะมีเครื่องหนึ่งทำงานที่ปิด / เริ่มอินสแตนซ์อื่น ๆ โดยใช้งาน cron หรืองานตามกำหนดเวลา
เห็นได้ชัดว่าหากคุณต้องการเพียงอินสแตนซ์เดียวนี่เป็นวิธีแก้ปัญหาที่มีราคาแพงเนื่องจากเครื่องหนึ่งเครื่องต้องทำงานอยู่เสมอและการจ่ายเงินประมาณ $ 80 ต่อเดือนสำหรับเครื่องจักรหนึ่งเครื่องเพื่อเรียกใช้งาน cron นั้นไม่คุ้มค่า
AutoScaling จำกัด เฉพาะการยุติอินสแตนซ์ หากคุณต้องการหยุดอินสแตนซ์และคงสถานะเซิร์ฟเวอร์ไว้สคริปต์ภายนอกเป็นแนวทางที่ดีที่สุด
คุณสามารถทำได้โดยการเรียกใช้งานในกรณีอื่นที่ใช้ 24/7 หรือคุณสามารถใช้บริการของบุคคลที่ 3 เช่น Ylastic (ดังกล่าวข้างต้น) หรือยอดจรวด
ตัวอย่างเช่นใน 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));
}
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 จัดตารางเวลา
แม้ว่าจะมีหลายวิธีในการบรรลุเป้าหมายนี้โดยใช้การปรับขนาดอัตโนมัติ แต่ก็อาจไม่เหมาะสำหรับทุกโอกาสเนื่องจากจะยุติอินสแตนซ์ งาน Cron จะไม่ทำงานในอินสแตนซ์เดียว (แม้ว่าจะสามารถใช้ได้อย่างสมบูรณ์แบบสำหรับสถานการณ์เช่นการหยุดอินสแตนซ์เดียวและกำหนดเวลาอินสแตนซ์อื่น ๆ เมื่อเรียกใช้อินสแตนซ์จำนวนมาก) คุณสามารถใช้การเรียก API เช่นStartInstancesRequestและStopInstancesRequestเพื่อให้ได้สิ่งเดียวกัน แต่คุณต้องพึ่งพาทรัพยากรที่สามอีกครั้ง มีแอปพลิเคชันมากมายที่กำหนดเวลาอินสแตนซ์ AWS ที่มีคุณสมบัติมากมาย แต่สำหรับวิธีแก้ปัญหาง่ายๆฉันขอแนะนำแอปฟรีเช่นsnapleaf.io
ใช่คุณสามารถทำได้โดยใช้ 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
และ 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"
}
]
}
สคริปต์ทุบตีต่อไปนี้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
และดูว่าส่งคืน 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
สามารถเริ่มต้นอินสแตนซ์
ฉันเชื่อว่าคำถามเริ่มต้นนั้นค่อนข้างสับสนเล็กน้อย ขึ้นอยู่กับสิ่งที่พาสต้าต้องการ: 1. เปิด / ยุติ (ที่เก็บอินสแตนซ์) - การปรับขนาดอัตโนมัติเป็นวิธีการแก้ปัญหาที่เหมาะสม (คำตอบของ Nakedible) 2. เริ่ม / หยุดอินสแตนซ์การบูต EBS - การปรับขนาดอัตโนมัติจะไม่ช่วยฉันใช้สคริปต์ตามกำหนดเวลาระยะไกล (เช่น , ec2 CLI)
คุณไม่สามารถทำได้โดยอัตโนมัติหรืออย่างน้อยก็ไม่ได้หากไม่มีการเขียนโปรแกรมและการจัดการ API ในไฟล์สคริปต์ หากคุณต้องการที่จะเป็นทางออกที่น่าเชื่อถือในการหยุดการเริ่มต้นใหม่และจัดการภาพของคุณ (น่าจะควบคุมค่าใช้จ่ายในสภาพแวดล้อมของคุณ) แล้วคุณอาจต้องการที่จะดูที่LabSlice คำเตือน: ฉันทำงานให้กับ บริษัท นี้