When I first heard the word Serverless I thought I would soon lose my job. No more servers, no more code, no more work to do, it's simple, isn't it?
What happened instead is that, like all other back-end developers, I have a new tool to do my job better.
In this article, I will briefly explain what Serverless is and what advantages it brings us. We will see the Bref library and how to deploy a Symfony application on AWS Lambda.
In the next article I will go into the details of the deployment, analyzing the various components involved and proposing solutions and use cases for this architecture.
Let's begin!
What does it mean really serverless?
Serverless is a word that very often may misguide one into thinking that there is no server where the application is running.
Serverless just means that developers don't have to maintain the infrastructure anymore because AWS will take care of it: developers can focus only on the code.
AWS provides a serverless service called Lambda where you can run code without provisioning or managing servers. Lambda is based on two main concepts: functions and events. A function is a piece of code (which can be written using various languages) that performs some sort of operation. An event is something that happened in your infrastructure, for instance:
A file is uploaded on an S3 bucket
A record is inserted in an Amazon DynamoDB table
When an event happens it will trigger the Lambda function and our code will run.
A big advantage of AWS Lambda service is a “pay-per-use” model: you are charged only for the actual compute time used — there is no charge when your code is not running. Let's compare it to a “traditional” EC2 scenario. In the graph below, you can see costs (green areas) are constant during the time: you pay the same amount of money, regardless of the actual use of your servers (blue area).
In a serverless scenario, costs are always tied to the actual use of your infrastructure.
Lambda is a very cheap service: 0,0000002 USD per request (a function run) with the first million requests per month free. This will increase if you need more memory or some other configurations.
When Lambda was released it supported very few languages and PHP wasn't one of them. In December 2018 AWS announced:
“Native PHP support on Lambda wasn't one of those features, but the new AWS Lambda runtime API and layers capabilities give us the ability to build a clean, supportable implementation of PHP on Lambda of our own.”
This means that you can import PHP binaries file into Lambda layer, thus being able to run any PHP code, even your Symfony Application.
PHP binaries need to be created following certain rules. Creating and maintaining those files is a very expensive and time-consuming activity but, lucky for us, Matthieu Napoli has created an open-source library called Bref that helps developers to deploy PHP applications on Lambda.
It provides:
PHP runtimes for AWS Lambda
A library to interface PHP code with Lambda API
Rich documentation
Deployment tools
Image from https://blog.theodo.com/2019/05/serverless-symfony-on-aws-lambda-with-bref/
Requirements
To deploy a Symfony Application into a Lambda with Bref you need:
AWS account with Access Key ID, Secret Access Key
Install and configure the serverless framework
Install and initialize Bref library
The first step is to configure AWS with your command line interface with this command
aws configure
The terminal will ask you to enter the Access Key ID, the Secret Access Key, the default region name and default output format.
Now you need to install the serverless framework, a tool to develop, deploy, test, secure, and monitor your Serverless applications
npm install -g serverless
To use this tool you need to associate your credentials with it by the following command:
serverless config credentials — provider aws — key <key> — secret <secret>
Now your terminal is configured so we can start to work into our Symfony application.
Bref
After you have created and configured your Symfony Application you can install Bref
To install it you need to launch into your command line interface:
composer require bref/bref
Now you need to initialize the project by running
vendor/bin/bref init
When you initialize bref, it creates automatically two files into the project root:
index.php that contains the function code
serverless.yml that contains the configuration for deploying on AWS
Example of standard configuration:
service: symfony-bref
provider:
name: aws
region: eu-central-1
runtime: provided
environment:
APP_ENV: prod
plugins:
- ./vendor/bref/bref
functions:
api:
handler: public/index.php
description: ''
timeout: 30 # in seconds (API Gateway has a timeout of 30 seconds)
layers:
- ${bref:layer.php-73-fpm}
events:
- http: 'ANY /'
- http: 'ANY /{proxy+}'
Usually, you have to add the environment with APP_ENV and change the region name.
Configure serverless to deploy your Symfony application
Before doing it, it's important to understand why the serverless framework can help us.
Some months ago bref make the deploy with AWS SAM an open-source framework that you can use to build serverless applications on AWS, it's a tool for CloudFormation with a not simple configuration.
AWS SAM has:
Template specification
Command-line interface
This is a standard SAM configuration:
AWSTemplateFormatVersion: '2010–09–09'
Transform: AWS::Serverless-2016–10–31
Description: 'Symfony test'
Resources:
MyFunction:
Type: AWS::Serverless::Function
Properties:
FunctionName: 'symfony-test'
Description: ''
CodeUri: .
Handler: public/index.php
Timeout: 30 # in seconds (API Gateway has a timeout of 30 seconds)
MemorySize: 1024 # The memory size is related to the pricing and CPU power
Runtime1sw: provided
Layers:
- 'arn:aws:lambda:eu-central-1:209497400698:layer:php-73-fpm:7'
Events:
# The function will match all HTTP URLs
HttpRoot:
Type: Api
Properties:
Path: /
Method: ANY
HttpSubPaths:
Type: Api
Properties:
Path: /{proxy+}
Method: ANY
Environment:
Variables:
MY_CUSTOM_ENV_VARIABLES: 'this is my custom env variables'
AWS_ENV_VARIABLES: '{{resolve:ssm:/env-aws-variable:1}}'
# Outputs show up in the CloudFormation dashboard
Outputs:
DemoHttpApi:
Description: 'URL of our function in the *Prod* environment'
Value: !Sub 'https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/'
The configuration is more complex and longer than serverless framework configuration.
In serverless framework you can add SAM configuration for complex configuration and another advantage of serverless framework is the multi-provider: you can use it for AWS or Azure or other providers without changing the configuration. AWS SAM is only for AWS.
For these reasons, Bref community decided to switch from AWS SAM to serverless framework.
To start your deploy you need to install Composer dependencies optimized for production launching this command into your CLI:
composer install --optimize-autoloader --no-dev
Now launching this command you will deploy your application:
serverless deploy
Now some subroutines start and in the end, you can see a link, if you click on it you can see your application works!
What really happened?
When you deploy into a Lambda service you will do it through a CloudFormation stack.
A stack is simply a group of service that composes an application, for example:
Databases
S3 Buckets
The serverless framework translates configuration from serverless.yaml file and creates an AWS CloudFormation template from it.
Based on that template, a stack is created (if needed), with no resources except for an S3 Bucket used to store your code as a zip file.
Lambda will get the new code, unzip it and replace the older code.
Serverless framework optimizes these operations by comparing hashes of the files and performing a new deploy only if needed.
That's it, simple as promised, a Symfony application deployed on Lambda.
In the next article, I'll tackle some issues like Symfony tweaks, use of environment variable and trigger upon events.
Top comments (0)