L. Karoubi
L. Karoubi Léo Karoubi est un étudiant de la promotion 2023 d'Epitech (Lyon). Il est passionné par la programmation bas niveau et les micro-processeurs

Experiencing the AWS lambda functions

Experiencing the AWS lambda functions

Thunderbolt is a set of AWS lambda functions for AWS resources scheduling. It is part of a bigger AWS project I am working on, named ParadigmShift, which was intended to be a global and high level AWS resources scheduler, it is well documented in the link above.

First things first : AWS

AWS is a cloud provider which provides a large list of services (databases/server/IA/storage/…).

AWS Lambda is a FAAS (Function As A Service) which allows you to run small code with a total abstraction of the under-layers. To be clear, you can put your code in the service and then trigger it by multiple ways. Lambda is the core of the serverless model on AWS.

serverless_asw_lambda

Thunderbolt

What is it?

Thunderbolt is a set of 3 lambda functions — because that were the three functions I needed when I created the project — used to manipulate Amazon RDS (SQL database), Amazon EC2 (Server), Amazon AppStream (application streaming). The manipulations are basically, power on/off and change instance type (number of cpus, memory allocated, …) when relevant.

Why ?

In fact Thunderbolt is used as a git submodule in a bigger AWS project named ParadigmShift. ParadigmShift was intended to be a global and high level AWS resources scheduler, it is well documented in the link above.

How ?

Even if it is included in a bigger scheme, the project actually can be deployed as is. The deployment is insured by AWS cloudformation which is a powerful IaC (Infrastructure as code) integrator. So pragmatically you can describe your resources in a text file and the CloudFormation service will interpret and generate your requests.

cfm

Technical side

A sample of the deployment script which uses an AWS Cloudformation template (SAM template to be accurate, but this is in the same idea).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
...
echo "-------- Create SAM bucket --------"

# Create the S3 bucket (storage in cloud as filesystem) which will be used for the deployment
aws s3api create-bucket                                         \
    --bucket $bucket                                            \
    --region $region                                            \
    --create-bucket-configuration LocationConstraint=$region    \
    --profile $awsprofile

echo "-------- Deploy lambas --------"

# Create the build
sam build --profile $awsprofile

# Package the build in the created bucket
sam package                                     \
    --s3-bucket $bucket                         \
    --output-template-file build/package.yml    \
    --profile $awsprofile

# Finally deploy the resources on the targeted AWS account
sam deploy                                      \
    --template-file build/package.yml           \
    --stack-name $project                       \
    --capabilities CAPABILITY_NAMED_IAM         \
    --region $region                            \
    --tags Project=$project                     \
    --profile $awsprofile                       \
    --parameter-overrides                       \
        Project=$project                        \

CLEANUP

trap - EXIT

A sample of the template which describes the lambda that handles the RDS and its role. The role is assigned to the lambda and allows the manipulation of other AWS services.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
  # describe the role: the rights on others AWS services and resources which can be affected
  rdsLamdaRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub "${Project}-rds-LambdaRole"
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: LogsPolicy
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - logs:CreateLogGroup
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                Resource: "*"
        # The important one, right to start/stop/modify RDS instance
        - PolicyName: rdsPolicy
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - rds:startDBInstance,
                  - rds:stopDBInstance,
                  - rds:modifyDBInstance
                Resource: "*"
  # describe the function and give the source code path
  rdsLambdaFunction:
      Type: AWS::Serverless::Function
      Properties:
          FunctionName: !Sub "${Project}-rds-handler"
          Description: rds start/stop/modify
          CodeUri: src
          Handler: rds-handler.handler
          Role: !GetAtt rdsLamdaRole.Arn
          Environment:
            Variables:
              Project: !Sub "${Project}"

An example of function in this RDS lambda which stops a RDS instance. The lambda is written in node.js.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function rds_stop(id)
{
    return new Promise((resolve, reject) => {
        const params = {
            DBInstanceIdentifier: id
        };
        /* 
         * call to AWS SDK
         **/
        rds.stopDBInstance(params, function(err, data) {
            if (err)
                return reject(err);
            else
                return resolve("Success")
        });
    });
}

For those who whant to go further, follow the repository page.

Improve ?

Handle more services and manipulations, if they are relevant for ParadigmShift project.