web-dev-qa-db-fra.com

Arrêt automatique et démarrage de l'instance Amazon EC2

Puis-je démarrer et terminer automatiquement mon instance Amazon à l'aide de l'API Amazon? Pouvez-vous s'il vous plaît décrire comment cela peut être fait? Idéalement, j'ai besoin de démarrer l'instance et de l'arrêter à des intervalles de temps spécifiés chaque jour.

88
Pasta

Juste au cas où quelqu'un trébucherait sur cette vieille question, vous pouvez réaliser la même chose en ajoutant une planification à un groupe de mise à l'échelle automatique: augmentez le nombre d'instances d'un groupe de mise à l'échelle automatique à 1 à certains moments, puis ramenez-le à 0 .

Et comme cette réponse suscite beaucoup de points de vue, j'ai pensé créer un lien vers un guide très utile à ce sujet: Exécution d'instances EC2 selon un calendrier récurrent avec Auto Scaling

100
Nakedible

Vous pouvez essayer d'utiliser directement les outils de l'API Amazon EC2. En réalité, il ne manque que deux commandes: ec2-start-instances et ec2-stop-instances .. Assurez-vous que les variables d'environnement telles que EC2_HOME, AWS_CREDENTIAL_FILE, EC2_CERT, EC2_PRIVATE_KEY, etc., sont correctement configuré et tous les fichiers d'informations d'identification, de certificat et de clé privée AWS se trouvent au bon emplacement; vous trouverez plus d'informations dans la documentation de l'API AWS EC2tools.

Vous pouvez d’abord tester la commande à la main puis, lorsque tout se passera bien, configurez crontab Unix ou tâches planifiées sous Windows. Vous pouvez trouver l'exemple Ci-dessous pour le fichier Linux/etc/crontab (n'oubliez pas que toutes les variables d'environnement Mentionnées ci-dessus doivent être présentes pour l'utilisateur 'Votre-compte'.

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

Je suis un développeur du projet BitNami Cloud, dans lequel nous emballons les outilsAWS (y compris ceux que j'ai mentionnés) dans un programme d'installation gratuit et facile à utiliser Que vous voudrez peut-être essayer: BitNami CloudTools pack stack

26
danoo

Je vous recommande de consulter le guide de mise en route EC2 , qui explique comment utiliser les outils de ligne de commande EC2 pour réaliser vos tâches. Vous pouvez facilement écrire ceci dans un travail cron (sous Linux/UNIX) ou planifié sous Windows pour appeler les commandes de démarrage et d'arrêt à un moment donné.

Si vous voulez le faire à partir de votre propre code, vous pouvez utiliser les API SOAP ou REST. voir le Guide du développeur pour plus de détails.

17
gareth_bowles

J'ai écrit du code en Python, en utilisant la bibliothèque Boto, pour le faire. Vous pouvez ajuster cela pour votre propre usage. Assurez-vous de l'exécuter dans le cadre d'un travail cron, puis vous pourrez démarrer ou arrêter autant d'instances que nécessaire pendant l'exécution des travaux 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

La société pour laquelle je travaille avait régulièrement des clients qui posaient des questions à ce sujet. Nous avons donc créé une application de planification gratuite EC2 disponible ici:

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

Il fonctionne sous Windows et Mac, vous permet de créer plusieurs planifications quotidiennes/hebdomadaires/mensuelles et vous permet d’utiliser des filtres correspondants pour inclure facilement un grand nombre d’instances ou inclut celles que vous ajouterez ultérieurement.

5
AntonyM

Si ce n’est pas une mission critique - Une chose simpliste à faire est de programmer le fichier de commandes pour exécuter «SHUTDOWN» (Windows) à 3 heures du matin tous les jours Alors au moins, vous ne courez pas le risque de laisser accidentellement une instance non désirée courir indéfiniment.

Évidemment, ce n'est que la moitié de l'histoire!

3
AndyM

AWS Data Pipeline fonctionne correctement. https://aws.Amazon.com/premiumsupport/knowledge-center/stop-start-ec2-instances/

Si vous souhaitez exclure les jours du début (par exemple, le week-end), ajoutez un objet ShellCommandPrecondition.

Dans AWS Console/Data Pipeline, créez un nouveau pipeline. Il est plus facile de modifier/importer une définition (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"
}
}

Mettez le script Bash à télécharger et à exécuter en tant que condition préalable dans votre compartiment S3

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

Lors de l'activation et de l'exécution du pipeline les week-ends, l'état d'intégrité du pipeline de la console AWS lit une "ERREUR" trompeuse. Le script bash renvoie une erreur (sortie 1) et EC2 n'est pas démarré. Les jours 1 à 5, le statut est "SAIN".

Pour arrêter automatiquement EC2 à l'heure de fermeture du bureau, utilisez la commande AWS CLI quotidiennement sans condition préalable.

2
user3526918

AutoScaling est limité aux instances de terminaison. Si vous souhaitez arrêter une instance et conserver l'état du serveur, un script externe est la meilleure approche. 

Vous pouvez le faire en exécutant un travail sur une autre instance fonctionnant 24 heures sur 24, 7 jours sur 7 ou vous pouvez utiliser un service tiers tel que Ylastic (mentionné ci-dessus) ou Rocket Peak

Par exemple, en C #, le code pour arrêter un serveur est assez simple: 

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 ajouter une planification à un groupe de mise à l'échelle automatique est la meilleure approche "en nuage" comme mentionné précédemment. 

Mais au cas où vous ne pourriez pas mettre fin à vos instances et en utiliser de nouvelles, par exemple si vous avez associé des adresses IP Elastic à etc. 

Vous pouvez créer un script Ruby pour démarrer et arrêter vos instances en fonction d'une plage de dates.

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

Consultez Amazon_start_stop pour créer un planificateur gratuitement à l'aide de Heroku Scheduler .

1
Pablo Cantero

Oui, vous pouvez le faire avec AWS Lambda. Vous pouvez sélectionner dans Cloudwatch le déclencheur qui s'exécute sur les expressions Cron en UTC.

Voici un lien connexe https://aws.Amazon.com/premiumsupport/knowledge-center/start-stop-lambda-cloudwatch/

Une autre alternative consiste à utiliser awscli qui est disponible à partir de pip, apt-get, yum ou brew, puis à exécuter aws configure avec vos informations d'identification exportées depuis IAM et à exécuter le script bash suivant, pour arrêter un EC2 étiqueté avec Name: Appname et Value: Appname Prod. Vous pouvez utiliser awscli pour baliser vos instances ou le baliser manuellement à partir de la console AWS. aws ec2 stop-instances va arrêter l'instance et jq est utilisé pour filtrer la requête json et récupérer le bon identifiant d'instance en utilisant les balises de aws ec2 describe-instances.

Pour vérifier que aws configure a réussi et renvoie la sortie json, exécutez aws ec2 describe-instances et votre identifiant d'instance en cours d'exécution devrait être présent dans la sortie. Voici un exemple de sortie

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

Le script bash suivant est stop-ec2.sh dans /home/centos/cron-scripts/ et s'inspire de this SO post

(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} )

Exécutez le fichier à l'aide de sh /home/centos/cron-scripts/stop-ec2.sh et vérifiez que l'instance EC2 est arrêtée. Pour déboguer, exécutez 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 et voyez qu'il renvoie l'ID d'instance correct qui a été marqué.

Ensuite, dans crontab -e, la ligne suivante peut être ajoutée 

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

qui enregistrera la sortie à /tmp/stop. Le 30 14 * * * est l'expression UTC cron que vous pouvez archiver dans https://crontab.guru/. De même, le remplacement par aws ec2 start-instances peut démarrer une instance.

1
devssh

Vous pouvez regarder Ylastic faire ceci. L’alternative semble avoir un ordinateur en cours d’exécution qui arrête/démarre d’autres instances à l’aide d’un travail périodique ou d’une tâche planifiée. 

Évidemment, si vous ne voulez qu'une instance, il s'agit d'une solution coûteuse, car une machine doit toujours fonctionner, et payer environ 80 dollars par mois pour qu'une machine exécute des tâches périodiques n'est pas rentable.

1
Chris S

Même s'il existe des moyens d'y parvenir à l'aide de la mise à l'échelle automatique, il est possible qu'elle ne convienne pas à toutes les occasions car elle met fin aux instances. Les tâches cron ne fonctionneront jamais pour une seule instance (bien qu'elles puissent parfaitement être utilisées pour des situations telles que l'arrêt d'une instance et la planification d'autres instances lors de l'exécution de plusieurs instances). Vous pouvez utiliser des appels API tels que StartInstancesRequest et StopInstancesRequest pour obtenir le même résultat, mais vous devez à nouveau vous fier à une troisième ressource. Il existe de nombreuses applications pour planifier des instances AWS avec de nombreuses fonctionnalités, mais pour une solution simple, je recommanderais une application gratuite telle que snapleaf.io

1
Upul Doluweera

Je pense que la question initiale était un peu déroutante. Cela dépend des besoins de Pasta: 1.launch/terminate (magasin d'instance) - Auto Scaling est la bonne solution (réponse de Nakedible) utiliser des scripts planifiés à distance (c.-à-d. ec2 CLI).

0
lk7777