Getting rid of servers is a lifesaver remedy. Ultimately, it saves you from all the server management headaches that come with managing servers.
On the other hand, serverless architectures automatically scale up and down without needing our concerns. So basically, you just need to write the code and let the cloud handle the rest!
Serverless architectures are easy to use, but ever think how you can deploy them quickly too? AWS Cloudformation takes the lead for it.
We are what we repeatedly do. Excellence, then, is not an act, but a habit. Try out Justly and start building your habits today!
We need to provide an agreement to our IAM user on whether it will be able to create and manage specific services on our behalf or not.
Cloudformation will use the same user to access all the required AWS services for creating a serverless deployment stack.
Add the above-mentioned permissions to your IAM user, if not given already.
AWS Lambda and API Gateway are the main AWS services, we will need for running our code with serverless architecture.
If you’re not familiar with the term serverless or AWS lambda, consider referring to Serverless microservices using AWS Lambda and API Gateway.
AWS Cloudformation is a service that allows you to deploy your applications without worrying about infrastructure.
AWS Lambda manages your code on behalf of you!
While choosing serverless architecture, we need to create an AWS Lambda function and API Gateway of our own, and the rest of the things are handled by lambda.
AWS Cloudformation manages Lambda deployment on your behalf!
While using Cloudformation, we don’t need to manage lambda and API Gateway creation by ourselves. Cloudformation takes care of it all.
However, AWS Cloudformation also works with servers and manages all the infrastructure in a pretty good way.
For Creating a lambda function we need to make a zip of our code and put it into s3.
Install aws-cli on your machine and execute the following commands to set up AWS CLI operations.
- aws configure set aws_access_key_id your_aws_acces_key_id
- aws configure set aws_secret_access_key your_aws_secret_access_key
- aws configure set region your_aws_region
- aws s3 cp test_lambda.zip s3://your_aws_bucket
Here, test_lambda.zip is our code, which we want to run by AWS Lambda(serverless architecture). The cp
command will copy the zip file to your lambda bucket.
As we have our code handy at s3, let’s address it and create a Clouformation stack.
But, wait! Before creating the stack directly I would recommend validating the template, that we will use for stack creation.
Validate Cloudformation template
- aws cloudformation validate-template --template-body file://serverless_deployment.yml
After a successful validation check, let’s create a stack. If any misconfiguration will be there validation will be failed with errors.
Create Cloudformation stack using AWS CLI
- aws cloudformation deploy --stack-name test-lambda-stack --template-file serverless_deployment.yml --parameter-overrides AwsRegion=aws_region AwsAccessKeyId=your_aws_access_key_id
AwsSecretAccessKey=your_aws_secret_access_key
LambdaBucket=lambda-test-bucket-006 LambdaUrl=test_lambda.zip
ApiGatewayStageName=prod --capabilities CAPABILITY_IAM CAPABILITY_NAMED_IAM
Visit Cloudformation stack deploy using AWS CLI for more information.
However, we can also use cloudformation create-stack command for stack creation, but this won’t allow updating our stack. It will delete first the older one and then create a new one in case of recreation.
Whilst, deploy command takes care of creating and updating on its own.
A template is a JSON-or-YAML-formatted text file that describes our AWS infrastructure. Visit Template anatomy for more detail on Cloudformation template structure.
Among all sections of the Cloudformation template, Resources are the most important and required ones.
AWS Cloudformation template allows us to create almost every type of resource using the template.
We will discuss more of our usage: Lambda and API Gateway
Note: We will go with YAML formatted template in this blog.
Let’s create a Lambda execution role, that is required to develop the Lambda function.
Basically, Clouformation creates resources from the Resources attributes of the template and gives outcomes as Outputs attributes of the template.
AWSTemplateFormatVersion: 2010-09-09
Description: Deploy serverless demo application.
Resources:
LambdaExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName:
Fn::Sub: "test-lambda-role"
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: "Allow"
Principal:
Service:
- "lambda.amazonaws.com"
Action: "sts:AssumeRole"
ManagedPolicyArns:
- "arn:aws:iam::aws:policy/AWSLambdaExecute"
- "arn:aws:iam::aws:policy/AmazonS3FullAccess"
- "arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess"
- "arn:aws:iam::aws:policy/AmazonKinesisFullAccess"
Path: "/"
Outputs:
LambdaRoleARN:
Description: Role for Lambda execution.
Value:
Fn::GetAtt:
- LambdaExecutionRole
- Arn
Export:
Name:
Fn::Sub: "test-lambda-role"
In the above snippet, we added the Resources attribute and mentioned we want to create LambdaExecutionRole(you can choose your favorite one!).
Resource:
Explore more at Cloudformation IAM Role template format for more details.
Output:
In the Outputs section, we have added LambdaRoleARN, which will be the ARN(URL) of the created lambda role that we have applied using the Resources stage.
After running the AWS CLI command to create the Clouformation stack, you should see the created resource and output in the AWS console like below.
Let’s create a Lambda function, that is required to run or code without setting up the development environment.
As we have seen in the creation of the LambdaExecutionRole, we will need resources and outputs for Lambda, too.
Resources:
LambdaFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName:
Fn::Sub: "test-lambda"
Description: Demo LambdaFunction for learning using cloudformation
Runtime: "go1.x"
Code:
S3Bucket: your_s3_bucket_name
S3Key: !Ref your_lambda_handler_name
Handler: main
MemorySize: 128
Timeout: 10
Role: !GetAtt LambdaExecutionRole.Arn
Environment:
Variables:
ACCESS_KEY_ID:
Fn::Sub: your_aws_secret_key_id
SECRET_ACCESS_KEY:
Fn::Sub: your_aws_secret_access_key
REGION_AWS:
Fn::Sub: your_aws_region
GIN_MODE: release
If you want to connect your lambda function to RDS or some other services which use VPC(like EC2). You need to provide an additional attribute named VpcConfig while creating a lambda function.
Visit the AWS Lambda function template Cloudformation to get deeper details.
After adding the Lambda function as resource and output, you will see
And the final output you can see, the Cloudformation stack has created a lambda function for you🎉.
Now as we already created a lambda function, it’s time to integrate it with API Gateway.
Let’s create an API gateway resource using Cloudformation.
Resources:
ApiGateway:
Type: AWS::ApiGateway::RestApi
Properties:
Description: test API Gateway
EndpointConfiguration:
Types:
- REGIONAL
BinaryMediaTypes: ['*/*']
DisableExecuteApiEndpoint: false
MinimumCompressionSize: 100
Name: test-API
Outputs:
ApiGatewayInvokeURL:
Value: !Sub https://${ApiGateway}.execute-api.${AWS::Region}.amazonaws.com/${ApiGatewayStageName}
Notes:
DisableExecuteApiEndpoint: true
, the endpoint returned by API Gateway(default) won’t work. So, if you want to integrate a custom domain with API gateway, you can make it true otherwise it should be false.Refer API Gateway RestAPI template for more details.
We have already created API Gateway, now it’s time to saturate it with required details like root method and proxy method.
API Gateway Method
Resources:
ApiGatewayRootMethod:
Type: AWS::ApiGateway::Method
Properties:
AuthorizationType: NONE
HttpMethod: ANY
Integration:
IntegrationHttpMethod: POST
Type: AWS_PROXY
Uri: !Sub
- arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${lambdaArn}/invocations
- lambdaArn: !GetAtt LambdaFunction.Arn
ResourceId: !GetAtt ApiGateway.RootResourceId
RestApiId: !Ref ApiGateway
Visit the API Gateway Method template for more information about the API Gateway method.
API Gateway Resource
Resources:
ApiGatewayRootResource:
Type: AWS::ApiGateway::Resource
DependsOn:
- ApiGatewayRootMethod
Properties:
RestApiId: !Ref ApiGateway
ParentId: !GetAtt ApiGateway.RootResourceId
PathPart: '{proxy+}'
Visit the API Gateway Resource template for more details.
AWS Lambda proxy method
Resources:
ApiGatewayResourceProxyMethod:
Type: AWS::ApiGateway::Method
DependsOn:
- ApiGatewayRootResource
Properties:
AuthorizationType: NONE
HttpMethod: ANY
Integration:
IntegrationHttpMethod: POST
Type: AWS_PROXY
Uri: !Sub
- arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${lambdaArn}/invocations
- lambdaArn: !GetAtt LambdaFunction.Arn
ResourceId: !Ref ApiGatewayRootResource
RestApiId: !Ref ApiGateway
It’s used to enable APIs to call a Lambda function with a single integration setup on a catch-all ANY method. For example,
CRUD operations consist of multiple request methods such as POST, GET, PUT, and DELETE and we don’t need to specify all of them to invoke our lambda.
Proxy handles all the methods by itself!
Visit the API Gateway Method template for more information about the API Gateway method.
After Adding the above-mentioned Resources, you will see the newly created resources in the resources tab of Cloudformation.
Now, as we are already done with the API Gateway configuration.
Let’s permit our API Gateway to invoke the earlier created Lambda function and deploy it.
Resources:
LambdaApiGatewayInvoke:
Type: AWS::Lambda::Permission
Properties:
Action: lambda:InvokeFunction
FunctionName: !GetAtt LambdaFunction.Arn
Principal: apigateway.amazonaws.com
SourceArn: !Sub arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${ApiGateway}/*/*/*
ApiGatewayDeployment:
Type: AWS::ApiGateway::Deployment
DependsOn:
- ApiGatewayResourceProxyMethod
Properties:
RestApiId: !Ref ApiGateway
StageName: !Ref ApiGatewayStageName
RestApi
resource to a stage so that clients can call the API over the internetVisit Lambda Invoke Permission and API Gateway Deployment for more information.
After adding lambda invoke permission and deploying API Gateway, you will see the newly added resources in the console.
Invoke the ApiGatewayInvokeURL along with your application route and you will see your lambda responded!🎊
By default, API Gateway provides a default route using which we can access our application routes, but it keeps changing on every deployment.
Hence, we need to bind it with the custom domain, which will remain constant, doesn’t matter API gateway changes though.
Resources:
ApiGatewayCustomDomainMapping:
Type: AWS::ApiGateway::BasePathMapping
DependsOn:
- ApiGatewayDeployment
Properties:
DomainName: !Ref CustomDomainName
RestApiId: !Ref ApiGateway
Stage: !Ref ApiGatewayStageName
Refer CustomDomain mapping template and API Gateway Custom domain mapping for more details.
Last but not least, Cloudformation works a way better to automate any AWS service deployments like EC2, IAM, and many more.
If you want to refer to the full code, it’s available at serverless deployment using Cloudformation with GitLab CI integration.
Keep automating!!