como parar e iniciar automaticamente a instância EC2 AWS
só quero parar e iniciar várias instâncias EC2 automática e periodicamente (não reiniciar).
Há alguma forma recomendada de fazer isto?5 answers
A Amazon publicou recentemente (Fev 2018) a ferramenta de escalonamento de instância EC2:
Tinha isto a funcionar na minha conta em 15 minutos, muito simples de usar e praticamente livre.O Scheduler de instância AWS é uma solução simples fornecida pelo AWS que permite aos clientes configurar facilmente os horários personalizados de início e paragem pela sua nuvem elástica de cálculo Amazónica (Amazon EC2) e Amazon Instâncias Relational Database Service (Amazon RDS). A solução é fácil de implantar e pode ajudar a reduzir os custos operacionais para ambos ambientes de desenvolvimento e produção. Clientes que utilizam presente solução para executar instâncias durante o horário de trabalho regular pode economizar até 70% em comparação com a execução dessas instâncias 24 horas por dia.
Https://aws.amazon.com/answers/infrastructure-management/instance-scheduler/
Esta solução pode ser modificada para obter a lista EC2 dinamicamente, ou operar num conjunto de instâncias que podem ser identificadas com base numa determinada marca.
Outra alternativa é utilizar awscli
que está disponível a partir de pip
, apt-get
, yum
ou brew
, e então executando aws configure
com as suas credenciais do IAM e executando o seguinte script bash, para parar um EC2 que foi marcado com Name: Appname
e Value: Appname Prod
. Pode usar awscli
para marcar as suas instâncias ou marcá-las manualmente a partir da consola AWS. aws ec2 stop-instances
irá parar a instância e jq
é usado para filtrar a pesquisa json e obter o id de instância correcto usando as marcas de aws ec2 describe-instances
.
Para verificar se aws configure
foi bem sucedido e devolve a execução do json aws ec2 describe-instances
e o seu id da instância em execução deverá estar lá no resultado. Aqui está uma saída de amostra
{
"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"
}
]
}
O seguinte script bash é stop-ec2.sh
em /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} )
Execute o ficheiro usando sh /home/centos/cron-scripts/stop-ec2.sh
e verifique se a instância EC2 é parada. Para depurar execute 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
e veja se devolve o ID de instância correcto que foi marcado.
Depois, em crontab -e
, pode ser aditada a seguinte linha
30 14 * * * sh /home/centos/cron-scripts/stop-ec2.sh >> /tmp/stop
Que irá registar a saída para /tmp/stop
. O 30 14 * * *
é a expressão de cron UTC em que poderá verificar https://crontab.guru/
Script Lambda to stop instance:
import json
import boto3
# Enter the region your instances are in. Include only the region without specifying Availability Zone; e.g., 'us-east-1'
region = 'us-east-1'
def lambda_handler(event, context):
ec2 = boto3.client('ec2', region_name=region)
filter = [{'Name': 'tag:Name', 'Values': ['****-env']}] //give instance name here in place of ****-env
instances = ec2.describe_instances(Filters=filter)
#ec2.stop_instances(InstanceIds=instances)
stop_instance = instances.get('Reservations')[0].get('Instances')[0].get('InstanceId')
stop_instances = []
stop_instances.append(stop_instance)
ec2.stop_instances(InstanceIds=stop_instances)
Script Lambda para iniciar a instância:
import json
import boto3
# Enter the region your instances are in. Include only the region without specifying Availability Zone; e.g., 'us-east-1'
region = 'us-east-1'
def lambda_handler(event, context):
ec2 = boto3.client('ec2', region_name=region)
filter = [{'Name': 'tag:Name', 'Values': ['****-env']}]
instances = ec2.describe_instances(Filters=filter)
#ec2.stop_instances(InstanceIds=instances)
start_instance = instances.get('Reservations')[0].get('Instances')[0].get('InstanceId')
start_instances = []
start_instances.append(start_instance)
ec2.start_instances(InstanceIds=start_instances)
O escalonador de ASG é a melhor e mais fácil opção para gerir a instância EC2 se estiver a usar o ASG. Se não usar ASG, então você pode usar qualquer solução AWS instance scheduler CF ou lambda com evento cloudwatch Cron.