AWS Lambda is a compute service that lets you run code without provisioning or managing servers. AWS Lambda executes your code only when needed and scales automatically, from a few requests per day to thousands per second.
AWS lambdas should be used for small and light functions. For more complicated or time expensive functions it is better to use and EC2
instance which can be turned on/off when needed to keep costs low.
The idea is to create a lambda that can start a system (both an EC2
and RDS
) using an API.
This lambda allow users to start or stop instances through html requests. There is an URL and users can specify in queryStringParameters which system they want to act upon and what action they want (start/stop/status
). For security reasons it is also needed to include a token in the headers.
And example of the data used would be:
headers = { "token": ****** } queryStringParameters = { "system_1": "start", "system_2": "stop" }
These lambda is created in python 3.6 and rely on aws boto3 library. There are 2 files:
First of all it will start an AWS session an it is important to start it in the correct region. There is no need to use any credentials since AWS has already put the ACCESS_KEY and SECRET_KEY as an environment vars and are used in boto3 background.
Important: use the appropiate region.
Then there are 2 functions: * act_instance_ec2 * act_instance_rds
For act_instance_ec2 it will simply start/stop the ec2 instance asked. For act_instance_rds it first will check the state of the instance and then it will act if possible.
The workflow is: * start rds: from 'stopped' to 'available' * stop rds: from 'available' to 'stopped'
There is a dictionary with the infos of the instances that the lambdas can act upon. The idea is that users can only use the name of the system (magento/vtiger
) and the dictionary will give the instance id.
Example of dictionary:
INSTANCES = { "system_1": { "EC2": "i-068e5489acdd4a544", "RDS": "db_1" }, "system_2": { "EC2": "i-0be4e5d15b667ad16", "RDS": "db_2" }, "other system": { "EC2": None, "RDS": None, } }
For the lambda instances_api there is some handling of the request. First it will check if the token is present and correct and if not it will return a json with a message of the actual problem.
If the token is correct it will iterate over the systems presents in the request params and if it is found in the INSTANCES dictionary and if the action is start/stop
it will act. The lambda will return a json with the result of each system, like this:
{ "system_1": { "EC2": "EC2 instance 'i-05acfb91d2225ecd3' started", "RDS": "ECS instance 'system_1' started" }, "system_2": { "EC2": "EC2 instance 'i-01dd4d50b6fad7de0' stopped", "RDS": "ECS not configured" } }
First of all there is some work to do in AWS IAM service. This will give the lambdas the following permissions:
EC2
instancesRDS
instancesTo do that first you will need to a policy and then assign it to a role.
policies
The policy config is:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ec2:DescribeInstanceStatus", "ec2:DescribeInstances", "ec2:StartInstances", "ec2:StopInstances" ], "Resource": [ "*" ] }, { "Effect": "Allow", "Action": [ "rds:DescribeDBInstances", "rds:StopDBInstance", "rds:StartDBInstance" ], "Resource": "*" }, { "Action": [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ], "Effect": "Allow", "Resource": "arn:aws:logs:*:*:*" } ] }
roles
functions
create function
lambda_function.py
aws.py
API Gateway is set used as a triger. Click at the left of the image, where it says add triger.
One way to give more functions to this lambda is to set times to start or stop certain systems. For example you could want to start a system at 7 am and then stop it at 19 pm on workdays. This could be useful for development
systems.
You can do this by two ways. First would be to create a second lambda that calls the first using html requests. The second would be to simply hardcode the action (look at lambda_handler_start.py
) to see this second option.
And you need to set the time triger by using AWS CloudWatch.
Events/rules
The cron expressions could be:
'start_instances lambda': 'start_weekdays': '0 7 ? * MON-FRI *'' 'stop_instances lambda': 'stop-fri': '00 14 ? * FRI *'' 'stop_midnight': '0 23 ? * * *'' 'stop_mon-thu': '00 19 ? * MON-THU *'